#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		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 *status_name[] = { "sitting", "requesting" , "speaking" };
 
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();
static void     UpdateStatus();
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");
 
	fprintf (stderr, "I'm user %s\n" , 
		 mydisplayname ? mydisplayname : "NULL");
        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);
		}
		if (the_event.type == DestroyNotify) {
		        ServiceDestroyNotify(&the_event);
		}
		XtDispatchEvent(&the_event);
	}
}
 
ServiceDestroyNotify(destroy_event)
 
XDestroyWindowEvent *destroy_event;
 
{ int		n;
  Arg		args[1];
 
  if (destroy_event->window != window) {
           return;
  }  
 
  DeleteAllUsers();
 
  /* reset the status label */
  n = 0;
  XtSetArg(args[n], XtNlabel, "Application removed! select a new one");	n++;
  XtSetValues (statusLabelW, args, n);
  
}
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);
	UpdateStatus (dpy, window);
	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;
	XtSetArg(args[n], XtNshapeStyle, XawShapeOval); n++;
	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 | StructureNotifyMask);
	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);
		UpdateStatus (dpy, window);
		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);
	UpdateStatus (dpy, window);
}
 
static void UpdateStatus(dpy, window)
 
Display *dpy;
Window   window;
 
{ XmuXHints mux_hints;
 
  XFlush (dpy);
  mux_hints.type = XMUXMessage;
  mux_hints.u.mess[XMUXType] = XMUXAction;
  mux_hints.u.mess[XMUXSubtype] = XMUXUpdateStatus;
  mux_hints.u.mess[XMUXDetail] = 0;
  XmuXSetHints (dpy, window, &mux_hints);
 
  XmuXSetHints (dpy, window, &mux_hints);
}
 
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);
}
