/*
 * display-x.c : Display routines for xarchie
 *
 * George Ferguson, ferguson@cs.rochester.edu, 23 Apr 1993.
 * 14 May 1993: Need <stdio.h> when DEBUG defined.
 *		Need to resize List in redrawBrowserPane() when MULTILIST
 *		not defined. 
 */

#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/AsciiText.h>
#ifdef MULTILIST
#include <MultiList.h>
#else
#include <X11/Xaw/List.h>
#endif
#include "xarchie.h"
#include "appres.h"
#include "browser.h"
#include "alert.h"
#include "xutil.h"
#include "stringdefs.h"			/* bezro, bcopy */
#include "debug.h"

/*
 * Functions defined here:
 */
/* Text output routines */
void setTitleText(), setStatusText();
void setSearchText(), setHostText(), setLocationText(), setFileText();
void setSizeText(), setModesText(), setDateText();

/* Button sensitivity routines */
void setQuerySensitive(), setAbortSensitive();
void setUpSensitive(), setDownSensitive();

/* Browser routines */
void initBrowser(),clearBrowser(),redrawBrowser();
void clearBrowserPane(), redrawBrowserPane(), unhighlightBrowserPane();
void clearBrowserItem(), redrawBrowserItem(), unhighlightBrowserItem();
void highlightBrowserItem(), setBrowserItem();
/* Browser action routines */
void nextBrowserPane(),prevBrowserPane();
void nextBrowserItem(),prevBrowserItem();
void toggleCurrentBrowserItem(),selectCurrentBrowserItem();

/* Misc. display routines */
void beep();

/* Internal routines */
static void updatePasteBuffer(), setListString();

/*
 * Data defined here:
 */
/*
 * These string arrays are needed since the only way to set a List
 * widget in X is to pass it an array of strings. That is, there's
 * no way to add items incrementally. Blech. Still, the arrays are
 * grown as needed, so these values can be way off, as they are.
 */
#define INIT_NUM_BROWSER_STRINGS 1
#define REALLOC_INCR(num) (2*(num))

static char **browserStrings[NUM_BROWSER_PANES];
static int numBrowserStrings[NUM_BROWSER_PANES];

/*	-	-	-	-	-	-	-	-	*/
/* Text output */

/*ARGSUSED*/
void
setTitleText(str)
char *str;
{
    /*EMPTY*/
}

void
setStatusText(str)
char *str;
{
    setWidgetString(statusText,str);
    XFlush(display);
}

void
setSearchText(str)
char *str;
{
    setWidgetString(searchText,str);
}

void
setHostText(str)
char *str;
{
    setWidgetString(hostText,str);
    if (appResources.pasteBuffer)
	updatePasteBuffer();
}

void
setLocationText(str)
char *str;
{
    setWidgetString(locationText,str);
    if (appResources.pasteBuffer)
	updatePasteBuffer();
}

void
setFileText(str)
char *str;
{
    setWidgetString(fileText,str);
    if (appResources.pasteBuffer)
	updatePasteBuffer();
}

void
setSizeText(str)
char *str;
{
    setWidgetString(sizeText,str);
}

void
setModesText(str)
char *str;
{
    setWidgetString(modesText,str);
}

void
setDateText(str)
char *str;
{
    setWidgetString(dateText,str);
}

static void
updatePasteBuffer()
{
    char *host,*loc,*file,*buf;

    host = getWidgetString(hostText);
    loc = getWidgetString(locationText);
    file = getWidgetString(fileText);
    buf = XtMalloc(strlen(host)+strlen(loc)+strlen(file)+3);
    sprintf(buf,"%s:%s/%s",host,loc,file);
    XStoreBytes(display,buf,strlen(buf));
    XtFree(buf);
}

/*	-	-	-	-	-	-	-	-	*/
/* Buttons */

void
setQuerySensitive(state)
int state;
{
    int i;

    XtSetSensitive(queryButton,(state > 0 ? True : False));
    /* Disable the Lists so they get redrawn in "gray" */
    for (i=0; i < NUM_BROWSER_PANES; i++)
	XtSetSensitive(browserLists[i],(state > 0 ? True : False));
    /* This is a simple way to disable the up/down buttons */
    XtSetSensitive(browserForm,(state > 0 ? True : False));
    /* Update the icon also (True=busy, when query off ie. state = 0) */
    setIconStatus((state > 0) ? False : True);
}

void
setAbortSensitive(state)
int state;
{
    XtSetSensitive(abortButton,(state > 0 ? True : False));
}

void
setUpSensitive(state)
int state;
{
    XtSetSensitive(browserUpButton,(state > 0 ? True : False));
}

void
setDownSensitive(state)
int state;
{
    XtSetSensitive(browserDownButton,(state > 0 ? True : False));
}

/*	-	-	-	-	-	-	-	-	*/
/* Browser */

void
initBrowser()
{
    /*EMPTY*//* Done by widget creation */
}

void
clearBrowser()
{
    int pane;

    for (pane=0; pane < NUM_BROWSER_PANES; pane++) {
	clearBrowserPane(pane);
    }
}

void
redrawBrowser()
{
    /*EMPTY*/
}

/* Browser panes */

void
clearBrowserPane(pane)
int pane;
{
    static char *emptyNames[] = { NULL };

#ifdef MULTILIST
    XfwfMultiListSetNewData((XfwfMultiListWidget)browserLists[pane],
			    emptyNames,0,0,False,(Boolean *)NULL);
#else
    XawListChange(browserLists[pane],emptyNames,0,0,False);
#endif
}

void
redrawBrowserPane(pane)
int pane;
{
#ifdef MULTILIST
    XfwfMultiListSetNewData((XfwfMultiListWidget)browserLists[pane],
			    browserStrings[pane],0,0,True,(Boolean *)NULL);
#else
    XawListChange(browserLists[pane],browserStrings[pane],0,0,True);
#endif
}

void
unhighlightBrowserPane(pane)
int pane;
{
#ifdef MULTILIST
    XfwfMultiListUnhighlightAll((XfwfMultiListWidget)browserLists[pane]);
#else
    XawListUnhighlight(browserLists[pane]);
#endif
}

/* Browser items */

/*ARGSUSED*/
void
clearBrowserItem(pane,item)
int pane,item;
{
    /*EMPTY*/
}

/*ARGSUSED*/
void
redrawBrowserItem(pane,item)
int pane,item;
{
    /*EMPTY*/
}

void
unhighlightBrowserItem(pane,item)
int pane,item;
{
#ifdef MULTILIST
    XfwfMultiListUnhighlightItem((XfwfMultiListWidget)browserLists[pane],item);
#else
    XawListUnhighlight(browserLists[pane]);
#endif
}

void
highlightBrowserItem(pane,item)
int pane,item;
{
    Arg args[1];
    int number;
    float percent;

#ifdef MULTILIST
    XfwfMultiListHighlightItem((XfwfMultiListWidget)browserLists[pane],item);
#else
    XawListHighlight(browserLists[pane],item);
#endif
    /* Move the scrollbar so we see the item */
    if (appResources.autoScroll) {
	XtSetArg(args[0],XtNnumberStrings,&number);
	XtGetValues(browserLists[pane],args,1);
	percent = (float)(item-1) / (float)number;
	if (percent < 0.0)
	    percent = 0.0;
	else if (percent > 100.)
	    percent = 100.0;
	XtCallCallbacks(browserScrollbars[pane],
			"jumpProc",(XtPointer)&percent);
    }
}

void
setBrowserItem(pane,item,str)
int pane,item;
char *str;
{
    /* Set the actual value */
    setListString(pane,item,str);
    /* Need a terminating NULL later, so add it now */
    setListString(pane,item+1,NULL);
}

/* Browser actions */

void
nextBrowserPane()
{
    /*EMPTY*//* Done with mouse */
}

void
prevBrowserPane()
{
    /*EMPTY*//* Done with mouse */
}

void
nextBrowserItem()
{
    /*EMPTY*//* Done with mouse */
}

void
prevBrowserItem()
{
    /*EMPTY*//* Done with mouse */
}

void
toggleCurrentBrowserItem()
{
    /*EMPTY*//* Done by X */
}

void
selectCurrentBrowserItem()
{
    /*EMPTY*//* Done by X */
}

/*	-	-	-	-	-	-	-	-	*/
/* Misc. display routines */

void
beep()
{
    XBell(display,0);
}

/*	-	-	-	-	-	-	-	-	*/
/*
 * setListString() : This routine provides access to the dynamically-grown
 *	lists of strings. I bzero() the allocated space even though I shouldn't
 *	need to.
 */
static void
setListString(pane,index,string)
int pane,index;
char *string;
{
    char **oldStr;
    int oldNum;

    DEBUG3("setting index %d of pane %d to \"%s\"\n",index,pane,string);
    if (pane >= NUM_BROWSER_PANES) {
	alert2("Attempt to set string in pane %d: \"%s\"",(char *)pane,string);
	return;
    }
    /* Free old string if there was one */
    if (index < numBrowserStrings[pane]) {
	XtFree((XtPointer)(*(browserStrings[pane]+index)));
	DEBUG0("  freed old string\n");
    }
    /* If this is the first call, get the initial string array */
    if (numBrowserStrings[pane] == 0) {
	DEBUG0("  getting initial string array\n");
	numBrowserStrings[pane] = INIT_NUM_BROWSER_STRINGS;
	browserStrings[pane] = (char **)XtCalloc(numBrowserStrings[pane],
						 sizeof(char *));
	bzero((char *)(browserStrings[pane]),
	      numBrowserStrings[pane]*sizeof(char *));
    }
    DEBUG1("  string array is size %d\n",numBrowserStrings[pane]);
    /* Grow the array until it's big enough for this string */
    while (index >= numBrowserStrings[pane]) {
	DEBUG0("  growing string array\n");
	oldStr = browserStrings[pane];
	oldNum = numBrowserStrings[pane];
	numBrowserStrings[pane] = REALLOC_INCR(numBrowserStrings[pane]);
	browserStrings[pane] = (char **)XtCalloc(numBrowserStrings[pane],
						 sizeof(char *));
	bzero((char *)(browserStrings[pane]),
	      numBrowserStrings[pane]*sizeof(char *));
	bcopy((char *)oldStr,(char *)(browserStrings[pane]),
	      oldNum*sizeof(char *));
	XtFree((XtPointer)oldStr);
    }
    DEBUG1("  string array is now size %d\n",numBrowserStrings[pane]);
    /* Finally, set this value */
    if (string == (char *)NULL)
	*(browserStrings[pane]+index) = (char *)NULL;
    else
	*(browserStrings[pane]+index) = XtNewString(string);
    DEBUG1("  done setting string \"%s\"\n",string);
}
