/*
 * 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: /mit/olhdev/src/motif/RCS/keywords.c,v $
 *      $Id: keywords.c,v 1.15 1992/08/12 11:02:09 lwvanels Exp $
 *      $Author: lwvanels $
 */

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

#include "global.h"
#include "widget_num.h"
#include "Cursor.h"
#include "menu.h"
#include "menupath.h"

extern int suppress_kwd_draw;

Menu *k_menu[10];
short k_current[10];
Widget k_menu_btn[10];
short k_current_menu = 0;

void
do_keyword_startup(kw)
     char *kw;
{
  char old_mp[1024], *ptr;
  long code;
  int len,i;
  short k_num_entries;
  Menu *m;
  MenuEntry *e;

  if (*kw == PATH_SEP_CHAR) {
    /* Absolute path */
    strcpy(old_mp,menupath);
    code = menupath_from_string(kw);
    if (code != 0) {
      strcpy(menupath,old_mp);
      com_err(program,code,"while parsing keyword");
    }
    else {
      ConstructContext(menupath);
    }
  }
  else {
    e = find_group("keywords");
    code = menu_load(e, &m);
    if (code)
      {
	com_err(program, code, "loading keyword menu", "");
	return;
      }
    k_current_menu = 0;
    k_menu[k_current_menu] = m;
    k_current[k_current_menu] = 0;

    len = strlen(kw);
    k_num_entries = size_menu(k_menu[k_current_menu]) -1;
    for (i=0; i<k_num_entries;i++) {
      e = nth_entry(k_menu[k_current_menu], i+1);
      if (!strncasecmp(field_value(e, NODE_LABEL), kw, len)) {
	k_current[k_current_menu] = i+1;
	break;
      }
    }
    if (k_current[k_current_menu]) {
      suppress_kwd_draw = 1;
      k_invoke(k_current[k_current_menu]);
    }
    else {
      if ((ptr = GetDefault(XtDisplay(w[TOPLEVEL]),
			    "Olh", "message.noKeywordMatch"))
	  == NULL)
	ptr = "No match.";
      sprintf(old_mp, ptr, kw);
      show_message(old_mp);
    }
  }
}

void
setup_keyword_dialog()
{
  Menu *m;
  MenuEntry *e;
  long code;
  static int kw_d_setup = 0;

  if (kw_d_setup == 0)
    {
      kw_d_setup = 1;
      WAIT_CURSOR;
      e = find_group("keywords");
      code = menu_load(e, &m);
      if (code)
	{
	  com_err(program, code, "loading keyword menu", "");
	  return;
	}
      k_current_menu = 0;
      k_menu[k_current_menu] = m;
      k_current[k_current_menu] = 0;
      XtSetSensitive(w[KWD_SEND_BTN],FALSE);
  
      k_do_menu(m);
      STANDARD_CURSOR;
    }
  CLEAR_MSG;
}

void
k_menu_callback(widget, tag, callback_data)
     Widget widget;
     int tag;
     XmAnyCallbackStruct *callback_data;
{
  if (k_current_menu != tag)
    {
      WAIT_CURSOR;

      k_current_menu = tag;
      k_do_menu(k_menu[k_current_menu]);
      STANDARD_CURSOR;
    }
}

void
k_do_menu(m)
     Menu *m;
{
  XmString entries[255];
  int i;
  Arg args[2];
  short k_num_entries;
  char buf[1024];
  MenuEntry *e;
  char *kwd_fld;

  if (k_current_menu == 0)
    XtSetSensitive(w[KWD_UP_BTN],FALSE);
  else
    XtSetSensitive(w[KWD_UP_BTN],TRUE);

  k_num_entries = size_menu(m) - 1;
  for (i = 0; i < k_num_entries; i++)
    {
      e = nth_entry(m, i+1);
      kwd_fld = field_value(e,IN_KEYWORDS);
      sprintf(buf, "%s  %s",
	      ((kwd_fld[0] == 'y') || (kwd_fld[0] == 'Y')) ? "*" : "  ",
	      field_value(e, NODE_LABEL));
      entries[i] = MOTIF_STRING(buf);
    }

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

  if(k_current[k_current_menu])
    {
      if (k_current[k_current_menu] >
	  XmListGetBottomPos((XmListWidget)w[KWD_LIST]))
	XmListSetBottomPos(w[KWD_LIST], k_current[k_current_menu]);
      XmListSelectPos(w[KWD_LIST], k_current[k_current_menu], FALSE);
    }
  else {
    XtSetSensitive(w[KWD_SEND_BTN],FALSE);
    XmListDeselectAllItems(w[KWD_LIST]);
  }
}


void
k_up_menu()
{
  if (k_current_menu == 0)
    return;

  WAIT_CURSOR;

  /* XmTextString calls the valueChanged callback, which destroys */
  /* k_current[k_current_menu].  So, we make sure we call it before */
  /* decrementing k_current_menu. */
  XmTextSetString(w[KWD_TEXT], "");

  k_current_menu--;
  if (k_current[k_current_menu] == 0)
    XtSetSensitive(w[KWD_SEND_BTN],FALSE);
  else
    XtSetSensitive(w[KWD_SEND_BTN],TRUE);
  k_do_menu(k_menu[k_current_menu]);
  STANDARD_CURSOR;
}



void
k_view_selected()
{
  char *ptr;

  if (k_current[k_current_menu])
    {
      /* XmTextSetString calls the valueChanged callback, which destroys */
      /* k_current[k_current_menu].  So, we cheat a bit... */
      k_current_menu++;
      XmTextSetString(w[KWD_TEXT], "");
      k_current_menu--;
      XmListSelectPos(w[KWD_LIST], k_current[k_current_menu], FALSE);

      k_invoke(k_current[k_current_menu]);
    }
  else
    {
      if ((ptr = GetDefault(XtDisplay(w[TOPLEVEL]),
			    "Olh", "message.noKeywordSelected"))
	  == NULL)
	ptr = "No keyword selected.";
      show_k_message(ptr);
    }
}


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

void
k_invoke(i)
     int i;
{
  Menu *m;
  MenuEntry *e, *e2;
  long code;
  char *ptr;
  char *foo;

  WAIT_CURSOR;

  e = nth_entry(k_menu[k_current_menu], i);

  if (is_menu(e))
    if (!strncasecmp(field_value(e, IN_KEYWORDS), "y", 1))
      {
	if (w[KWD_DLG] == NULL) {
	  MakeDialog(KWD_DLG);
	  XtMapWidget(w[KWD_DLG]);
	}
	code = menu_load(e, &m);
	if (code)
	  {
	    com_err(program, code, "loading %s",
		    field_value(e, FILE_LOCATION));
	    STANDARD_CURSOR;
	    return;
	  }
	k_current_menu++;
	k_menu[k_current_menu] = m;
	k_current[k_current_menu] = 0;
	XtSetSensitive(w[KWD_SEND_BTN],FALSE);

	k_do_menu(m);
      }
    else
      {
	ptr = field_value(e, POINTER);
	code = pointerEntry(ptr, &e2);
	if (code || (!e2))
	  {
	    com_err(program, code, "locating module, continuing.", "");
	    make_parents_menupath(e);
	  }
	else
	  {
	    make_parents_menupath(e2);
	    /** HACK! e2 won't have a pointer entry, so we just muck **/
	    /** with menupath directly... **/
	    resize_menupath(strlen(menupath) + strlen(ptr));
	    strcat(menupath, ptr);
	  }
	if (ConstructContext(menupath) != 0) {
	  STANDARD_CURSOR;
	  return;
	}
	if (w[KWD_DLG] != NULL) {
	  ptr = GetDefault(XtDisplay(w[TOPLEVEL]), "Olh",
			   "keywordDialog.autoPopdown");
	  if (ptr == NULL
	      || !strncasecmp(ptr, "on", 2)
	      || !strncasecmp(ptr, "t", 1)
	      || !strncasecmp(ptr, "1", 1))
	    XtUnmapWidget(w[KWD_DLG]);
	}
      }
  else
    if (is_doc(e))
      {
	make_parents_menupath(e);
	if (ConstructContext(menupath) != 0) {
	  STANDARD_CURSOR;
	  return;
	}
	foo = field_value(e, NODE_LABEL);
	XmListAddItemUnselected(w[HIST_LIST],
				MOTIF_STRING(foo),
				0);
	XmListSetBottomPos(w[HIST_LIST], 0);
	if (is_plain_text(e))
	  {
	    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\"",
			field_value(e,NODE_LABEL));
	    }
	    else {
	      /* convert to text and use internal viewer */
#ifdef LOG_USAGE
	      log_view(field_value(e,FILE_LOCATION));
#endif
	      viewTextFile(e,field_value(e,NODE_LABEL));
	    }
	  }
	ptr = GetDefault(XtDisplay(w[TOPLEVEL]), "Olh",
			 "keywordDialog.autoPopdown");
	if (ptr == NULL
	    || !strncasecmp(ptr, "on", 2)
	    || !strncasecmp(ptr, "t", 1)
	    || !strncasecmp(ptr, "1", 1))
	  XtUnmapWidget(w[KWD_DLG]);
      }

  STANDARD_CURSOR;
}


void k_entered(widget, tag, callback_data)
     Widget widget;
     int tag;
     XmAnyCallbackStruct *callback_data;
{
  char *text;
  char old_mp[1024];
  long code;

  text = XmTextGetString(widget);
  if (text[0] == PATH_SEP_CHAR)
    {
      strcpy(old_mp,menupath);
      code = menupath_from_string(text);
      if (code != 0) {
	XtFree(text);
	strcpy(menupath,old_mp);
	return;
      }
      XtFree(text);
      /*  Even though XmTextSetString calls the valueChanged callback, */
      /*  which destroys k_current[k_current_menu], that's OK in this */
      /*  case because it's zero anyway. */
      XmTextSetString(widget, "");

      if (ConstructContext(menupath) != 0) {
	return;
      }
      text = GetDefault(XtDisplay(w[TOPLEVEL]), "Olh",
			"keywordDialog.autoPopdown");
      if (text == NULL
	    || !strncasecmp(text, "on", 2)
	    || !strncasecmp(text, "t", 1)
	    || !strncasecmp(text, "1", 1))
	XtUnmapWidget(w[KWD_DLG]);
      return;
    }
    
  if (k_current[k_current_menu])
    {
      XtFree(text);

      /* XmTextSetString calls the valueChanged callback, which destroys */
      /* k_current[k_current_menu].  So, we cheat a bit... */
      k_current_menu++;
      XmTextSetString(widget, "");
      k_current_menu--;
      XmListSelectPos(w[KWD_LIST], k_current[k_current_menu], FALSE);

      k_invoke(k_current[k_current_menu]);
    }
}


void k_changed(widget, tag, callback_data)
     Widget widget;
     int tag;
     XmAnyCallbackStruct *callback_data;
{
  char *text, *ptr;
  int len;
  int i;
  short k_num_entries;
  MenuEntry *e;
  char buf[1024];
  int not_empty = TRUE;
  int old;

  text = XmTextGetString(widget);
  old = k_current[k_current_menu];
  k_current[k_current_menu] = 0;

  if (text[0] == PATH_SEP_CHAR  ||  !text[0])
    not_empty = FALSE;

  if (not_empty)
    {
      len = strlen(text);

      k_num_entries = size_menu(k_menu[k_current_menu]) - 1;
      for (i = 0; i < k_num_entries; i++)
	{
	  e = nth_entry(k_menu[k_current_menu], i+1);
	  if (!strncasecmp(field_value(e, NODE_LABEL), text, len))
	    {
	      if (old == 0)
		XtSetSensitive(w[KWD_SEND_BTN],TRUE);
	      k_current[k_current_menu] = i+1;
	      break;
	    }
	}
    }

  if (k_current[k_current_menu])
    {
      XmListSetPos(w[KWD_LIST], k_current[k_current_menu]);
      XmListSelectPos(w[KWD_LIST], k_current[k_current_menu], FALSE);
      CLEAR_MSG;
    }
  else
    {
      XmListDeselectAllItems(w[KWD_LIST]);
      if (not_empty)
	{
	  if ((ptr = GetDefault(XtDisplay(w[TOPLEVEL]),
				"Olh", "message.noKeywordMatch"))
	      == NULL)
	    ptr = "No match.";
	  sprintf(buf, ptr, text);
	  show_k_message(buf);
	}
    }

  XtFree(text);
}
