/* X-Designer
** (c) 1992, 1993, 1994, 1995
** Imperial Software Technology (IST),
** 95 London Street,
** Reading,
** Berkshire,
** United Kingdom RG1 4QA.
**
** Telephone: +44 1734 587055
** Fax:       +44 1734 589005
** Email:     support@ist.co.uk
*/
 
#if !defined(lint) && !defined(NOSCCS)
static char *sccsid = "@(#)helplink.c     1.12" ; /* 96/04/24 */
#endif /* lint && NOSCCS */
 
/* 
** File:       helplink.c
** Purpose:    Provision of WorkShop Visual Help-based online help for 
**             visu-generated applications
** Created by: Giles P.J. Thomas (giles@ist.co.uk)
** Date:       3rd February 1996
*/

#include <stdio.h>
#include <X11/Intrinsic.h>

/********** Structures used by this code: **********/

typedef struct _XDHelpDoc_s {

    char  *doc ;         /* The document name */

    char **path ;        /* The default path, if one exists */

    int    handle ;      /* UNUSED - FrameMaker help uses this */

    Bool   new_window ;  /* Flag to tell us if we need a new window */

} _XDHelpDoc_t, *_XDHelpDoc_p;

typedef struct _XDHelpPair_s {

    _XDHelpDoc_p   doc ;          /* The document to load */

    char         **tag ;          /* The tag within it to go to */

    Bool           open_doc ;     /* Should we be going to the start of the
				    document (True) or the tag with name
				    <widget name> (False)? */

} _XDHelpPair_t, *_XDHelpPair_p;


/********** Utility functions **********/


/*
** Function to build a tag from the given tag, the widget, and the 
** open_doc value. Result does not need to be freed.
*/
static char *
FullTag( oldTag, open_doc, w )
    char **oldTag ;
    Bool   open_doc ;
    Widget w ;
{
    if ( oldTag != NULL )
	return *oldTag ;

    if ( open_doc )
	return "" ;

    return XtName( w ) ;
}


/*
** Function to build a full pathname from the default path and a
** document filename.  Caller must free result.
*/
static char *
FullFilename( file, path )
    char *file ;
    char *path ;
{
    char *filename ;

    /* if the filename's relative or there's no default path anyway, we
       just return the filename */
    if ( file[0] == '/' || path == NULL )
	return strdup( file ) ;

    /* Otherwise we concatenate the two and return the result */
    filename = (char *) XtMalloc( strlen( path ) + strlen( file ) + 2 ) ;
    sprintf( filename, "%s/%s", path, file ) ;

}


/*
** Function to build a URL from a filename and a tag
*/
static char *
FullURL( filename, tag )
    char *filename ;
    char *tag ;
{
    char *url = (char *) XtMalloc( strlen( filename ) + strlen( tag ) + 10 ) ;

    sprintf( url, "%s#%s", filename, tag ) ;

    return url ;
}


/********** The help link function itself **********/

void
XDhelp_link( w, client_data, call_data )
    Widget    w ;
    XtPointer client_data ;
    XtPointer call_data ;
{
    _XDHelpPair_p  helpPair = (_XDHelpPair_p) client_data ;
    char          *tag,
	          *filename,
	          *url ;

    Widget         thisOne = w ;
    Widget         IPCwidget ;
    
    if ( helpPair == NULL ) {
	fputs( "Error in help link; NULL help pair.\n", stderr ) ;
	return ;
    }

    if ( helpPair->doc == NULL ) {
	fputs( "Error in help link; NULL help document\n", stderr ) ;
	return ;
    }

    /* We use a widget for IPC with WorkShop Visual Help.  This must be the 
       same widget for every call, as the protocol would leave us with
       one WorkShop Visual Help for each widget we used.  So, we walk up the 
       hierarchy until we find the application shell and we use that.
       This has the down side that we will be waiting for property changes
       on our application shell, which happens fairly regularly due to
       window manager interactions, but it has the useful feature that
       we do not need to remeber (and avoid destroying) a particular widget
       simply because we're using it for IPC - if the application shell
       has been destroyed, we will be very unlikely to be calling help
       systems... */
    while ( thisOne != NULL ) {
	IPCwidget = thisOne ;
	thisOne = XtParent( thisOne ) ;
    }

    /* If we can't find a widget to use for communication, we might as
       well give up... */
    if ( IPCwidget == NULL ) {
	fputs( "Cannot find widget to use for WorkShop Visual Help IPC\n", stderr ) ;
	return ;
    }

    tag = FullTag( helpPair->tag, helpPair->open_doc,  w ) ;
    filename = FullFilename( helpPair->doc->doc, *helpPair->doc->path ) ;
    url = FullURL( filename, tag ) ;

    XDHelp( IPCwidget, url ) ;

    free( filename ) ;
    free( url ) ;
}
