#ifndef lint
static char rcsid[] = "";
#endif /* lint */

#include        <stdio.h>
#include        <X11/Xatom.h>
#include        <X11/IntrinsicP.h>
#include        <X11/Intrinsic.h>
#include        <X11/StringDefs.h>
#include        <X11/Shell.h>
#include        <X11/CoreP.h>

#include        <X11/Xaw/Cardinals.h>
#include        <X11/Xaw/List.h>
#include        <X11/Xaw/Paned.h>
#include        <X11/Xaw/Command.h>
#include        <X11/Xaw/Box.h>
#include        <X11/Xaw/AsciiText.h>
#include        <X11/Xaw/TextP.h>
#include        <X11/Xaw/TextSinkP.h>
#include        <X11/Xaw/Label.h>

#include        "Person.h"
#include        "XmuX.h"

#define		INITVAL		1
#define		HUNDRED		100
#define		STOCKMESSAGE	"Click on user to give chalk to"
#define		MAX(a,b)	((a) > (b) ? (a) : (b))
#define		_MUX_STATUS	4
#define		XMUX_STATUS_NAME	"XMUX_STATUS"

#define		GIVE		0
#define		DELETE		1

#define		ANARCHY		0
#define		POLITE		1

typedef struct {
	char	*displayname;
	char	*fullname;
	char	*login;
	int	status;
	Boolean	chair;
} DisplayEntry, *DisplayEntryPtr;

DisplayEntryPtr	displays;

static	char *adduserbuttons[] = {
		"add user",
		"abort",
		NULL};

static	char *top_button_list[] = {
		"add user",
		"delete user",
		"choose app",
		"quit",
		NULL};

static void	MyMainLoop();
static void	SelectCB();
static void	NumCB();
static void	TopCB(), BotCB();
void		GetInput();

extern Window	Select_Window();
extern XtAppContext	_XtDefaultAppContext();
extern char     *getenv();

Display		*dpy;
Window		window;
Widget		top_buttons[10];
Widget		topW, listW, statusLabelW, aclPaneW;
int		char_width = 8;
Widget		inputPopupW = 0, inputTextW;
Widget		aclPopupW = 0;
void		TopSelect();
void		TriggerInput();
Widget		addLabelW;
TextWidget	addTextW;
static void	DoDelete();
void		(*input_function)() = NULL;
char		*saved_line = NULL;
int		saved_index = -1;
int		mode = GIVE;
int		paradigm = POLITE;
Widget		paneW, box1W, box2W, box3W;
Widget		people[10];
Widget		labels[10];
Atom		host_atom, chalk_atom, status_atom;
Boolean		ihavethechalk = True;
char		*mydisplayname;
char		changed_host[50];
char		my_new_chalkholder[50];
Boolean		need_to_redisplay_hosts = True;
static char	oldhostlist[200];

main (argc, argv)
int argc;
char *argv[];
{
	Arg		args[5];
	unsigned int	n, i;
	char		**toplist = top_button_list;
	char		myname[32];
	static XtActionsRec actions[] = {
		{"TriggerInput",	TriggerInput}};

	if (argc > 1) {
		if (argv[1][0] == 'a') {
			paradigm = ANARCHY;
		}
	}

	switch (paradigm) {
	case ANARCHY:
		fprintf (stderr, "Working in anarchy mode\n");
		break;
	case POLITE:
		fprintf (stderr, "Working in polite mode\n");
		break;
	}

	strcpy (changed_host, "\0");
	strcpy (my_new_chalkholder, "gunk");

	topW = XtInitialize("topwidget", "Chalkbox", NULL, 0, &argc, argv);

	dpy = XtDisplay(topW);
	mydisplayname = getenv ("DISPLAY");

        XtAppAddActions (       XtWidgetToApplicationContext(topW),
					actions, XtNumber(actions));

	n = 0;
	paneW = XtCreateManagedWidget(
			"pane",
			panedWidgetClass,
			topW,
			args,
			n);

	n = 0;
	box1W = XtCreateManagedWidget(
			"box1",
			boxWidgetClass,
			paneW,
			args,
			n);
	n = 0;
	box2W = XtCreateManagedWidget(
			"box2",
			boxWidgetClass,
			paneW,
			args,
			n);

	gethostname (myname, 32);

	n = 0;
	XtSetArg(args[n], XtNlabel, "No application selected");	n++;
	statusLabelW = XtCreateManagedWidget(
			"statuslabel",
			labelWidgetClass,
			paneW,
			args,
			n);

	n = 0;
	box3W = XtCreateManagedWidget(
			"box3",
			boxWidgetClass,
			paneW,
			args,
			n);

	for (i = 0; *toplist; toplist++, i++) {
		n = 0;
		XtSetArg(args[n], XtNlabel, *toplist);	n++;

		top_buttons[i] = XtCreateManagedWidget(
				"topbutton",
				commandWidgetClass,
				box3W,
				args,
				n);

		XtAddCallback (top_buttons[i], XtNcallback, TopCB, i);
	}

	XtRealizeWidget(topW);

	host_atom = XInternAtom (dpy, XMUX_HOSTS_NAME, False);
	if (!host_atom) {
		printf ("Atom %s not valid!\n", XMUX_HOSTS_NAME);
		return (BadAtom);
	}

	chalk_atom = XInternAtom (dpy, XMUX_CHALKHOLDER_NAME, False);
	if (!chalk_atom) {
		printf ("Atom %s not valid!\n", XMUX_CHALKHOLDER_NAME);
		return (BadAtom);
	}

	status_atom = XInternAtom (dpy, XMUX_STATUS_NAME, False);
	if (!status_atom) {
		printf ("Atom %s not valid!\n", XMUX_STATUS_NAME);
		return (BadAtom);
	}

	MyMainLoop();
}

static void
MyMainLoop()
{
	XEvent		the_event;
	XtAppContext	app = _XtDefaultAppContext();

	while (1) {
		XtAppNextEvent(app, &the_event);
		if (the_event.type == PropertyNotify) {
			ServicePropertyNotify(&the_event);
		}
		if (the_event.type == ClientMessage) {
			ServiceClientMessage(&the_event);
		}
		XtDispatchEvent(&the_event);
	}
}

ServiceClientMessage(client_event)
XClientMessageEvent	*client_event;
{
}

ServicePropertyNotify(prop_event)
XPropertyEvent	*prop_event;
{

	if (prop_event->window != window) {
		return;
	}
	if (prop_event->atom == chalk_atom) {
		HandleChalkChange(prop_event);
	}
	if (prop_event->atom == host_atom) {
		HandleHostChange(prop_event);
	}
	if (prop_event->atom == status_atom) {
		DisplayUsers();
	}
}

/*
**  If I'm just sent off a request to add or delete a user, this is my
**  confirmation that it worked.  Check that this is so, and if so,
**  add or delete the status entry for the user.
**
*/

HandleHostChange(prop_event)
XPropertyEvent	*prop_event;
{
	Atom		atomback;
	int		formatback;
	unsigned long	itemsback, bytesback;
	char		*hostlist, *status;
	int		n;
	Arg		args[5];
	int		i;
	char		newstatus[200];
	char		localentry[80];
	char		*hoststart, *oldhoststart, *statusstart;
	char		*hostend, *oldhostend, *statusend;

	if (! *changed_host) {
		need_to_redisplay_hosts = True;
		return;
	}
	fprintf (stderr, "Handling host change\n");

	XGetWindowProperty(	dpy, window, host_atom, 0L, 200L,
				False, AnyPropertyType, &atomback,
				&formatback, &itemsback, &bytesback,
				&hostlist);

	fprintf (stderr, "hostlist = '%s'\n",hostlist);
	fprintf (stderr, "oldhostlist = '%s'\n",oldhostlist);
	if (!hostlist) return;

	XGetWindowProperty(	dpy, window, status_atom, 0L, 200L,
				False, AnyPropertyType, &atomback,
				&formatback, &itemsback, &bytesback,
				&status);
	fprintf (stderr, "status = '%s'\n",status);

/*
** Bootstrapping or adding a new host.
*/
	if (	(!oldhostlist[0]) || 
		(strlen (oldhostlist) < strlen (hostlist))) {
		fprintf (stderr, "Adding a host/bootstrapping\n");

		if (!status)
			sprintf (newstatus, "S=%d|C=%d", PERSON_SITTING, True);
		else
			sprintf (newstatus, "S=%d|C=%d,%s", PERSON_SITTING, True, status);
	}

/*
** Say what?  No change, do nothing.
*/
	else if (!strcmp (oldhostlist, hostlist)) {
		fprintf (stderr, "No change, returning\n");
		return;
	}

/*
** Deleting an existing host...need to find its status entry and delete it.
** Walk through old and new host lists until you find an entry that is
** different, then delete the corresponding status entry.
*/
	else {
		fprintf (stderr, "Deleting a host\n");
		
		hoststart = hostlist;
		oldhoststart = oldhostlist;
		statusstart = status;

		hostend = strchr(hostlist, ',');
		oldhostend = strchr(oldhostlist, ',');
		statusend = strchr(status, ',');
		*newstatus = '\0';

		while (hostend && oldhostend && statusend) {
			*hostend = '\0'; 
			*oldhostend = '\0';
			*statusend = '\0';

			if (strcmp (hoststart, oldhoststart))
				break;

			sprintf (	newstatus,"%s%s%s",
					newstatus,
					(*newstatus ? "," : ""),
					statusstart);
			*hostend = ',';
			*oldhostend = ',';
			*statusend = ',';

			hoststart = hostend + 1;
			oldhoststart = oldhostend + 1;
			statusstart = statusend + 1;

			hostend = strchr(hoststart, ',');
			oldhostend = strchr(oldhoststart, ',');
			statusend = strchr(statusstart, ',');
		}
/*
** Save the leftovers, if there are any
*/
		if (statusend)
			sprintf (	newstatus,"%s%s%s",
					newstatus,
					(*newstatus ? "," : ""),
					statusend + 1);
	}

	fprintf (stderr, "newstatus = '%s'\n",newstatus);

	XChangeProperty (	dpy, window, status_atom, 
				XA_STRING, 8,
				PropModeReplace, newstatus,
				strlen (newstatus) + 1);

	strcpy (changed_host, "\0");
	strcpy (oldhostlist, hostlist);
	need_to_redisplay_hosts = True;
}

HandleChalkChange(prop_event)
XPropertyEvent	*prop_event;
{
	Atom		atomback;
	int		formatback;
	unsigned long	itemsback, bytesback;
	char		*chalkdata, *hostlist, *statusdata;
	char		*hostend, *statusend;
	int		n;
	Arg		args[5];
	int		i;
	char		buffer[80];
	XmuXHints	mux_hints;

	XGetWindowProperty(	dpy, window, chalk_atom, 0L, 200L,
				False, AnyPropertyType, &atomback,
				&formatback, &itemsback, &bytesback,
				&chalkdata);

/*
** Not a change I asked for.  Don't do anything now...I'll notice when
** the status property changes.
*/
	if (strcmp (chalkdata, my_new_chalkholder)) {
		return;
	}

/*
** Sit the current speaker down and make the new guy stand up.
*/
	for (i = 0; displays[i].displayname; i++) {
		if (displays[i].status == PERSON_SPEAKER)
			displays[i].status = PERSON_SITTING;
		if (!strcmp (chalkdata, displays[i].displayname))
			displays[i].status = PERSON_SPEAKER;
	}

	SendStatus();
	strcpy (my_new_chalkholder, "gunk");
}

static void
AddCB(w, client_data, call_data)
Widget	w;
XtPointer	client_data;
XtPointer	call_data;
{
	char		*tempstring, *temp;
	Arg		args[5];
	unsigned int	n, i;
	Widget		labelW;
	XmuXHints	mux_hints;
	char		statusline[80];

	if (!inputPopupW)
		return;

	if (client_data != 0)
		goto ABORT;

	n = 0;
	XtSetArg(args[n], XtNstring, &tempstring);		n++;
	XtGetValues (inputTextW, args, n);

	temp = (char *) malloc (80);

	sprintf (temp, "+%s",tempstring);
	mux_hints.type = XMUXProperty;
	mux_hints.u.strings[0] = XMUX_CPORT_NAME;
	mux_hints.u.strings[1] = temp;
	XmuXSetHints (dpy, window, &mux_hints);

	strcpy (changed_host, tempstring);

	n = 0;
	XtSetArg(args[n], XtNlabel, "waiting for new user");		n++;
	XtSetValues (statusLabelW, args, n);

ABORT:
	n = 0;
	XtSetArg(args[n], XtNlabel, STOCKMESSAGE);	n++;
	XtSetValues (statusLabelW, args, n);

	XtDestroyWidget(inputPopupW);
	XtSetKeyboardFocus(topW, topW);
	inputPopupW = 0;
}

AddUserToList(name, status)
char	*name;
char	*status;
{
	Arg		args[5];
	unsigned int	n, i;
	char		*newguy;
	Dimension	newwidth;
	Atom		atomback;
	int		formatback;
	unsigned long	itemsback, bytesback;
	char		*statusdata, *end, *start;
	XmuXHints	mux_hints;

	if (displays) {
		for (i = 0; displays[i].displayname; i++)
			;
		displays = (DisplayEntryPtr) 
			realloc (displays, (i + 2) * sizeof (DisplayEntry));
	}
	else {
		displays = (DisplayEntryPtr) 
			malloc (2 * sizeof (DisplayEntry));
		i = 0;
	}

	displays[i].fullname = (char *) NULL;
	displays[i].login = (char *) NULL;
	displays[i].status = (int) NULL;
	displays[i].chair = (Boolean) NULL;

	newguy = (char *) malloc (80);
	sprintf (newguy, "%s", name);
	displays[i].displayname = newguy;
	displays[i + 1].displayname = NULL;

	FillDisplayEntry(&(displays[i]), status);

	newwidth = MAX (((i + 1) * HUNDRED + 20), 300);

	n = 0;
	XtSetArg(args[n], XtNwidth, newwidth);		n++;
	XtSetValues (paneW, args, n);

	n = 0;
	if (displays[i].fullname) {
		XtSetArg(args[n], XtNlabel, displays[i].fullname);	n++;
	}
	else {
		XtSetArg(args[n], XtNlabel, displays[i].displayname);	n++;
	}

	labels[i] = XtCreateManagedWidget(	"namelabel",
					commandWidgetClass,
					box2W,
					args,
					n);
	XtAddCallback (labels[i], XtNcallback, SelectCB, i);

	n = 0;
	people[i] = XtCreateManagedWidget(	"personlabel",
					personWidgetClass,
					box1W,
					args,
					n);
	XtAddCallback (people[i], XtNcallback, SelectCB, i);
}

Fill(dest, source)
char	**dest, *source;
{
	if (!source) {
		fprintf (stderr, "WARNING!  Null source passed to Fill\n");
		return;
	}
	*dest = (char *) malloc (strlen(source));
	strcpy (dest, source);
}

/*
** parse the status entry and fill the data structure appropriately.
*/

FillDisplayEntry(pde, status)
DisplayEntryPtr	pde;
char		*status;
{
	char	*start, *end;

	for (start = status;;) {
		end = strchr(start, '|');
		if (end)
			*end = '\0';

		switch (*start) {
		case 'N':
			Fill(&(pde->fullname), start);
			break;
		case 'L':
			Fill(&(pde->login), start);
			break;
		case 'S':
			pde->status = atoi(start + 2);
			break;
		case 'C':
			pde->chair = atoi(start + 2);
			break;
		}

		if (end) {
			*end = '|';
			start = end + 1;
		}
		else
			break;
	}
}

DeleteAllUsers()
{
	int	i;
	
	if (!displays)
		return;

	for (i = 0; displays[i].displayname; i++) {
		free(displays[i].displayname);
		if (displays[i].fullname)
			free(displays[i].fullname);
		if (displays[i].login)
			free(displays[i].login);
		displays[i].displayname = 0;
		XtDestroyWidget(labels[i]);
		labels[i] = 0;
		XtDestroyWidget(people[i]);
		people[i] = 0;
	}
	free(displays);
	displays = 0;
}

static void
TopCB(w, client_data, call_data)
Widget	w;
XtPointer	client_data;
XtPointer	call_data;
{
	XawListReturnStruct	*which;
	int		n;
	Arg		args[5];

	switch ( (int) client_data) {
		case 0:
			SetUpForAdd();
			break;
		case 1:
			n = 0;
			XtSetArg(args[n], XtNlabel, "Click on user to delete");	n++;
			XtSetValues (statusLabelW, args, n);
			mode = DELETE;
			break;
		case 2:
			GetNewApp();
			break;
		case 3:
			exit(0);
	}

}

GetNewApp()
{
	window = Select_Window(dpy);
	XSelectInput(dpy, window, PropertyChangeMask);
	DeleteAllUsers();
	DisplayUsers();
}

DisplayUsers()
{
	Atom		atomback;
	int		formatback;
	unsigned long	itemsback, bytesback;
	char		*chalkdata, *hostlist, *statusdata;
	char		*hostend, *statusend;
	int		n;
	Arg		args[5];
	int		i;
	char		buffer[80];
	XmuXHints	mux_hints;

	XGetWindowProperty(	dpy, window, host_atom, 0L, 200L,
				False, AnyPropertyType, &atomback,
				&formatback, &itemsback, &bytesback,
				&hostlist);
	if (!hostlist) {
		n = 0;
		XtSetArg(args[n], XtNlabel, "Not a shared application--Choose another");		n++;
		XtSetValues (statusLabelW, args, n);
		return;
	}

	strcpy (oldhostlist, hostlist);

	XGetWindowProperty(	dpy, window, chalk_atom, 0L, 200L,
				False, AnyPropertyType, &atomback,
				&formatback, &itemsback, &bytesback,
				&chalkdata);

	XGetWindowProperty(	dpy, window, status_atom, 0L, 200L,
				False, AnyPropertyType, &atomback,
				&formatback, &itemsback, &bytesback,
				&statusdata);

	if (!chalkdata || !statusdata) {
/*
** Bootstrapping...
*/
		sprintf (buffer, "S=%d|C=%d", PERSON_SPEAKER, True);

		XChangeProperty (	dpy, window, status_atom, 
					XA_STRING, 8,
					PropModeReplace, buffer,
					strlen (buffer) + 1);

		sprintf (buffer, "Assigning chalk to first user\n");
		n = 0;
		XtSetArg(args[n], XtNlabel, buffer);		n++;
		XtSetValues (statusLabelW, args, n);

		mux_hints.type = XMUXMessage;
		mux_hints.u.mess[XMUXType] = XMUXAction;
		mux_hints.u.mess[XMUXSubtype] = XMUXPassChalk;
		mux_hints.u.mess[XMUXDetail] = 0;
		XmuXSetHints (dpy, window, &mux_hints);

		XGetWindowProperty(	dpy, window, status_atom, 0L, 200L,
					False, AnyPropertyType, &atomback,
					&formatback, &itemsback, &bytesback,
					&statusdata);

		if (!statusdata) {
			fprintf (stderr, "Bootstrap failed!\n");
			return;
		}

	}

	if (	(!displays) || need_to_redisplay_hosts) {
		need_to_redisplay_hosts = False;

		DeleteAllUsers();
	
		hostend = strchr(hostlist, ',');
		statusend = strchr(statusdata, ',');

		while (hostend && statusend) {
			*hostend = '\0';
			*statusend = '\0';
			AddUserToList(hostlist, statusdata);
			*hostend = ',';
			*statusend = ',';
			statusdata = statusend + 1;
			hostlist = hostend + 1;
			statusend = strchr(statusdata, ',');
			hostend = strchr(hostlist, ',');
		}

		if (hostend || statusend) {
			n = 0;
			XtSetArg(args[n], XtNlabel, "Error parsing host/status atoms");		n++;
			XtSetValues (statusLabelW, args, n);
			return;
		}

		AddUserToList(hostlist, statusdata);
	}
	else {
	}

	n = 0;
	XtSetArg(args[n], XtNlabel, STOCKMESSAGE);	n++;
	XtSetValues (statusLabelW, args, n);

	UpdateIcons();
}

SetUpForAdd()
{
	int		n;
	Arg		args[5];
	n = 0;
	XtSetArg(args[n], XtNlabel, "Adding a new user");	n++;
	XtSetValues (statusLabelW, args, n);
	GetInput("Name of new user:", adduserbuttons, AddCB);

}

void
GetInput(label, button_list, return_function)
char	*label;
char	**button_list;
void	(*return_function)();
{
	Arg		args[5];
	unsigned int	n, i;
	Widget		button, inputPaneW, inputBox1W;
	Position	parentx, parenty;
	Dimension	parentwidth, mywidth;

	if (inputPopupW)
		return;

	input_function = return_function;

	n = 0;
	XtSetArg(args[n], XtNwidth, &parentwidth);	n++;
	XtSetArg(args[n], XtNx, &parentx);		n++;
	XtSetArg(args[n], XtNy, &parenty);		n++;
	XtGetValues (topW, args, n);

	mywidth = 35 * char_width;

	n = 0;
	XtSetArg(args[n], XtNwidth, mywidth);		n++;
	XtSetArg(args[n], XtNtransient, True);		n++;
	XtSetArg(args[n], XtNtransientFor, topW);	n++;
	XtSetArg(args[n], XtNx, 
		parentx + ((parentwidth - mywidth) / 2));	n++;
	XtSetArg(args[n], XtNy, parenty + 100);		n++;

	inputPopupW = XtCreatePopupShell(	
			"inputpopup", 
			transientShellWidgetClass,
			topW,
			args,
			n);

	inputPaneW = XtCreateManagedWidget(
			"pane",
			panedWidgetClass,
			inputPopupW,
			NULL,
			0);

	n = 0;
	XtSetArg(args[n], XtNlabel, label);	n++;
	(void) XtCreateManagedWidget(
			"label",
			labelWidgetClass,
			inputPaneW,
			args,
			n);

	n = 0;
	XtSetArg(args[n], XtNborderWidth, 0);			n++;
	XtSetArg(args[n], XtNeditType, XawtextEdit);		n++;

	inputTextW = XtCreateManagedWidget(
			"text",
			asciiTextWidgetClass,
			inputPaneW,
			args,
			n);

	n = 0;
	XtSetArg(args[n], XtNborderWidth, 0);			n++;
	inputBox1W = XtCreateManagedWidget(
			"inputbox",
			boxWidgetClass,
			inputPaneW,
			args,
			n);

	for (i = 0; *button_list; button_list++, i++) {
		n = 0;
		XtSetArg(args[n], XtNlabel, *button_list);	n++;

		button = XtCreateManagedWidget(
				"anybutton",
				commandWidgetClass,
				inputBox1W,
				args,
				n);

		XtAddCallback (button, XtNcallback, return_function, i);
	}

	XtPopup(inputPopupW, XtGrabNone);
	XtSetKeyboardFocus(inputPaneW, inputTextW);
}

void
TriggerInput(w, event, params, num_params)
Widget  w;
XEvent  *event;
String  *params;
int     *num_params;
{
	if (*num_params < 1)
		return;

	if (!input_function)
		return;

/*
** Simulate pressing button zero, if passed "Go"
*/
	(*input_function) (w, (XtPointer) strcmp(params[0], "Go"), NULL);

}

static void
SelectCB(w, client_data, call_data)
Widget	w;
XtPointer	client_data;
XtPointer	call_data;
{
	switch (paradigm) {
	case ANARCHY:
		AnarchicClick((int) client_data);
		break;
	case POLITE:
		RequestClick((int) client_data);
		break;
	}
}
	

AnarchicClick(selected)
int selected;
{
	XmuXHints	mux_hints;
	Arg		args[5];
	unsigned int	n, i;

	switch (mode) {
	case GIVE:
		strcpy (my_new_chalkholder, displays[selected].displayname);
		mux_hints.type = XMUXMessage;
		mux_hints.u.mess[XMUXType] = XMUXAction;
		mux_hints.u.mess[XMUXSubtype] = XMUXPassChalk;
		mux_hints.u.mess[XMUXDetail] = selected;
		XmuXSetHints (dpy, window, &mux_hints);
		break;

	case DELETE:
		DoDelete(selected);
		mode = GIVE;
		n = 0;
		XtSetArg(args[n], XtNlabel, STOCKMESSAGE);	n++;
		XtSetValues (statusLabelW, args, n);
		break;
	}
}

RequestClick(selected)
int selected;
{
	XmuXHints	mux_hints;
	Arg		args[5];
	unsigned int	n, i;
	char		statusline[80];

/*
** I can pass the chalk if I have it.
*/
	if (ihavethechalk) {
		AnarchicClick(selected);
	}
/*
** Otherwise, I can make a request for it.
*/
	else {
		if (!strcmp (displays[selected].displayname, mydisplayname)) {
			displays[selected].status = PERSON_REQUEST;
			SendStatus();
		}
		else {
			sprintf (statusline, "You do not have the chalk");
			n = 0;
			XtSetArg(args[n], XtNlabel, statusline);	n++;
			XtSetValues (statusLabelW, args, n);
		}
	}
}

SendStatus()
{
	char	status[200];
	char	localentry[80];
	int i;

	if (!displays)
		return;

	*status = '\0';

	for (i = 0; displays[i].displayname; i++) {
		*localentry = '\0';
		if (displays[i].fullname)
			sprintf (	localentry, "%sN=%s|", 
					localentry, displays[i].fullname);

		if (displays[i].login)
			sprintf (	localentry, "%sL=%s|", 
					localentry, displays[i].login);

		sprintf (	localentry, "%sS=%d|", 
				localentry, displays[i].status);

		sprintf (	localentry, "%sC=%d", 
				localentry, displays[i].chair);

		if (*status)
			sprintf (status, "%s,%s", status, localentry);
		else
			sprintf (status, "%s", localentry);
	}

	XChangeProperty (	dpy, window, status_atom, 
				XA_STRING, 8,
				PropModeReplace, status,
				strlen (status) + 1);
}

static void
DoDelete(which)
int which;
{
	char		*tempstring, *temp;
	Arg		args[5];
	unsigned int	n, i;
	Widget		labelW;
	XmuXHints	mux_hints;

	temp = (char *) malloc (80);
	sprintf (temp, "-%s", displays[which].displayname);

	mux_hints.type = XMUXProperty;
	mux_hints.u.strings[0] = XMUX_CPORT_NAME;
	mux_hints.u.strings[1] = temp;
	XmuXSetHints (dpy, window, &mux_hints);

	strcpy (changed_host, displays[which].displayname);

	DisplayUsers();

	free(temp);
}


UpdateIcons()
{

	Arg		args[5];
	unsigned int	n, i;
	char		statusline[80];
	Atom		atomback;
	int		formatback;
	unsigned long	itemsback, bytesback;
	char		*statusdata, *end;
	int		status;
	XmuXHints	mux_hints;

	if (!displays)
		return;


	XGetWindowProperty(	dpy, window, status_atom, 0L, 200L,
				False, AnyPropertyType, &atomback,
				&formatback, &itemsback, &bytesback,
				&statusdata);

	if (!statusdata)
		return;

	i = 0;
	sprintf (statusline, "No one has the chalk");
	ihavethechalk = False;

	do {
		end = strchr(statusdata, ',');
		if (end)
			*end = '\0';
		FillDisplayEntry(&(displays[i]), statusdata);
		if (displays[i].status == PERSON_SPEAKER) {
			if (!strcmp (mydisplayname, displays[i].displayname)) {
				sprintf (statusline, "You have the chalk");
				ihavethechalk = True;
			}
			else {
				sprintf (statusline, "User %s has the chalk", displays[i].displayname);
			}
		}
		n = 0;
		XtSetArg(args[n], XtNpose, displays[i].status);	n++;
		XtSetValues (people[i], args, n);
		statusdata = end + 1;
		i++;
	} while (end);

	n = 0;
	XtSetArg(args[n], XtNlabel, statusline);	n++;
	XtSetValues (statusLabelW, args, n);
}
