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