1088 lines
29 KiB
C
1088 lines
29 KiB
C
|
#include <stdlib.h>
|
||
|
|
||
|
#include "ansi_decls.h"
|
||
|
#include "ansi.h"
|
||
|
|
||
|
struct intermediate {
|
||
|
unsigned char buf[2];
|
||
|
int count;
|
||
|
};
|
||
|
|
||
|
struct param {
|
||
|
unsigned char buf[128];
|
||
|
int buf_count;
|
||
|
unsigned int params[16];
|
||
|
int count;
|
||
|
};
|
||
|
|
||
|
struct ansi_context {
|
||
|
struct sm_context base_context;
|
||
|
struct intermediate i_ctx;
|
||
|
struct param p_ctx;
|
||
|
unsigned char private;
|
||
|
struct ansi_actions cbs;
|
||
|
put_handler put_cb;
|
||
|
void *put_ctx;
|
||
|
osc_handler osc_put_cb;
|
||
|
void *osc_put_ctx;
|
||
|
};
|
||
|
|
||
|
/* Ground State (start state) */
|
||
|
|
||
|
static struct sm_transition ground_transitions[] = {
|
||
|
{ ground_execute_pred, do_execute, NULL },
|
||
|
{ ground_print_pred, do_print, NULL },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state ground = {
|
||
|
.name = "Ground",
|
||
|
.entry_action = NULL,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = ground_transitions
|
||
|
};
|
||
|
|
||
|
/* Escape State */
|
||
|
|
||
|
static struct sm_transition escape_transitions[] = {
|
||
|
{ escape_execute_pred, do_execute, NULL },
|
||
|
{ escape_ignore_pred, do_ignore, NULL },
|
||
|
{ escape_to_ground_pred, do_esc_dispatch, &ground },
|
||
|
{ escape_to_escape_intermediate_pred, do_collect, &escape_intermediate },
|
||
|
{ escape_to_string_pred, NULL, &sos_pm_apc_string },
|
||
|
{ escape_to_dcs_entry_pred, NULL, &dcs_entry },
|
||
|
{ escape_to_osc_string_pred, NULL, &osc_string },
|
||
|
{ escape_to_csi_entry_pred, NULL, &csi_entry },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state escape = {
|
||
|
.name = "Escape",
|
||
|
.entry_action = do_clear,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = escape_transitions
|
||
|
};
|
||
|
|
||
|
/* Escape Intermediate State */
|
||
|
|
||
|
static struct sm_transition escape_intermediate_transitions[] = {
|
||
|
{ escape_intermediate_execute_pred, do_execute, NULL },
|
||
|
{ escape_intermediate_collect_pred, do_collect, NULL },
|
||
|
{ escape_intermediate_ignore_pred, do_ignore, NULL },
|
||
|
{ escape_intermediate_to_ground_pred, do_esc_dispatch, &ground },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state escape_intermediate = {
|
||
|
.name = "Escape Intermediate",
|
||
|
.entry_action = NULL,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = escape_intermediate_transitions
|
||
|
};
|
||
|
|
||
|
/* CSI Entry State */
|
||
|
|
||
|
static struct sm_transition csi_entry_transitions[] = {
|
||
|
{ csi_entry_execute_pred, do_execute, NULL },
|
||
|
{ csi_entry_ignore_pred, do_ignore, NULL },
|
||
|
{ csi_entry_to_ground_pred, do_csi_dispatch, &ground },
|
||
|
{ csi_entry_to_param_pred, do_param, &csi_param },
|
||
|
{ csi_entry_to_param_collect_pred, do_collect, &csi_param },
|
||
|
{ csi_entry_to_intermediate_pred, do_collect, &csi_intermediate },
|
||
|
{ csi_entry_to_ignore_pred, NULL, &csi_ignore },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state csi_entry = {
|
||
|
.name = "CSI Entry",
|
||
|
.entry_action = do_clear,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = csi_entry_transitions
|
||
|
};
|
||
|
|
||
|
/* CSI Param State */
|
||
|
|
||
|
static struct sm_transition csi_param_transitions[] = {
|
||
|
{ csi_param_execute_pred, do_execute, NULL },
|
||
|
{ csi_param_param_pred, do_param, NULL },
|
||
|
{ csi_param_ignore_pred, do_ignore, NULL },
|
||
|
{ csi_param_to_ground_pred, do_csi_dispatch, &ground },
|
||
|
{ csi_param_to_intermediate_pred, do_collect, &csi_intermediate },
|
||
|
{ csi_param_to_ignore_pred, NULL, &csi_ignore },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state csi_param = {
|
||
|
.name = "CSI Param",
|
||
|
.entry_action = NULL,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = csi_param_transitions
|
||
|
};
|
||
|
|
||
|
/* CSI Intermediate State */
|
||
|
|
||
|
static struct sm_transition csi_intermediate_transitions[] = {
|
||
|
{ csi_intermediate_execute_pred, do_execute, NULL },
|
||
|
{ csi_intermediate_collect_pred, do_collect, NULL },
|
||
|
{ csi_intermediate_ignore_pred, do_ignore, NULL },
|
||
|
{ csi_intermediate_to_ground_pred, do_csi_dispatch, &ground },
|
||
|
{ csi_intermediate_to_ignore_pred, NULL, &csi_ignore },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state csi_intermediate = {
|
||
|
.name = "CSI Intermediate",
|
||
|
.entry_action = NULL,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = csi_intermediate_transitions
|
||
|
};
|
||
|
|
||
|
/* CSI Ignore State */
|
||
|
|
||
|
static struct sm_transition csi_ignore_transitions[] = {
|
||
|
{ csi_ignore_execute_pred, do_execute, NULL },
|
||
|
{ csi_ignore_ignore_pred, do_ignore, NULL },
|
||
|
{ csi_ignore_to_ground_pred, NULL, &ground },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state csi_ignore = {
|
||
|
.name = "CSI Ignore",
|
||
|
.entry_action = NULL,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = csi_ignore_transitions
|
||
|
};
|
||
|
|
||
|
/* DCS Entry State */
|
||
|
|
||
|
static struct sm_transition dcs_entry_transitions[] = {
|
||
|
{ dcs_entry_ignore_pred, do_ignore, NULL },
|
||
|
{ dcs_entry_to_intermediate_pred, do_collect, &dcs_intermediate },
|
||
|
{ dcs_entry_to_ignore_pred, NULL, &dcs_ignore },
|
||
|
{ dcs_entry_to_param_pred, do_param, &dcs_param },
|
||
|
{ dcs_entry_to_param_collect_pred, do_collect, &dcs_param },
|
||
|
{ dcs_entry_to_passthrough_pred, NULL, &dcs_passthrough },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state dcs_entry = {
|
||
|
.name = "DCS Entry",
|
||
|
.entry_action = do_clear,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = dcs_entry_transitions
|
||
|
};
|
||
|
|
||
|
/* DCS Param State */
|
||
|
|
||
|
static struct sm_transition dcs_param_transitions[] = {
|
||
|
{ dcs_param_ignore_pred, do_ignore, NULL },
|
||
|
{ dcs_param_param_pred, do_param, NULL },
|
||
|
{ dcs_param_to_ignore_pred, NULL , &dcs_ignore },
|
||
|
{ dcs_param_to_intermediate_pred, do_collect, &dcs_intermediate },
|
||
|
{ dcs_param_to_passthrough_pred, NULL, &dcs_passthrough },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state dcs_param = {
|
||
|
.name = "DCS Param",
|
||
|
.entry_action = NULL,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = dcs_param_transitions
|
||
|
};
|
||
|
|
||
|
/* DCS Intermediate State */
|
||
|
|
||
|
static struct sm_transition dcs_intermediate_transitions[] = {
|
||
|
{ dcs_intermediate_ignore_pred, do_ignore, NULL },
|
||
|
{ dcs_intermediate_collect_pred, do_collect, NULL },
|
||
|
{ dcs_intermediate_to_passthrough_pred, NULL, &dcs_passthrough },
|
||
|
{ dcs_intermediate_to_ignore_pred, NULL, &dcs_ignore },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state dcs_intermediate = {
|
||
|
.name = "DCS Intermediate",
|
||
|
.entry_action = NULL,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = dcs_intermediate_transitions
|
||
|
};
|
||
|
|
||
|
/* DCS Passthrough State */
|
||
|
|
||
|
static struct sm_transition dcs_passthrough_transitions[] = {
|
||
|
{ dcs_passthrough_ignore_pred, do_ignore, NULL },
|
||
|
{ dcs_passthrough_put_pred, do_put, NULL },
|
||
|
{ dcs_passthrough_to_ground_pred, NULL, &ground },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state dcs_passthrough = {
|
||
|
.name = "DCS Passthrough",
|
||
|
.entry_action = do_hook,
|
||
|
.exit_action = do_unhook,
|
||
|
.transitions = dcs_passthrough_transitions
|
||
|
};
|
||
|
|
||
|
/* DCS Ignore State */
|
||
|
|
||
|
static struct sm_transition dcs_ignore_transitions[] = {
|
||
|
{ dcs_ignore_ignore_pred, do_ignore, NULL },
|
||
|
{ dcs_ignore_to_ground_pred, NULL, &ground },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state dcs_ignore = {
|
||
|
.name = "DCS Ignore",
|
||
|
.entry_action = NULL,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = dcs_ignore_transitions
|
||
|
};
|
||
|
|
||
|
/* OSC String State */
|
||
|
|
||
|
static struct sm_transition osc_string_transitions[] = {
|
||
|
{ osc_string_ignore_pred, do_ignore, NULL },
|
||
|
{ osc_string_put_pred, do_osc_put, NULL },
|
||
|
{ osc_string_to_ground_pred, NULL, &ground },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state osc_string = {
|
||
|
.name = "OSC String",
|
||
|
.entry_action = do_osc_start,
|
||
|
.exit_action = do_osc_end,
|
||
|
.transitions = osc_string_transitions
|
||
|
};
|
||
|
|
||
|
/* SOS/PM/APC String State */
|
||
|
|
||
|
static struct sm_transition sos_pm_apc_string_transitions[] = {
|
||
|
{ sos_pm_apc_string_ignore_pred, do_ignore, NULL },
|
||
|
{ sos_pm_apc_string_to_ground_pred, NULL, &ground },
|
||
|
{}
|
||
|
};
|
||
|
static struct sm_state sos_pm_apc_string = {
|
||
|
.name = "SOS/PM/APC String",
|
||
|
.entry_action = NULL,
|
||
|
.exit_action = NULL,
|
||
|
.transitions = sos_pm_apc_string_transitions
|
||
|
};
|
||
|
|
||
|
/* Global Transitions - Active at all states */
|
||
|
|
||
|
static struct sm_transition global_transitions[] = {
|
||
|
{ global_execute_pred, do_execute, &ground },
|
||
|
{ global_to_escape_pred, NULL, &escape },
|
||
|
{ global_to_string_pred, NULL, &sos_pm_apc_string },
|
||
|
{ global_to_dcs_pred, NULL, &dcs_entry },
|
||
|
{ global_to_osc_pred, NULL, &osc_string },
|
||
|
{}
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Single global machine definition, for now
|
||
|
*/
|
||
|
|
||
|
struct ansi_context ansi_machine = {
|
||
|
.base_context = {
|
||
|
.current_state = &ground,
|
||
|
.global_transitions = global_transitions
|
||
|
},
|
||
|
.i_ctx = {
|
||
|
.buf = {0, 0},
|
||
|
.count = 0
|
||
|
},
|
||
|
.p_ctx = {
|
||
|
.buf = {0},
|
||
|
.buf_count = 0,
|
||
|
.params = {0},
|
||
|
.count = 0
|
||
|
},
|
||
|
.private = 0,
|
||
|
.cbs = {
|
||
|
.graphic_cb = NULL,
|
||
|
.control_cb = NULL,
|
||
|
.esc_cb = NULL,
|
||
|
.csi_cb = NULL,
|
||
|
.str_cb = NULL,
|
||
|
.osc_cb = NULL
|
||
|
},
|
||
|
.put_cb = NULL,
|
||
|
.put_ctx = NULL,
|
||
|
.osc_put_cb = NULL,
|
||
|
.osc_put_ctx = NULL
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Predicates
|
||
|
*/
|
||
|
|
||
|
/* Global State */
|
||
|
|
||
|
static int global_execute_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode == 0x18) ||
|
||
|
(keycode == 0x1A) ||
|
||
|
((keycode & 0xF0) == 0x80) ||
|
||
|
((keycode >= 0x91) && (keycode <= 0x97)) ||
|
||
|
(keycode == 0x99) ||
|
||
|
(keycode == 0x9A) );
|
||
|
}
|
||
|
|
||
|
static int global_to_escape_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return (keycode == 0x1B);
|
||
|
}
|
||
|
|
||
|
static int global_to_string_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode == 0x98) ||
|
||
|
(keycode == 0x9E) ||
|
||
|
(keycode == 0x9F) );
|
||
|
}
|
||
|
|
||
|
static int global_to_dcs_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return (keycode == 0x90);
|
||
|
}
|
||
|
|
||
|
static int global_to_osc_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return (keycode == 0x9D);
|
||
|
}
|
||
|
|
||
|
/* Ground State */
|
||
|
|
||
|
static int ground_execute_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
if (code >= 0xA0) code = code & 0x7F;
|
||
|
|
||
|
return ( (keycode < 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) );
|
||
|
}
|
||
|
|
||
|
static int ground_print_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
if (code >= 0xA0) code = code & 0x7F;
|
||
|
|
||
|
return ( (keycode >= 0x20) && (keycode <= 0x7F) );
|
||
|
}
|
||
|
|
||
|
/* SOS/PM/APC String State */
|
||
|
|
||
|
static int sos_pm_apc_string_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
unsigned char keycode7 = keycode & 0x7F;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) ||
|
||
|
( (keycode7 >= 0x20) && (keycode7 <= 0x7F) ) );
|
||
|
}
|
||
|
|
||
|
static int sos_pm_apc_string_to_ground_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return (keycode == 0x9C);
|
||
|
}
|
||
|
|
||
|
/* Escape State */
|
||
|
|
||
|
static int escape_execute_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) );
|
||
|
}
|
||
|
|
||
|
static int escape_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ((keycode & 0x7F) == 0x7F);
|
||
|
}
|
||
|
|
||
|
static int escape_to_ground_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( ((keycode >= 0x30) && (keycode <= 0x4F)) ||
|
||
|
((keycode >= 0x51) && (keycode <= 0x57)) ||
|
||
|
( keycode == 0x59) ||
|
||
|
( keycode == 0x5A) ||
|
||
|
( keycode == 0x5C) ||
|
||
|
((keycode >= 0x60) && (keycode <= 0x7E)) );
|
||
|
}
|
||
|
|
||
|
static int escape_to_escape_intermediate_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ((keycode7 >= 0x20) && (keycode7 <= 0x2F));
|
||
|
}
|
||
|
|
||
|
static int escape_to_string_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode == 0x58) ||
|
||
|
(keycode == 0x5E) ||
|
||
|
(keycode == 0x5F) );
|
||
|
}
|
||
|
|
||
|
static int escape_to_dcs_entry_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return (keycode == 0x50);
|
||
|
}
|
||
|
|
||
|
static int escape_to_osc_string_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return (keycode == 0x5D);
|
||
|
}
|
||
|
|
||
|
static int escape_to_csi_entry_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return (keycode == 0x5B);
|
||
|
}
|
||
|
|
||
|
/* Escape Intermediate State */
|
||
|
|
||
|
static int escape_intermediate_execute_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) );
|
||
|
}
|
||
|
|
||
|
static int escape_intermediate_collect_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ((keycode7 >= 0x20) && (keycode7 <= 0x2F));
|
||
|
}
|
||
|
|
||
|
static int escape_intermediate_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ((keycode & 0x7F) == 0x7F);
|
||
|
}
|
||
|
|
||
|
static int escape_intermediate_to_ground_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ((keycode7 >= 0x30) && (keycode7 <= 0x7E));
|
||
|
}
|
||
|
|
||
|
/* CSI Entry State */
|
||
|
|
||
|
static int csi_entry_execute_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) );
|
||
|
}
|
||
|
|
||
|
static int csi_entry_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ((keycode & 0x7F) == 0x7F);
|
||
|
}
|
||
|
|
||
|
static int csi_entry_to_ground_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ((keycode7 >= 0x40) && (keycode7 <= 0x7E));
|
||
|
}
|
||
|
|
||
|
static int csi_entry_to_param_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x30) && (keycode7 <= 0x39)) ||
|
||
|
( keycode7 == 0x3B) );
|
||
|
}
|
||
|
|
||
|
static int csi_entry_to_param_collect_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x3C) && (keycode7 <= 0x3F)) );
|
||
|
}
|
||
|
|
||
|
static int csi_entry_to_intermediate_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x20) && (keycode7 <= 0x2F)) );
|
||
|
}
|
||
|
|
||
|
static int csi_entry_to_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ((keycode & 0x7F) == 0x3A);
|
||
|
}
|
||
|
|
||
|
/* CSI Param State */
|
||
|
|
||
|
static int csi_param_execute_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) );
|
||
|
}
|
||
|
|
||
|
static int csi_param_param_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x30) && (keycode7 <= 0x39)) ||
|
||
|
( keycode7 == 0x3B) );
|
||
|
}
|
||
|
|
||
|
static int csi_param_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ((keycode & 0x7F) == 0x7F);
|
||
|
}
|
||
|
|
||
|
static int csi_param_to_ground_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ((keycode7 >= 0x40) && (keycode7 <= 0x7E));
|
||
|
}
|
||
|
|
||
|
static int csi_param_to_intermediate_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x20) && (keycode7 <= 0x2F)) );
|
||
|
}
|
||
|
|
||
|
static int csi_param_to_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x3C) && (keycode7 <= 0x3F)) ||
|
||
|
(keycode7 == 0x3A) );
|
||
|
}
|
||
|
|
||
|
/* CSI Intermediate State */
|
||
|
|
||
|
static int csi_intermediate_execute_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) );
|
||
|
}
|
||
|
|
||
|
static int csi_intermediate_collect_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x20) && (keycode7 <= 0x2F)) );
|
||
|
}
|
||
|
|
||
|
static int csi_intermediate_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ((keycode & 0x7F) == 0x7F);
|
||
|
}
|
||
|
|
||
|
static int csi_intermediate_to_ground_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ((keycode7 >= 0x40) && (keycode7 <= 0x7E));
|
||
|
}
|
||
|
|
||
|
static int csi_intermediate_to_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x30) && (keycode7 <= 0x3F)) );
|
||
|
}
|
||
|
|
||
|
/* CSI Ignore State */
|
||
|
|
||
|
static int csi_ignore_execute_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) );
|
||
|
}
|
||
|
|
||
|
static int csi_ignore_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x20) && (keycode7 <= 0x3F)) ||
|
||
|
( keycode7 == 0x7F) );
|
||
|
}
|
||
|
|
||
|
static int csi_ignore_to_ground_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ((keycode7 >= 0x40) && (keycode7 <= 0x7E));
|
||
|
}
|
||
|
|
||
|
/* DCS Entry State */
|
||
|
|
||
|
static int dcs_entry_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) ||
|
||
|
((keycode & 0x7F) == 0x7F) );
|
||
|
}
|
||
|
|
||
|
static int dcs_entry_to_intermediate_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ((keycode7 >= 0x20) && (keycode7 <= 0x2F));
|
||
|
}
|
||
|
|
||
|
static int dcs_entry_to_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ((keycode & 0x7F) == 0x3A);
|
||
|
}
|
||
|
|
||
|
static int dcs_entry_to_param_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x30) && (keycode7 <= 0x39)) ||
|
||
|
( keycode7 == 0x3B) );
|
||
|
}
|
||
|
|
||
|
static int dcs_entry_to_param_collect_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x3C) && (keycode7 <= 0x3F)) );
|
||
|
}
|
||
|
|
||
|
static int dcs_entry_to_passthrough_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ((keycode7 >= 0x40) && (keycode7 <= 0x7E));
|
||
|
}
|
||
|
|
||
|
/* DCS Param State */
|
||
|
|
||
|
static int dcs_param_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) ||
|
||
|
((keycode & 0x7F) == 0x7F) );
|
||
|
}
|
||
|
|
||
|
static int dcs_param_param_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x30) && (keycode7 <= 0x39)) ||
|
||
|
( keycode7 == 0x3B) );
|
||
|
}
|
||
|
|
||
|
static int dcs_param_to_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x3C) && (keycode7 <= 0x3F)) ||
|
||
|
( keycode7 == 0x3A) );
|
||
|
}
|
||
|
|
||
|
static int dcs_param_to_intermediate_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x20) && (keycode7 <= 0x2F)) );
|
||
|
}
|
||
|
|
||
|
static int dcs_param_to_passthrough_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x40) && (keycode7 <= 0x7E)) );
|
||
|
}
|
||
|
|
||
|
/* DCS Intermediate State */
|
||
|
|
||
|
static int dcs_intermediate_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) ||
|
||
|
((keycode & 0x7F) == 0x7F) );
|
||
|
}
|
||
|
|
||
|
static int dcs_intermediate_collect_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x20) && (keycode7 <= 0x2F)) );
|
||
|
}
|
||
|
|
||
|
static int dcs_intermediate_to_passthrough_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x40) && (keycode7 <= 0x7E)) );
|
||
|
}
|
||
|
|
||
|
static int dcs_intermediate_to_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x30) && (keycode7 <= 0x3F)) );
|
||
|
}
|
||
|
|
||
|
/* DCS Passthrough State */
|
||
|
|
||
|
static int dcs_passthrough_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ((keycode & 0x7F) == 0x7F);
|
||
|
}
|
||
|
|
||
|
static int dcs_passthrough_put_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
unsigned char keycode7 = keycode & 0x7F;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) ||
|
||
|
( (keycode7 >= 0x20) && (keycode7 <= 0x7E) ) );
|
||
|
}
|
||
|
|
||
|
static int dcs_passthrough_to_ground_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return (keycode == 0x9C);
|
||
|
}
|
||
|
|
||
|
/* DCS Ignore State */
|
||
|
|
||
|
static int dcs_ignore_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
unsigned char keycode7 = keycode & 0x7F;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) ||
|
||
|
( (keycode7 >= 0x20) && (keycode7 <= 0x7F) ) );
|
||
|
}
|
||
|
|
||
|
static int dcs_ignore_to_ground_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return (keycode == 0x9C);
|
||
|
}
|
||
|
|
||
|
/* OSC String State */
|
||
|
|
||
|
static int osc_string_ignore_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return ( (keycode <= 0x17) ||
|
||
|
(keycode == 0x19) ||
|
||
|
( (keycode >= 0x1C) && (keycode <= 0x1F) ) );
|
||
|
}
|
||
|
|
||
|
static int osc_string_put_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode7 = (unsigned char)(code & 0x7F);
|
||
|
return ( ((keycode7 >= 0x20) && (keycode7 <= 0x7F)) );
|
||
|
}
|
||
|
|
||
|
static int osc_string_to_ground_pred(sm_event_id code)
|
||
|
{
|
||
|
unsigned char keycode = (unsigned char)code;
|
||
|
return (keycode == 0x9C);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Actions
|
||
|
*/
|
||
|
#define LOG_ACTIONS 0
|
||
|
|
||
|
#if LOG_ACTIONS
|
||
|
#include <stdio.h>
|
||
|
#define LOG_ACTION(state, action, event) printf("ANSI: In %s, took act %s on char 0x%02x\n", state, action, (unsigned char)event)
|
||
|
#define DUMP_STATE(state_) dump_state(state_)
|
||
|
void dump_state(struct ansi_context *actx) {
|
||
|
int i;
|
||
|
printf("Parser Context:\n");
|
||
|
printf(" Current State: %s\n", actx->base_context.current_state->name);
|
||
|
printf(" Private marker: %c\n", actx->private ? actx->private : ' ');
|
||
|
printf(" Intermediates (%d): ", actx->i_ctx.count);
|
||
|
for (i = 0; i < actx->i_ctx.count; i++) {
|
||
|
printf("%c ", actx->i_ctx.buf[i]);
|
||
|
}
|
||
|
printf("\n");
|
||
|
printf(" Parameters (%d): ", actx->p_ctx.count);
|
||
|
for (i = 0; i < actx->p_ctx.count; i++) {
|
||
|
printf("%d ", actx->p_ctx.params[i]);
|
||
|
}
|
||
|
printf("\n");
|
||
|
if (actx->p_ctx.buf_count > 0) {
|
||
|
printf(" In-progress: ");
|
||
|
for (i = 0; i < actx->p_ctx.buf_count; i++) {
|
||
|
printf("%d", actx->p_ctx.buf[i]);
|
||
|
}
|
||
|
printf("\n");
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
#define LOG_ACTION(state, action, event)
|
||
|
#define DUMP_STATE(state_)
|
||
|
#endif
|
||
|
|
||
|
/* Do nothing */
|
||
|
static void do_ignore(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
LOG_ACTION(ctx->current_state->name, "IGNORE", code);
|
||
|
(void)actx; (void)code;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Map code to a glyph according to current character set mappings and shift states
|
||
|
and display it. */
|
||
|
static void do_print(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
LOG_ACTION(ctx->current_state->name, "PRINT", code);
|
||
|
actx->cbs.graphic_cb(code);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Immediately execute a C0 or C1 control function */
|
||
|
static void do_execute(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
LOG_ACTION(ctx->current_state->name, "EXECUTE", code);
|
||
|
actx->cbs.control_cb(code);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Forget current private flag, intermediate characters, final character, and parameters */
|
||
|
static void do_clear(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
LOG_ACTION(ctx->current_state->name, "CLEAR", code);
|
||
|
(void)code;
|
||
|
actx->private = '\0';
|
||
|
actx->i_ctx.count = 0;
|
||
|
actx->p_ctx.buf_count = 0;
|
||
|
actx->p_ctx.count = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Collect private flag or intermediate character for later processing */
|
||
|
static void do_collect(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
LOG_ACTION(ctx->current_state->name, "COLLECT", code);
|
||
|
if (code == '?') {
|
||
|
actx->private = code;
|
||
|
} else {
|
||
|
int idx = actx->i_ctx.count;
|
||
|
if (idx < 2) {
|
||
|
actx->i_ctx.buf[idx] = code;
|
||
|
}
|
||
|
actx->i_ctx.count++;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static void finish_param(struct ansi_context *actx, unsigned char in)
|
||
|
{
|
||
|
int pow, digit, number;
|
||
|
|
||
|
/* parameter separator with empty buffer indicates default */
|
||
|
if (actx->p_ctx.buf_count == 0 && in != ';') {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pow = 1;
|
||
|
digit = 0;
|
||
|
number = 0;
|
||
|
while (actx->p_ctx.buf_count > 0) {
|
||
|
digit = actx->p_ctx.buf[--actx->p_ctx.buf_count];
|
||
|
number += digit * pow;
|
||
|
pow = pow * 10;
|
||
|
}
|
||
|
if (actx->p_ctx.count < 16) {
|
||
|
actx->p_ctx.params[actx->p_ctx.count++] = number;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Build a list of parameters from collected characters */
|
||
|
static void do_param(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
LOG_ACTION(ctx->current_state->name, "PARAM", code);
|
||
|
if (code == ';') {
|
||
|
finish_param(actx, (unsigned char)code);
|
||
|
} else {
|
||
|
actx->p_ctx.buf[actx->p_ctx.buf_count++] = code - '0';
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Determine control function from intermediate characters and final character and execute it */
|
||
|
static void do_esc_dispatch(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
struct function_id esc_id;
|
||
|
int i;
|
||
|
LOG_ACTION(ctx->current_state->name, "ESC_DISPATCH", code);
|
||
|
finish_param(actx, 0);
|
||
|
DUMP_STATE(actx);
|
||
|
esc_id.i_count_priv = actx->i_ctx.count;
|
||
|
for (i = 0; i < esc_id.i_count_priv; i++) {
|
||
|
esc_id.intermediates[i] = actx->i_ctx.buf[i];
|
||
|
}
|
||
|
esc_id.final = code;
|
||
|
|
||
|
actx->cbs.esc_cb(esc_id);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Determine control function from private marker, intermediate characters, and final character;
|
||
|
execute it, passing the parameter list */
|
||
|
static void do_csi_dispatch(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
struct function_id csi_id;
|
||
|
int i;
|
||
|
|
||
|
LOG_ACTION(ctx->current_state->name, "CSI_DISPATCH", code);
|
||
|
finish_param(actx, 0);
|
||
|
DUMP_STATE(actx);
|
||
|
|
||
|
csi_id.i_count_priv = actx->i_ctx.count;
|
||
|
for (i = 0; i < csi_id.i_count_priv; i++) {
|
||
|
csi_id.intermediates[i] = actx->i_ctx.buf[i];
|
||
|
}
|
||
|
if (actx->private) {
|
||
|
csi_id.i_count_priv |= 0x80;
|
||
|
}
|
||
|
csi_id.final = code;
|
||
|
|
||
|
actx->cbs.csi_cb(csi_id, actx->p_ctx.count, actx->p_ctx.params);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Determine control function from private marker, intermediate characters, and final character;
|
||
|
execute it, passing the parameter list. Also install a handler for PUT for the rest of the
|
||
|
control string. */
|
||
|
static void do_hook(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
struct function_id str_id;
|
||
|
struct str_hook hook;
|
||
|
int i;
|
||
|
|
||
|
LOG_ACTION(ctx->current_state->name, "HOOK", code);
|
||
|
finish_param(actx, 0);
|
||
|
DUMP_STATE(actx);
|
||
|
|
||
|
str_id.i_count_priv = actx->i_ctx.count;
|
||
|
for (i = 0; i < str_id.i_count_priv; i++) {
|
||
|
str_id.intermediates[i] = actx->i_ctx.buf[i];
|
||
|
}
|
||
|
if (actx->private) {
|
||
|
str_id.i_count_priv |= 0x80;
|
||
|
}
|
||
|
str_id.final = code;
|
||
|
|
||
|
actx->cbs.str_cb(&hook, str_id, actx->p_ctx.count, actx->p_ctx.params);
|
||
|
actx->put_cb = hook.handler_fn;
|
||
|
actx->put_ctx = hook.user_ctx;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Pass the codes to the PUT handler installed by HOOK */
|
||
|
static void do_put(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
LOG_ACTION(ctx->current_state->name, "PUT", code);
|
||
|
|
||
|
if (actx->put_cb) {
|
||
|
actx->put_cb(actx->put_ctx, code);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Call PUT handler with end of data code, then uninstall it */
|
||
|
static void do_unhook(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
LOG_ACTION(ctx->current_state->name, "UNHOOK", code);
|
||
|
|
||
|
if (actx->put_cb) {
|
||
|
actx->put_cb(actx->put_ctx, code);
|
||
|
actx->put_cb = NULL;
|
||
|
actx->put_ctx = NULL;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Initialize OSC Handler */
|
||
|
static void do_osc_start(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
struct osc_hook hook;
|
||
|
(void)code;
|
||
|
|
||
|
LOG_ACTION(ctx->current_state->name, "OSC_START", code);
|
||
|
|
||
|
actx->cbs.osc_cb(&hook);
|
||
|
actx->osc_put_cb = hook.handler_fn;
|
||
|
actx->osc_put_ctx = hook.user_ctx;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Pass the code to the OSC Handler */
|
||
|
static void do_osc_put(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
LOG_ACTION(ctx->current_state->name, "OSC_PUT", code);
|
||
|
|
||
|
if (actx->osc_put_cb) {
|
||
|
actx->osc_put_cb(actx->osc_put_ctx, code);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Clean up the OSC Handler state */
|
||
|
static void do_osc_end(struct sm_context *ctx, sm_event_id code)
|
||
|
{
|
||
|
struct ansi_context *actx = (struct ansi_context *)ctx;
|
||
|
LOG_ACTION(ctx->current_state->name, "OSC_END", code);
|
||
|
|
||
|
if (actx->osc_put_cb) {
|
||
|
actx->osc_put_cb(actx->osc_put_ctx, code);
|
||
|
actx->osc_put_cb = NULL;
|
||
|
actx->osc_put_ctx = NULL;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* External API Functions
|
||
|
*/
|
||
|
|
||
|
struct ansi_context *new_ansi_context(struct ansi_actions *actions)
|
||
|
{
|
||
|
ansi_machine.cbs.graphic_cb = actions->graphic_cb;
|
||
|
ansi_machine.cbs.control_cb = actions->control_cb;
|
||
|
ansi_machine.cbs.esc_cb = actions->esc_cb;
|
||
|
ansi_machine.cbs.csi_cb = actions->csi_cb;
|
||
|
ansi_machine.cbs.str_cb = actions->str_cb;
|
||
|
ansi_machine.cbs.osc_cb = actions->osc_cb;
|
||
|
|
||
|
return &ansi_machine;
|
||
|
}
|
||
|
|
||
|
void ansi_context_put(struct ansi_context *ctx, unsigned char code)
|
||
|
{
|
||
|
sm_put_event((struct sm_context *)ctx, code);
|
||
|
}
|