/***************************************************************************/
/***************************************************************************/
/*                                                                         */
/*   (c) 1995-1999.  The Regents of the University of California.  All     */
/*   rights reserved.                                                      */
/*                                                                         */
/*   This work was produced at the University of California, Lawrence      */
/*   Livermore National Laboratory (UC LLNL) under contract no.            */
/*   W-7405-ENG-48 (Contract 48) between the U.S. Department of Energy     */
/*   (DOE) and The Regents of the University of California (University)    */
/*   for the operation of UC LLNL.  Copyright is reserved to the           */
/*   University for purposes of controlled dissemination,                  */
/*   commercialization through formal licensing, or other disposition      */
/*   under terms of Contract 48; DOE policies, regulations and orders;     */
/*   and U.S. statutes.  The rights of the Federal Government are          */
/*   reserved under Contract 48 subject to the restrictions agreed upon    */
/*   by the DOE and University.                                            */
/*                                                                         */
/*                                                                         */
/*                              DISCLAIMER                                 */
/*                                                                         */
/*   This software was prepared as an account of work sponsored by an      */
/*   agency of the United States Government.  Neither the United States    */
/*   Government nor the University of California nor any of their          */
/*   employees, makes any warranty, express or implied, or assumes any     */
/*   liability or responsibility for the accuracy, completeness, or        */
/*   usefulness of any information, apparatus, product, or process         */
/*   disclosed, or represents that its specific commercial products,       */
/*   process, or service by trade name, trademark, manufacturer, or        */
/*   otherwise, does not necessarily constitute or imply its               */
/*   endorsement, recommendation, or favoring by the United States         */
/*   Government or the University of California. The views and opinions    */
/*   of the authors expressed herein do not necessarily state or reflect   */
/*   those of the United States Government or the University of            */
/*   California, and shall not be used for advertising or product          */
/*   endorsement purposes.                                                 */
/*                                                                         */
/*   Permission to use, copy, modify and distribute this software and its  */
/*   documentation for any non-commercial purpose, without fee, is         */
/*   hereby granted, provided that the above copyright notice and this     */
/*   permission notice appear in all copies of the software and            */
/*   supporting documentation, and that all UC LLNL identification in      */
/*   the user interface remain unchanged.  The title to copyright LLNL     */
/*   XDIR shall at all times remain with The Regents of the University     */
/*   of California and users agree to preserve same. Users seeking the     */
/*   right to make derivative works with LLNL XDIR for commercial          */
/*   purposes may obtain a license from the Lawrence Livermore National    */
/*   Laboratory's Technology Transfer Office, P.O. Box 808, L-795,         */
/*   Livermore, CA 94550.                                                  */
/*                                                                         */
/***************************************************************************/
/***************************************************************************/

#include <Xm/RowColumn.h>
#include <Xm/CascadeBG.h>
#include <Xm/PushBG.h>
#include "xdir.h"
#include "list.h"
#include "history.h"

#define HOSTWIDTH 3

static char *msg1 = "Unable to redisplay directory.\n\nDirectory window might be out of date.";

void cb_show_dirwin();
void update_host_pullright();
struct sl_struct *create_null_array_list();
int wins_strcmp();
char *cstring_to_text();

extern struct dirwin_st *dirwin_head;
extern struct st_host_info hinfo[];
extern Display *display;


/*
 * initialize_wins_menu - Initialize the "Wins" menu by creating a bunch
 *                        of placeholder menu items.
 */
void
initialize_wins_menu(dirwin)
struct dirwin_st *dirwin;
{
	XmString string = XmStringCreateSimple("Dummy");
	Widget w_pulldown;
	int i;

	/* Get Wins menu pulldown */
	XtVaGetValues(dirwin->w_winsMenu, XmNsubMenuId, &w_pulldown, NULL);

	/* Add items to the wins menu, but leave them unmanaged */
	for (i=0; i< MAXHOSTS; i++) {
		dirwin->w_hostDirMenu[i] = XtVaCreateWidget(
			"",
			xmCascadeButtonGadgetClass,
			w_pulldown,
			XmNlabelString,	string,
			NULL
		);
	}

	XmStringFree(string);
}


/*
 * update_wins_menu - Update "Wins" menu.  Should be called after a
 *                    directory window is added or deleted.
 */
void
update_wins_menu()
{
	struct dirwin_st *dirwin;
	struct sl_struct *list;
	XmString string;
	Widget w_pulldown;
	Widget w_pullright;
	int i;
	int j;
	int host;
	int host_has_dirwin[MAXHOSTS];
	char *hostuser;
	char control[20];
	char hoststr[HOSTWIDTH+1];
	char *username;

	/* Which hosts have directory windows? */
	for (i=0; i<MAXHOSTS; i++)
		host_has_dirwin[i] = False;
	dirwin = dirwin_head;
	while (dirwin) {
		host_has_dirwin[dirwin->host] = True;
		dirwin = dirwin->next;
	}

	/* Create list of host/user names which have directory windows displayed */
	sprintf(control, "%%0%dd%%s  (%%s)", HOSTWIDTH);
	list = create_null_array_list();
	for (i=0; i<MAXHOSTS; i++)
		if (host_has_dirwin[i]) {
			if (i == LOCAL)
				username = XtNewString("Local");
			else
				username = XtNewString(hinfo[i].username);
			hostuser = XtMalloc(HOSTWIDTH+strlen(hinfo[i].hostname)
				+strlen(username)+6);
			sprintf(hostuser, control, i, hinfo[i].hostname, username);
			XtFree(username);
			add_to_array_list(&list, hostuser);
			XtFree(hostuser);
		}
	quicksort(list->entries, list->nentries, wins_strcmp);

    /* Enter host/user names into "Wins" menu of each directory window */
	dirwin = dirwin_head;
	while (dirwin) {
		XtVaGetValues(dirwin->w_winsMenu, XmNsubMenuId, &w_pulldown, NULL);
		for (i=0; i<list->nentries; i++) {
			string = XmStringCreateSimple(&(list->entries[i][HOSTWIDTH]));
			bcopy(list->entries[i], hoststr, HOSTWIDTH);
			hoststr[HOSTWIDTH] = '\0';
			sscanf(hoststr, "%d", &host);
			XtVaSetValues(dirwin->w_hostDirMenu[i],
				XmNlabelString,	string,
				XmNuserData, (XtPointer)host,
				NULL);
			XmStringFree(string);
			XtManageChild(dirwin->w_hostDirMenu[i]);
			if (i >= dirwin->max_host_menu_used) {
				w_pullright = XmCreatePulldownMenu(w_pulldown, "pullright",
					NULL, 0);
				XtVaSetValues(dirwin->w_hostDirMenu[i], XmNsubMenuId,
					w_pullright, NULL);
				string = XmStringCreateSimple("Dummy");
				for (j=0; j<MAXHOSTDIRS; j++) {
					dirwin->w_hostDirMenuItem[i][j] = XtVaCreateWidget(
						"",
						xmPushButtonGadgetClass,
						w_pullright,
						XmNlabelString, string,
						NULL
					);
					XtAddCallback(dirwin->w_hostDirMenuItem[i][j],
						XmNactivateCallback, cb_show_dirwin,
						(XtPointer)dirwin->w_hostDirMenu[i]);
				}
				XmStringFree(string);
				dirwin->max_host_menu_used = i;
			}
		update_host_pullright(dirwin, i);
		}
		for (i=list->nentries; i<MAXHOSTS; i++)
			XtUnmanageChild(dirwin->w_hostDirMenu[i]);
		dirwin = dirwin->next;
	}

	/* Free stuff */
	release_array_list(list);
}


/*
 * update_host_pullright - Update the pullright menu for the associated
 *                         host/user in the "Wins" menu.
 */
void
update_host_pullright(dirwin, hindex)
struct dirwin_st *dirwin;
int hindex;
{
	XmString string;
	int i;
	int host;
	struct sl_struct *list;
	struct dirwin_st *dwin;

	/* Determine host number */
	XtVaGetValues(dirwin->w_hostDirMenu[hindex], XmNuserData, &host, NULL);

	/* Create list of directory windows for host/user */
	list = create_null_array_list();
	dwin = dirwin_head;
	while (dwin) {
		if (dwin->host == host)
			add_to_array_list(&list, dwin->dirname);
		dwin = dwin->next;
	}
	quicksort(list->entries, list->nentries, strcmp);

    /* Enter directory paths into pullright menupane */
    for (i=0; i<list->nentries; i++) {
        string = XmStringCreateSimple(list->entries[i]);
        XtVaSetValues(dirwin->w_hostDirMenuItem[hindex][i],
			XmNlabelString, string, NULL);
        XmStringFree(string);
        XtManageChild(dirwin->w_hostDirMenuItem[hindex][i]);
    }
    for (i=list->nentries; i<MAXHOSTDIRS; i++)
        XtUnmanageChild(dirwin->w_hostDirMenuItem[hindex][i]);

	/* Free stuff */
	release_array_list(list);
}


/*
 * cb_show_dirwin - Callback to show directory window displaying the
 *                  selected directory.
 */
void
cb_show_dirwin(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
	Widget w_hostDirMenu = (Widget)client_data;
	XmString string;
	char *path;
	int host;
	struct dirwin_st *dirwin;
	struct entry_info *einfo;
	int retval;

	/* Start operation */
	if (!start_op(False))
		return;

	/* Clear error flag */
	raise_okflag();

	/* Determine host number */
	XtVaGetValues(w_hostDirMenu, XmNuserData, &host, NULL);

	/* Get directory path */
	XtVaGetValues(widget, XmNlabelString, &string, NULL);
	path = cstring_to_text(string);
	XmStringFree(string);   /* Yes, this is necessary */

	/* Update cache of referenced directories */
	add_to_history(DIRECTORY, hinfo[host].hostname, path);
	update_goto_menus_for_host(host);

	/* Which directory window? */
	retval = is_dir_displayed(host, path, &dirwin, &einfo);
	if (!retval || einfo)  /* Sanity check */
		fatal_error("Bug in cb_show_dirwin()");

	/* Make operation interruptable */
	if (dirwin->host != LOCAL)
		show_stop_button(dirwin);

	/* Make sure connection is still good */
	if (dirwin->host != LOCAL) {
		retval = check_connection(dirwin->host, dirwin);
		if (retval < 0) {
			restore_prev_cursor();
			switch (retval) {
			case -6:
				record_abort("Show Directory Window");
				break;
			case -1:
				record_and_alert(msg1, dirwin->w_shell);
			}
			hide_stop_button();
			end_op();
			return;
		}
	}

	/* Display selected directory window */
	retval = display_dir(host, dirwin, path, False, True, False, False);
	XtFree(path);
	switch (retval) {
	case -6:
		record_abort("Show Directory Window");
		break;
	case -1:
		record_and_alert(msg1, dirwin->w_shell);
		break;
	case -3:
		restore_lost_connection(host, dirwin);
	}
	if (dirwin->host != LOCAL)
		hide_stop_button();

	/* End operation */
	end_op();
}


/*
 * wins_strcmp - Compare strings "string1" and "string2", but ignoring 
 *               the first HOSTWIDTH bytes.  Returns negative value if
 *               "string1" is ess than "string2", 0 if "string1" equals
 *               "string2", and positive value if "string1" is greater
 *               than "string2".
 */
wins_strcmp(string1, string2)
char *string1;
char *string2;
{
	return strcmp(string1+HOSTWIDTH, string2+HOSTWIDTH);
}



syntax highlighted by Code2HTML, v. 0.9.1