/* resources.c
   process application resources(options) using the X resource manager. */

     /*---------------------------------------------------------------*/
     /* Xgopher        version 1.3     08 April 1993                  */
     /*                version 1.2     20 November 1992               */
     /*                version 1.1     20 April 1992                  */
     /*                version 1.0     04 March 1992                  */
     /* 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, 1993 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/Xlib.h>
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>


#include "osdep.h"

#include "conf.h"
#include "globals.h"
#include "resources.h"
#include "typeres.h"
#include "popres.h"
#include "listP.h"
#include "misc.h"
#include "panel.h"

/* Note on boolean data types.
   Xlib.h	defines Bool, True, False (as int, 1, 0)
   Intrinsic.h	defines Boolean, TRUE, FALSE (as typedef char, 1, 0)

   To keep some modules of this program independent of X, the new
   type BOOLEAN is introduced (typedef int), and constants TRUE and
   FALSE are conditionally defined in conf.h to be 1 and 0.
   An implicit conversion from Boolean (resources) to BOOLEAN
   is assumed. */


static	char	*initPrintCmd, *initImageCmd, *initTelnetCmd,
		*initTn3270Cmd, *initBkFile;
static	Boolean		initAppendBk, initLoadBk, initResetOptions;
static	showLevel	initShowItems;

static	Widget	topLevel;

/* saveChangableResources
   save initial value of resources that may be changed during execution */

void
saveChangableResources(arP)
gopherAppResourcesP	arP;
{
	char	*temp;

	initBkFile =
		(char *) malloc(sizeof(char) * (strlen(arP->bookmarkFile)+1));
	strcpy(initBkFile, arP->bookmarkFile);

	initPrintCmd =
		(char *) malloc(sizeof(char) * (strlen(arP->printCommand)+1));
	strcpy(initPrintCmd, arP->printCommand);

	initImageCmd =
		(char *) malloc(sizeof(char) * (strlen(arP->imageCommand)+1));
	strcpy(initImageCmd, arP->imageCommand);

	initTelnetCmd =
		(char *) malloc(sizeof(char) * (strlen(arP->telnetCommand)+1));
	strcpy(initTelnetCmd, arP->telnetCommand);

	initTn3270Cmd =
		(char *) malloc(sizeof(char) * (strlen(arP->tn3270Command)+1));
	strcpy(initTn3270Cmd, arP->tn3270Command);

	initAppendBk	= arP->appendBookmarks;
	initShowItems	= arP->showItems;
	initLoadBk	= arP->loadBookmarks;
	initResetOptions= arP->resetOptions;
}


/* restoreChangableResources
   restore initial value of resources that may have been changed
   during execution */

void
restoreChangableResources(arP)
gopherAppResourcesP	arP;
{
	arP->bookmarkFile	= initBkFile;
	arP->printCommand	= initPrintCmd;
	arP->imageCommand	= initImageCmd;
	arP->telnetCommand	= initTelnetCmd;
	arP->tn3270Command	= initTn3270Cmd;

	arP->appendBookmarks	= initAppendBk;
	arP->showItems		= initShowItems;
	arP->loadBookmarks	= initLoadBk;
	arP->resetOptions	= initResetOptions;
}


#define DEF_PREFIX	"< ? >"
#define DEF_DESCR	"type ? item"
#define DEF_DESCR_LEN	32

/* getTypeResources
   get resources that define an extended type */

typeResources *
getTypeResources(name, class)
char	*name, *class;
{
	static typeResources	typeRes;
	static char		defPrefix[PREFIX_LEN+1];
	static char		defDescr[DEF_DESCR_LEN];
	char			t;
	char			*p;

	/* assume last character of name is the type letter */
	/* substitute this letter in place of the '?' in defaults */

	t = name[strlen(name)-1];

	strncpy(defPrefix, DEF_PREFIX, PREFIX_LEN);
	p = index(defPrefix, '?');
	if (p != (char *) NULL) *p = t;

	strncpy(defDescr, DEF_DESCR, DEF_DESCR_LEN);
	p = index(defDescr, '?');
	if (p != (char *) NULL) *p = t;

	typeEntry[TE_DESCR].default_addr = defDescr;
	typeEntry[TE_PREFIX].default_addr = defPrefix;
	XtGetSubresources (topLevel, (XtPointer) &typeRes,
				(String) name, (String) class,
				typeEntry, XtNumber(typeEntry), NULL, 0); 

	return (&typeRes);
}


/* getPopupPosResources
   get resources that define popup positioning */

popupPosResources *
getPopupPosResources(name, class, defaults)
char			*name, *class;
popupPosResources	*defaults;
{
	static popupPosResources popupPosRes;

	/* each popup may request its own defaults.  Set them now. */

	popupPosEntry[PE_FROM].default_addr =
				(XtPointer) defaults->positionFrom;
	popupPosEntry[PE_X].default_addr = 
				(XtPointer) defaults->xPosition;
	popupPosEntry[PE_Y].default_addr = 
				(XtPointer) defaults->yPosition;
	popupPosEntry[PE_HJUST].default_addr = 
				(XtPointer) defaults->horizontalJustification;
	popupPosEntry[PE_VJUST].default_addr = 
				(XtPointer) defaults->verticalJustification;
	popupPosEntry[PE_XPERCENT].default_addr = 
				(XtPointer) ((int) defaults->xPercent);
	popupPosEntry[PE_YPERCENT].default_addr = 
				(XtPointer) ((int) defaults->yPercent);

	XtGetSubresources (topLevel, (XtPointer) &popupPosRes,
				(String) name, (String) class,
				popupPosEntry, XtNumber(popupPosEntry),
				NULL, 0); 

	return (&popupPosRes);
}


/* getApplicationResources
   get application resources */

gopherAppResources *
getApplicationResources(top, argc, argv)
Widget	top;
int	argc;
char	**argv;
{
	static gopherAppResources	appResources;

	topLevel = top;

	/* get application resources */

	XtGetApplicationResources(topLevel, (XtPointer) &appResources,
			resources, XtNumber(resources), NULL, 0);

	if (! appResources.defaultsInstalled) return NULL;

	/* in public mode, apply restrictions such as are desirable
	   for a public login to Xgopher.  */
	
	if (appResources.publicMode) {
		appResources.allowSave		= False;
		appResources.allowPrint		= False;
		appResources.allowTelnet	= False;
		appResources.allowTn3270	= False;
		appResources.allowBookmarkSave	= False;
		appResources.allowCopy		= False;
		appResources.appendBookmarks	= True;
		appResources.loadBookmarks	= True;
		appResources.markRoot		= True;
		appResources.resetOptions	= True;
		appResources.optionsButton	= False;
		appResources.singleItemButton	= False;
		appResources.showItems		= showAvailable;


		/* these are other resources that the installer
		   may wish to set in the resources file, but
		   they should not be forced here.

			appResources.allowImage		= False;
			appResources.hasSound		= False;

			appResources.warpCursor		= True;
			appResources.doubleClick	= False;
			appResources.concurrentText	= 1;
			appResources.allowHold		= False;
			appResources.allowFtp		= False;
			appResources.bookmarkFile	= <filename>;

		    the next two should go as a pair:
			appResources.restartButton	= False;
			appResources.swapRestartAndQuit	= True;

		   Also, be sure that any remaining commands (imageCommand,
		   soundCommand, etc.) have no shell-escapes or other
		   ways to do damage.
		*/
	}

	itemStart     = appResources.itemStart;
	itemIncrement = appResources.itemIncrement;
	dirStart      = appResources.dirStart;
	dirIncrement  = appResources.dirIncrement;

	setHelpFile (appResources.helpFile);
	setBkmkFile (appResources.bookmarkFile);
	setBkmkAppend (appResources.appendBookmarks);

	infoDirLabel = XtMalloc(
		sizeof (char) * strlen(appResources.infoDirLabel) + 1);
	markDirLabel = XtMalloc(
		sizeof (char) * strlen(appResources.markDirLabel) + 1);
	strcpy(infoDirLabel, appResources.infoDirLabel);
	strcpy(markDirLabel, appResources.markDirLabel);

	if (appResources.logFile != NULL  &&  *appResources.logFile != NULLC) {

		/* use open/fdopen instead of just fopen so the
		   mode can be set for privacy in the log file */

		int	logFD;

		if ((logFD = open (tildePath(appResources.logFile),
			      O_WRONLY | O_CREAT, LOG_FILE_MODE)) < 0) {
			perror ("open");
			fprintf (stderr, "cannot open log file \'%s\'\n",
					tildePath(appResources.logFile));
			logFP = NULL;
		} else if ((logFP = fdopen(logFD, "w")) == NULL) {
			fprintf (stderr, "cannot open log file \'%s\'\n",
					tildePath(appResources.logFile));
		} else {
			setbuf(logFP, NULL);
		}
	} else {
		logFP = NULL;
	}

	saveChangableResources(&appResources);


#ifdef DEBUG
	LOG (logFP, "Application Resources\n");
	LOG (logFP, "\tdefaultsInstalled:\t%s\n",
			appResources.defaultsInstalled ? "True" : "False");
	LOG (logFP, "\tresourcesVersion:\t%s\n",
			appResources.resourcesVersion);
	LOG (logFP, "\trootServer:\t%s\n",
			appResources.rootServer);
	LOG (logFP, "\trootPort:\t%d\n",
			appResources.rootPort);
	LOG (logFP, "\trootPath:\t%s\n",
			appResources.rootPath);
	LOG (logFP, "\tmainTitle:\t%s\n",
			appResources.mainTitle);
	LOG (logFP, "\tallowSave:\t%s\n",
			appResources.allowSave ? "True" : "False");
	LOG (logFP, "\tallowPrint:\t%s\n",
			appResources.allowPrint ? "True" : "False");
	LOG (logFP, "\tprintCommand:\t%s\n",
			appResources.printCommand);
	LOG (logFP, "\thelpFile:\t%s\n",
			appResources.helpFile);
	LOG (logFP, "\tdirectoryTime:\t%d\n",
			 appResources.directoryTime);
	LOG (logFP, "\tallowImage:\t%s\n",
			appResources.allowImage ? "True" : "False");
	LOG (logFP, "\timageCommand:\t%s\n",
			appResources.imageCommand);
	LOG (logFP, "\thasSound:\t%s\n",
			appResources.hasSound ? "True" : "False");
	LOG (logFP, "\tsoundCommand:\t%s\n",
			appResources.soundCommand);
	LOG (logFP, "\tbookmarkFile:\t%s\n",
			appResources.bookmarkFile);
	LOG (logFP, "\tallowBookmarkSave:\t%s\n",
			appResources.allowBookmarkSave ? "True" : "False");
	LOG (logFP, "\tappendBookmarks:\t%s\n",
			appResources.appendBookmarks ? "True" : "False");
	LOG (logFP, "\tallowTelnet:\t%s\n",
			appResources.allowTelnet ? "True" : "False");
	LOG (logFP, "\ttelnetCommand:\t%s\n",
			appResources.telnetCommand);
	LOG (logFP, "\tallowTn3270:\t%s\n",
			appResources.allowTn3270 ? "True" : "False");
	LOG (logFP, "\ttn3270Command:\t%s\n",
			appResources.tn3270Command);
	LOG (logFP, "\tloadBookmarks:\t%s\n",
			appResources.loadBookmarks ? "True" : "False");
	LOG (logFP, "\trestartButton:\t%s\n",
			appResources.restartButton ? "True" : "False");
	LOG (logFP, "\tswapRestartAndQuit:\t%s\n",
			appResources.swapRestartAndQuit ? "True" : "False");
	LOG (logFP, "\toptionsButton:\t%s\n",
			appResources.optionsButton ? "True" : "False");
	LOG (logFP, "\tsingleItemButton:\t%s\n",
			appResources.singleItemButton ? "True" : "False");
	LOG (logFP, "\tshowItems:\t%d\n",
			appResources.showItems);
	LOG (logFP, "\tallowFtp:\t%s\n",
			appResources.allowFtp ? "True" : "False");
	LOG (logFP, "\tpublicMode:\t%s\n",
			appResources.publicMode ? "True" : "False");
	LOG (logFP, "\tstatusWindow:\t%s\n",
			appResources.statusWindow ? "True" : "False");
	LOG (logFP, "\timageServers:\t%s\n",
			appResources.imageServers);
	LOG (logFP, "\tsoundServers:\t%s\n",
			appResources.soundServers);
	LOG (logFP, "\ttextServers:\t%s\n",
			appResources.textServers);
	LOG (logFP, "\tdirHistory:\t%s\n",
			appResources.dirHistory ? "True" : "False");
	LOG (logFP, "\tnameText:\t%s\n",
			appResources.nameText ? "True" : "False");
	LOG (logFP, "\tcommonText:\t%s\n",
			appResources.commonText ? "True" : "False");
	LOG (logFP, "\tconcurrentText:\t%d\n",
			 appResources.concurrentText);
	LOG (logFP, "\tallowHold:\t%s\n",
			appResources.allowHold ? "True" : "False");
	LOG (logFP, "\tresetOptions:\t%s\n",
			appResources.resetOptions ? "True" : "False");
	LOG (logFP, "\titemStart:\t%d\n",
			 appResources.itemStart);
	LOG (logFP, "\titemIncrement:\t%d\n",
			 appResources.itemIncrement);
	LOG (logFP, "\tdirStart:\t%d\n",
			 appResources.dirStart);
	LOG (logFP, "\tdirIncrement:\t%d\n",
			 appResources.dirIncrement);
	LOG (logFP, "\twarpCursor:\t%s\n",
			appResources.warpCursor ? "True" : "False");
	LOG (logFP, "\tdoubleClick:\t%s\n",
			appResources.doubleClick ? "True" : "False");
	LOG (logFP, "\tmarkRoot:\t%s\n",
			appResources.markRoot ? "True" : "False");
	LOG (logFP, "\textendedTypes:\t%s\n",
			 appResources.extendedTypes);
	LOG (logFP, "\ttempDirectory:\t%s\n",
			 appResources.tempDirectory);
	LOG (logFP, "\tlogFile:\t%s\n",
			 appResources.logFile==NULL ? 
					"<none>" : appResources.logFile);
	LOG (logFP, "\tprefixFile:\t%.*s\n",
			 PREFIX_LEN, appResources.prefixFile);
	LOG (logFP, "\tprefixDir:\t%.*s\n",
			 PREFIX_LEN, appResources.prefixDir);
	LOG (logFP, "\tprefixTelnet:\t%.*s\n",
			 PREFIX_LEN, appResources.prefixTelnet);
	LOG (logFP, "\tprefixTn3270:\t%.*s\n",
			 PREFIX_LEN, appResources.prefixTn3270);
	LOG (logFP, "\tprefixCSO:\t%.*s\n",
			 PREFIX_LEN, appResources.prefixCSO);
	LOG (logFP, "\tprefixIndex:\t%.*s\n",
			 PREFIX_LEN, appResources.prefixIndex);
	LOG (logFP, "\tprefixBinary:\t%.*s\n",
			 PREFIX_LEN, appResources.prefixBinary);
	LOG (logFP, "\tprefixImage:\t%.*s\n",
			 PREFIX_LEN, appResources.prefixImage);
	LOG (logFP, "\tprefixSound:\t%.*s\n",
			 PREFIX_LEN, appResources.prefixSound);
	LOG (logFP, "\tprefixUnknown:\t%.*s\n",
			 PREFIX_LEN, appResources.prefixUnknown);
#endif /* DEBUG */

	return &appResources;
}
