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_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: m_main.c,v 1.3 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/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
40 int vi_ifd = -1;
41 int vi_ofd = -1;
42 IPVIWIN *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
62 static pid_t pid;
63 static Pixel icon_fg,
64 icon_bg;
65 static Pixmap icon_pm;
66 static Widget top_level;
67 static XtAppContext ctx;
68
69 static void XutInstallColormap __P((String, Widget));
70 static void XutSetIcon __P((Widget, int, int, Pixmap));
71 static void onchld __P((int));
72 static void onexit __P((void));
73
74 #if ! defined(ColorIcon)
75 static 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 */
83 String 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__)
get_fallback_rsrcs(String name)127 static String *get_fallback_rsrcs( String name )
128 #else
129 static 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__)
create_top_level_shell(int * argc,char ** argv)164 static void create_top_level_shell( int *argc, char **argv )
165 #else
166 static 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
260 int
main(int argc,char ** argv)261 main(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
294 static void
XutSetIcon(Widget wid,int height,int width,Pixmap p)295 XutSetIcon(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 */
339 static enum { cmap_look, cmap_use, cmap_ignore } cmap_state = cmap_look;
340
341 static Boolean use_colormap = False;
342
343 static XutResource colormap_resources[] = {
344 { "installColormap", XutRKboolean, &use_colormap }
345 };
346
347 static void
XutInstallColormap(String name,Widget wid)348 XutInstallColormap(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 */
390 static void
onchld(int signo)391 onchld(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 */
402 static void
onexit(void)403 onexit(void)
404 {
405 exit (0);
406 }
407