/*
 * Copyright 1990 by Baylor College of Medicine ALL RIGHTS RESERVED. 
 *
 * This program is subject to a license agreement between 
 * Baylor College of Medicine and MIT. Any use inconsistent with
 * said license and any use by persons other than the faculty, 
 * students and staff at MIT or any use on a computer not operated 
 * as part of the Athena Computing Environment (ACE) is expressly 
 * prohibited.
 */
/****************************************************************
 * File: vns_comm.c
 * Date: 03/07/91
 *
 * Description:
 *   This file contains several client functions that communicate
 *   with VNS. These functions allows client applications to "tell"
 *   VNS to do things such as display a page.
 *
 * Revisions:
 ****************************************************************/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <signal.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Intrinsic.h>
#include <varargs.h>

#include "vns_comm.h"

/****************************************************************
 *              Private Functions
 ****************************************************************/

static time_is_up = FALSE ;

static
times_up()
{
	time_is_up = TRUE ;
}

static
char *
wait_for_reply(vc,timeout,format,va_alist)
	VnsConnection *vc;
	Boolean timeout;
	char *format;
	va_dcl
{
	va_list pvar ;
	static char buf[1024] ;
	va_start(pvar) ;
	vsprintf(buf,format,pvar) ;
	va_end(pvar) ;

	XChangeProperty(vc->dpy,vc->root,vc->request,vc->request_type,8,
			PropModeReplace,buf,strlen(buf)) ;
	XFlush(vc->dpy) ;

	/* set alarm if a timeout is desired */
	if (timeout)
	{
		ualarm(10 * 1000000L,0L) ;
	}

	time_is_up = FALSE ;
	while(!time_is_up)
	{
		XEvent event ;
		XCheckTypedWindowEvent(vc->dpy,vc->root,PropertyNotify,&event) ;
		if (event.xproperty.atom == vc->reply)
		{
            int type,format,nitems,left ;
            char *request ;
            if (XGetWindowProperty(vc->dpy,vc->root,vc->reply,0,1024,
                TRUE,vc->reply_type,&type,&format,&nitems,
                &left,&request) == Success &&
                type == vc->reply_type)
            {
				return request ;
            }
		}
	}
	fprintf(stderr,"Timed out waiting for reply from VNS.  Is it running?\n") ;
	fflush(stderr) ;
	return NULL ;
}

/****************************************************************
 *              Client Functions
 ****************************************************************/

/****************************************************************
 * Function: vns_open_xdisplay() 
 * Date: 03/11/91
 *
 * Description:
 *   This function establishes a display connection with the X
 *   server. This function is provided so that non-X applications
 *   can use the vns_comm library.
 *
 * Linkage: Display *vns_open_xdisplay()
 *
 * Returns: The X display pointer if successful. NULL otherwise.
 *
 * Revisions:
 ****************************************************************/
Display *
vns_open_xdisplay()
{
	Display *dpy ;

	dpy = XOpenDisplay("");
	if (dpy == NULL)
	{
		return NULL;
	}

	return dpy;
}

/****************************************************************
 * Function: vns_initialize 
 * Date: 03/11/91
 *
 * Description:
 *   This function initializes the vns_comm library. If successful,
 *   it returns the connection pointer.
 *
 * Linkage: VnsConnection *vns_initialize(dpy,db)
 *   Display *dpy - The X diplay connection pointer
 *   char *db     - database name
 *
 * Returns: the vns connection pointer if successful. NULL otherwise.
 *
 * Revisions:
 ****************************************************************/
VnsConnection *
vns_initialize(dpy,db)
	Display *dpy;
	char *db;
{
	if (dpy != NULL)
	{
		VnsConnection *vc = (VnsConnection *)malloc(sizeof(VnsConnection));

		vc->dpy = dpy;
		vc->db = strdup(db);
		vc->root = DefaultRootWindow(vc->dpy);
		vc->request = XInternAtom(vc->dpy,"VNS_REQUEST",False);
		vc->request_type = XInternAtom(vc->dpy,"VNS_REQUEST_TYPE",False);
		vc->reply = XInternAtom(vc->dpy,"VNS_REPLY",False);
		vc->reply_type = XInternAtom(vc->dpy,"VNS_REPLY_TYPE",False);
		XSelectInput(vc->dpy,vc->root,PropertyChangeMask);
		signal(SIGALRM,times_up) ;
		{
			char *reply = wait_for_reply(vc,True,"ping") ;
			if (reply == NULL)
			{
				free((char *)vc);
				return NULL;
			}
			free(reply) ;
			return vc;
		}
	}
	else
	{
		return NULL;
	}
}

/****************************************************************
 * Function: vns_display_page
 * Date: 03/11/91
 *
 * Description:
 *   This function opens a specific page in the specified notebook.
 *
 * Linkage: int vns_display_page(vc,nid,pid)
 *   VnsConnection *vc - connection pointer (see vns_initialize)
 *   int nid           - notebook id
 *   int pid           - page id
 *
 * Revisions:
 ****************************************************************/
int
vns_display_page(vc,nid,pid)
	VnsConnection *vc;
	int nid;
	int pid;
{
	char *reply = wait_for_reply(vc,True,"display_page %d %d",nid,pid) ;
	if (reply != NULL)
	{
		free(reply) ;
		return 0 ;
	}
	else
	{
		return -1 ;
	}
}

/****************************************************************
 * Function: vns_select_page
 * Date: 04/09/91
 *
 * Description:
 *   This function asks VNS to allow the user to select a page
 *   and return the full path to this page. VNS will activate
 *   the "link-here" icons for all displayed pages allowing
 *   the user to select a page.
 *
 * Linkage: char *vns_select_page(vc)
 *   VnsConnection *vc - connection pointer (see vns_initialize)
 *
 * Revisions:
 ****************************************************************/
char *
vns_select_page(vc)
	VnsConnection *vc;
{
	char *reply = wait_for_reply(vc,False,"select_page") ;

	return reply;
}

/****************************************************************
 * Function: vns_close_page
 * Date: 04/09/91
 *
 * Description:
 *   This function tells VNS to close the specified page.
 *
 * Linkage: int vns_close_page(vc,nid,pid)
 *   VnsConnection *vc - connection pointer (see vns_initialize)
 *   int nid           - notebook id
 *   int pid           - page id
 *
 * Revisions:
 ****************************************************************/
int
vns_close_page(vc,nid,pid)
	VnsConnection *vc;
	int nid;
	int pid;
{
	char *reply = wait_for_reply(vc,True,"close_page %d %d",nid,pid) ;
	if (reply != NULL)
	{
		free(reply) ;
		return 0 ;
	}
	else
	{
		return -1 ;
	}
}

/****************************************************************
 * Function: vns_show_outlines
 * Date: 03/12/91
 *
 * Description:
 *   This function tells VNS to show outlines around objects.
 *
 * Linkage: int vns_show_outlines(vc,state)
 *   VnsConnection *vc - connection pointer (see vns_initialize)
 *   Boolean state     - on or off state
 *
 * Revisions:
 ****************************************************************/
int
vns_show_outlines(vc,state)
	VnsConnection *vc;
	Boolean state;
{
}

/****************************************************************
 * Function: vns_exit
 * Date: 03/12/91
 *
 * Description:
 *   This function free the connection pointer and cleans up
 *   after the clinet.
 *
 * Linkage: int vns_exit(vc)
 *   VnsConnection *vc - connection pointer (see vns_initialize)
 *
 * Revisions:
 ****************************************************************/
int
vns_exit(vc)
	VnsConnection *vc;
{
}
