/*
 * main program
 */

#include <stdio.h>
#include <string.h>
#include <syscall.h>
#include <com_err.h>
#include <X11/cursorfont.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <discuss/discuss.h>
#include <signal.h>
#include "Meeting.h"
#include "stuff.h"

#define APP_NAME  "xdiscuss"
#define APP_CLASS "Discuss"

extern const char *getenv (const char *);

static int argc;
int screen;
static const char **argv;

static char const rcsid[] =
    "$Header: /afs/sipb.mit.edu/project/discuss/.cvsroot/discuss/source/xdsc/main.c,v 1.6 1992/06/26 02:25:49 raeburn Exp $";

const char *whoami;
struct _XtAppStruct * app_context;
struct _XDisplay * dpy;
Widget toplevel, big_w, cmd_box;
int vert_bbox, n_mtgs, do_sort, one_win;
struct button_info *meeting_list;

static const XrmOptionDescRec options[] = {
    { "-box",	"*mode",	XrmoptionNoArg,	"box"		},
    { "-list",	"*mode",	XrmoptionNoArg,	"list"		},
    { "-immediate", "*mode",	XrmoptionNoArg,	"immediate"	},
    { "-sort",	"*sort",	XrmoptionNoArg, "true"		},
    { "-single_window", "*oneWindow", XrmoptionNoArg, "true"	},
    { "-1",	"*oneWindow",	XrmoptionNoArg, "true"	},
};

typedef struct {
    String mode;
    Boolean sort;
    Boolean one_win;
} defaults;

static defaults defs;
int one_win;

/* cannot be `const' */
static XtResource app_resources[] = {
    { "mode", "Mode",
	  XtRString, sizeof (String), XtOffset (defaults *, mode),
	  XtRString, "list", },
    { "sort", "Sort",
	  XtRBoolean, sizeof (Boolean), XtOffset (defaults *, sort),
	  XtRString, "false", },
    { "oneWindow", "OneWindow",
	  XtRBoolean, sizeof (Boolean), XtOffset (defaults *, one_win),
	  XtRString, "false" },
};

extern void schedule_window_destruction_cb ();

int main(int ac, const char **av) {
    int code;
    argc = ac;
    argv = av;
    whoami = argv[0];
    {
	register char *cp;
	cp = strrchr (whoami, '/');
	if (cp)
	    whoami = cp+1;
    }
    initialize_dsc_error_table ();
    code = find_rc_filename();
    (void) endservent ();
    if (code) {
	com_err(whoami, code, " can't locate .meetings file");
	return 1;
    }
    {
	/* Kludge Alert!!! */
	const char *path = getenv ("PATH");
	int len = (path ? strlen (path) : 0) + 50;
	char *path2 = alloca (len);
	const char *appl = getenv ("XAPPLRESDIR");
	int len2 = (appl ? strlen (appl) : 0) + 100;
	strcpy (path2, path);
	strcat (path2, ":/mit/discuss/exl");
	setenv ("PATH", path2);
#if 0
	if (len2 > len)
	    path2 = alloca (len2);
	if (appl)
	    strcat (strcpy (path2, appl), ":");
	else
	    path2[0] = 0;
	strcat (path2, "/usr/sipb/lib/app-defaults/");
	setenv ("XAPPLRESDIR", path2);
#else
	setenv ("XAPPLRESDIR", "/mit/discuss/source/xdsc");
#endif
    }
    XtToolkitInitialize ();
    app_context = XtCreateApplicationContext ();
    dpy = XtOpenDisplay (app_context, (char *) NULL, APP_NAME, APP_CLASS,
			 options, XtNumber (options), &argc, argv);
    if (!dpy) {
	com_err (whoami, 0, "Can't open display!");
	return 1;
    }
    argc--, argv++;
    if (argc > 1) {
	com_err (whoami, 0, "usage: %s [ options ] [ meeting_name ]",
		 whoami);
	return 1;
    }
    toplevel = XtAppCreateShell (APP_NAME, APP_CLASS,
				 applicationShellWidgetClass, dpy,
				 0, 0);
    XtGetApplicationResources (toplevel, (XtPointer) &defs,
			       app_resources, XtNumber (app_resources),
			       NULL, 0);
    one_win = defs.one_win;
    {
	/* workaround for various bugs */
	extern int XConnectionNumber (Display *);
	/* Xlib: close-on-exec isn't set */
	(void) fcntl (XConnectionNumber (XtDisplay (toplevel)),
		      F_GETFD, 1);
	/* Discuss: could receive SIGPIPE */
	(void) signal (SIGPIPE, SIG_IGN);
    }
    vert_bbox = strcmp (defs.mode, "box");
    do_sort = defs.sort;
    screen = DefaultScreen (dpy);
    {
	Arg a;
	a.name = XtNtitle, a.value = (XtArgVal) "X discuss";
	XtSetValues (toplevel, &a, 1);
    }

    if (argc == 0)
	windows ();
    else {
	/* pull up one-meeting window */
	XtCallbackRec callbacks[2];
	Arg a[2];
	callbacks[0].callback = schedule_window_destruction_cb;
	callbacks[0].closure = (caddr_t) toplevel;
	callbacks[1].callback = NULL;
	XtSetArg (a[0], XtNquitCallback, callbacks);
	XtSetArg (a[1], XtNmeetingName, *argv);
	XtCreateManagedWidget (*argv, discussMeetingWidgetClass, toplevel,
			       a, XtNumber (a));
    }

realize:
    XtRealizeWidget (toplevel);
#ifdef XDSC_CURSOR
    XDefineCursor(XtDisplay(toplevel), XtWindow(toplevel),
		  XCreateFontCursor(XtDisplay(toplevel), XDSC_CURSOR));
#endif
    XtAppMainLoop (app_context);
    /* shouldn't ever return */
    fprintf (stderr, "returned from XtMainLoop?!?\n");
    return 1;
}

#ifdef DEBUG
int abort();

int _exit(int code) {
    static const char hex[16] = "0123456789abcdef";
    static const char broke_msg[] = "exiting with status 0x";
    char frep[3];
    if (code) {
	code &= 0xff;
	frep[0] = hex[code>>4];
	frep[1] = hex[code&0xf];
	frep[2] = '\n';
	write (2, broke_msg, sizeof (broke_msg));
	write (2, frep, 2);
	abort ();
    }
    syscall (SYS_exit, 0);
}
#endif /* DEBUG */
