/***************************************************************************/
/***************************************************************************/
/*                                                                         */
/*   (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/PushBG.h>
#include "xdir.h"

struct file_viewer_st {
	char *name;
	int indx;
	Widget w_shell;
	struct file_viewer_st *prev;
	struct file_viewer_st *next;
};

static struct file_viewer_st *tail_file_viewers = NULL;
static struct file_viewer_st *head_file_viewers = NULL;

extern struct dirwin_st *dirwin_head;
extern Display *display;
extern int screen;

void cb_popup_file_viewer();
void update_viewed_files_menus();
void update_viewed_files_menu();


/*
 * manage_file_viewer - Added the indicated internal file viewer to the list
 *                      of viewers to be managed.  "name" is the name of the
 *                      file and "w_shell" is the widget id of the viewer's
 *                      shell.
 */
void
manage_file_viewer(name, w_shell)
char *name;
Widget w_shell;
{
	struct file_viewer_st *ptr;
	struct file_viewer_st *p;
	int retval;
	int indx;
	char *title;

	/* Find position in list to add viewer */
	indx = 1;
	ptr = head_file_viewers;
	while (ptr) {
		retval = strcmp(name, ptr->name);
		if (retval < 0)
			break;
		else if (retval == 0) {
			while (ptr && !strcmp(name, ptr->name) && (indx == ptr->indx)) {
				indx++;
				ptr = ptr->next;
			}
			break;
		} else
			ptr = ptr->next;
	}

	/* Allocate node for viewer */
	p = XtNew(struct file_viewer_st);
	p->name = XtNewString(name);
	p->indx = indx;
	p->w_shell = w_shell;

	/* Insert viewer into list */
	if (ptr) {
		p->prev = ptr->prev;
		p->next = ptr;
		if (ptr->prev)
			ptr->prev->next = p;
		else
			head_file_viewers = p;
		ptr->prev = p;
	} else {   /* Add to tail */
		if (tail_file_viewers)
			tail_file_viewers->next = p;
		else
			head_file_viewers = p;
		p->prev = tail_file_viewers;
		p->next = NULL;
		tail_file_viewers = p;
	}

	/* Update viewer's title bar with file name */
	if (indx == 1)
		title = XtNewString(name);
	else {
		title = XtMalloc(strlen(name)+10);
		sprintf(title, "%s <%d>", name, indx);
	}
	XtVaSetValues(w_shell, XmNtitle, title, NULL);
	XtFree(title);

	/* Update "Viewed Files" menus */
	update_viewed_files_menus();
}


/*
 * unmanage_file_viewer - Remove the indicated internal file viewer from
 *                        the list of viewers to be managed.  "w_shell"
 *                        is the widget id of the viewer's shell.
 */
void
unmanage_file_viewer(w_shell)
Widget w_shell;
{
	struct file_viewer_st *ptr;

	ptr = head_file_viewers;
	while (ptr) {
		if (w_shell == ptr->w_shell) {
			if (ptr->next) 
				ptr->next->prev = ptr->prev;
			else
				tail_file_viewers = ptr->prev;
			if (ptr->prev)
				ptr->prev->next = ptr->next;
			else
				head_file_viewers = ptr->next;
			XtFree(ptr->name);
			XtFree((char *)ptr);
			update_viewed_files_menus();
			return;
		}
		ptr = ptr->next;
	}

	/* Sanity check */
	fatal_error("Bug in unmanage_file_viewer()");
}


/*
 * initialize_viewed_files_menu - Initialize the "Viewed Files" menu by
 *                                creating a bunch of placeholder menu
 *                                items.
 */
void
initialize_viewed_files_menu(dirwin)
struct dirwin_st *dirwin;
{
	XmString string;
	int i;
	Widget w_pulldown;

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

	/* Now create the menu items, but leave them unmanaged */
	string = XmStringCreateSimple("Dummy");
	for (i=0; i<MAXVIEWERS; i++) {
		dirwin->w_viewedFilesMenuItem[i] = XtVaCreateWidget(
            "",
            xmPushButtonGadgetClass,
            w_pulldown,
            XmNlabelString, string,
            NULL
        );
        XtAddCallback(dirwin->w_viewedFilesMenuItem[i], XmNactivateCallback,
            cb_popup_file_viewer, (XtPointer)NULL);
    }
    XmStringFree(string);
}


/*
 * update_viewed_files_menus - Update the "Viewed Files" menu in each of
 *                             directory windows.
 */
void
update_viewed_files_menus()
{
	struct dirwin_st *dirwin;

	dirwin = dirwin_head;
	while (dirwin) {
		update_viewed_files_menu(dirwin);
		dirwin = dirwin->next;
	}
}


/*
 * update_viewed_files_menu - Update the "Viewed Files" menu in the
 *                            specified directory window.
 */
void
update_viewed_files_menu(dirwin)
struct dirwin_st *dirwin;
{
	int i;
	XmString label;
	struct file_viewer_st *ptr;
	char *name;
	
	/* Get rid of current menu items */
	for (i=0; i<MAXVIEWERS; i++)
		XtUnmanageChild(dirwin->w_viewedFilesMenuItem[i]);

	/* Set sensitivity of "Viewed Files" menu */
	if (head_file_viewers)
		XtSetSensitive(dirwin->w_viewedFilesMenu, True);
	else
		XtSetSensitive(dirwin->w_viewedFilesMenu, False);

	/* Enter file viewer names into menu */
	i = 0;
	ptr = head_file_viewers;
	while (ptr) {
		if (ptr->indx == 1)
			name = XtNewString(ptr->name);
		else {
			name = XtMalloc(strlen(ptr->name)+10);
			sprintf(name, "%s <%d>", ptr->name, ptr->indx);
		}
		label = XmStringCreateSimple(name);
		XtFree(name);
		XtVaSetValues(dirwin->w_viewedFilesMenuItem[i],
			XmNlabelString,	label,
			XmNuserData,	(XtPointer)ptr->w_shell,
			NULL
		);
		XmStringFree(label);
		XtManageChild(dirwin->w_viewedFilesMenuItem[i]);
		i++;
		ptr = ptr->next;
	}
}


/*
 * cb_popup_file_viewer - Callback to pop file viewer window to top.
 */
void
cb_popup_file_viewer(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
	Widget w_shell;

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

	/* Clear error flag */
	raise_okflag();

	XtVaGetValues(widget, XmNuserData, &w_shell, NULL);
	XMapRaised(display, XtWindow(w_shell));

	/* End operation */
	end_op();
}


/*
 * number_of_internal_viewers - Returns the number of internal viewers in
 *                              use.
 */
number_of_internal_viewers()
{
	int count = 0;
	struct file_viewer_st *ptr;

	ptr = head_file_viewers;
	while (ptr) {
		count++;
		ptr = ptr->next;
	}

	return count;
}


/*
 * iconify_file_viewer_windows - Iconify each file viewer window.
 */
void
iconify_file_viewer_windows()
{
	struct file_viewer_st *ptr;

	ptr = head_file_viewers;
	while (ptr) {
		XIconifyWindow(display, XtWindow(ptr->w_shell), screen);
		ptr = ptr->next;
	}
}


/*
 * deiconify_file_viewer_windows - Deiconify each file viewer window.
 */
void
deiconify_file_viewer_windows()
{
	struct file_viewer_st *ptr;

	ptr = head_file_viewers;
	while (ptr) {
		XMapWindow(display, XtWindow(ptr->w_shell));
		ptr = ptr->next;
	}
}



syntax highlighted by Code2HTML, v. 0.9.1