#include <9pm/windows.h>
#include <9pm/u.h>
#include <9pm/libc.h>
#include <9pm/ns.h>
#include <9pm/thread.h>
#include <9pm/threadimpl.h>

static void
ndflt(void *a, char *msg)
{
	noted(NDFLT);
}

static void (*notifyf)(void*, char*) = ndflt;

static struct {
	int a;
	char *s;
} tab[] = {
	CTRL_C_EVENT,		"interrupt",
	CTRL_BREAK_EVENT,	"kill",
	CTRL_CLOSE_EVENT,	"close console",
	CTRL_LOGOFF_EVENT,	"logoff console",
	CTRL_SHUTDOWN_EVENT,	"shutdown console",
};

static void handlestart(void*);
static BOOL WINAPI
handler(DWORD a)
{
	Proc *p;

	p = getproc();
	memmove(p->sigerrjmp, p->errjmp, sizeof p->sigerrjmp);
	p->nsigerrjmp = p->nerrjmp;
	p->nerrjmp = 0;	
	proccreate(handlestart, (void*)a, 8192);
	p->nerrjmp = p->nsigerrjmp;
	memmove(p->errjmp, p->sigerrjmp, sizeof p->errjmp);
	return 0;
}

static void
handlestart(void *param)
{
	int i, a;
	char *msg;
	char buf[32];
	Proc *p;

	a = (int)param;
	snprint(buf, sizeof buf, "%d", a);
	for(i=0; i<nelem(tab); i++)
		if(a==tab[i].a)
			msg = tab[i].s;
	p = getproc();
	p->sigres = NDFLT;
	if(setjmp(p->sigbuf)==0)
		(*notifyf)(nil, msg);
	switch(p->sigres){
	case NCONT:
		ExitThread(0);
	default:
		ExitProcess(0);
	}
}

int
pm_noted(int res)
{
	Proc *p;

	p = getproc();
	p->sigres = res;
	longjmp(p->sigbuf, 1);
	abort();
	return -1;
}

int
pm_notify(void (*f)(void*, char*))
{
	static int reg;

	notifyf = f;
	if(!reg){
		reg=1;
		SetConsoleCtrlHandler(handler, 1);
	}		
	return 0;
}

