/* options.c
   make and handle callbacks for the Xgopher options panel */

     /*---------------------------------------------------------------*/
     /* Xgopher        version 1.2     20 November 1991               */
     /*                version 1.1     20 April 1991                  */
     /*                version 1.0     04 March 1991                  */
     /* X window system client for the University of Minnesota        */
     /*                                Internet Gopher System.        */
     /* Allan Tuchman, University of Illinois at Urbana-Champaign     */
     /*                Computing and Communications Services Office   */
     /* Copyright 1992 by                                             */
     /*           the Board of Trustees of the University of Illinois */
     /* Permission is granted to freely copy and redistribute this    */
     /* software with the copyright notice intact.                    */
     /*---------------------------------------------------------------*/


#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Toggle.h>
#include <X11/Xaw/AsciiText.h>

#include "gopher.h"
#include "misc.h"
#include "help.h"
#include "panel.h"
#include "bkmkfile.h"
#include "appres.h"
#include "options.h"
#include "compatR4.h"
#include "xglobals.h"
#include "globals.h"
#include "gui.h"
#include "osdep.h"


static Widget	topLevel,
		opPanel;
static Widget		showAll, appendBk, loadBk, reset;
static Widget		bkSave, printCmd, imageCmd, telCmd, t32Cmd;


/* toggleNotify
   toggle notify callback */

static void
toggleNotify(w, client_data, call_data)
Widget		w;
XtPointer	client_data, call_data;
{
	Arg	args[3];
	Cardinal n;
	Boolean	set;

	/* change the bitmap according to the current state of the toggle */

	n = 0;
	XtSetArg(args[n], XtNstate, &set);  n++;
	XtGetValues(w, args, n);

	n = 0;
	XtSetArg(args[n], XtNbitmap, set ? checkPixmap : uncheckPixmap);  n++;
	XtSetValues(w, args, n);
}


/* createToggleL
   create a labelled toggle widget pair */

static Widget
createToggleL(name, parent, below)
char	*name;
Widget	parent, below;
{
	char	tempName[50];
	Widget	theBox, theToggle, theLabel;
	Arg	args[3];
	Cardinal n;

	strcpy(tempName, name);
	strcat(tempName, "Box");
	n = 0;
	XtSetArg(args[n], XtNorientation, XtorientHorizontal);  n++;
	if (below != NULL) {
	    XtSetArg(args[n], XtNfromVert, XtParent(below));  n++;
	}
	theBox = XtCreateManagedWidget(tempName, boxWidgetClass,
			parent, args, n);

	n = 0;
	XtSetArg(args[n], XtNbitmap, checkPixmap);  n++;
	theToggle = XtCreateManagedWidget(name, toggleWidgetClass,
			theBox, args, n);
	XtAddCallback(theToggle, XtNcallback, toggleNotify, NULL);

	strcpy(tempName, name);
	strcat(tempName, "Label");
	theLabel = XtCreateManagedWidget(tempName, labelWidgetClass,
			theBox, NULL, (Cardinal) 0);
	
	return theToggle;
	
}


/* createTextFieldL
   create a labelled single-line text field widget pair */

static Widget
createTextFieldL(name, parent, below)
char	*name;
Widget	parent, below;
{
	char	tempName[50];
	Widget	theForm, theText, theLabel;
	Arg	args[8];
	Cardinal	n;
	Dimension	w, h;

	strcpy(tempName, name);
	strcat(tempName, "Form");
	n = 0;
	if (below != NULL)
	    XtSetArg(args[n], XtNfromVert, XtParent(below));  n++;
	theForm = XtCreateManagedWidget(tempName, formWidgetClass,
			parent, args, n);

	strcpy(tempName, name);
	strcat(tempName, "Label");
	n = 0;
	XtSetArg(args[n], XtNbottom, XawChainBottom);  n++;
	XtSetArg(args[n], XtNtop, XawChainTop);  n++;
	XtSetArg(args[n], XtNright, XawChainLeft);  n++;
	XtSetArg(args[n], XtNleft, XawChainLeft);  n++;
	theLabel = XtCreateManagedWidget(tempName, labelWidgetClass,
			theForm, args, n);
	getTextSize(theLabel, 25, 1, &w, &h);
	n = 0;
	XtSetArg(args[n], XtNwidth, w);  n++;
	XtSetArg(args[n], XtNheight, h);  n++;
	XtSetValues(theLabel, args, n);
	
	n = 0;
	XtSetArg(args[n], XtNresizable, True);  n++;
	XtSetArg(args[n], XtNeditType, XawtextEdit);  n++;
	XtSetArg(args[n], XtNfromHoriz, theLabel);  n++;
	XtSetArg(args[n], XtNbottom, XawChainBottom);  n++;
	XtSetArg(args[n], XtNtop, XawChainTop);  n++;
	XtSetArg(args[n], XtNright, XawChainRight);  n++;
	XtSetArg(args[n], XtNleft, XawChainLeft);  n++;
	theText = XtCreateManagedWidget(name, asciiTextWidgetClass,
			theForm, args, n);
	setTextWidgetSize(theText, 25, 1);
	XtOverrideTranslations(theText,
			XtParseTranslationTable(OneLineTextTr));  n++;

	return theText;
	
}


/* setToggle
   set the state of a toggle button explicitly */

static void
setToggle(w, value)
Widget	w;
Boolean	value;
{
	Arg		args[2];
	Cardinal	n;

	n = 0;
	XtSetArg(args[n], XtNstate, value);  n++;
	XtSetValues(w, args, n);
}


/* setText
   set the contents of a text field to a string */

static void
setText(w, value)
Widget	w;
String	value;
{
	Arg		args[2];
	Cardinal	n;

	n = 0;
	XtSetArg(args[n], XtNstring, value);  n++;
	XtSetValues(w, args, n);
}


/* getToggle
   set the current state of a toggle button */

static Boolean
getToggle(w)
Widget	w;
{
	Arg		args[2];
	Cardinal	n;
	Boolean		value;

	n = 0;
	XtSetArg(args[n], XtNstate, &value);  n++;
	XtGetValues(w, args, n);

	return value;
}


/* getText
   get the current contents of a text field */

static char *
getText(w)
Widget	w;
{
	Arg		args[2];
	Cardinal	n;
	String		value;

	n = 0;
	XtSetArg(args[n], XtNstring, &value);  n++;
	XtGetValues(w, args, n);

	return value;
}


/* setOptionsAtEntry
   set the panel to reflect the options when the panel popped up */

static void
setOptionsAtEntry()
{
	setToggle(showAll, appResources->allItems);
	XtCallActionProc(showAll, "notify", NULL, NULL, 0);

	setToggle(appendBk, appResources->appendBookmarks);
	XtCallActionProc(appendBk, "notify", NULL, NULL, 0);

	setToggle(loadBk, appResources->loadBookmarks);
	XtCallActionProc(loadBk, "notify", NULL, NULL, 0);

	setToggle(reset, appResources->resetOptions);
	XtCallActionProc(reset, "notify", NULL, NULL, 0);

	/* it's ok to do this because this file is for reading, too. */

	setText(bkSave, appResources->bookmarkFile);

	if (appResources->allowPrint) {
		setText(printCmd, appResources->printCommand);
	}
	if (appResources->allowImage) {
		setText(imageCmd, appResources->imageCommand);
	}
	if (appResources->allowTelnet) {
		setText(telCmd, appResources->telnetCommand);
	}
	if (appResources->allowTn3270) {
		setText(t32Cmd, appResources->tn3270Command);
	}
}


/* changeOptionsAtExit
   set the application options to reflect the current state of the panel */

static void
changeOptionsAtExit()
{
	char	*value, *str;

	appResources->allItems		= getToggle(showAll);
	appResources->appendBookmarks	= getToggle(appendBk);
	appResources->loadBookmarks	= getToggle(loadBk);
	appResources->resetOptions	= getToggle(reset);

	setBkmkAppend(appResources->appendBookmarks);

	/* the following code could be a not-too-serious memory leak.
	   the assignment of new string values to the appResources
	   strings is leaving old values dangling.  The problem is
	   that we don't know if the original values are dynamically
	   allocated and can be freed or static storage.  This
	   isn't a real problem because there isn't that much memory
	   at stake. */

	/* it's ok to do this because this file is for reading, too. */

		value = getText(bkSave);
		str = malloc(sizeof(char) * strlen(value) + 1);
		strcpy(str, value);
		appResources->bookmarkFile = str;

		setBkmkFile (value);

	if (appResources->allowPrint) {
		value = getText(printCmd);
		str = malloc(sizeof(char) * strlen(value) + 1);
		strcpy(str, value);
		appResources->printCommand = str;
	}

	if (appResources->allowImage) {
		value = getText(imageCmd);
		str = malloc(sizeof(char) * strlen(value) + 1);
		strcpy(str, value);
		appResources->imageCommand = str;
	}

	if (appResources->allowTelnet) {
		value = getText(telCmd);
		str = malloc(sizeof(char) * strlen(value) + 1);
		strcpy(str, value);
		appResources->telnetCommand = str;
	}

	if (appResources->allowTn3270) {
		value = getText(t32Cmd);
		str = malloc(sizeof(char) * strlen(value) + 1);
		strcpy(str, value);
		appResources->tn3270Command = str;
	}
}


/* displayOptionsPanel
   pop up the options panel window */

void
displayOptionsPanel()
{
	positionPopup(opPanel, POS_appPanel,
			topLevel, 0, 10, 0, 0);

	XtPopup(opPanel, XtGrabNone);

	setOptionsAtEntry();

	return;
}


/* removeOptionsPanel
   pop down the options panel window */

void
removeOptionsPanel()
{
	XtPopdown(opPanel);

	return;
}


/* doneProc
   done callback for options panel */

static void
doneProc(w, client_data, call_data)
Widget		w;
XtPointer	client_data, call_data;
{
	/* set the options selected then pop down the options panel */

	removeOptionsPanel();

	changeOptionsAtExit();

	checkButtonState(BS_loadMarks | BS_saveMarks);
}


/* cancelProc
   cancel callback for options panel */

static void
cancelProc(w, client_data, call_data)
Widget		w;
XtPointer	client_data, call_data;
{
	/* do not change any of these options, but pop down the options panel */

	removeOptionsPanel();
}


/* helpProc
   help callback for options panel. */

static void
helpProc(w, client_data, call_data)
Widget		w;
XtPointer	client_data, call_data;
{
	char	*string;

	showHelp("options help");
}


/* doneActionProc
   implement the done action */

static void
doneActionProc(w, event, params, numParams)
Widget		w;
XEvent		*event;
String		*params;
Cardinal	*numParams;
{
	doneProc(NULL, NULL, NULL);
}


/* cancelActionProc
   implement the cancel action */

static void
cancelActionProc(w, event, params, numParams)
Widget		w;
XEvent		*event;
String		*params;
Cardinal	*numParams;
{
	cancelProc(NULL, NULL, NULL);
}


/* helpActionProc
   implement the help action */

static void
helpActionProc(w, event, params, numParams)
Widget		w;
XEvent		*event;
String		*params;
Cardinal	*numParams;
{
	helpProc(NULL, NULL, NULL);
}


/* makeOptionsPanel
   create the elements of the xgopher options panel */

void
makeOptionsPanel(top)
Widget	top;
{
	Widget		doneButton, helpButton, cancelButton,
			opForm, buttonBox;
	Widget		itemsForm, previous;
	Arg		args[10];
	Cardinal	n;

	static XtActionsRec	actionsTable[] = {
				{"optDone",   doneActionProc},
				{"optCancel", cancelActionProc},
				{"optHelp",   helpActionProc},
				};
	/*
	static char		defaultTranslations[] = "Ctrl<Key>d:  done()";
	XtTranslations	transTable;
	*/



	topLevel = top;

	XtAppAddActions(appcon, actionsTable, XtNumber(actionsTable));


	/* create gopher options panel */

	n = 0;
	XtSetArg(args[n], XtNtitle, "Xgopher Options");  n++;
	opPanel = XtCreatePopupShell("optionsPanel", transientShellWidgetClass,
					topLevel, args, n);
		/*
		XtAugmentTranslations(opPanel, transTable);
		*/

	/* create OPTIONS form */

	opForm = XtCreateManagedWidget("optionsForm", formWidgetClass,
					opPanel, NULL, (Cardinal) 0);


	/* create BUTTON box */

	buttonBox = XtCreateManagedWidget("buttonBox", boxWidgetClass,
					opForm, NULL, (Cardinal) 0);



	/* create ITEMS form */

	itemsForm = XtCreateManagedWidget("itemsForm", formWidgetClass,
					opForm, NULL, (Cardinal) 0);

	/* create toggles */

	showAll = createToggleL("showAll", itemsForm, NULL);
	appendBk = createToggleL("appendBk", itemsForm, showAll);
	loadBk = createToggleL("loadBk", itemsForm, appendBk);
	reset = createToggleL("reset", itemsForm, loadBk);
	previous = reset;


	/* create text fields */

	/* it's ok to do this because this file is for reading, too. */

		previous =
		bkSave = createTextFieldL("bkSave", itemsForm, previous);

	if (appResources->allowPrint) {
		previous =
		printCmd = createTextFieldL("printCmd", itemsForm, previous);
	}
	if (appResources->allowImage) {
		previous =
		imageCmd = createTextFieldL("imageCmd", itemsForm, previous);
	}
	if (appResources->allowTelnet) {
		previous =
		telCmd = createTextFieldL("telCmd", itemsForm, previous);
	}
	if (appResources->allowTn3270) {
		t32Cmd = createTextFieldL("t3270Cmd", itemsForm, previous);
	}
				

	/* create QUIT button */

	doneButton = XtCreateManagedWidget("done", commandWidgetClass,
					buttonBox, NULL, (Cardinal) 0);
		XtAddCallback(doneButton, XtNcallback, doneProc, NULL);

	/* create CANCEL button */

	cancelButton = XtCreateManagedWidget("cancel", commandWidgetClass,
					buttonBox, NULL, (Cardinal) 0);
		XtAddCallback(cancelButton, XtNcallback, cancelProc, NULL);

	/* create HELP button */

	helpButton = XtCreateManagedWidget("help", commandWidgetClass,
					buttonBox, NULL, (Cardinal) 0);
		XtAddCallback(helpButton, XtNcallback, helpProc, NULL);


	return;
}

