/*
 * This file is part of the OLH On-Line Help system
 *
 *	Chris VanHaren
 *      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/athena.mit.edu/astaff/project/olhdev/src/motif/RCS/main.c,v $
 *      $Id: main.c,v 1.16 1992/05/01 20:47:46 lwvanels Exp $
 *      $Author: lwvanels $
 */

#include <stdio.h>
#include <varargs.h>

#include <X11/StringDefs.h>
#include <Xm/Xm.h>
#include <Xm/PushB.h>

#include "Xm/Mu.h"
#include "global.h"
#include "widget_num.h"

#include "menu.h"
#include "menupath.h"

Menu *menu[512];
short current[512];
short viewed[512];
Widget menu_btn[512];
short current_menu = 0;
MenuEntry *top_entry;
char *top_pointer;

char *program;
int hist_on;
char *hist_on_text;
char *hist_off_text;

void WaitForExpose();


#ifdef __STDC__
# define        P(s) s
#else
# define P(s) ()
#endif
static void c_e_hook P((char *whoami , long code , char *format ,
			va_list args ));
#ifdef NO_VPRINT
static int vsprintf P((char *str , char *fmt ,
		       va_list ap ));
#endif

static void attach_hook P((char *filsys ));
static void attach_done_hook P((char *filsys , long status ));
static void usage P((void ));

#undef P

extern void add_converter();


/*
 * Command line options table.
 */

OlhResources olh_res;

static XrmOptionDescRec options[] = {
  {"-external",	"*useViewers",	XrmoptionNoArg,	"True"},
  {"-internal",	"*useViewers",	XrmoptionNoArg,	"False"},
  {"-config",   "*configMenu",   XrmoptionSepArg, NULL},
  {"-locker",   "*configLocker",XrmoptionSepArg, NULL},
};

#define Offset(field) (XtOffset(OlhResources *, field))

static XtResource my_resources[] = {
  {"useViewers", XtCBoolean, XtRBoolean, sizeof(Boolean),
     Offset(use_viewers), XtRImmediate, (caddr_t) FALSE},
  {"configMenu", XtCString, XtRString, sizeof(String),
     Offset(config_loc), XtRImmediate, (caddr_t)
       "/mit/logos/lib/config.menu"}, 
  {"configLocker", XtCString, XtRString, sizeof(String),
     Offset(config_locker), XtRImmediate, (caddr_t) "logos"},
};

#undef Offset

static void
usage()
{
  fprintf(stderr, "usage: %s [-options ...] [keyword token]\n\n", program);
  fprintf(stderr, "where options include\n");
  fprintf(stderr,
      "    -display dpy            X server on which to display\n");
  fprintf(stderr,
      "    -geometry geom          size and location of window\n");
  fprintf(stderr,
      "    -external               enable external viewers\n");
  fprintf(stderr,
      "    -internal               disalble external viewers, use internal\n");
  fprintf(stderr, "\n");
  exit(1);
}

/****************************************************************
 * MAIN -- make interface and start XtMainLoop			*
 ****************************************************************/
void
main(argc, argv)
     int argc;
     char **argv;
{
  Arg arg;
  long code;
  Menu *m;
  MenuEntry *e;
  Display *display;
  char *ptr;

/*
 *  Find out what my name is today...  useful for printing in error
 *  messages, etc.
 */

  program = rindex(*argv,'/');
  if(program == (char *) NULL)
    program = *argv;
  if(*program == '/')
    ++program;

/*
 *  First, try opening display.  If this fails, print a 'nice' error
 *  message and exit.
 */

  if ((display = XOpenDisplay(NULL)) == NULL)
    {
      fprintf(stderr, "\n%s:\tUnable to open X display.  Check to make sure that your DISPLAY\n\tenvironment variable is set.  Type:\n\n", program);
      fprintf(stderr, "\t\tprintenv  DISPLAY\n\n\tto see if it is set.\n\n");
      fprintf(stderr, "\tIf it is not, usually the problem can be fixed by setting your\n\tDISPLAY to 'unix:0.0'.   Type:\n\n");
      fprintf(stderr, "\t\tsetenv  DISPLAY  unix:0.0\n\n\tand try running this program again.  Any problems you may have\n");
      fprintf(stderr, "\tbeen having while trying to run X programs may be due to problem.\n");
      fprintf(stderr, "\tTry running them again after setting your DISPLAY variable.  If\n");
      fprintf(stderr, "\tyou are still having problems, you may want to use the text\n\tinterface for OLH instead.  Type:\n\n\t\thelp -tty\n\n");
      exit(-1);
    }
  XCloseDisplay(display);

/*
 *  If opening display was successful, then initialize toolkit, display,
 *  interface, etc.
 */

#ifdef LOG_USAGE
  log_startup("olh_motif");
#endif
  w[TOPLEVEL] = XtInitialize(NULL, "Olh",
			     options, XtNumber(options), &argc, argv);
  add_converter();
  XtGetApplicationResources( w[TOPLEVEL], (caddr_t) &olh_res,
			    my_resources, XtNumber(my_resources), NULL,
			    (Cardinal) 0);
  config_loc = olh_res.config_loc;
  config_locker = olh_res.config_locker;
  MuInitialize(w[TOPLEVEL]);
  display = XtDisplay(w[TOPLEVEL]);

/*
  XtSetArg(arg, XmNallowShellResize, TRUE);
  XtSetValues(w[TOPLEVEL], &arg, 1);
*/
  MakeInterface();

  init_hash_table();
  code = menu_init(NULL);
  if (code) {
    fprintf(stderr,"There was an error loading the initial configuration menu\n");
    fprintf(stderr,"from the file `%s' in the locker `%s'\n",config_loc,
	    config_locker);
#ifdef ATHENA
    fprintf(stderr,"Please call a consultant for help at 3-4435\n");
#endif
    fprintf(stderr,"The error was:\n");
    com_err(program,code,"in menu init","");
    exit(1);
  }
  e = find_group("main");
  code = menu_load(e, &m);
  if (code)
    {
      com_err(program, code, "loading main menu", "");
      exit(1);
    }
  current_menu = 0;
  menu[current_menu] = m;
  top_entry = e;
  top_pointer = field_value(e, POINTER);
  current[current_menu] = 0;
  viewed[current_menu] = FALSE;
  add_to_menupath(e);
  do_menu(m);

  if ((ptr = GetDefault(display, "Olh", "copyright")) != NULL)
    show_message(ptr);

#ifdef HIDDEN
  hist_on_text = GetDefault(display, "Olh", "toggleHistory.on.labelString");
  hist_off_text = GetDefault(display, "Olh", "toggleHistory.off.labelString");
  ptr = GetDefault(display, "Olh", "toggleHistory.value");
  if (ptr == NULL
      || !strncasecmp(ptr, "on", 2)
      || !strncasecmp(ptr, "t", 1)
      || !strncasecmp(ptr, "1", 1))
    {
      hist_on = TRUE;
      if ((W = MuGetWidget("hist_tog")) == NULL)
	fprintf(stderr,
		"%s: Unable to set label on history toggle button\n",
		program);
      else if (hist_off_text != NULL)
	{
	  XtSetArg(arg, XmNlabelString, MOTIF_STRING(hist_off_text));
	  XtSetValues(W, &arg, 1);
	}
      XtManageChild(w[HIST_FORM]);
    }
  else
    {
      hist_on = FALSE;
      if ((W = MuGetWidget("hist_tog")) == NULL)
	fprintf(stderr,
		"%s: Unable to set label on history toggle button\n",
		program);
      else if (hist_on_text != NULL)
	{
	  XtSetArg(arg, XmNlabelString, MOTIF_STRING(hist_on_text));
	  XtSetValues(W, &arg, 1);
	}
      /* No need to unmanage here, since it was not managed at create-time. */
    }
#endif /* HIDDEN */

  XtSetArg(arg, XmNlabelString,
	   MOTIF_STRING(field_value(nth_entry(m, 0), NODE_LABEL)));
  W = menu_btn[current_menu] = XtCreateManagedWidget("temp",
						     xmPushButtonWidgetClass,
						     w[MENU_MENU], &arg, 1);
  XtAddCallback(W, XmNactivateCallback, menu_callback, current_menu);

  XtSetArg(arg, XmNmenuHistory, W);
  XtSetValues(w[MENU_OPT], &arg, 1);

/*
 * Go into XtMainLoop.  This does not exit.  Rather, the user exits the
 *  program by clicking on "quit" or through some other action.
 */

  set_com_err_hook(c_e_hook);
  olh_attach_hook = attach_hook;
  olh_attach_done_hook = attach_done_hook;

  XtRealizeWidget(w[TOPLEVEL]);
  if (argc > 1) {
    do_keyword_startup(argv[1]);
    if (current_menu != 0)
      XtSetSensitive(w[UP_BTN],TRUE);
  }
  XtMainLoop();
}

static void
c_e_hook(whoami, code, format, args)
     char *whoami;
     long code;
     char *format;
     va_list args;
{
  char buffer[BUFSIZ];
  char buffer2[BUFSIZ];

  vsprintf(buffer, format, args);
  sprintf(buffer2, "%s %s", error_message(code), buffer);
  MuWarningSync(buffer2);
}

#ifdef NO_VPRINT
static int
vsprintf(str, fmt, ap)
     char *str;
     char *fmt;
     va_list ap;
{
  FILE f;
  int len;

  f._flag = _IOWRT+_IOSTRG;
  f._ptr = (char *)str;
  f._cnt = 32767;
  len = _doprnt(fmt, ap, &f);
  *f._ptr = 0;
  return (len);
}
#endif

static void
attach_hook(filsys)
     char *filsys;
{
  static char *ptr = NULL;
  char buf[1024];

  if (ptr == NULL)
    {
      if ((ptr = GetDefault(XtDisplay(w[TOPLEVEL]), "Olh", "wait.attach"))
	  == NULL)
	ptr = "Attaching.";
    }

  sprintf(buf, ptr, filsys);
  show_message(buf);
  WaitForExpose(w[MSG_LBL]);
}

static void
attach_done_hook(filsys, status)
     char *filsys;
     long status;
{
  CLEAR_MSG;
  if (status != 0)
    com_err(program, status, "(%s)", filsys);
}

void
WaitForExpose(w)
     Widget w;
{
  XEvent event;
  Display * display = XtDisplay(w);
  Window window = XtWindow(w);

  XWindowEvent(display, window, ExposureMask, &event); /* wait for expose... */

  XtDispatchEvent(&event);	/* process it */

  XSync(display,0);		/* flush out any requests made during */
  				/* XtDispatchEvent() */
}
