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