/**************************************************************
 *
 *	CRISP - Custom Reduced Instruction Set Programmers Editor
 *
 *	(C) Paul Fox, 1989
 *
 *    Please See COPYLEFT notice.
 *
 **************************************************************/
# include	"list.h"
# include	"clk.h"

# define	MAX_REGISTER	(REG_MAX + 1)

Head_p	reg[MAX_REGISTER];
static	rchk();
long	interval = 0;
long	time_last_key_pressed = 0;
static void remove_macro();
int	trigger_level = 0;	/* Keep track of nested triggers.	*/

void
init_register()
{	int	i;
	for (i = 0; i < MAX_REGISTER; i++)
		reg[i] = ll_init();
}
int
call_registered_macro()
{
	int	i = rchk();

	if (i >= 0)
		trigger(i);

	return 0;
}
int
register_macro()
{	int	i = rchk();
	int	local = argv[3].l_flags == F_NULL ? FALSE : argv[3].l_int;
	char	*str;

	if (i < 0)
		return 0;
	str = strdup(argv[2].l_str);
	if (local && i == REG_TYPED)
		ll_append(curbp->b_register, str);
	else
		ll_append(reg[i], str);
	return 0;
}
int
unregister_macro()
{	int	i = rchk();
	int	local = argv[3].l_flags == F_NULL ? FALSE : argv[3].l_int;
	char	*str = get_str(2);

	if (i < 0)
		return 0;

	acc_assign_int(0L);
	if (local && i == REG_TYPED)
		remove_macro(curbp->b_register, str);
	else
		remove_macro(reg[i], str);
	return 0;
}
static void
remove_macro(lp, str)
Head_p	lp;
char	*str;
{	register List_p llp;

	for (llp = ll_first(lp); llp; llp = ll_next(llp)) {
		char *cp = (char *) ll_elem(llp);
		if (strcmp(cp, str) == 0) {
			acc_assign_int(1L);
			chk_free(cp);
			ll_delete(llp);
			break;
			}
		}

}
static int
rchk()
{	int	i = argv[1].l_int;
	extern char *command_name;

	if (i < 0 || i >= MAX_REGISTER) {
		errorf("%s: invalid parameters.", command_name);
		return -1;
		}
	return i;
}
/**********************************************************************/
/*   Call  the  registered  macros  of  a specific type. If no macro  */
/*   registered  then  return  0. Otherwise return value of the last  */
/*   macro called. Must be an integer).				      */
/**********************************************************************/
int
trigger(type)
int	type;
{	extern int msg_level;
	int	saved_msg_level;
	List_p	llp = NULL, blp = NULL;
	List_p	next_lp;

	if (type < 0)
		return -1;

	if (type == REG_TYPED) {
		if (curbp && curbp->b_register)
			blp = ll_first(curbp->b_register);
		}
	if (reg[type])
		llp = ll_first(reg[type]);

	if (llp == NULL && blp == NULL)
		return -1;

	saved_msg_level = msg_level;
	msg_level = 1;
	acc_assign_int(0L);
	trace_trigger(type);
	trigger_level++;
	while (blp) {
		next_lp = ll_next(blp);
		str_exec((char *) ll_elem(blp));
		blp = next_lp;
		}
	while (llp) {
		next_lp = ll_next(llp);
		str_exec((char *) ll_elem(llp));
		llp = next_lp;
		}
	trigger_level--;
	msg_level = saved_msg_level;
	if (type == REG_CTRLC && acc_get_ival())
		check_exit();
	return acc_get_ival();
}
void
reg_idle()
{	extern int p_level;
	extern	u_int16	ttcol, ttrow;
	extern int prompting;
	u_int16	old_col = ttcol;
	u_int16	old_row = ttrow;

	if (p_level < 2 && !prompting) {
		trigger(REG_IDLE);
		update();
		ttmove(old_row, old_col);
		ttflush();
		}		
}
int
inq_idefault()
{
	acc_assign_int((long) interval);
	return 0;
}
void
set_idle_default()
{
	acc_assign_int((long) interval);
	interval = argv[1].l_int;
}
void
inq_itime()
{
	extern long time();

	/***********************************************/
	/*   If  no  key  pressed  yet  then  pretend  */
	/*   user just pressed a key.		       */
	/***********************************************/
	if (time_last_key_pressed == 0)
		acc_assign_int((long) 0);
	else
		acc_assign_int((long) (time((long *) 0) - time_last_key_pressed));
}
