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