info.c revision 8108eb18
1/* $Xorg: info.c,v 1.5 2001/02/09 02:05:59 xorgcvs Exp $ */
2/******************************************************************************
3
4Copyright 1993, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25******************************************************************************/
26/* $XFree86: xc/programs/xsm/info.c,v 1.5 2001/01/17 23:46:28 dawes Exp $ */
27
28#include "xsm.h"
29#include "restart.h"
30#include "popup.h"
31#include "info.h"
32#include "prop.h"
33
34#include <X11/Shell.h>
35#include <X11/Xaw/Form.h>
36#include <X11/Xaw/List.h>
37#include <X11/Xaw/Command.h>
38#include <X11/Xaw/SimpleMenu.h>
39#include <X11/Xaw/MenuButton.h>
40#include <X11/Xaw/SmeBSB.h>
41#include <X11/Xaw/AsciiText.h>
42
43static Pixmap checkBitmap;
44
45Widget clientInfoPopup;
46Widget   clientInfoForm;
47Widget     viewPropButton;
48Widget	   cloneButton;
49Widget	   killClientButton;
50Widget	   clientInfoDoneButton;
51Widget	   restartHintButton;
52Widget	     restartHintMenu;
53Widget		restartIfRunning;
54Widget		restartAnyway;
55Widget		restartImmediately;
56Widget		restartNever;
57Widget     clientListWidget;
58Widget	   noClientsLabel;
59Widget	   manualRestartLabel;
60Widget	   manualRestartCommands;
61
62Widget clientPropPopup;
63Widget   clientPropForm;
64Widget     clientPropDoneButton;
65Widget     clientPropTextWidget;
66
67
68
69void
70ShowHint(ClientRec *client)
71{
72    static Widget active = NULL;
73    int hint = client->restartHint;
74
75    if (active)
76	XtVaSetValues (active, XtNleftBitmap, None, NULL);
77
78    if (hint == SmRestartIfRunning)
79	active = restartIfRunning;
80    else if (hint == SmRestartAnyway)
81	active = restartAnyway;
82    else if (hint == SmRestartImmediately)
83	active = restartImmediately;
84    else if (hint == SmRestartNever)
85	active = restartNever;
86
87    XtVaSetValues (active, XtNleftBitmap, checkBitmap, NULL);
88}
89
90
91
92typedef struct {
93    char *bufStart;
94    char *bufPtr;
95    int bufSize;
96    int bytesLeft;
97} Buffer;
98
99#define BUF_START_SIZE 1024
100#define BUF_GROW_SIZE 256
101
102
103static void
104AppendStr(Buffer *buffer, char *str)
105{
106    int len = strlen (str);
107
108    if ((buffer->bytesLeft - 1) < len)
109    {
110	int newBufSize = buffer->bufSize + len + BUF_GROW_SIZE;
111	char *newbuf = (char *) malloc (newBufSize);
112	int bytesUsed = buffer->bufPtr - buffer->bufStart;
113	memcpy (newbuf, buffer->bufStart, bytesUsed);
114	newbuf[bytesUsed] = '\0';
115	free (buffer->bufStart);
116	buffer->bufStart = newbuf;
117	buffer->bufPtr = newbuf + bytesUsed;
118	buffer->bufSize = newBufSize;
119	buffer->bytesLeft = newBufSize - bytesUsed;
120    }
121
122    strcat (buffer->bufPtr, str);
123    buffer->bufPtr += len;
124    buffer->bytesLeft -= len;
125}
126
127
128void
129DisplayProps(ClientRec *client)
130{
131    int index;
132    List *pl, *pj, *vl;
133    PropValue *pval;
134    Buffer buffer;
135    static int first_time = 1;
136
137    for (index = 0; index < numClientListNames; index++)
138	if (clientListRecs[index] == client)
139	    break;
140
141    if (index >= numClientListNames)
142	return;
143
144    buffer.bufStart = buffer.bufPtr = (char *) malloc (BUF_START_SIZE);
145    buffer.bufSize = buffer.bytesLeft = BUF_START_SIZE;
146    buffer.bufStart[0] = '\0';
147
148    if (ListCount (client->props) > 0)
149    {
150	char number[10];
151	char *ptr;
152
153	AppendStr (&buffer, "*** ID = ");
154	AppendStr (&buffer, client->clientId);
155	AppendStr (&buffer, " ***\n\n");
156
157	for (pl = ListFirst (client->props); pl; pl = ListNext (pl))
158	{
159	    Prop *pprop = (Prop *) pl->thing;
160
161	    AppendStr (&buffer, "Name:		");
162	    AppendStr (&buffer, pprop->name);
163	    AppendStr (&buffer, "\n");
164	    AppendStr (&buffer, "Type:		");
165	    AppendStr (&buffer, pprop->type);
166	    AppendStr (&buffer, "\n");
167	    AppendStr (&buffer, "Num values:	");
168	    sprintf (number, "%d", ListCount (pprop->values));
169	    AppendStr (&buffer, number);
170	    AppendStr (&buffer, "\n");
171
172	    if (strcmp (pprop->type, SmCARD8) == 0)
173	    {
174		char *card8;
175		int value;
176
177		vl = ListFirst (pprop->values);
178		pval = (PropValue *) vl->thing;
179
180		card8 = pval->value;
181		value = *card8;
182
183		AppendStr (&buffer, "Value 1:	");
184		sprintf (number, "%d", value);
185		AppendStr (&buffer, number);
186
187		if (strcmp (pprop->name, SmRestartStyleHint) == 0)
188		{
189		    if (value == SmRestartAnyway)
190			AppendStr (&buffer, " (Restart Anyway)");
191		    else if (value == SmRestartImmediately)
192			AppendStr (&buffer, " (Restart Immediately)");
193		    else if (value == SmRestartNever)
194			AppendStr (&buffer, " (Restart Never)");
195		    else
196			AppendStr (&buffer, " (Restart If Running)");
197		}
198
199		AppendStr (&buffer, "\n");
200	    }
201	    else
202	    {
203		int propnum = 0;
204
205		for (pj = ListFirst (pprop->values); pj; pj = ListNext (pj))
206		{
207		    propnum++;
208
209		    pval = (PropValue *) pj->thing;
210		    AppendStr (&buffer, "Value ");
211		    sprintf (number, "%d", propnum);
212		    AppendStr (&buffer, number);
213		    AppendStr (&buffer, ":	");
214		    AppendStr (&buffer, (char *) pval->value);
215		    AppendStr (&buffer, "\n");
216		}
217	    }
218
219	    AppendStr (&buffer, "\n");
220	}
221
222	XtVaSetValues (clientPropTextWidget,
223	    XtNstring, buffer.bufStart,
224	    NULL);
225
226	sprintf (buffer.bufStart,
227	    "SM Properties : %s", clientListNames[index]);
228
229	ptr = Strstr (buffer.bufStart, ")   Restart");
230	if (ptr) *(ptr + 1) = '\0';
231
232	XtVaSetValues (clientPropPopup,
233	    XtNtitle, buffer.bufStart,
234	    XtNiconName, buffer.bufStart,
235	    NULL);
236
237	if (client_prop_visible)
238	{
239	    /* Make sure it is visible */
240
241	    XMapRaised (XtDisplay (topLevel), XtWindow (clientPropPopup));
242	}
243	else
244	{
245	    PopupPopup (mainWindow, clientPropPopup,
246		False, first_time, 50, 150, "DelPropWinAction()");
247
248	    client_prop_visible = 1;
249
250	    if (first_time)
251		first_time = 0;
252	}
253    }
254
255    free (buffer.bufStart);
256}
257
258
259
260static void
261ClientListXtProc(Widget w, XtPointer client_data, XtPointer callData)
262{
263    XawListReturnStruct *current = (XawListReturnStruct *) callData;
264    ClientRec *client;
265
266    if (!current || current->list_index < 0)
267	return;
268
269    client = clientListRecs[current->list_index];
270    ShowHint (client);
271    current_client_selected = current->list_index;
272    if (client_prop_visible)
273	DisplayProps (client);
274}
275
276
277
278
279static void
280ViewPropXtProc(Widget w, XtPointer client_data, XtPointer callData)
281{
282    ClientRec *client;
283    XawListReturnStruct *current;
284
285    current = XawListShowCurrent (clientListWidget);
286
287    if (!current || current->list_index < 0)
288    {
289	if (current)
290	    XtFree ((char *) current);
291	return;
292    }
293
294    client = clientListRecs[current->list_index];
295    DisplayProps (client);
296    XtFree ((char *) current);
297}
298
299
300
301static void
302CloneXtProc(Widget w, XtPointer client_data, XtPointer callData)
303{
304    ClientRec *client;
305    XawListReturnStruct *current;
306
307    current = XawListShowCurrent (clientListWidget);
308
309    if (!current || current->list_index < 0)
310    {
311	if (current)
312	    XtFree ((char *) current);
313	return;
314    }
315
316    client = clientListRecs[current->list_index];
317
318    if (client)
319	Clone (client, False /* don't use saved state */);
320
321    XtFree ((char *) current);
322}
323
324
325
326static void
327KillClientXtProc(Widget w, XtPointer client_data, XtPointer callData)
328{
329    ClientRec *client;
330    XawListReturnStruct *current;
331
332    current = XawListShowCurrent (clientListWidget);
333
334    if (!current || current->list_index < 0)
335    {
336	if (current)
337	    XtFree ((char *) current);
338	return;
339    }
340
341    client = clientListRecs[current->list_index];
342
343    SmsDie (client->smsConn);
344
345    XtFree ((char *) current);
346}
347
348
349
350static void
351listDoneXtProc(Widget w, XtPointer client_data, XtPointer callData)
352{
353    XtPopdown (clientInfoPopup);
354    client_info_visible = 0;
355}
356
357
358
359char *
360GetProgramName(char *fullname)
361{
362    char *lastSlash = NULL;
363    int i;
364
365    for (i = 0; i < (int) strlen (fullname); i++)
366	if (fullname[i] == '/')
367	    lastSlash = &fullname[i];
368
369    if (lastSlash)
370	return (lastSlash + 1);
371    else
372	return (fullname);
373}
374
375
376
377void
378UpdateClientList(void)
379{
380    ClientRec *client;
381    char *progName, *hostname, *tmp1, *tmp2;
382    String clientInfo;
383    int maxlen1, maxlen2;
384    char extraBuf1[80], extraBuf2[80];
385    char *restart_service_prop;
386    List *cl, *pl;
387    int i, k;
388    static int reenable_asap = 0;
389
390    if (clientListNames)
391    {
392	/*
393	 * Free the previous list of names.  Xaw doesn't make a copy of
394	 * our list, so we need to keep it around.
395	 */
396
397	for (i = 0; i < numClientListNames; i++)
398	    XtFree (clientListNames[i]);
399
400	XtFree ((char *) clientListNames);
401
402	clientListNames = NULL;
403    }
404
405    if (clientListRecs)
406    {
407	/*
408	 * Free the mapping of client names to client records
409	 */
410
411	XtFree ((char *) clientListRecs);
412	clientListRecs = NULL;
413    }
414
415    maxlen1 = maxlen2 = 0;
416    numClientListNames = 0;
417
418    for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
419    {
420	client = (ClientRec *) cl->thing;
421
422	progName = NULL;
423	restart_service_prop = NULL;
424
425	for (pl = ListFirst (client->props); pl; pl = ListNext (pl))
426	{
427	    Prop *pprop = (Prop *) pl->thing;
428	    List *vl = ListFirst (pprop->values);
429	    if (vl != NULL)
430	    {
431	    	PropValue *pval = (PropValue *) vl->thing;
432
433	    	if (strcmp (pprop->name, SmProgram) == 0)
434	    	{
435			progName = GetProgramName ((char *) pval->value);
436
437			if ((int) strlen (progName) > maxlen1)
438			    maxlen1 = strlen (progName);
439	    	}
440	    	else if (strcmp (pprop->name, "_XC_RestartService") == 0)
441	    	{
442			restart_service_prop = (char *) pval->value;
443	    	}
444	    }
445	}
446
447	if (!progName)
448	    continue;
449
450	if (restart_service_prop)
451	    tmp1 = restart_service_prop;
452	else if (client->clientHostname)
453	    tmp1 = client->clientHostname;
454	else
455	    continue;
456
457	if ((tmp2 = (char *) strchr (tmp1, '/')) == NULL)
458	    hostname = tmp1;
459	else
460	    hostname = tmp2 + 1;
461
462	if ((int) strlen (hostname) > maxlen2)
463	    maxlen2 = strlen (hostname);
464
465	numClientListNames++;
466    }
467
468    if (numClientListNames == 0)
469    {
470	XtSetSensitive (viewPropButton, 0);
471	XtSetSensitive (cloneButton, 0);
472	XtSetSensitive (killClientButton, 0);
473	XtSetSensitive (restartHintButton, 0);
474
475	XtUnmanageChild (clientListWidget);
476	XtManageChild (noClientsLabel);
477
478	reenable_asap = 1;
479
480	return;
481    }
482
483    if (reenable_asap)
484    {
485	XtSetSensitive (viewPropButton, 1);
486	XtSetSensitive (cloneButton, 1);
487	XtSetSensitive (killClientButton, 1);
488	XtSetSensitive (restartHintButton, 1);
489
490	XtUnmanageChild (noClientsLabel);
491	XtManageChild (clientListWidget);
492
493	reenable_asap = 0;
494    }
495
496    clientListNames = (String *) XtMalloc (
497	numClientListNames * sizeof (String));
498    clientListRecs = (ClientRec **) XtMalloc (
499	numClientListNames * sizeof (ClientRec *));
500
501    i = 0;
502    for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
503    {
504	ClientRec *client = (ClientRec *) cl->thing;
505	int extra1, extra2;
506	char *hint;
507
508	progName = NULL;
509	restart_service_prop = NULL;
510
511	for (pl = ListFirst (client->props); pl; pl = ListNext (pl))
512	{
513	    Prop *pprop = (Prop *) pl->thing;
514	    List *vl = ListFirst (pprop->values);
515
516	    if (vl != NULL)
517	    {
518	    	PropValue *pval = (PropValue *) vl->thing;
519	    	if (strcmp (pprop->name, SmProgram) == 0)
520	    	{
521			progName = GetProgramName ((char *) pval->value);
522	    	}
523	    	else if (strcmp (pprop->name, "_XC_RestartService") == 0)
524	    	{
525			restart_service_prop = (char *) pval->value;
526	    	}
527	    }
528	}
529
530	if (!progName)
531	    continue;
532
533	if (restart_service_prop)
534	    tmp1 = restart_service_prop;
535	else if (client->clientHostname)
536	    tmp1 = client->clientHostname;
537	else
538	    continue;
539
540	if ((tmp2 = (char *) strchr (tmp1, '/')) == NULL)
541	    hostname = tmp1;
542	else
543	    hostname = tmp2 + 1;
544
545	extra1 = maxlen1 - strlen (progName) + 5;
546	extra2 = maxlen2 - strlen (hostname);
547
548	if (client->restartHint == SmRestartIfRunning)
549	    hint = "Restart If Running";
550	else if (client->restartHint == SmRestartAnyway)
551	    hint = "Restart Anyway";
552	else if (client->restartHint == SmRestartImmediately)
553	    hint = "Restart Immediately";
554	else if (client->restartHint == SmRestartNever)
555	    hint = "Restart Never";
556	else
557	    hint = "";
558
559	clientInfo = (String) XtMalloc (strlen (progName) +
560	    extra1 + extra2 + 3 + strlen (hostname) + 3 + strlen (hint) + 1);
561
562	for (k = 0; k < extra1; k++)
563	    extraBuf1[k] = ' ';
564	extraBuf1[extra1] = '\0';
565
566	for (k = 0; k < extra2; k++)
567	    extraBuf2[k] = ' ';
568	extraBuf2[extra2] = '\0';
569
570	sprintf (clientInfo, "%s%s (%s%s)   %s", progName, extraBuf1,
571	    hostname, extraBuf2, hint);
572
573	clientListRecs[i] = client;
574	clientListNames[i++] = clientInfo;
575    }
576
577    XawListChange (clientListWidget,
578	clientListNames, numClientListNames, 0, True);
579}
580
581
582
583static void
584RestartHintXtProc(Widget w, XtPointer client_data, XtPointer callData)
585{
586    XawListReturnStruct *current;
587    ClientRec *client;
588    Widget active;
589    int found = 0;
590    List *pl;
591    char hint;
592
593    current = XawListShowCurrent (clientListWidget);
594
595    if (!current || current->list_index < 0)
596    {
597	if (current)
598	    XtFree ((char *) current);
599	return;
600    }
601
602    client = clientListRecs[current->list_index];
603
604    active = XawSimpleMenuGetActiveEntry (restartHintMenu);
605
606    if (active == restartIfRunning)
607	hint = SmRestartIfRunning;
608    else if (active == restartAnyway)
609	hint = SmRestartAnyway;
610    else if (active == restartImmediately)
611	hint = SmRestartImmediately;
612    else if (active == restartNever)
613	hint = SmRestartNever;
614    else
615    {
616	XtFree ((char *) current);
617	return;
618    }
619
620    client->restartHint = hint;
621
622    for (pl = ListFirst (client->props); pl; pl = ListNext (pl))
623    {
624	Prop *pprop = (Prop *) pl->thing;
625
626	if (strcmp (SmRestartStyleHint, pprop->name) == 0)
627	{
628	    List *vl = ListFirst (pprop->values);
629
630	    PropValue *pval = (PropValue *) vl->thing;
631
632	    *((char *) (pval->value)) = hint;
633	    found = 1;
634	    break;
635	}
636    }
637
638    if (!found)
639    {
640	SmProp prop;
641	SmPropValue propval;
642
643	prop.name = SmRestartStyleHint;
644	prop.type = SmCARD8;
645	prop.num_vals = 1;
646	prop.vals = &propval;
647	propval.value = (SmPointer) &hint;
648	propval.length = 1;
649
650	SetProperty (client, &prop, False /* don't free it */);
651    }
652
653    UpdateClientList ();
654    XawListHighlight (clientListWidget, current_client_selected);
655    ShowHint (client);
656
657    if (client_prop_visible && clientListRecs &&
658	clientListRecs[current_client_selected] == client)
659    {
660	DisplayProps (client);
661    }
662
663    XtFree ((char *) current);
664}
665
666
667
668static void
669clientPropDoneXtProc(Widget w, XtPointer client_data, XtPointer callData)
670{
671    XtPopdown (clientPropPopup);
672    client_prop_visible = 0;
673}
674
675
676
677void
678ClientInfoStructureNotifyXtHandler(Widget w, XtPointer closure,
679				   XEvent *event,
680				   Boolean *continue_to_dispatch)
681{
682    if (event->type == MapNotify)
683    {
684	UpdateClientList ();
685
686	if (current_client_selected >= 0)
687	    XawListHighlight (clientListWidget, current_client_selected);
688
689	XtRemoveEventHandler (clientInfoPopup, StructureNotifyMask, False,
690	    ClientInfoStructureNotifyXtHandler, NULL);
691    }
692}
693
694
695
696void
697ClientInfoXtProc(Widget w, XtPointer client_data, XtPointer callData)
698{
699    static int first_time = 1;
700
701    if (client_info_visible)
702    {
703	/* Make sure it is visible */
704
705	XMapRaised (XtDisplay (topLevel), XtWindow (clientInfoPopup));
706    }
707    else
708    {
709	UpdateClientList ();
710
711	if (clientListRecs && clientListRecs[0])
712	{
713	    current_client_selected = 0;
714	    XawListHighlight (clientListWidget, 0);
715	    ShowHint (clientListRecs[0]);
716	    if (client_prop_visible)
717		DisplayProps (clientListRecs[0]);
718	}
719	else
720	    current_client_selected = -1;
721
722	if (first_time && num_clients_in_last_session > 0 &&
723	    num_clients_in_last_session != numClientListNames)
724	{
725	    XtAddEventHandler (clientInfoPopup, StructureNotifyMask, False,
726	        ClientInfoStructureNotifyXtHandler, NULL);
727	}
728
729	PopupPopup (mainWindow, clientInfoPopup,
730	    False, first_time, 100, 50, "DelClientInfoWinAction()");
731
732	client_info_visible = 1;
733
734	if (first_time)
735	    first_time = 0;
736    }
737}
738
739
740#define CHECK_WIDTH 9
741#define CHECK_HEIGHT 8
742
743static unsigned char check_bits[] = {
744   0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
745   0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00
746};
747
748
749
750static void
751DelClientInfoWinAction(Widget w, XEvent *event, String *params,
752		       Cardinal *num_params)
753{
754    XtCallCallbacks (clientInfoDoneButton, XtNcallback, NULL);
755}
756
757
758
759static void
760DelPropWinAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
761{
762    XtCallCallbacks (clientPropDoneButton, XtNcallback, NULL);
763}
764
765
766
767void
768create_client_info_popup(void)
769
770{
771    /*
772     * Install actions for WM_DELETE_WINDOW
773     */
774
775    static XtActionsRec actions[] = {
776        {"DelClientInfoWinAction", DelClientInfoWinAction},
777        {"DelPropWinAction", DelPropWinAction}
778    };
779
780    XtAppAddActions (appContext, actions, XtNumber (actions));
781
782
783    /*
784     * Make checkmark bitmap
785     */
786
787    checkBitmap = XCreateBitmapFromData (
788	XtDisplay (topLevel), RootWindowOfScreen (XtScreen (topLevel)),
789	(char *) check_bits, CHECK_WIDTH, CHECK_HEIGHT);
790
791
792    /*
793     * Pop up for List Clients button.
794     */
795
796    clientInfoPopup = XtVaCreatePopupShell (
797	"clientInfoPopup", topLevelShellWidgetClass, topLevel,
798	XtNallowShellResize, True,
799	NULL);
800
801
802    clientInfoForm = XtVaCreateManagedWidget (
803	"clientInfoForm", formWidgetClass, clientInfoPopup,
804	NULL);
805
806    viewPropButton = XtVaCreateManagedWidget (
807	"viewPropButton", commandWidgetClass, clientInfoForm,
808        XtNfromHoriz, NULL,
809        XtNfromVert, NULL,
810	XtNtop, XawChainTop,
811	XtNbottom, XawChainTop,
812	XtNleft, XawChainLeft,
813	XtNright, XawChainLeft,
814        NULL);
815
816    XtAddCallback (viewPropButton, XtNcallback, ViewPropXtProc, 0);
817
818
819    cloneButton = XtVaCreateManagedWidget (
820	"cloneButton", commandWidgetClass, clientInfoForm,
821        XtNfromHoriz, viewPropButton,
822        XtNfromVert, NULL,
823	XtNtop, XawChainTop,
824	XtNbottom, XawChainTop,
825	XtNleft, XawChainLeft,
826	XtNright, XawChainLeft,
827        NULL);
828
829    XtAddCallback (cloneButton, XtNcallback, CloneXtProc, 0);
830
831
832    killClientButton = XtVaCreateManagedWidget (
833	"killClientButton", commandWidgetClass, clientInfoForm,
834        XtNfromHoriz, cloneButton,
835        XtNfromVert, NULL,
836	XtNtop, XawChainTop,
837	XtNbottom, XawChainTop,
838	XtNleft, XawChainLeft,
839	XtNright, XawChainLeft,
840        NULL);
841
842    XtAddCallback (killClientButton, XtNcallback, KillClientXtProc, 0);
843
844
845    restartHintButton = XtVaCreateManagedWidget (
846	"restartHintButton", menuButtonWidgetClass, clientInfoForm,
847	XtNmenuName, "restartHintMenu",
848        XtNfromHoriz, killClientButton,
849        XtNfromVert, NULL,
850	XtNtop, XawChainTop,
851	XtNbottom, XawChainTop,
852	XtNleft, XawChainLeft,
853	XtNright, XawChainLeft,
854	NULL);
855
856    restartHintMenu = XtVaCreatePopupShell (
857	"restartHintMenu", simpleMenuWidgetClass, clientInfoForm,
858	NULL);
859
860    restartIfRunning = XtVaCreateManagedWidget (
861	"restartIfRunning", smeBSBObjectClass, restartHintMenu,
862	XtNleftMargin, 18,
863	NULL);
864
865    restartAnyway = XtVaCreateManagedWidget (
866	"restartAnyway", smeBSBObjectClass, restartHintMenu,
867	XtNleftMargin, 18,
868	NULL);
869
870    restartImmediately = XtVaCreateManagedWidget (
871	"restartImmediately", smeBSBObjectClass, restartHintMenu,
872	XtNleftMargin, 18,
873	NULL);
874
875    restartNever = XtVaCreateManagedWidget (
876	"restartNever", smeBSBObjectClass, restartHintMenu,
877	XtNleftMargin, 18,
878	NULL);
879
880    XtAddCallback (restartIfRunning, XtNcallback, RestartHintXtProc, 0);
881    XtAddCallback (restartAnyway, XtNcallback, RestartHintXtProc, 0);
882    XtAddCallback (restartImmediately, XtNcallback, RestartHintXtProc, 0);
883    XtAddCallback (restartNever, XtNcallback, RestartHintXtProc, 0);
884
885
886    clientInfoDoneButton = XtVaCreateManagedWidget (
887	"clientInfoDoneButton", commandWidgetClass, clientInfoForm,
888        XtNfromHoriz, restartHintButton,
889        XtNfromVert, NULL,
890	XtNtop, XawChainTop,
891	XtNbottom, XawChainTop,
892	XtNleft, XawChainLeft,
893	XtNright, XawChainLeft,
894        NULL);
895
896    XtAddCallback (clientInfoDoneButton, XtNcallback, listDoneXtProc, 0);
897
898
899    clientListWidget = XtVaCreateManagedWidget (
900	"clientListWidget", listWidgetClass, clientInfoForm,
901        XtNdefaultColumns, 1,
902	XtNforceColumns, True,
903        XtNfromHoriz, NULL,
904        XtNfromVert, viewPropButton,
905	XtNresizable, True,
906	XtNtop, XawChainTop,
907	XtNbottom, XawChainTop,
908	NULL);
909
910    XtAddCallback (clientListWidget, XtNcallback, ClientListXtProc, 0);
911
912    noClientsLabel = XtVaCreateWidget (
913	"noClientsLabel", labelWidgetClass, clientInfoForm,
914        XtNfromHoriz, NULL,
915        XtNfromVert, viewPropButton,
916        XtNborderWidth, 0,
917	XtNtop, XawChainTop,
918	XtNbottom, XawChainTop,
919	NULL);
920
921    manualRestartLabel = XtVaCreateManagedWidget (
922	"manualRestartLabel", labelWidgetClass, clientInfoForm,
923        XtNfromHoriz, NULL,
924        XtNfromVert, clientListWidget,
925        XtNborderWidth, 0,
926        XtNvertDistance, 20,
927	XtNtop, XawChainBottom,
928	XtNbottom, XawChainBottom,
929	XtNleft, XawChainLeft,
930	XtNright, XawChainLeft,
931	NULL);
932
933    manualRestartCommands = XtVaCreateManagedWidget (
934	"manualRestartCommands", asciiTextWidgetClass, clientInfoForm,
935        XtNfromHoriz, NULL,
936        XtNfromVert, manualRestartLabel,
937	XtNeditType, XawtextEdit,
938	XtNresizable, True,
939	XtNresize, XawtextResizeWidth,
940	XtNscrollVertical, XawtextScrollAlways,
941	XtNwidth, 350,
942	XtNheight, 100,
943	XtNtop, XawChainBottom,
944	XtNbottom, XawChainBottom,
945	NULL);
946
947    /*
948     * Pop up for viewing client properties
949     */
950
951    clientPropPopup = XtVaCreatePopupShell (
952	"clientPropPopup", topLevelShellWidgetClass, topLevel,
953	XtNallowShellResize, True,
954	NULL);
955
956
957    clientPropForm = XtVaCreateManagedWidget (
958	"clientPropForm", formWidgetClass, clientPropPopup,
959	NULL);
960
961    clientPropDoneButton = XtVaCreateManagedWidget (
962	"clientPropDoneButton", commandWidgetClass, clientPropForm,
963        XtNfromHoriz, NULL,
964        XtNfromVert, NULL,
965	XtNtop, XawChainTop,
966	XtNbottom, XawChainTop,
967	XtNleft, XawChainLeft,
968	XtNright, XawChainLeft,
969        NULL);
970
971    XtAddCallback (clientPropDoneButton, XtNcallback, clientPropDoneXtProc, 0);
972
973
974    clientPropTextWidget = XtVaCreateManagedWidget (
975	"clientPropTextWidget", asciiTextWidgetClass, clientPropForm,
976        XtNfromHoriz, NULL,
977        XtNfromVert, clientPropDoneButton,
978	XtNeditType, XawtextRead,
979        XtNdisplayCaret, False,
980	XtNscrollVertical, XawtextScrollWhenNeeded,
981	XtNscrollHorizontal, XawtextScrollWhenNeeded,
982	XtNresizable, True,
983	XtNtop, XawChainTop,
984	XtNbottom, XawChainBottom,
985	NULL);
986}
987