#ifndef lint
static char *sccsid = "@(#)xcal_popup.c	3.5 (Hillside Systems) 1/16/91";
static char *copyright = "@(#)Copyright 1989,1990 Peter Collinson, Hillside Systems";
#endif  /* lint */
/***

* module name:
	xcal_popup.c
* function:
	Deal with various popups for xcal
	There are two main ones:
	a)	the centre button causes a popup date selection popup
	b)	the right button causes an exit popup
* history:
	Written November 1989
	Peter Collinson
	Hillside Systems
* (C) Copyright: 1989 Hillside Systems/Peter Collinson
	
	For full permissions and copyright notice - see xcal.c
***/
#include <stdio.h>
#include <ctype.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Xaw/AsciiText.h>
#include "xcal.h"

static void AskDialog();
static void NoCal();
static void YesCal();
static char *DateParse();
static int MonScan();
static void LeaveDialog();
static void NoLeave();
static void YesLeave();
static  void NoEdit();

/*
 *	This routine deals with most of the work to create
 *	a dialog popup, it is passed a function which is called
 *	to create the dialog box
 *
 *	The widget here is used for positioning, these popups are
 *	always children of the toplevel widget
 */
void
DialogPopup(w, fn, arg)
	Widget	w;
	void (*fn)();
	caddr_t	arg;
{
	Widget	pop;
	Arg	args[5];
	Position x,y;
	Position nx, ny;
	Dimension width, height, border;
	
	/*
	 *	Get the position of the toplevel so we can
	 *	position the dialog box properly
	 */
	XtSetArg(args[0], XtNwidth, &width);
	XtSetArg(args[1], XtNheight, &height);
	XtGetValues(w, args, 2);
	XtTranslateCoords(w, (Position)(width/2),
                          (Position)(height/2), &x, &y);
						  
	/*
	 *	Create a popup to hold the dialog
	 */
	XtSetArg(args[0], XtNallowShellResize, True);
	XtSetArg(args[1], XtNinput, True);
	XtSetArg(args[2], XtNx, x);
	XtSetArg(args[3], XtNy, y);
	XtSetArg(args[4], XtNsaveUnder, TRUE);
	pop = XtCreatePopupShell("question", transientShellWidgetClass, toplevel, args, 5);

	/*
	 *	Set up the dialog
	 */
	(*fn)(pop, arg);

	XtRealizeWidget(pop);

	/*
	 *	We can now worry if this box is actually off the screen
	 */
	XtSetArg(args[0], XtNwidth, &width);
	XtSetArg(args[1], XtNheight, &height);
	XtSetArg(args[2], XtNborderWidth, &border);
	XtGetValues(pop, args, 3);

	border <<= 1;
	XtTranslateCoords(pop, (Position)0, (Position)0, &nx, &ny);

	if ((nx + width + border) > WidthOfScreen(XtScreen(toplevel)))
		nx = WidthOfScreen(XtScreen(toplevel)) - width - border;
	else nx = x;

	if ((ny + height + border) > HeightOfScreen(XtScreen(toplevel)))
		ny = HeightOfScreen(XtScreen(toplevel)) - height - border;
	else ny = y;

	if (nx != x || ny != y)
	{	XtSetArg(args[0], XtNx, nx);
		XtSetArg(args[1], XtNy, ny);
		XtSetValues(pop, args, 2);
	}
	XtPopup(pop, XtGrabNone);
}

/************************************************************************/
/*									*/
/*									*/
/*	Deals with middle button presses - ask for a date		*/
/*									*/
/*									*/
/************************************************************************/

/*
 *	SetDate - ask for a date and start a calendar
 *	This is an action routine
 */
/* ARGSUSED */
void
SetDate(w, event, params, numb)
	Widget w;
	XEvent *event;
	String *params;
	Cardinal *numb;
{
	DialogPopup(toplevel, AskDialog, NULL);
}

/* ARGSUSED */
static void
AskDialog(pop, noop)
	Widget pop;
	Cardinal noop;
{
	Widget	dia;
	Arg	args[2];
	WidgetList children;    /* which is Widget children[] */
	Cardinal num_children;
	int	i;

	/* Take from args: "Enter mm yyyy?" */
	XtSetArg(args[0], XtNvalue, "");
	dia =  XtCreateManagedWidget("newdate", dialogWidgetClass, pop, args, 1);
	XawDialogAddButton(dia, "ok", YesCal, dia);
	XawDialogAddButton(dia, "cancel", NoCal, pop);
	/*
	 *	I would like to add CR translations to the text box
	 *	the only way to get the widget seems to be to use
	 *	an R4 feature to get the WidgetList
	 */
	XtSetArg(args[0], XtNchildren, &children);
	XtSetArg(args[1], XtNnumChildren, &num_children);
	XtGetValues(dia, (ArgList)args, 2);
	for (i = 0; i < num_children; i++)
	{	if (XtClass(children[i]) == asciiTextWidgetClass)
		{	/* Bingo */
			XtOverrideTranslations(
			    children[i],
		            XtParseTranslationTable("<Key>Return: SetDateAction()")
					       );

		}
		else
		if (XtClass(children[i]) == labelWidgetClass)
		{	XtSetArg(args[0], XtNresizable, True);
			XtSetValues(children[i], args, 1);
		}
	}
			  
}

/*
 *	No we don't want a specified date
 *	Closure here is the pop shell
 */
/* ARGSUSED */
static void
NoCal(w, closure, call_data)
	Widget w;
	caddr_t	closure;
	caddr_t call_data;
{
	XtDestroyWidget((Widget)closure);
}

/*
 *	Yes we do want a specified date
 *	Closure here is the dialog widget
 */
/* ARGSUSED */
static void
YesCal(w, closure, call_data)
	Widget w;
	caddr_t	closure;
	caddr_t call_data;
{
	Widget	dia;
	Arg	args[2];
	Date	wanted;
	char	*errstr;
	
	dia = (Widget)closure;
	/*
	 *	Parse the string
	 */
	if (errstr = DateParse(XawDialogGetValueString(dia), &wanted))
	{	/* insert an error message in the widget */
		XtSetArg(args[0], XtNlabel, errstr);
		XtSetValues(dia, args, 1);
		XBell(XtDisplay(toplevel), 0);
		return;
	}
	XtDestroyWidget(XtParent(dia));
	NewMonthStrip(&wanted);
}

/*
 *	Action mapped to by CR in the dialog
 */
/* ARGSUSED */
void
TextCal(w, event, params, numb)
	Widget w;
	XEvent *event;
	String *params;
	Cardinal *numb;
{
	YesCal(w, (caddr_t)XtParent(w), 0);	/* parent of text widget is the */
					/* dialog box */
}

/*
 *	Parse a date string
 */
static char *
DateParse(str, da)
	register char *str;
	Date	*da;
{
	register char	*wk;
	int	lastc;
	int	mo;
	
	*da = today;

	wk = str;
	while (isspace(*wk)) wk++;
	if (*wk == '\0')
		return("No data found");
	str = wk;
	if (isdigit(*str))
	{	while (isdigit(*str))
			str++;
		lastc = *str;
		*str++ = '\0';
		mo = atoi(wk);
		if (mo < 1 || mo > 12)
			return("Illegal month number");
		da->month = mo - 1;
	}
	else
	if (isalpha(*str))
	{	/* be kind - allow month names */
		while (isalpha(*str))
		{	if (isupper(*str))
				*str = tolower(*str);
			str++;
		}
		lastc = *str;
		*str++ = '\0';
		mo = MonScan(wk);
		if (mo < 0)
			return("Cannot find month name");
		da->month = mo;
	}
	if (lastc)
	{	wk = str;
		while(isspace(*wk))
			wk++;
		str = wk;
		if (*str)
			da->year = atoi(wk);
	}
	return(NULL);
}

/*
 *	Given a string look in our database for a number
 */
static int
MonScan(monstr)
char *monstr;
{
    char *a, *b;
    int ca, cb;
    int	mon;

    for (mon = 0; mon < 12; mon++)
	for (a = monstr, b = appResources.mon[mon]; ;)
	{	ca = *a++;
		if(ca == '\0')
			return(mon);
		if (isupper(ca))
			ca = tolower(ca);
		cb = *b++;
		if (cb == '\0')
			break;
		if (isupper(cb))
			cb = tolower(cb);
		if (ca != cb)
			break;
	}
	return(-1);
}

/************************************************************************/
/*									*/
/*									*/
/*	Deals with right button presses - exit				*/
/*									*/
/*									*/
/************************************************************************/
/*
 *	Get out - possibly
 */
/* ARGSUSED */
void
AskLeave(w, event, params, numb)
	Widget w;
	XEvent *event;
	String *params;
	Cardinal *numb;
{

	DialogPopup(toplevel, LeaveDialog, NULL);
}

/* ARGSUSED */
static void
LeaveDialog(pop, noop)
	Widget pop;
	Cardinal noop;
{	Widget	di;

	/* Take "Really exit? from resources */
	di =  XtCreateManagedWidget("exit", dialogWidgetClass, pop, NULL, 0);
	XawDialogAddButton(di, "yes", YesLeave, 0);
	XawDialogAddButton(di, "no", NoLeave, pop);
}

/* ARGSUSED */
static void
YesLeave(w, closure, call_data)
	Widget w;
	caddr_t	closure;
	caddr_t call_data;
{
	Leave(0);
}

/* ARGSUSED */
static void
NoLeave(w, closure, call_data)
	Widget w;
	caddr_t	closure;
	caddr_t call_data;
{
	XtDestroyWidget((Widget)closure);
}

/************************************************************************/
/*									*/
/*									*/
/*	Deal with an attempt to double edit some data			*/
/*									*/
/*									*/
/************************************************************************/


void
NoEditIsPossible(w, da)
	Widget	w;
	Date	*da;
{
	static	char	errmsg[32];	

	(void) sprintf(errmsg, "Already editing %d %s %d", da->day, appResources.mon[da->month], da->year);

	DialogPopup(w, NoEdit, errmsg);

}

void
NoDayEditIsPossible(w, day)
	Widget	w;
	Cardinal day;
{
	static	char	errmsg[32];	

	(void) sprintf(errmsg, "Already editing %s", appResources.day[day]);

	DialogPopup(w, NoEdit, errmsg);

}

static void
NoEdit(pop, errmsg)
	Widget	pop;
	String	errmsg;
{
	Arg		args[2];
	Widget		dia;

	XtSetArg(args[0], XtNlabel, errmsg);
	dia =  XtCreateManagedWidget("noedit", dialogWidgetClass, pop, args, 1);
	XawDialogAddButton(dia, "ok", NoCal, pop);
}
