/*
 * @(#)Confirm - a Yes/No confirmation window with optional prompt argument.
 *
 * From an idea contributed by Mitchell L. Model <mlm@odi.com> on 5-17-89
 *
 * Copyright 1990,1991,1992 by National Semiconductor Corporation
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of National Semiconductor Corporation not
 * be used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 *
 * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
 * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
 * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
 * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * Author:  Michael C. Wagnitz - National Semiconductor Corporation
 *
 */
#include "global.h"

#define	btnsepr	7

typedef struct _result {
			Bool	*popflg;
			Bool	*var;
			Widget	shell;
		       } *Result;
void
ProcessOneEvent(Display *display)
{
 static XEvent event;

 XNextEvent(display, &event);
 XtDispatchEvent(&event);
} /* ProcessOneEvent */


static Result
MakeResult(Widget shell, int *popflg, int *resultvar)
{
 Result rec = (Result) XtMalloc((unsigned) sizeof(struct _result));

 rec->popflg	= popflg;
 rec->var	= resultvar;
 rec->shell	= shell;

 return rec;
} /* MakeResult */


/* ARGSUSED */
/*
** ClearConfirm - get rid of the confirmation box.
*/
void
ClearConfirm(Widget w, int val, Result result)
{
 XtPopdown(result->shell);
 XtDestroyWidget(result->shell);
 *result->popflg = FALSE;
 *result->var = val;
} /* ClearConfirm */


/* ARGSUSED */
void
Yes(Widget w, XtPointer closure, XtPointer call_data)
         
       	        
                  			/* unused */
{
 Result result = (Result) closure;

 ClearConfirm(w, TRUE, result);
}


/* ARGSUSED */
void
No(Widget w, XtPointer closure, XtPointer call_data)
      	  
       	        
       	          			/* unused */
{
 Result result = (Result) closure;

 ClearConfirm(w, FALSE, result);
} /* No */


/*
 * Confirm - put up a window asking for confirmation.
 */
Bool
Confirm(char *prompt)
{
 int		root_x, root_y, child_x, child_y;
 int		nargs, buttons, labelwidth, yeswidth, btnborder, btnwidth;
 Dimension      rWidth, rBorder, rHeight;
 Bool		popped_up = FALSE, result = FALSE;
 String		query = NULL;
 String		Translations = "<BtnDown>,<BtnUp>:\n";
 Window		root, child;
 Widget		shell, form, label, yes, no;
 Arg		args[4];
 Result		resultrec;

/*
** First, find out if expert flag is set.  If so, just return True.
*/
 if (XMail.expert == TRUE)
    return TRUE;
/*
** Find out where the mouse is, so we can put the confirmation
** box right there.
*/
 XQueryPointer(XtDisplay(toplevel), XtWindow(toplevel), &root, &child,
		  &root_x, &root_y, &child_x, &child_y, &buttons);
 /*
 ** Construct the confirmation box
 */
 shell=XtCreatePopupShell("Confirm",overrideShellWidgetClass,toplevel,args,0);

 XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(Translations));
 XtSetArg(args[1], XtNborderWidth, 0);
 form = XtCreateManagedWidget("form", formWidgetClass, shell, args, 2);

 if (! prompt) label = NULL;
 else {
    if (query = (String) XtMalloc((unsigned) strlen(prompt) + 2)) {
       (void) strcpy(query, prompt);
       (void) strcat(query, "?");
       XtSetArg(args[0], XtNlabel, query);
      } else XtSetArg(args[0], XtNlabel, "");

    XtSetArg(args[1], XtNjustify, XtJustifyCenter);
    XtSetArg(args[2], XtNborderWidth, 0);
    label = XtCreateManagedWidget("prompt", labelWidgetClass, form, args, 3);
    XtFree((String) query);		/* XtFree tests if target is null */
   }

 nargs = 0;
 XtSetArg(args[nargs], XtNhorizDistance, btnsepr);		nargs++;
 if (prompt) {
    XtSetArg(args[nargs], XtNfromVert, label);			nargs++;
    XtSetArg(args[nargs], XtNvertDistance, 12);			nargs++;
   }
 yes = XtCreateManagedWidget("yes", commandWidgetClass, form, args, nargs);

 nargs = 1;
 XtSetArg(args[nargs], XtNfromHoriz, yes);			nargs++;
 if (prompt) {
    XtSetArg(args[nargs], XtNfromVert, label);			nargs++;
    XtSetArg(args[nargs], XtNvertDistance, 12);			nargs++;
   }
 no = XtCreateManagedWidget("no", commandWidgetClass, form, args, nargs);

 if (! label)
    labelwidth = 0;
 else {
    XtSetArg(args[0], XtNwidth, &rWidth); 
    XtGetValues(label, args, ONE);
    labelwidth = (int) rWidth;
   }
    
 XtSetArg(args[0], XtNwidth, &rWidth); 
 XtSetArg(args[1], XtNborder, &rBorder); 
 XtGetValues(yes, args, TWO);

 yeswidth = (int) rWidth;
 btnborder = (int) rBorder;

 btnwidth = (labelwidth - btnsepr - (2 * btnborder)) / 2;
 if (btnwidth < yeswidth) btnwidth = yeswidth;

 XtSetArg(args[0], XtNwidth, btnwidth); 
 XtSetValues(yes, args, ONE);
 XtSetValues(no, args, ONE);

 XtRealizeWidget(shell);

 XtSetArg(args[0], XtNwidth, &rWidth); 
 XtSetArg(args[1], XtNheight, &rHeight); 
 XtGetValues(shell, args, TWO);

 root_x -= ( (int) rWidth)  / 2;
 root_y -= ( (int) rHeight) / 2;
/*
** Keep confirm popup within root window borders (don't place it off-screen)
*/
 if (root_x + (int)rWidth > RootWidth)
     root_x = RootWidth - rWidth ;
 if (root_x < 0) root_x = 0;

 if (root_y + (int)rHeight > RootHeight)
     root_y = RootHeight - rHeight;
 if (root_y < 0) root_y = 0;

 XtSetArg(args[0], XtNx, root_x); 
 XtSetArg(args[1], XtNy, root_y); 
 XtSetValues(shell, args, TWO);

 resultrec = MakeResult(shell, &popped_up, &result);
 XtAddCallback(yes, XtNcallback, Yes, (XtPointer)resultrec);
 XtAddCallback(no, XtNcallback, No, (XtPointer)resultrec);

 if (XMail.bellRing)			/* ring bell if not silenced by user */
    XBell (XtDisplay (toplevel), 33);

 XtPopup(shell, XtGrabExclusive);

 popped_up = TRUE;

 while (popped_up) ProcessOneEvent(XtDisplay(shell));

 return result;
} /* Confirm */
