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