ansi_terminal/ansi.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);
}