/*
 *
 */

#include <stdio.h>
#include <com_err.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Paned.h>
#include <discuss/discuss.h>
#include "stuff.h"

/* this function borrowed from R3, since R4 seems to have tossed it */
static
#ifdef __GNUC__
inline
#endif
Pixmap XtGrayPixmap (screen) Screen *screen; {
    return XmuCreateStippledPixmap(screen, BlackPixelOfScreen(screen),
					   WhitePixelOfScreen(screen),
				   DefaultDepthOfScreen(screen));
}

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

#if 0
static const char *const _ckm_states[] = {
    "NOT_ACTIVE",
    "RUNNING",
    "RUN_AGAIN",
    "BACKGROUND",
};
#endif

enum _ckm_state {
    NOT_ACTIVE,
    RUNNING,
    RUN_AGAIN,
    BACKGROUND
};

static enum _ckm_state ckm_state = NOT_ACTIVE;

static Pixel black, gray, white;
static int initialized;
static XtWorkProcId ckm_workproc;

cmd_quit()
{
#if 0
    XtDestroyWidget(toplevel);
    term_rpc ();		/* can you say "abstraction violation"? */
#endif
    exit(0);
}

static int ckm_current_mtg_no;
static name_blk * changed_nbp;
static int n_changed;

Boolean check_a_meeting (void * xxx) {
    struct button_info * bp = xxx;
    int code, is_changed;
    short updated;
    Arg args[2];

    if (!changed_nbp)
	changed_nbp = malloc (n_mtgs * sizeof (name_blk));
    if (!bp)
	bp = meeting_list + ckm_current_mtg_no;
    if (bp->error)
	goto skip_check;
    if (vert_bbox) {
	bp->label[1] = '.';
	XtSetArg (args[0], XtNlabel, bp->label);
	XtSetValues (bp->button, args, 1);
    }
    else {
	XtSetArg (args[0], XtNborderPixmap, NULL);
	XtSetArg (args[1], XtNborderColor, white);
	XtSetValues (bp->button, args, 2);
    }
    updated = 0;
    dsc_updated_mtg (&bp->nb, &updated, &code);
    if (code) {
	bp->error++;
	if (vert_bbox) {
	    const char *msg = error_message (code);
	    /* " ? Meeting_Name: error_message" */
	    bp->label = XtRealloc (bp->label,
				   strlen (*bp->nb.aliases)
				   + strlen (msg) + 9);
	    sprintf (bp->label, " ? %s: %s", *bp->nb.aliases, msg);
	    XtSetArg (args[0], XtNlabel, bp->label);
	}
	else {
	    com_err (whoami, code, "checking meeting %s", *bp->nb.aliases);
	}
	XtSetArg (args[1], XtNsensitive, False);
	XtSetValues (bp->button, args, 1);
    }
    else {
	if (updated) {
	    if (!vert_bbox)
		args[0].value = (XtArgVal) gray;
	    is_changed = !(bp->nb.status & DSC_ST_CHANGED);
	    bp->nb.status |= DSC_ST_CHANGED;
	}
	else {
	    if (!vert_bbox)
		args[0].value = (XtArgVal) NULL;
	    is_changed = bp->nb.status & DSC_ST_CHANGED;
	    bp->nb.status &= ~DSC_ST_CHANGED;
	}
	if (is_changed)
	    changed_nbp[n_changed++] = bp->nb;
	args[1].value = black;
	if (vert_bbox) {
	    bp->label[1] = updated ? 'c' : ' ';
	    XtSetArg (args[0], XtNlabel, bp->label);
	    XtSetValues (bp->button, args, 1);
	}
	else {
	    XtSetValues (bp->button, args, 2);
	    /* XXX -- SetValues(borderPixmap) isn't an implemented feature */
	    if (!updated)
		XSetWindowBorderPixmap (XtDisplay (bp->button),
					XtWindow (bp->button), gray);
	}
    }
skip_check:
    ckm_current_mtg_no++;
    if (ckm_current_mtg_no < n_mtgs)
	goto requeue;
    ckm_current_mtg_no = n_changed = 0;
    /* we've finished this pass through the list */
    if (n_changed) {
	dsc_update_mtg_set ((char *) NULL, changed_nbp, n_changed, &code);
	if (code)
	    com_err (whoami, code, "updating .meetings file from ckm");
	n_changed = 0;
    }
    if (ckm_state == RUN_AGAIN) {
	ckm_state = RUNNING;
    requeue:
	ckm_workproc = XtAppAddWorkProc (app_context,
					 check_a_meeting, (void *) NULL);
    }
    else
	ckm_state = NOT_ACTIVE;
    return True;
}

cmd_ckm () {
    if (ckm_state != NOT_ACTIVE) {
	ckm_state = RUN_AGAIN;
	return;
    }
    ckm_state = RUNNING;
    ckm_current_mtg_no = n_changed = 0;
    ckm_workproc = XtAppAddWorkProc (app_context, check_a_meeting,
				     (void *) NULL);
}

#ifdef DEBUG
cmd_abort() {
    abort ();
}

static const XtCallbackRec abort_callback[] = {
    { (XtCallbackProc) cmd_abort, NULL },
    { NULL, NULL },
};

#endif

static const XtCallbackRec quit_callback[] = {
    { (XtCallbackProc) cmd_quit, NULL },
    { NULL, NULL },
};

static const XtCallbackRec ckm_callback[] = {
    { (XtCallbackProc) cmd_ckm, NULL },
    { NULL, NULL },
};

set_up_cmd_button_box()
{
    Arg arg[10];
    cmd_box = XtCreateManagedWidget("commands", boxWidgetClass, big_w, 0, 0);

    XtSetArg(arg[0], XtNcallback, ckm_callback);
    (void) XtCreateManagedWidget("check_meetings", commandWidgetClass, cmd_box,
				 arg, 1);

    XtSetArg(arg[0], XtNcallback, quit_callback);
    (void) XtCreateManagedWidget("quit", commandWidgetClass, cmd_box,
				 arg, 1);
#ifdef DEBUG
    XtSetArg(arg[0], XtNcallback, abort_callback);
    (void) XtCreateManagedWidget("abort", commandWidgetClass, cmd_box,
				 arg, 1);
#endif

    /* fire one up at startup */
    cmd_ckm ();
}

static XtCallbackRec mtg_callback[] = {
    { (XtCallbackProc)select_mtg, NULL },
    { NULL, NULL }
};

static Arg btn_args[] = {
    { XtNname, (XtArgVal) NULL },
    { XtNlabel, (XtArgVal) NULL },
    { XtNcallback, (XtArgVal) mtg_callback },
    { XtNborderPixmap, (XtArgVal) NULL },
};

set_up_mtg_button_box (void) {
    Widget box;
    WidgetList children;
    name_blk *meetings;
    name_blk *nbp;
    int code, i;

    if (!initialized) {
	black = BlackPixel (dpy, screen);
	white = WhitePixel (dpy, screen);
	gray = XtGrayPixmap (XtScreen (big_w));
	initialized = 1;
    }
    box = big_w;
    if (vert_bbox) {
	box = XtCreateManagedWidget ("meeting_vbox", viewportWidgetClass,
				     box, 0, 0);
	box = XtCreateManagedWidget ("pane", panedWidgetClass, box, 0, 0);
    }
    else {
	box = XtCreateManagedWidget("meeting_bbox", boxWidgetClass, box, 0, 0);
    }
    dsc_expand_mtg_set ((char *)NULL, "*", &meetings, &n_mtgs, &code);
    if (code) {
	com_err (whoami, code, "Can't get list of meetings.");
	exit(1);
    }
    meeting_list = malloc (n_mtgs * sizeof (*meeting_list));
    nbp = meetings;
    if (vert_bbox) {
    }
    else
	btn_args[3].value = (XtArgVal) gray;
    children = alloca (n_mtgs * sizeof (Widget));
    for (i = 0; i < n_mtgs; i++) {
	char *name;
	int j, len;
	Widget w;

	meeting_list[i].error = 0;
	meeting_list[i].nb = nbp[i];
	name = nbp[i].aliases[0]; /* use primary name */
	if (vert_bbox) {
	    char *label;
	    for (j = 0, len = 8; nbp[i].aliases[j]; j++)
		len += strlen (nbp[i].aliases[j]) + 2;
	    label = malloc (len);
	    strcpy (label, " ? ");
	    strcat (label, nbp[i].aliases[0]);
	    if (j > 1) {
		for (j = 1; nbp[i].aliases[j]; j++) {
		    strcat (label,
			    (j == 1) ? " (" : ", ");
		    strcat (label, nbp[i].aliases[j]);
		}
		strcat (label, ")");
	    }
	    meeting_list[i].label = label;
	}
	else
	    meeting_list[i].label = name;
	btn_args[0].value = (XtArgVal) name;
	btn_args[1].value = (XtArgVal) meeting_list[i].label;
	mtg_callback[0].closure = (caddr_t) &meeting_list[i];
	w = XtCreateWidget(name, commandWidgetClass, box,
			   btn_args, XtNumber(btn_args));
	meeting_list[i].button = w;
	children[i] = w;
    }
    XtManageChildren (children, n_mtgs);
    if (one_win)
	select_null_mtg ();
}
