/*
 * $Source: /mit/jik/sipbsrc/src/xscreensaver/RCS/getstring.c,v $
 * $Author: jik $
 *
 * This file is part of xscreensaver.  It contains the code for the
 * dialog widgets that pop up to get short strings.
 *
 * Author: Jonathan Kamens, MIT Project Athena and
 *                          MIT Student Information Processing Board
 *
 * This code may be distributed freely as long as this notice is kept
 * intact in its entirety and every effort is made to send all
 * corrections and improvements to the code back to the author.  Also,
 * don't try to make any money off of it or pretend that you wrote it.
 *
 * My copyright isn't on this code because I didn't write it (Well,
 * actually, I wrote the PopupAtPointer code, but that's besides the
 * point.).  This code was written by Barry Jaspan
 * (bjaspan@Athena.MIT.edu), so he holds the copyright.  Conditions
 * are the same, though -- send comments back to me, and I'll forward
 * them.
 * 		jik
 */

#ifndef lint
     static char rcsid_getstring_c[] = "$Header: /mit/jik/sipbsrc/src/xscreensaver/RCS/getstring.c,v 1.12 1992/03/19 18:40:09 jik Exp $";
#endif

#include "xsaver.h"
#include <X11/Shell.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Command.h>
#include "globals.h"
#include "getstring.h"

extern char *malloc();

static char buf[1024];
static Widget gs_shell, dialog;
static void (*call_func)();
void PopupAtPointer(), PopupSafe();
static int	prev_x = -1, prev_y = -1;

static void AcceptValue()
{
     if (debug_file) {
	  fprintf(debug_file,
		  "About to destroy getstring widget 0x%x (window id 0x%x) in AcceptValue.\n",
		  gs_shell, XtWindow(gs_shell));
     }
     XtDestroyWidget(gs_shell);
     (*call_func)(buf);
}

static void CancelValue()
{
     if (debug_file) {
	  fprintf(debug_file,
		  "About to destroy getstring widget 0x%x (window id 0x%x) in CancelValue.\n",
		  gs_shell, XtWindow(gs_shell));
     }
     XtDestroyWidget(gs_shell);
     (*call_func)((char *) NULL);
}

void init_getstring()
{
     static XtActionsRec action_table[] = {
	  {"AcceptValue", (XtActionProc) AcceptValue},
          {"CancelValue", (XtActionProc) CancelValue}
     };

     XtAppAddActions(app_context, action_table,XtNumber(action_table));
}


void xscr_getstring(parent, name, label, length, func, usage)
   Widget parent;
   char *name, *label;
   int length;
   void (*func)();
   int usage;
{
     Widget text_widget, label_widget, button1, button2;
     Dimension dialog_width;
     int text_horizDistance;
     Dimension text_borderWidth;
     
     call_func = func;
     *buf = '\0';
     
     /* Create Popup Shell to it is centered in parent */
     gs_shell = XtCreatePopupShell("gsShell", transientShellWidgetClass,
				   parent, NULL, 0);
     dialog = XtVaCreateManagedWidget(name, formWidgetClass, gs_shell,
				      NULL);
     label_widget = XtVaCreateManagedWidget("label", labelWidgetClass, dialog,
					    XtNlabel, label,
					    NULL);
     text_widget = XtVaCreateManagedWidget("value", asciiTextWidgetClass,
					   dialog,
					   XtNfromVert, label_widget,
					   XtNstring, buf,
					   NULL);
     if (length > 0)
	  XtVaSetValues(text_widget, XtNlength, length);

     button1 = XtVaCreateManagedWidget("gsAccept", commandWidgetClass,
				       dialog,
				       XtNfromVert, text_widget,
				       NULL);
     button2 = XtVaCreateManagedWidget("gsCancel", commandWidgetClass,
				       dialog,
				       XtNfromVert, text_widget,
				       XtNfromHoriz, button1,
				       NULL);
     XtAddCallback(button1, XtNcallback, AcceptValue, (XtPointer) 0);
     XtAddCallback(button2, XtNcallback, CancelValue, (XtPointer) 0);

     XtSetKeyboardFocus(dialog, text_widget);

     XtRealizeWidget(gs_shell);

     XtVaGetValues(dialog, XtNwidth, &dialog_width, NULL);
     XtVaGetValues(text_widget,
		   XtNhorizDistance, &text_horizDistance,
		   XtNborderWidth, &text_borderWidth,
		   NULL);
     
     XtVaSetValues(text_widget, XtNwidth,
		   (Dimension) (dialog_width -
				2 * (text_horizDistance + text_borderWidth)),
		   NULL);
		   
     if ((usage == GS_PREVPOS) && (prev_x == -1))
	  usage = GS_CURSORPOS;
     switch (usage) {
     case GS_CURSORPOS:
	  PopupAtPointer(gs_shell, parent, XtGrabExclusive);
	  break;
     case GS_PREVPOS:
	  PopupSafe(gs_shell, (Dimension) prev_x, (Dimension) prev_y,
		    XtGrabExclusive);
	  break;
     case GS_WMPOS:
	  XtPopup(gs_shell, XtGrabExclusive);
	  break;
     default:  /* Same as GS_WMPOS */
	  XtPopup(gs_shell, XtGrabExclusive);
	  break;
     }
}



void PopupSafe(w, x, y, GrabType)
Widget w;
Dimension x, y;
XtGrabKind GrabType;
{
     Dimension width, height, border;
     Arg arglist[5];
     int i = 0;

     XtSetArg(arglist[i], XtNwidth, &width); i++;
     XtSetArg(arglist[i], XtNheight, &height); i++;
     XtSetArg(arglist[i], XtNborderWidth, &border); i++;
     XtGetValues(w, arglist, i); 			i = 0;
     if (x + width + 2 * border > display_width)
	  x = display_width - width - 2 * border;
     if (y + height + 2 * border > display_height)
	  y = display_height - height - 2 * border;
     XtSetArg(arglist[i], XtNx, x); i++;
     XtSetArg(arglist[i], XtNy, y); i++;
     XtSetValues(w, arglist, i);
     prev_x = x;  prev_y = y;

     XtPopup(w, GrabType);
}


     
/* This came straight from the new xscreensaver */
void PopupAtPointer(w, parent, GrabType)
Widget 	w, parent;
XtGrabKind 	GrabType;
{
     Window garbage1, garbage2, window;
     int root_x, root_y, x2, y2;
     unsigned int mask;
     Dimension width, height, border;
     Arg arglist[3];
     
     window = XtWindow(parent);

     if (XQueryPointer(dpy, window, &garbage1, &garbage2,
		       &root_x, &root_y, &x2, &y2, &mask)) {
	  XtSetArg(arglist[0], XtNwidth, &width);
	  XtSetArg(arglist[1], XtNheight, &height);
	  XtSetArg(arglist[2], XtNborderWidth, &border);
	  XtGetValues(w, arglist, 3);
	  if (root_x >= width / 2 + border)
	       root_x -= width / 2 + border;
	  else
	       root_x = 0;

	  PopupSafe(w, (Dimension) root_x, (Dimension) root_y, GrabType);
     }
}

