/*
 * This file is part of the OLH On-Line Help system
 *
 *	Chris VanHaren
 *	Lucien Van Elsen
 *      MIT Project Athena
 *
 * Copyright (C) 1990 by the Massachusetts Institute of Technology.
 * For copying and distribution information, see the file "mit-copyright.h".
 *
 *      $Source: /afs/sipb.mit.edu/project/sipb-athena/repository/src/olh/motif/invoke.c,v $
 *      $Id: invoke.c,v 1.1 1992/05/01 17:09:31 lwvanels Exp $
 *      $Author: lwvanels $
 */

#include <sys/errno.h>
#include <sys/file.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <Xm/PushB.h>
#include <Xm/Text.h>
#include <Xm/Mu.h>

#include "global.h"
#include "widget_num.h"
#include "Cursor.h"
#include "menu_et.h"

#ifdef NEEDS_ERRNO_DEFS
extern int errno;
extern int sys_nerr;
extern char *sys_errlist[];
#endif

static short num_entries;

#define is_plain_text(e) (!strcmp("plain_text", field_value((e), FILE_FORMAT))\
			  || !strcmp("", field_value((e), FILE_FORMAT)))

void
view(num)
     int num;
{
  static int go_up = FALSE;
  static int select_first = FALSE;
  char *ptr;

  if (!current[current_menu])
    {
      if (num == 1)
	current[current_menu] = 1;
      else if (num == -1)
	current[current_menu] = num_entries;
      else if (num == 0)
	{
	  if (select_first)
	    {
	      select_first = FALSE;
	      current[current_menu] = 1;
	    }
	  else
	    {
	      select_first = TRUE;
	      if ((ptr = GetDefault(XtDisplay(w[TOPLEVEL]),
				    "Olh", "message.noneSelected"))
		  == NULL)
		ptr = "None selected";
	      show_message(ptr);
	      return;
	    }
	}
    }

  if (viewed[current_menu])
    {
      if ((num == 1) || (num == -1))
	{
	  current[current_menu] += num;
	  if ((current[current_menu] > num_entries) ||
	      (current[current_menu] < 1))
	    {
	      if (go_up)
		{
		  go_up = FALSE;
		  up_menu();
		  return;
		}
	      if (current[current_menu] > num_entries)
		{
		  if (current_menu == 0)
		    {
		      if ((ptr = GetDefault(XtDisplay(w[TOPLEVEL]),
					    "Olh", "message.topAndNoMore"))
			  == NULL)
			ptr = "Top and no more.";
		      show_message(ptr);
		    }
		  else
		    {
		      go_up = TRUE;
		      if ((ptr = GetDefault(XtDisplay(w[TOPLEVEL]),
					    "Olh", "message.noMore"))
			  == NULL)
			ptr = "No more.";
		      show_message(ptr);
		    }
		  current[current_menu] = num_entries;
		}
	      if (current[current_menu] < 1)
		{
		  if (current_menu == 0)
		    {
		      if ((ptr = GetDefault(XtDisplay(w[TOPLEVEL]),
					    "Olh", "message.topAndNoPrev"))
			  == NULL)
			ptr = "Top and no prev.";
		      show_message(ptr);
		    }
		  else
		    {
		      go_up = TRUE;
		      if ((ptr = GetDefault(XtDisplay(w[TOPLEVEL]),
					    "Olh", "message.noPrev"))
			  == NULL)
			ptr = "No prev.";
		      show_message(ptr);
		    }
		  current[current_menu] = 1;
		}
	      return;
	    }
	  if (current[current_menu] >
	      XmListGetBottomPos((XmListWidget)w[MENU_LIST]))
	    XmListSetBottomPos(w[MENU_LIST], current[current_menu]);
	  else if (current[current_menu] <
		   XmListGetTopPos((XmListWidget)w[MENU_LIST]))
	    XmListSetPos(w[MENU_LIST], current[current_menu]);
	}
    }

  XmListSelectPos(w[MENU_LIST], current[current_menu], FALSE);
  viewed[current_menu] = TRUE;
  go_up = FALSE;
  invoke(current[current_menu]);
}

void
invoke(i)
     int i;
{
  Menu *m;
  MenuEntry *e;
  Arg arg;
  long code;
  char *ptr;
  char *foo;

  CLEAR_MSG;
  WAIT_CURSOR;

  e = nth_entry(menu[current_menu], i);

  if (is_doc(e))
    {
      foo = field_value(e,NODE_LABEL);
#ifdef HIDDEN
      XmListAddItemUnselected(w[HIST_LIST],
			      MOTIF_STRING(foo),
			      0);
      XmListSetBottomPos(w[HIST_LIST], 0);
#endif
      if (is_plain_text(e))
	{
#ifdef LOG_USAGE
	  log_view(field_value(e,FILE_LOCATION));
#endif
	  viewFile(doc_string(e), foo);
	}
      else
	{
	  if (olh_res.use_viewers) {
	    /* Start up external viewer */
	    if ((ptr = GetDefault(XtDisplay(w[TOPLEVEL]),
				  "Olh", "wait.viewer")) != NULL)
	      show_message(ptr);
	    code = viewdoc(e, X, NULL);
	    if (code)
	      com_err(program,code,"Viewing \"%s\"",foo);
	  }
	  else {
	    /* convert to text and use internal viewer */
	    viewTextFile(e, foo);
	    CLEAR_MSG;
	  }
	}
    }

  if (is_menu(e))
    {
      code = menu_load(e, &m);
      if (code)
	{
	  com_err(program, code, "loading %s", field_value(e, FILE_LOCATION));
	}
      else
	{
	  add_to_menupath(e);
#ifdef DEBUG
	  fprintf(stderr, "DEBUG (invoke):\nmenupath=%s\n", menupath);
#endif
	  XtSetSensitive(w[UP_BTN],TRUE);
	  current_menu++;
	  menu[current_menu] = m;
	  current[current_menu] = 0;
	  viewed[current_menu] = FALSE;

	  XtSetArg(arg, XmNlabelString,
		   MOTIF_STRING(field_value(nth_entry(m, 0), NODE_LABEL)));
	  if (menu_btn[current_menu] == (Widget) NULL)
	    {
	      W = menu_btn[current_menu] = XtCreateManagedWidget("temp",
						     xmPushButtonWidgetClass,
						     w[MENU_MENU], &arg, 1);
	      XtAddCallback(W, XmNactivateCallback, menu_callback,
			    current_menu);
	    }
	  else
	    {
	      XtSetValues(menu_btn[current_menu], &arg, 1);
	      XtManageChild(menu_btn[current_menu]);
	    }

	  XtSetArg(arg, XmNmenuHistory, menu_btn[current_menu]);
	  XtUnmanageChild(w[MENU_OPT]);
	  XtSetValues(w[MENU_OPT], &arg, 1);
	  XtManageChild(w[MENU_OPT]);
	  do_menu(m);
	}
    }

  STANDARD_CURSOR;
}

void
viewFile(text, name)
     char *text;
     char *name;
{
  Arg arg;
  static char *stored = "";

  if (strcmp(name, stored))
    {
      XtSetArg(arg, XmNlabelString, MOTIF_STRING(name));
      XtSetValues(w[TEXT_LBL], &arg, 1);
      stored = name;
    }
  XmTextSetString(w[TEXT_TEXT], text);
  XtMapWidget(w[TEXT_DLG]);

  free(text);
  return;
}

void
viewTextFile(e,name)
     MenuEntry *e;
     char *name;
{
  char *buf;
  struct stat statb;
  int fd;
  char filename[MAXPATHLEN];
  char prefix[MAXPATHLEN];
  long code;

  strcpy(filename,"/tmp/olh_viewXXXXXX");
  mktemp(filename);
  strcpy(prefix,"ofile=");
  strcat(prefix,filename);

  code = viewdoc(e, ASCII_FILE, prefix);
  if (code == ERR_MENU_NOVIEWER) {
    if ((buf = GetDefault(XtDisplay(w[TOPLEVEL]), "Olh",
			  "warning.noconvert")) == NULL)
      buf = "Cannot convert to ascii; use an external viewer";
    MuErrorSync(buf);
    return;
  }
  if (code) {
    com_err(program,code,"viewing \"%s\"", field_value(e, FILE_LOCATION));
    return;
  }

  if ((fd = open(filename,O_RDONLY,0)) < 0) {
    com_err(program,errno,"Error opening file \"%s\"", filename);
    return;
  }
  if (fstat(fd,&statb) < 0) {
    com_err(program,errno,"Error stat'ing file \"%s\"", filename);
    return;
  }
  if ((buf = (char *)malloc(statb.st_size)) == NULL) {
    com_err(program,errno,"Error- could not allocate %d bytes of memory",
	    statb.st_size);
    return;
  }
  if (read(fd, buf, statb.st_size) < 0) {
    com_err(program,errno,"Error reading %s", filename);
    free(buf);
    return;
  }
  buf[statb.st_size] = '\0';
  close(fd);
  unlink(filename);
  viewFile(buf,name);
  return;
}

void
do_menu(m)
     Menu *m;
{
  XmString entries[255];
  int i;
  Arg args[2];
  char buf[1024];
  MenuEntry *e;
  char *ptr;

  CLEAR_MSG;
  num_entries = size_menu(m) - 1;
  if (num_entries == 0)
    {
      if ((ptr = GetDefault(XtDisplay(w[TOPLEVEL]),
			    "Olh", "warning.emptyMenu"))
	  == NULL)
	ptr = "Empty menu.";
      up_menu();
      show_message(ptr);
      return;
    }

  for (i = 0; i < num_entries; i++)
    {
      e = nth_entry(m, i+1);
      sprintf(buf, "%4d%s  %s", i+1,
	      is_menu(e) ? "*" : "  ",
	      field_value(e, NODE_LABEL));
      entries[i] = MOTIF_STRING(buf);
    }

  XtSetArg(args[0], XmNitemCount, num_entries);
  XtSetArg(args[1], XmNitems, entries);
  XtSetValues(w[MENU_LIST], args, 2);

  if(current[current_menu])
    {
      if (current[current_menu] >
	  XmListGetBottomPos((XmListWidget)w[MENU_LIST]))
	XmListSetBottomPos(w[MENU_LIST], current[current_menu]);
      XmListSelectPos(w[MENU_LIST], current[current_menu], FALSE);
      XmSetHighlight((XmListWidget)w[MENU_LIST], current[current_menu] - 1);
    }
  else
    {
      XmListDeselectAllItems(w[MENU_LIST]);
      XmListSetPos(w[MENU_LIST], 1);
    }

#ifdef HIDDEN
  XmListAddItemUnselected(w[HIST_LIST],
			  MOTIF_STRING(field_value(nth_entry(m, 0),
						  NODE_LABEL)),
			  0);
  XmListSetBottomPos(w[HIST_LIST], 0);
#endif
}
