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__) 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__) 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 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 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 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 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 403 onexit(void) 404 { 405 exit (0); 406 } 407