/* HHELP Invokes the Microsoft HtmlHelp viewer.
 * 
 * HHELP(HELPFILE) displays HELPFILE in an HtmlHelp
 * Viewer window. HELPFILE is a path that specified
 * either an html file (.html) or a compressed
 * html (.chm) file. Input focus returns to the desktop
 * when a user closes the help window.
 *
 * HHELP(CHMFILE, HELPFILE) displays a file contained
 * in a compressed help file. CHMFILE specifies the path
 * to the compressed help file. HELPFILE is the name
 * of the file to be displayed.
 *
 * HHELP(CHMFILE, HELPFILE, WINTYPE) displays the help file
 * in the window of the specified type. The window type
 * must be defined in CHMFILE.
 *
 * Copyright (c) 1984-98 by The MathWorks, Inc.
 * $Revision: 1.6 $
 */
#include "mex.h"
#include <math.h>
#include <windows.h>
#include <htmlhelp.h>


/*
 * Define a window for displaying HTML files that are not
 * part of a compressed collection.
 */

/* Structure that defines a plain help window,
   i.e., a window with only a content pane and
   no buttons. */


#define NOT_DEFINED ((HWND)(-1))

/* Create a plain window. */
static void PlainWindow_create() {

  static HH_WINTYPE PlainWindow;
  static initialized = false;
  HWND handle;

  if (initialized==false) {
	PlainWindow.cbStruct = sizeof(HH_WINTYPE);
	PlainWindow.fUniCodeStrings = FALSE;
	PlainWindow.pszType = "plain";
	PlainWindow.fsValidMembers = HHWIN_PARAM_SHOWSTATE;
	PlainWindow.fsWinProperties = 0;
	PlainWindow.pszCaption = "MATLAB Help";
	PlainWindow.dwStyles = 0;
	PlainWindow.nShowState = SW_SHOW;
	PlainWindow.paInfoTypes = NULL;
	initialized = true;
  }

/* PK: 12/30/98 WISH: Could not get the following working. Need to check for resourse leaks!
  handle = HtmlHelp(0, 0, HH_GET_WIN_TYPE, (DWORD) &PlainWindow);
  if (handle==NOT_DEFINED) {
*/
	handle = HtmlHelp(NULL, NULL, HH_SET_WIN_TYPE, (DWORD) &PlainWindow);

/*
	if (handle!=NULL) mexErrMsgTxt("Invalid Help Window Creation");
  }
*/

  
}


/* hhelp mex file initialization flag. 
   Should be set to a non-zero value 
   once hhelp has been initialized. */
static int initialized = 0;


/* Function called when the hhelp mex file
   is unloaded. */
static void exitmex(void) {
  
  /* Close all open help windows. */
  HtmlHelp( NULL, NULL, HH_CLOSE_ALL, 0) ;

}

/* Initialization function called the first time
   hhelp is invoked. */
static int initmex() {

  /* Register exit function. */
  mexAtExit(exitmex);

  /* Prevent hhelp from being cleared by clear all. Otherwise
     clear all would cause any open help windows to be closed
	 prematurely. */
  mexLock();

  return 1;
}


/*
 * Helper function that invokes the HTML help viewer.
 *
 * Arguments:
 *
 * owner   - Handle of the window that currently has the
 *           input focus, for example, the MATLAB command
 *           window. HTML Help assigns ownership of
 *           the viewer window to the focus window. This
 *           means that the viewer window is always on top
 *           of the focus window. If null, the viewer is
 *           unowned and thus can be manipulate by the user
 *           independent of the application window.
 *
 * coll    - Path of the HTML collection (.chm) file
 *           or html file to be displayed.
 *
 * topic   - Name of the topic (html) file within the .chm 
 *           to be displayed.
 *
 * Usage:

 * To display an uncompressed HTML file, pass the file's
 * path in the second argument and 0 in the third, e.g.,
 *
 *   htmlhelp(0, "d:\v5\help\topic.html", 0);
 *
 * To display a compressed collection, pass the path of
 * the collection in the second argument and 0 in the
 * third, e.g.,
 * 
 *   htmlhelp(0, "d:\v5\help\ml_graph.chm", 0);
 *
 * To display a topic within a compressed collection, pass
 * the path to the collection in the second argument and
 * the name of the topic file in the third, e.g.,
 *
 *   htmlhelp(0, "d:\v5\help\ml_graph.chm", "axes.html");      
 */
void htmlhelp(HWND owner, LPCSTR coll, LPCSTR topic) {
  if (!HtmlHelp(owner, coll, HH_DISPLAY_TOPIC, (DWORD) topic))
	mexErrMsgTxt("Could not open HTML Help window.\nSee \"Known Software and Documentation Problems\"\non the MATLAB Help Desk for more information.");
}

/*
 * Extracts a string argument from an mxArray.
 */
char* getStrArg(int nlhs,
		mxArray *plhs[],
		int nrhs,
		const mxArray *prhs[],
		int argn) {
  char* str;
  unsigned int strlen;
  int status;

  /* Get length of argument */
  strlen = (mxGetM(prhs[argn]) * mxGetN(prhs[argn])) + 1;

  /* Allocate buffer */
  str = mxCalloc(strlen, sizeof(char));

  /* Copy string. */
  status = mxGetString(prhs[argn], str, strlen);

  if (status == 0) {
    /*    mexPrintf("  Displaying %s.\n", file); */
  }
  else {
    mexPrintf("Argument number: %d.\n", argn);
    mexErrMsgTxt("Invalid string argument.");
  }

  return str;
}


/*
 * Implementation of hhelp function
 */
void mexFunction(int nlhs,
		 mxArray *plhs[],
		 int nrhs,
		 const mxArray *prhs[]) {

  char* file    = NULL;
  char* filewin = NULL;
  char* subfile = NULL;
  char* wintype = NULL;

  /* Initialize self, if not already initialized. */
  if (!initialized)
	  initialized = initmex();

  /*  Check for proper number of arguments. */
  if (nrhs < 1 || nrhs > 3) 
    mexErrMsgTxt("Two or three input arguments required.");


  file = getStrArg(nlhs, plhs, nrhs, prhs, 0);

  /* 
   *  Check to see if a topic file within a collection
   *  is specified.
   */
  if (nrhs > 1) {
    subfile = getStrArg(nlhs, plhs, nrhs, prhs, 1);
    if (strlen(subfile) == 0) {
	  mxFree(subfile);
      subfile = NULL;
	}
  }

  /*
   * Get windows type argument if present.
   */
  if (nrhs > 2) {
    wintype = getStrArg(nlhs, plhs, nrhs, prhs, 2);
  

    /*
     * HTML Help requires that you append the window type to the
     * path of the compressed collection, e.g.,
     *
     *   d:\v5\help\ml_graph.chm>cs_help
     */
    filewin = mxCalloc(strlen(file) + strlen(wintype) + 2, sizeof(char));
    strcpy(filewin, file);

    if (strlen(wintype) > 0) {
      strcat(filewin, ">");
      strcat(filewin, wintype);


      /* Recent versions of HTMLHelp seem to destroy, rather than hide,
	     a help window closed by the user. Thus, it's necessary to
		 recreate the window each time. */	     
	  if (!strcmp(wintype, "plain"))
	    PlainWindow_create();
    }
  }

  htmlhelp(NULL, filewin, subfile);

  mxFree(file);
  mxFree(subfile);
  mxFree(wintype);
  mxFree(filewin);

}

/* End of file. */
