xref: /netbsd-src/external/bsd/nvi/dist/motif_l/m_options.c (revision 2f698edb5c1cb2dcd9e762b0abb50c41dde8b6b7)
1 /*-
2  * Copyright (c) 1996
3  *	Rob Zimmermann.  All rights reserved.
4  * Copyright (c) 1996
5  *	Keith Bostic.  All rights reserved.
6  *
7  * See the LICENSE file for redistribution information.
8  */
9 
10 #include "config.h"
11 
12 #include <sys/cdefs.h>
13 #if 0
14 #ifndef lint
15 static const char sccsid[] = "Id: m_options.c,v 8.22 2003/11/05 17:09:59 skimo Exp  (Berkeley) Date: 2003/11/05 17:09:59 ";
16 #endif /* not lint */
17 #else
18 __RCSID("$NetBSD: m_options.c,v 1.2 2014/01/26 21:43:45 christos Exp $");
19 #endif
20 
21 #include <sys/types.h>
22 #include <sys/queue.h>
23 
24 #include <X11/X.h>
25 #include <X11/Intrinsic.h>
26 #include <Xm/DialogS.h>
27 #include <Xm/Form.h>
28 #include <Xm/Frame.h>
29 #include <Xm/LabelG.h>
30 #include <Xm/PushBG.h>
31 #include <Xm/TextF.h>
32 #include <Xm/ToggleBG.h>
33 #include <Xm/RowColumn.h>
34 
35 #include <bitstring.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 
40 #undef LOCK_SUCCESS
41 #include "../common/common.h"
42 #include "../ipc/ip.h"
43 #include "m_motif.h"
44 
45 extern int vi_ofd;
46 
47 static void set_opt __P((Widget, XtPointer, XtPointer));
48 
49 
50 /* constants */
51 
52 #if defined(SelfTest)
53 
54 /* in production, get these from the resource list */
55 
56 #define	toggleColumns	6
57 
58 #endif
59 
60 
61 /*
62  * global data
63  */
64 
65 static Widget	preferences = NULL;
66 
67 static optData display[] = {
68 	{ optToggle,	"comment",	},
69 	{ optToggle,	"flash",	},
70 	{ optToggle,	"leftright",	},
71 	{ optToggle,	"list",		},
72 	{ optToggle,	"number",	},
73 	{ optToggle,	"octal",	},
74 	{ optToggle,	"ruler",	},
75 	{ optToggle,	"showmode",	},
76 	{ optToggle,	"slowopen",	},
77 	{ optToggle,	"verbose",	},
78 	{ optToggle,	"windowname",	},
79 	{ optTerminator,		},
80 }, display_int[] = {
81 	{ optInteger,	"report",	},
82 	{ optInteger,	"scroll",	},
83 	{ optInteger,	"shiftwidth",	},
84 	{ optInteger,	"sidescroll",	},
85 	{ optInteger,	"tabstop",	},
86 	{ optInteger,	"window",	},
87 	{ optTerminator,		},
88 }, display_str[] = {
89 	{ optString,	"noprint",	},
90 	{ optString,	"print",	},
91 	{ optTerminator,		},
92 }, files[] = {
93 	{ optToggle,	"autowrite",	},
94 	{ optToggle,	"lock",		},
95 	{ optToggle,	"readonly",	},
96 	{ optToggle,	"writeany",	},
97 	{ optTerminator,		},
98 }, files_str[] = {
99 	{ optString,	"backup",	},
100 	{ optString,	"path",		},
101 	{ optTerminator,		},
102 }, general[] = {
103 	{ optToggle,	"exrc",		},
104 	{ optToggle,	"lisp",		},
105 	{ optToggle,	"modeline",	},
106 	{ optToggle,	"sourceany",	},
107 	{ optToggle,	"tildeop",	},
108 	{ optTerminator,		},
109 }, general_int[] = {
110 	{ optInteger,	"taglength",	},
111 	{ optTerminator,		},
112 }, general_str[] = {
113 	{ optString,	"cdpath",	},
114 	{ optString,	"directory",	},
115 	{ optString,	"msgcat",	},
116 	{ optString,	"recdir",	},
117 	{ optString,	"shell",	},
118 	{ optString,	"shellmeta",	},
119 	{ optString,	"tags",		},
120 	{ optTerminator,		},
121 }, input[] = {
122 	{ optToggle,	"altwerase",	},
123 	{ optToggle,	"autoindent",	},
124 	{ optToggle,	"remap",	},
125 	{ optToggle,	"showmatch",	},
126 	{ optToggle,	"ttywerase",	},
127 	{ optTerminator,		},
128 }, input_int[] = {
129 	{ optInteger,	"escapetime",	},
130 	{ optInteger,	"keytime",	},
131 	{ optInteger,	"matchtime",	},
132 	{ optInteger,	"timeout",	},
133 	{ optInteger,	"wraplen",	},
134 	{ optInteger,	"wrapmargin",	},
135 	{ optTerminator,		},
136 }, input_str[] = {
137 	{ optString,	"cedit",	},
138 	{ optString,	"filec",	},
139 	{ optTerminator,		},
140 }, search[] = {
141 	{ optToggle,	"extended",	},
142 	{ optToggle,	"iclower",	},
143 	{ optToggle,	"ignorecase",	},
144 	{ optToggle,	"magic",	},
145 	{ optToggle,	"searchincr",	},
146 	{ optToggle,	"wrapscan",	},
147 	{ optTerminator,		},
148 }, search_str[] = {
149 	{ optString,	"paragraphs",	},
150 	{ optString,	"sections",	},
151 	{ optTerminator,		},
152 };
153 
154 /* ********* NOTE ***********
155  * Sheet 0 will always be shown first.  It does not matter to the Xt code
156  * which sheet that is, so it ought to be the one users interact with most.
157  * Best guess is that's general editor options, but it might be Search/re.
158  * ********* NOTE ***********
159  */
160 static	optSheet sheets[] = {
161 	{	"Display",
162 		"These options control how text is displayed on the screen",
163 		NULL,
164 		display,
165 		display_int,
166 		display_str,
167 	},
168 	{	"Files",
169 		"These options control how the editor handles files",
170 		NULL,
171 		files,
172 		NULL,
173 		files_str,
174 	},
175 	{	"Input",
176 		"These options control text input behavior",
177 		NULL,
178 		input,
179 		input_int,
180 		input_str,
181 	},
182 	{	"Search/RE",
183 	"These options control searching and Regular Expression behavior",
184 		NULL,
185 		search,
186 		NULL,
187 		search_str,
188 	},
189 	{	"Editor",
190 		"These options control general editor configuration",
191 		NULL,
192 		general,
193 		general_int,
194 		general_str,
195 	},
196 };
197 
198 
199 /* callbacks */
200 
201 #if defined(SelfTest)
__vi_cancel_cb()202 void __vi_cancel_cb()
203 {
204     puts( "cancelled" );
205 }
206 #endif
207 
208 
destroyed(void)209 static	void destroyed(void)
210 {
211     int i;
212 
213     puts( "destroyed" );
214 
215     /* some window managers destroy us upon popdown */
216     for (i=0; i<XtNumber(sheets); i++) {
217 	sheets[i].holder = NULL;
218     }
219     preferences = NULL;
220 }
221 
222 
window_unmapped(Widget w,XtPointer ptr,XEvent * ev,Boolean * cont)223 static	void	window_unmapped(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont)
224 {
225     if ( ev->type == UnmapNotify ) {
226 #if defined(SelfTest)
227 	puts( "unmapped" );
228 #endif
229 	XtPopdown( XtParent( preferences ) );
230     }
231 }
232 
233 /*
234  * __vi_editopt --
235  *	Set an edit option based on a core message.
236  *
237  * PUBLIC: int __vi_editopt __P((IPVI *, const char *, u_int32_t, const char *, u_int32_t, u_int32_t));
238  */
239 int
__vi_editopt(IPVI * ipvi,const char * str1,u_int32_t len1,const char * str2,u_int32_t len2,u_int32_t val1)240 __vi_editopt(IPVI *ipvi, const char *str1, u_int32_t len1, const char *str2, u_int32_t len2, u_int32_t val1)
241 {
242 	optData *opt;
243 
244 #undef	NSEARCH
245 #define	NSEARCH(list) {							\
246 	for (opt = list; opt->kind != optTerminator; ++opt)		\
247 		if (!strcmp(opt->name, str1))			\
248 			goto found;					\
249 }
250 
251 	NSEARCH(display);
252 	NSEARCH(display_int);
253 	NSEARCH(display_str);
254 	NSEARCH(files);
255 	NSEARCH(files_str);
256 	NSEARCH(general);
257 	NSEARCH(general_int);
258 	NSEARCH(general_str);
259 	NSEARCH(input);
260 	NSEARCH(input_int);
261 	NSEARCH(input_str);
262 	NSEARCH(search);
263 	NSEARCH(search_str);
264 
265 	return (0);
266 
267 found:	switch (opt->kind) {
268 	case optToggle:
269 		opt->value = (void *)val1;
270 		break;
271 	case optInteger:
272 		if (opt->value != NULL)
273 			free(opt->value);
274 		if ((opt->value = malloc(8)) != NULL)
275 			(void)snprintf(opt->value,
276 			    8, "%lu", (u_long)val1);
277 		break;
278 	case optString:
279 	case optFile:
280 		if (opt->value != NULL)
281 			free(opt->value);
282 		if ((opt->value = malloc(len2)) != NULL)
283 			memcpy(opt->value, str2, len2);
284 		break;
285 	case optTerminator:
286 		abort();
287 	}
288 	return (0);
289 }
290 
291 /*
292  * set_opt --
293  *	Send a set-edit-option message to core.
294  */
295 static void
set_opt(Widget w,XtPointer closure,XtPointer call_data)296 set_opt(Widget w, XtPointer closure, XtPointer call_data)
297 {
298 	optData *opt;
299 	Boolean set;
300 	IP_BUF ipb;
301 	String str;
302 	extern IPVI ipvi_motif;
303 
304 	opt = closure;
305 
306 	ipb.code = VI_EDITOPT;
307 	ipb.str1 = opt->name;
308 	ipb.len1 = strlen(opt->name);
309 
310 	switch (opt->kind) {
311 	case optToggle:
312 		XtVaGetValues(w, XmNset, &set, 0);
313 		ipb.val1 = set;
314 		ipb.len2 = 0;
315 
316 		vi_wsend(&ipvi_motif, "ab1", &ipb);
317 		if (ipb.val1) {
318 			opt->value = (void *)!set;
319 			/*
320 			 * RAZ:
321 			 * How do we turn off the button?  We don't want to
322 			 * go recursive where we set it and it calls set_opt
323 			 * to tell the core.  Is that possible?
324 			 */
325 			XtVaSetValues(w, XmNset, &set, 0);
326 			break;
327 		}
328 
329 		if (strcmp(opt->name, "ruler") == 0)
330 			if (set)
331 				__vi_show_text_ruler_dialog(
332 				    __vi_screen->area, "Ruler");
333 			else
334 				__vi_clear_text_ruler_dialog();
335 		break;
336 	case optInteger:
337 		str = XmTextFieldGetString(w);
338 		ipb.val1 = atoi(str);
339 		ipb.len2 = 0;
340 		vi_send(vi_ofd, "ab1", &ipb);
341 		break;
342 	case optFile:
343 	case optString:
344 		ipb.str2 = XmTextFieldGetString(w);
345 		ipb.len2 = strlen(ipb.str2);
346 		vi_send(vi_ofd, "ab1", &ipb);
347 		break;
348 	case optTerminator:
349 		abort();
350 	}
351 }
352 
353 
354 /* add toggles to the property sheet */
355 
356 #if defined(__STDC__)
add_toggle(Widget parent,optData * option)357 static	void	add_toggle( Widget parent, optData *option )
358 #else
359 static	void	add_toggle( parent, option )
360 	Widget	parent;
361 	optData	*option;
362 #endif
363 {
364     Widget	w;
365 
366     w = XtVaCreateManagedWidget( option->name,
367 				 xmToggleButtonGadgetClass,
368 				 parent,
369 				 XmNset,	(Boolean) option->value,
370 				 0
371 				 );
372     XtAddCallback( w, XmNvalueChangedCallback, set_opt, option );
373 }
374 
375 
create_toggles(Widget outer,optData * toggles)376 static	Widget	create_toggles(Widget outer, optData *toggles)
377 {
378     Widget	inner;
379     int		i;
380 
381     inner = XtVaCreateWidget( "toggleOptions",
382 			      xmRowColumnWidgetClass,
383 			      outer,
384 			      XmNpacking,		XmPACK_COLUMN,
385 			      XmNnumColumns,		4,
386 			      XmNtopAttachment,		XmATTACH_FORM,
387 			      XmNrightAttachment,	XmATTACH_FORM,
388 			      XmNleftAttachment,	XmATTACH_FORM,
389 			      0
390 			      );
391 
392     /* first the booleans */
393     for (i=0; toggles[i].kind != optTerminator; i++) {
394 	add_toggle( inner, &toggles[i] );
395     }
396     XtManageChild( inner );
397 
398     return inner;
399 }
400 
401 
402 /* draw text fields and their labels */
403 
404 #if defined(__STDC__)
add_string_options(Widget parent,optData * options)405 static	void	add_string_options( Widget parent,
406 				    optData *options
407 				    )
408 #else
409 static	void	add_string_options( parent, options )
410 	Widget	parent;
411 	optData	*options;
412 #endif
413 {
414     int		i;
415     Widget	f, w;
416 
417     for ( i=0; options[i].kind != optTerminator; i++ ) {
418 
419 	f = XtVaCreateWidget( "form",
420 			      xmFormWidgetClass,
421 			      parent,
422 			      0
423 			      );
424 
425 	XtVaCreateManagedWidget( options[i].name,
426 				 xmLabelGadgetClass,
427 				 f,
428 				 XmNtopAttachment,	XmATTACH_FORM,
429 				 XmNbottomAttachment,	XmATTACH_FORM,
430 				 XmNleftAttachment,	XmATTACH_FORM,
431 				 XmNrightAttachment,	XmATTACH_POSITION,
432 				 XmNrightPosition,	20,
433 				 XmNalignment,		XmALIGNMENT_END,
434 				 0
435 				 );
436 
437 	w = XtVaCreateManagedWidget( "text",
438 				     xmTextFieldWidgetClass,
439 				     f,
440 				     XmNtopAttachment,		XmATTACH_FORM,
441 				     XmNbottomAttachment,	XmATTACH_FORM,
442 				     XmNrightAttachment,	XmATTACH_FORM,
443 				     XmNleftAttachment,		XmATTACH_POSITION,
444 				     XmNleftPosition,		20,
445 				     0
446 				     );
447 
448 	XmTextFieldSetString( w, (char *) options[i].value );
449 	XtAddCallback( w, XmNactivateCallback, set_opt, &options[i] );
450 	XtManageChild( f );
451     }
452 }
453 
454 
455 /* draw and display a single page of properties */
456 
457 #if defined(__STDC__)
create_sheet(Widget parent,optSheet * sheet)458 static	Widget		create_sheet( Widget parent, optSheet *sheet )
459 #else
460 static	Widget		create_sheet( parent, sheet )
461 	Widget		parent;
462 	optSheet	*sheet;
463 #endif
464 {
465     Widget	outer, inner, frame;
466     Dimension	height;
467     XmString	str;
468 
469     outer = XtVaCreateWidget( sheet->name,
470 			      xmFormWidgetClass,
471 			      parent,
472 			      XmNtopAttachment,		XmATTACH_FORM,
473 			      XmNrightAttachment,	XmATTACH_FORM,
474 			      XmNbottomAttachment,	XmATTACH_FORM,
475 			      XmNleftAttachment,	XmATTACH_FORM,
476 			      XmNshadowType,		XmSHADOW_ETCHED_IN,
477 			      XmNshadowThickness,	2,
478 			      XmNverticalSpacing,	4,
479 			      XmNhorizontalSpacing,	4,
480 			      0
481 			      );
482 
483     /* add descriptive text */
484     frame = XtVaCreateManagedWidget( "frame",
485 				    xmFrameWidgetClass,
486 				    outer,
487 				    XmNtopAttachment,		XmATTACH_FORM,
488 				    XmNrightAttachment,		XmATTACH_FORM,
489 				    XmNleftAttachment,		XmATTACH_FORM,
490 				    0
491 				    );
492     str = XmStringCreateLtoR( sheet->description, XmSTRING_DEFAULT_CHARSET );
493     XtVaCreateManagedWidget( "description",
494 			     xmLabelGadgetClass,
495 			     frame,
496 			     XmNlabelString,		str,
497 			     0
498 			     );
499     XmStringFree( str );
500 
501     /* Add the toggles. */
502     inner = create_toggles( outer, sheet->toggles );
503     XtVaSetValues( inner,
504 		   XmNtopAttachment,	XmATTACH_WIDGET,
505 		   XmNtopWidget,	frame,
506 		   0
507 		   );
508 
509     /* the string options go here */
510     inner = XtVaCreateWidget( "otherOptions",
511 			      xmRowColumnWidgetClass,
512 			      outer,
513 			      XmNpacking,		XmPACK_COLUMN,
514 			      XmNtopAttachment,		XmATTACH_WIDGET,
515 			      XmNtopWidget,		inner,
516 			      XmNrightAttachment,	XmATTACH_FORM,
517 			      XmNbottomAttachment,	XmATTACH_FORM,
518 			      XmNleftAttachment,	XmATTACH_FORM,
519 			      0
520 			      );
521 
522     /* Optionally, the ints. */
523     if ( sheet->ints != NULL )
524 	add_string_options( inner, sheet->ints );
525 
526      /* Optionally, the rest. */
527     if ( sheet->others != NULL )
528 	add_string_options( inner, sheet->others );
529 
530     XtManageChild( inner );
531 
532     /* finally, force resize of the parent */
533     XtVaGetValues( outer, XmNheight, &height, 0 );
534     XtVaSetValues( parent, XmNheight, height, 0 );
535 
536     return outer;
537 }
538 
539 
540 /* change preferences to another sheet */
541 
change_sheet(Widget parent,int current)542 static	void	change_sheet(Widget parent, int current)
543 {
544     static int		current_sheet = -1;
545 
546     /* create a new one? */
547     if ( sheets[current].holder == NULL )
548 	sheets[current].holder = create_sheet( parent, &sheets[current] );
549 
550     /* done with the old one? */
551     if ( current_sheet != -1 && sheets[current_sheet].holder != NULL )
552 	XtUnmanageChild( sheets[current_sheet].holder );
553 
554     current_sheet = current;
555     XtManageChild( sheets[current].holder );
556     XtManageChild( parent );
557 }
558 
559 
560 /* Draw and display a dialog the describes vi options */
561 
562 #if defined(__STDC__)
create_options_dialog(Widget parent,String title)563 static	Widget	create_options_dialog( Widget parent, String title )
564 #else
565 static	Widget	create_options_dialog( parent, title )
566 	Widget	parent;
567 	String	title;
568 #endif
569 {
570     Widget	box, form, inner;
571     int		i;
572     char	buffer[1024];
573 
574     /* already built? */
575     if ( preferences != NULL ) return preferences;
576 
577     box = XtVaCreatePopupShell( title,
578 				xmDialogShellWidgetClass,
579 				parent,
580 				XmNtitle,		title,
581 				XmNallowShellResize,	False,
582 				0
583 				);
584     XtAddCallback( box, XmNpopdownCallback, __vi_cancel_cb, 0 );
585     XtAddCallback( box, XmNdestroyCallback, destroyed, 0 );
586     XtAddEventHandler( box,
587 		       SubstructureNotifyMask,
588 		       False,
589 		       window_unmapped,
590 		       NULL
591 		       );
592 
593     form = XtVaCreateWidget( "options",
594 			     xmFormWidgetClass,
595 			     box,
596 			     0
597 			     );
598 
599     /* copy the pointers to the sheet names */
600     *buffer = '\0';
601     for (i=0; i<XtNumber(sheets); i++) {
602 	strcat( buffer, "|" );
603 	strcat( buffer, sheets[i].name );
604     }
605 
606     inner = __vi_CreateTabbedFolder( "tabs",
607 				    form,
608 				    buffer,
609 				    XtNumber(sheets),
610 				    change_sheet
611 				    );
612 
613     /* build the property sheets early */
614     for ( i=0; i<XtNumber(sheets); i++ )
615 	change_sheet( inner, i );
616 
617     /* manage all of the sheets right now */
618     for ( i=0; i<XtNumber(sheets); i++ )
619 	XtManageChild( sheets[i].holder );
620     XtManageChild( form );
621 
622     /* remove all but the first one */
623     for ( i=0; i<XtNumber(sheets); i++ )
624 	XtUnmanageChild( sheets[i].holder );
625     change_sheet( inner, 0 );	/* show first sheet first */
626 
627     /* keep this global, we might destroy it later */
628     preferences = form;
629 
630     /* done */
631     return form;
632 }
633 
634 
635 
636 /*
637  * module entry point
638  *
639  * __vi_show_options_dialog --
640  *
641  *
642  * PUBLIC: void __vi_show_options_dialog __P((Widget, String));
643  */
644 void
__vi_show_options_dialog(Widget parent,String title)645 __vi_show_options_dialog(Widget parent, String title)
646 {
647     Widget 	db = create_options_dialog( parent, title );
648 #if defined(SelfTest)
649     Widget	shell = XtParent( db );
650 #endif
651 
652     XtManageChild( db );
653 
654 #if defined(SelfTest)
655     /* wait until it goes away */
656     XtPopup( shell, XtGrabNone );
657 #else
658     /* wait until it goes away */
659     __vi_modal_dialog( db );
660 #endif
661 }
662 
663 
664 
665 /* module entry point
666  * Utilities for the search dialog
667  *
668  * __vi_toggle --
669  *	Returns the current value of a toggle.
670  *
671  * PUBLIC: int __vi_toggle __P((char *));
672  */
673 int
__vi_toggle(char * name)674 __vi_toggle(char *name)
675 {
676 	optData *opt;
677 
678 #undef	NSEARCH
679 #define	NSEARCH(list) {							\
680 	for (opt = list; opt->kind != optTerminator; ++opt)		\
681 		if (!strcmp(opt->name, name))				\
682 			return ((int)opt->value);			\
683 }
684 	NSEARCH(display);
685 	NSEARCH(files);
686 	NSEARCH(general);
687 	NSEARCH(input);
688 	NSEARCH(search);
689 
690 	return (0);
691 }
692 
693 /*
694  * __vi_create_search_toggles --
695  *	Creates the search toggles.  This is so the options and search widgets
696  *	share their appearance.
697  *
698  * PUBLIC: Widget __vi_create_search_toggles __P((Widget, optData[]));
699  */
700 Widget
__vi_create_search_toggles(Widget parent,optData * list)701 __vi_create_search_toggles(Widget parent, optData *list)
702 {
703 	optData *opt;
704 
705 	/*
706 	 * Copy current options information into the search table.
707 	 *
708 	 * XXX
709 	 * This is an O(M*N) loop, but I don't think it matters.
710 	 */
711 	for (opt = list; opt->kind != optTerminator; ++opt)
712 		opt->value = (void *)__vi_toggle(opt->name);
713 
714 	return (create_toggles(parent, list));
715 }
716 
717 
718 #if defined(SelfTest)
719 
720 #if defined(__STDC__)
show_options(Widget w,XtPointer data,XtPointer cbs)721 static void show_options( Widget w, XtPointer data, XtPointer cbs )
722 #else
723 static void show_options( w, data, cbs )
724 Widget w;
725 XtPointer	data;
726 XtPointer	cbs;
727 #endif
728 {
729     __vi_show_options_dialog( data, "Preferences" );
730 }
731 
main(int argc,char * argv[])732 main( int argc, char *argv[] )
733 {
734     XtAppContext	ctx;
735     Widget		top_level, rc, button;
736     extern		exit();
737 
738     /* create a top-level shell for the window manager */
739     top_level = XtVaAppInitialize( &ctx,
740 				   argv[0],
741 				   NULL, 0,	/* options */
742 				   (ArgcType) &argc,
743 				   argv,	/* might get modified */
744 				   NULL,
745 				   NULL
746 				   );
747 
748     rc = XtVaCreateManagedWidget( "rc",
749 				  xmRowColumnWidgetClass,
750 				  top_level,
751 				  0
752 				  );
753 
754     button = XtVaCreateManagedWidget( "Pop up options dialog",
755 				      xmPushButtonGadgetClass,
756 				      rc,
757 				      0
758 				      );
759     XtAddCallback( button, XmNactivateCallback, show_options, rc );
760 
761     button = XtVaCreateManagedWidget( "Quit",
762 				      xmPushButtonGadgetClass,
763 				      rc,
764 				      0
765 				      );
766     XtAddCallback( button, XmNactivateCallback, exit, 0 );
767 
768     XtRealizeWidget(top_level);
769     XtAppMainLoop(ctx);
770 }
771 #endif
772