xref: /netbsd-src/external/bsd/nvi/dist/motif/m_main.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
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 #ifndef lint
13 static const char sccsid[] = "Id: m_main.c,v 8.40 2003/11/05 17:09:58 skimo Exp  (Berkeley) Date: 2003/11/05 17:09:58 ";
14 #endif /* not lint */
15 
16 #include <sys/types.h>
17 #include <sys/queue.h>
18 
19 #include <X11/Intrinsic.h>
20 #include <X11/StringDefs.h>
21 #include <Xm/MainW.h>
22 
23 #include <bitstring.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #undef LOCK_SUCCESS
30 #include "../common/common.h"
31 #include "../ipc/ip.h"
32 #include "../motif_l/m_motif.h"
33 #include "../motif_l/vi_mextern.h"
34 
35 int     vi_ifd = -1;
36 int     vi_ofd = -1;
37 IPVIWIN   *ipvi_motif;
38 
39 #if XtSpecificationRelease == 4
40 #define	ArgcType	Cardinal *
41 #else
42 #define	ArgcType	int *
43 #endif
44 
45 #if defined(ColorIcon)
46 #if XT_REVISION >= 6
47 #include <X11/xpm.h>
48 #else
49 #include "xpm.h"
50 #endif
51 
52 #include "nvi.xpm"		/* Icon pixmap. */
53 #else
54 #include "nvi.xbm"		/* Icon bitmap. */
55 #endif
56 
57 static	pid_t		pid;
58 static	Pixel		icon_fg,
59 			icon_bg;
60 static	Pixmap		icon_pm;
61 static	Widget		top_level;
62 static	XtAppContext	ctx;
63 
64 static void XutInstallColormap __P((String, Widget));
65 static void XutSetIcon __P((Widget, int, int, Pixmap));
66 static void onchld __P((int));
67 static void onexit __P((void));
68 
69 #if ! defined(ColorIcon)
70 static  XutResource resource[] = {
71     { "iconForeground",	XutRKpixel,	&icon_fg	},
72     { "iconBackground",	XutRKpixel,	&icon_bg	},
73 };
74 #endif
75 
76 
77 /* resources for the vi widgets unless the user overrides them */
78 String	fallback_rsrcs[] = {
79 
80     "*font:			-*-*-*-r-*--14-*-*-*-m-*-*-*",
81     "*text*fontList:		-*-*-*-r-*--14-*-*-*-m-*-*-*",
82     "*Menu*fontList:		-*-helvetica-bold-r-normal--14-*-*-*-*-*-*-*",
83     "*fontList:			-*-helvetica-medium-r-normal--14-*-*-*-*-*-*-*",
84     "*pointerShape:		xterm",
85     "*busyShape:		watch",
86     "*iconName:			vi",
87 
88 #if ! defined(ColorIcon)
89     /* coloring for the icons */
90     "*iconForeground:	XtDefaultForeground",
91     "*iconBackground:	XtDefaultBackground",
92 #endif
93 
94     /* layout for the tag stack dialog */
95     "*Tags*visibleItemCount:			5",
96 
97     /* for the text ruler */
98     "*rulerFont:		-*-helvetica-medium-r-normal--14-*-*-*-*-*-*-*",
99     "*rulerBorder:		5",
100 
101     /* layout for the new, temporary preferences page */
102     "*toggleOptions.numColumns:			6",	/* also used by Find */
103     "*Preferences*tabWidthPercentage:		0",
104     "*Preferences*tabs.shadowThickness:		2",
105     "*Preferences*tabs.font:	-*-helvetica-bold-r-normal--14-*-*-*-*-*-*-*",
106 
107     /* --------------------------------------------------------------------- *
108      * anything below this point is only defined when we are not running CDE *
109      * --------------------------------------------------------------------- */
110 
111     /* Do not define default colors when running under CDE
112      * (e.g. VUE on HPUX). The result is that you don't look
113      * like a normal desktop application
114      */
115     "?background:			gray75",
116     "?screen.background:		wheat",
117     "?highlightColor:			red",
118     "?Preferences*options.background:	gray90",
119 };
120 
121 #if defined(__STDC__)
122 static	String	*get_fallback_rsrcs( String name )
123 #else
124 static	String	*get_fallback_rsrcs( name )
125 	String	name;
126 #endif
127 {
128     String	*copy = (String *) malloc( (1+XtNumber(fallback_rsrcs))*sizeof(String) );
129     int		i, running_cde;
130     Display	*d;
131 
132     /* connect to server and see if the CDE atoms are present */
133     d = XOpenDisplay(0);
134     running_cde = is_cde( d );
135     XCloseDisplay(d);
136 
137     for ( i=0; i<XtNumber(fallback_rsrcs); i++ ) {
138 
139 	/* stop here if running CDE */
140 	if ( fallback_rsrcs[i][0] == '?' ) {
141 	    if ( running_cde ) break;
142 	    fallback_rsrcs[i] = strdup(fallback_rsrcs[i]);
143 	    fallback_rsrcs[i][0] = '*';
144 	}
145 
146 	copy[i] = malloc( strlen(name) + strlen(fallback_rsrcs[i]) + 1 );
147 	strcpy( copy[i], name );
148 	strcat( copy[i], fallback_rsrcs[i] );
149     }
150 
151     copy[i] = NULL;
152     return copy;
153 }
154 
155 
156 /* create the shell widgetry */
157 
158 #if defined(__STDC__)
159 static	void	create_top_level_shell( int *argc, char **argv )
160 #else
161 static	void	create_top_level_shell( argc, argv )
162 	int	*argc;
163 	char	**argv;
164 #endif
165 {
166     char	*ptr;
167     Widget	main_w, editor;
168     Display	*display;
169 
170     /* X gets quite upset if the program name is not simple */
171     if (( ptr = strrchr( argv[0], '/' )) != NULL ) argv[0] = ++ptr;
172     vi_progname = argv[0];
173 
174     /* create a top-level shell for the window manager */
175     top_level = XtVaAppInitialize( &ctx,
176 				   vi_progname,
177 				   NULL, 0,	/* options */
178 				   (ArgcType) argc,
179 				   argv,	/* might get modified */
180 				   get_fallback_rsrcs( argv[0] ),
181 				   NULL
182 				   );
183     display = XtDisplay(top_level);
184 
185     /* might need to go technicolor... */
186     XutInstallColormap( argv[0], top_level );
187 
188     /* create our icon
189      * do this *before* realizing the shell widget in case the -iconic
190      * option was specified.
191      */
192     {
193 #if defined(ColorIcon)
194     int			nvi_width, nvi_height;
195     XpmAttributes	attr;
196 
197     attr.valuemask = 0;
198     XpmCreatePixmapFromData( display,
199 			     DefaultRootWindow(display),
200 			     nvi_xpm,
201 			     &icon_pm,
202 			     NULL,
203 			     &attr
204 			     );
205     nvi_width = attr.width;
206     nvi_height = attr.height;
207 #else
208     /* check the resource database for interesting resources */
209     __XutConvertResources( top_level,
210 			 vi_progname,
211 			 resource,
212 			 XtNumber(resource)
213 			 );
214 
215     icon_pm = XCreatePixmapFromBitmapData(
216 			display,
217 		        DefaultRootWindow(display),
218 			(char *) nvi_bits,
219 			nvi_width,
220 			nvi_height,
221 			icon_fg,
222 			icon_bg,
223 			DefaultDepth( display, DefaultScreen(display) )
224 			);
225 #endif
226     XutSetIcon( top_level, nvi_height, nvi_width, icon_pm );
227     }
228 
229     /* in the shell, we will stack a menubar an editor */
230     main_w = XtVaCreateManagedWidget( "main",
231 				      xmMainWindowWidgetClass,
232 				      top_level,
233 				      NULL
234 				      );
235 
236     /* create the menubar */
237     XtManageChild( (Widget) vi_create_menubar( main_w ) );
238 
239     /* add the VI widget from the library */
240     editor = vi_create_editor( "editor", main_w, onexit );
241 
242     /* put it up */
243     XtRealizeWidget( top_level );
244 
245     /* We *may* want all keyboard events to go to the editing screen.
246      * If the editor is the only widget in the shell that accepts
247      * keyboard input, then the user will expect that he can type when
248      * the pointer is over the scrollbar (for example).  This call
249      * causes that to happen.
250      */
251     XtSetKeyboardFocus( top_level, XtNameToWidget( editor, "*screen" ) );
252 }
253 
254 
255 int
256 main(int argc, char **argv)
257 {
258 	IPVI* ipvi;
259 	/*
260 	 * Initialize the X widgetry.  We must do this before picking off
261 	 * arguments as well-behaved X programs have common argument lists
262 	 * (e.g. -rv for reverse video).
263 	 */
264 	create_top_level_shell(&argc, argv);
265 
266 	/* We need to know if the child process goes away. */
267 	(void)signal(SIGCHLD, onchld);
268 
269 	vi_create(&ipvi, 0);
270 	(void)ipvi->run(ipvi, argc, argv);
271 	ipvi->new_window(ipvi,&ipvi_motif,-1);
272 	ipvi_motif->set_ops(ipvi_motif, &ipsi_ops_motif);
273 	/* Run vi: the parent returns, the child is the vi process. */
274 	vi_ifd = ipvi_motif->ifd;
275 	vi_ofd = ipvi_motif->ofd;
276 	pid = ipvi->pid;
277 
278 	/* Tell X that we are interested in input on the pipe. */
279 	XtAppAddInput(ctx, vi_ifd,
280 	    (XtPointer)XtInputReadMask, vi_input_func, NULL);
281 
282 	/* Main loop. */
283 	XtAppMainLoop(ctx);
284 
285 	/* NOTREACHED */
286 	abort();
287 }
288 
289 static void
290 XutSetIcon(Widget wid, int height, int width, Pixmap p)
291 {
292     Display	*display = XtDisplay(wid);
293     Window	win;
294 
295     /* best bet is to set the icon window */
296     XtVaGetValues( wid, XtNiconWindow, &win, 0 );
297 
298     if ( win == None ) {
299 	win = XCreateSimpleWindow( display,
300 				   RootWindow( display,
301 				   DefaultScreen( display ) ),
302 				   0, 0,
303 				   width, height,
304 				   0,
305 				   CopyFromParent,
306 				   CopyFromParent
307 				   );
308     }
309 
310     if ( win != None ) {
311 	XtVaSetValues( wid, XtNiconWindow, win, 0 );
312 	XSetWindowBackgroundPixmap( display, win, p );
313     }
314 
315     else {
316 	/* do it the old fashioned way */
317 	XtVaSetValues( wid, XtNiconPixmap, p, 0 );
318     }
319 }
320 
321 /* Support for multiple colormaps
322  *
323  * XutInstallColormap( String name, Widget wid )
324  *	The first time called, this routine checks to see if the
325  *	resource "name*installColormap" is "True".  If so, the
326  *	widget is assigned a newly allocated colormap.
327  *
328  *	Subsequent calls ignore the "name" parameter and use the
329  *	same colormap.
330  *
331  *	Future versions of this routine may handle multiple colormaps
332  *	by name.
333  */
334 static	enum { cmap_look, cmap_use, cmap_ignore } cmap_state = cmap_look;
335 
336 static	Boolean	use_colormap = False;
337 
338 static XutResource	colormap_resources[] = {
339     { "installColormap",	XutRKboolean,	&use_colormap	}
340 };
341 
342 static void
343 XutInstallColormap(String name, Widget wid)
344 {
345     static Colormap cmap = 0;
346     static Display  *cmap_display = 0;
347     Display	*display = XtDisplay(wid);
348 
349     /* what is the current finite state? */
350     if ( cmap_state == cmap_look ) {
351 
352 	/* what does the resource say? */
353 	__XutConvertResources( wid,
354 			     name,
355 			     colormap_resources,
356 			     XtNumber(colormap_resources)
357 			     );
358 
359 	/* was the result "True"? */
360 	if ( ! use_colormap ) {
361 	    cmap_state = cmap_ignore;
362 	    return;
363 	}
364 
365 	/* yes it was */
366 	cmap_state = cmap_use;
367 	cmap_display = display;
368 	cmap = XCopyColormapAndFree( display,
369 				     DefaultColormap( display,
370 						      DefaultScreen( display )
371 						      )
372 				     );
373     }
374 
375     /* use the private colormap? */
376     if ( cmap_state == cmap_use ) {
377 	XtVaSetValues( wid, XtNcolormap, cmap, 0 );
378     }
379 }
380 
381 /*
382  * onchld --
383  *	Handle SIGCHLD.
384  */
385 static void
386 onchld(int signo)
387 {
388 	/* If the vi process goes away, we exit as well. */
389 	if (kill(pid, 0))
390 		vi_fatal_message(top_level, "The vi process died.  Exiting.");
391 }
392 
393 /*
394  * onexit --
395  *	Function called when the editor "quits".
396  */
397 static void
398 onexit(void)
399 {
400 	exit (0);
401 }
402