sources-request@mirror.TMC.COM (04/21/87)
Submitted by: edmoy%opal.Berkeley.EDU@berkeley.edu Mod.sources: Volume 9, Issue 58 Archive-name: xterm6.6b/Part05 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # main.c menu.c if test -f main.c then echo shar: will not overwrite existing file "'main.c'" else echo 'x - main.c' cat << \RAZZLE!DAZZLE > main.c /* * $Source: /u1/X/xterm/RCS/main.c,v $ * $Header: main.c,v 10.101 86/12/01 16:58:10 swick Rel $ */ #include <X/mit-copyright.h> /* Copyright Massachusetts Institute of Technology 1984, 1985 */ /* main.c */ #ifndef lint static char sccs_id[] = "@(#)main.c\tX10/6.6B\t12/28/86"; #endif lint #include <pwd.h> #include <sgtty.h> #include <sys/wait.h> #include <sys/time.h> #include <sys/resource.h> #include <stdio.h> #include <sys/file.h> #include <errno.h> #include <signal.h> #include <strings.h> #include <setjmp.h> #include <utmp.h> #include <sys/param.h> /* for NOFILE */ #include <X/Xlib.h> #include "scrollbar.h" #include "ptyx.h" #include "data.h" #include "error.h" #include "main.h" int switchfb[] = {0, 2, 1, 3}; static int reapchild (); static char *brdr_color; static char **command_to_exec; #ifdef TIOCCONS static int Console; #endif TIOCCONS static struct sgttyb d_sg = { 0, 0, 0177, CKILL, EVENP|ODDP|ECHO|XTABS|CRMOD }; static struct tchars d_tc = { CINTR, CQUIT, CSTART, CSTOP, CEOF, CBRK, }; static struct ltchars d_ltc = { CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT }; static int d_disipline = NTTYDISC; static int d_lmode = LCRTBS|LCRTERA|LCRTKIL|LCTLECH; static char def_bold_font[] = DEFBOLDFONT; static char def_font[] = DEFFONT; static char def_title_font[] = DEFTITLEFONT; static char def_icon_font[] = DEFICONFONT; static char display[256]; static char etc_utmp[] = "/etc/utmp"; static char *get_ty; static char *iconbitmap; static int inhibit; static int log_on; static int login_shell; static char passedPty[2]; /* name if pty if slave */ static int loginpty; static char *tekiconbitmap; static int tslot; static char *xdef[] = { "ActiveIcon", /* DEF_ACTIVEICON */ "AllowIconInput", /* DEF_ALLOWICONINPUT */ "AutoRaise", /* DEF_AUTORAISE */ "Background", /* DEF_BACKGROUND */ "BodyFont", /* DEF_BODYFONT */ "BoldFont", /* DEF_BOLDFONT */ "Border", /* DEF_BORDER */ "BorderWidth", /* DEF_BORDERWIDTH */ "C132", /* DEF_C132 */ "Curses", /* DEF_CURSES */ "Cursor", /* DEF_CURSOR */ "DeiconifyWarp", /* DEF_DEICONWARP */ "Foreground", /* DEF_FOREGROUND */ "IconBitmap", /* DEF_ICONBITMAP */ "IconFont", /* DEF_ICONFONT */ "IconStartup", /* DEF_ICONSTARTUP */ "InternalBorder", /* DEF_INTERNALBORDER */ "JumpScroll", /* DEF_JUMPSCROLL */ #ifdef KEYBD "KeyBoard", /* DEF_KEYBOARD */ #endif KEYBD "LogFile", /* DEF_LOGFILE */ "Logging", /* DEF_LOGGING */ "LogInhibit", /* DEF_LOGINHIBIT */ "LoginShell", /* DEF_LOGINSHELL */ "MarginBell", /* DEF_MARGINBELL */ "Mouse", /* DEF_MOUSE */ "NMarginBell", /* DEF_NMARGINBELL */ "PageOverlap", /* DEF_PAGEOVERLAP */ "PageScroll", /* DEF_PAGESCROLL */ "ReverseVideo", /* DEF_REVERSEVIDEO */ "ReverseWrap", /* DEF_REVERSEWRAP */ "SaveLines", /* DEF_SAVELINES */ "ScrollBar", /* DEF_SCROLLBAR */ "ScrollInput", /* DEF_SCROLLINPUT */ "ScrollKey", /* DEF_SCROLLKEY */ "SignalInhibit", /* DEF_SIGNALINHIBIT */ "StatusLine", /* DEF_STATUSLINE */ "StatusNormal", /* DEF_STATUSNORMAL */ "TekIconBitmap", /* DEF_TEKICONBITMAP */ "TekInhibit", /* DEF_TEKINHIBIT */ "TextUnderIcon", /* DEF_TEXTUNDERICON */ "TitleBar", /* DEF_TITLEBAR */ "TitleFont", /* DEF_TITLEFONT */ "VisualBell", /* DEF_VISUALBELL */ 0, }; #ifdef UTMP static int added_utmp_entry; #endif UTMP main (argc, argv) int argc; char **argv; { register Screen *screen = &term.screen; register char *strind; register int i, pty; register char **cp; short fnflag = 0; /* True iff -fn option used */ short fbflag = 0; /* True iff -fb option used */ int Xsocket, mode; extern onalarm(); char *malloc(); char *basename(); int xerror(), xioerror(); #ifdef KEYBD extern char *keyboardtype; /* used in XKeyBind.c */ char *getenv(); #endif KEYBD xterm_name = (strcmp(*argv, "-") == 0) ? "xterm" : basename(*argv); term.flags = WRAPAROUND | SMOOTHSCROLL | AUTOREPEAT; screen->border = DEFBORDER; screen->borderwidth = DEFBORDERWIDTH; screen->reversestatus = TRUE; screen->mappedVwin = &screen->fullVwin; screen->mappedTwin = &screen->fullTwin; f_b = def_bold_font; f_n = def_font; f_t = def_title_font; f_i = def_icon_font; display[0] = '\0'; #ifdef KEYBD if((strind = getenv("KEYBD")) && *strind) { if((keyboardtype = malloc(strlen(strind) + 1)) == NULL) SysError(ERROR_KMALLOC); strcpy(keyboardtype, strind); } #endif KEYBD /* * go get options out of default file */ for(i = 0, cp = xdef ; *cp ; i++, cp++) { if(!(strind = XGetDefault(xterm_name, *cp))) continue; switch(i) { case DEF_ACTIVEICON: if (strcmp (strind, "on") == 0) screen->active_icon = TRUE; continue; case DEF_ALLOWICONINPUT: if (strcmp (strind, "on") == 0) term.flags |= ICONINPUT; continue; case DEF_AUTORAISE: if (strcmp (strind, "on") == 0) screen->autoraise = TRUE; continue; case DEF_BACKGROUND: back_color = strind; continue; case DEF_BODYFONT: f_n = strind; fnflag = TRUE; continue; case DEF_BOLDFONT: f_b = strind; fbflag = TRUE; continue; case DEF_BORDER: brdr_color = strind; continue; case DEF_BORDERWIDTH: screen->borderwidth = atoi (strind); continue; case DEF_C132: if (strcmp (strind, "on") == 0) screen->c132 = TRUE; continue; case DEF_CURSES: if (strcmp (strind, "on") == 0) screen->curses = TRUE; continue; case DEF_CURSOR: curs_color = strind; continue; case DEF_DEICONWARP: if (strcmp (strind, "on") == 0) screen->deiconwarp = TRUE; continue; case DEF_FOREGROUND: fore_color = strind; continue; case DEF_ICONBITMAP: iconbitmap = strind; continue; case DEF_ICONFONT: f_i = strind; continue; case DEF_ICONSTARTUP: if (strcmp (strind, "on") == 0) screen->icon_show = -1; continue; case DEF_INTERNALBORDER: screen->border = atoi (strind); continue; case DEF_JUMPSCROLL: if (strcmp (strind, "on") == 0) { screen->jumpscroll = TRUE; term.flags &= ~SMOOTHSCROLL; } continue; #ifdef KEYBD case DEF_KEYBOARD: if(keyboardtype) free(keyboardtype); keyboardtype = strind; continue; #endif KEYBD case DEF_LOGFILE: if(screen->logfile = malloc(strlen(strind) + 1)) strcpy(screen->logfile, strind); continue; case DEF_LOGGING: if (strcmp (strind, "on") == 0) log_on = TRUE; continue; case DEF_LOGINHIBIT: if (strcmp (strind, "on") == 0) inhibit |= I_LOG; continue; case DEF_LOGINSHELL: if (strcmp (strind, "on") == 0) login_shell = TRUE; continue; case DEF_MARGINBELL: if (strcmp (strind, "on") == 0) screen->marginbell = TRUE; continue; case DEF_MOUSE: mous_color = strind; continue; case DEF_NMARGINBELL: n_marginbell = atoi (strind); continue; case DEF_PAGEOVERLAP: if((screen->pageoverlap = atoi (strind) - 1) < 0) screen->pageoverlap = -1; continue; case DEF_PAGESCROLL: if (strcmp (strind, "on") == 0) screen->pagemode = TRUE; continue; case DEF_REVERSEVIDEO: if (strcmp (strind, "on") == 0) re_verse = TRUE; continue; case DEF_REVERSEWRAP: if (strcmp (strind, "on") == 0) term.flags |= REVERSEWRAP; continue; case DEF_SAVELINES: save_lines = atoi (strind); continue; case DEF_SCROLLBAR: if (strcmp (strind, "on") == 0) screen->scrollbar = SCROLLBARWIDTH; continue; case DEF_SCROLLINPUT: if (strcmp (strind, "on") == 0) screen->scrollinput = TRUE; continue; case DEF_SCROLLKEY: if (strcmp (strind, "on") == 0) screen->scrollkey = TRUE; continue; case DEF_SIGNALINHIBIT: if (strcmp (strind, "on") == 0) inhibit |= I_SIGNAL; continue; case DEF_STATUSLINE: if (strcmp (strind, "on") == 0) screen->statusline = TRUE; continue; case DEF_STATUSNORMAL: screen->reversestatus = (strcmp (strind, "on") != 0); continue; case DEF_TEKICONBITMAP: tekiconbitmap = strind; continue; case DEF_TEKINHIBIT: if (strcmp (strind, "on") == 0) inhibit |= I_TEK; continue; case DEF_TEXTUNDERICON: if (strcmp (strind, "on") == 0) screen->textundericon = TRUE; continue; case DEF_TITLEBAR: if (strcmp (strind, "on") == 0) screen->fullVwin.titlebar = TRUE; continue; case DEF_TITLEFONT: f_t = strind; continue; case DEF_VISUALBELL: if (strcmp (strind, "on") == 0) screen->visualbell = TRUE; continue; } } /* parse command line */ for (argc--, argv++ ; argc > 0 ; argc--, argv++) { if (**argv == '=') { geo_metry = *argv; continue; } if (**argv == '%') { T_geometry = *argv; *T_geometry = '='; continue; } if (**argv == '#') { icon_geom = *argv; *icon_geom = '='; continue; } if((strind = index (*argv, ':')) != NULL) { strncpy(display, *argv, sizeof(display)); continue; } if(!(i = (**argv == '-')) && **argv != '+') Syntax (); switch(argument(&(*argv)[1])) { case ARG_132: screen->c132 = i; continue; #ifdef TIOCCONS case ARG__C: Console = i; continue; #endif TIOCCONS case ARG__L: { char tt[32]; L_flag = 1; get_ty = argv[--argc]; strcpy(tt,"/dev/"); strcat(tt, get_ty); tt[5] = 'p'; loginpty = open( tt, O_RDWR, 0 ); dup2( loginpty, 4 ); close( loginpty ); loginpty = 4; tt[5] = 't'; chown(tt, 0, 0); chmod(tt, 0622); if (open(tt, O_RDWR) < 0) { consolepr("open failed\n"); } signal(SIGHUP, SIG_IGN); vhangup(); setpgrp(0,0); signal(SIGHUP, SIG_DFL); (void) close(0); open(tt, O_RDWR, 0); dup2(0, 1); dup2(0, 2); continue; } case ARG__S: if(i) { if (--argc <= 0) Syntax (); sscanf(*++argv, "%c%c%d", passedPty, passedPty+1, &am_slave); if (am_slave <= 0) Syntax(); } else am_slave = 0; continue; case ARG_AI: screen->active_icon = i; continue; case ARG_AR: screen->autoraise = i; continue; case ARG_B: if(i) { if (--argc <= 0) Syntax (); screen->border = atoi (*++argv); } else screen->border = DEFBORDER; continue; case ARG_BD: if(i) { if (--argc <= 0) Syntax (); brdr_color = *++argv; } else brdr_color = NULL; continue; case ARG_BG: if(i) { if (--argc <= 0) Syntax (); back_color = *++argv; } else back_color = NULL; continue; case ARG_BW: if(i) { if (--argc <= 0) Syntax (); screen->borderwidth = atoi (*++argv); } else screen->borderwidth = DEFBORDERWIDTH; continue; case ARG_CR: if(i) { if (--argc <= 0) Syntax (); curs_color = *++argv; } else curs_color = NULL; continue; case ARG_CU: screen->curses = i; continue; #ifdef DEBUG case ARG_D: debug = i; continue; #endif DEBUG case ARG_DW: screen->deiconwarp = i; continue; case ARG_E: if(!i) Syntax(); if (argc <= 1) Syntax (); command_to_exec = ++argv; break; case ARG_FB: if(fbflag = i) { if (--argc <= 0) Syntax (); f_b = *++argv; fbflag = TRUE; } else { f_b = def_bold_font; fbflag = FALSE; } continue; case ARG_FG: if(i) { if (--argc <= 0) Syntax (); fore_color = *++argv; } else fore_color = NULL; continue; case ARG_FI: if (i) { if (--argc <= 0) Syntax(); f_i = *++argv; } else f_i = def_icon_font; continue; case ARG_FN: if(fnflag = i) { if (--argc <= 0) Syntax (); f_n = *++argv; fnflag = TRUE; } else { f_n = def_font; fnflag = FALSE; } continue; case ARG_FT: if(i) { if (--argc <= 0) Syntax (); f_t = *++argv; } else f_t = def_title_font; continue; case ARG_I: screen->icon_show = i ? -1 : 0; continue; case ARG_IB: if(i) { if (--argc <= 0) Syntax (); iconbitmap = *++argv; } else iconbitmap = NULL; continue; case ARG_IT: if(i) { if (--argc <= 0) Syntax (); tekiconbitmap = *++argv; } else tekiconbitmap = NULL; continue; case ARG_J: if(screen->jumpscroll = i) term.flags &= ~SMOOTHSCROLL; else term.flags |= SMOOTHSCROLL; continue; #ifdef KEYBD case ARG_K: if(i) { if (--argc <= 0) Syntax (); keyboardtype = *++argv; } else keyboardtype = NULL; continue; #endif KEYBD case ARG_L: log_on = i; continue; case ARG_LF: if(screen->logfile) free(screen->logfile); if(i) { if (--argc <= 0) Syntax (); if(screen->logfile = malloc(strlen(*++argv) + 1)) strcpy(screen->logfile, *argv); } else screen->logfile = NULL; continue; case ARG_LS: login_shell = i; continue; case ARG_MB: screen->marginbell = i; continue; case ARG_MS: if(i) { if (--argc <= 0) Syntax (); mous_color = *++argv; } else mous_color = NULL; continue; case ARG_N: if(i) { if (--argc <= 0) Syntax (); win_name = *++argv; } else win_name = NULL; continue; case ARG_NB: if(i) { if (--argc <= 0) Syntax (); n_marginbell = atoi (*++argv); } else n_marginbell = N_MARGINBELL; continue; case ARG_PO: if(i) { if (--argc <= 0) Syntax (); if((screen->pageoverlap = atoi (*++argv) - 1) < 0) screen->pageoverlap = -1; } else screen->pageoverlap = 0; continue; case ARG_PS: screen->pagemode = i; continue; case ARG_RV: re_verse = i; continue; case ARG_RW: if(i) term.flags |= REVERSEWRAP; else term.flags &= ~REVERSEWRAP; continue; case ARG_S: screen->multiscroll = i; continue; case ARG_SB: screen->scrollbar = i ? SCROLLBARWIDTH : 0; continue; case ARG_SI: screen->scrollinput = i; continue; case ARG_SK: screen->scrollkey = i; continue; case ARG_SL: if(i) { if (--argc <= 0) Syntax (); save_lines = atoi (*++argv); } else save_lines = SAVELINES; continue; case ARG_SN: screen->reversestatus = !i; continue; case ARG_ST: screen->statusline = i; continue; case ARG_T: screen->TekEmu = i; continue; case ARG_TB: screen->fullVwin.titlebar = i; continue; case ARG_TI: screen->textundericon = i; continue; case ARG_VB: screen->visualbell = i; continue; default: Syntax (); } break; } term.initflags = term.flags; if (fnflag && !fbflag) f_b = NULL; if (!fnflag && fbflag) f_n = f_b; if(!win_name) { if(get_ty) { char b[256]; gethostname(b, sizeof(b) - 1); b[sizeof(b) - 1] = 0; if(strind = index(b, '.')) /* remove domain */ *strind = 0; win_name = malloc(strlen(b) + 8); strcpy(win_name, "login("); strcat(win_name, b); strcat(win_name, ")"); } else win_name = (am_slave ? "xterm slave" : (command_to_exec ? basename(command_to_exec[0]) : xterm_name)); } if(inhibit & I_TEK) screen->TekEmu = FALSE; /* set up stderr properly */ i = -1; #ifdef DEBUG if(debug) i = open ("xterm.debug.log", O_WRONLY | O_CREAT | O_TRUNC, 0666); else #endif DEBUG if(get_ty) i = open("/dev/console", O_WRONLY); if(i >= 0) fileno(stderr) = i; if(fileno(stderr) != (NOFILE - 1)) { dup2(fileno(stderr), (NOFILE - 1)); if(fileno(stderr) >= 3) close(fileno(stderr)); fileno(stderr) = (NOFILE - 1); } signal (SIGCHLD, reapchild); signal (SIGHUP, SIG_IGN); signal(SIGALRM, onalarm); /* open a terminal for client */ get_terminal (); spawn (); Xsocket = screen->display->fd; pty = screen->respond; if (am_slave) { /* Write window id so master end can read and use */ write(pty, screen->TekEmu ? (char *)&TWindow(screen) : (char *)&VWindow(screen), sizeof(Window)); write(pty, "\n", 1); } if(log_on) { log_on = FALSE; StartLog(screen); } screen->inhibit = inhibit; mode = 1; if (ioctl (pty, FIONBIO, &mode) == -1) SysError (ERROR_FIONBIO); pty_mask = 1 << pty; X_mask = 1 << Xsocket; Select_mask = pty_mask | X_mask; max_plus1 = (pty < Xsocket) ? (1 + Xsocket) : (1 + pty); #ifdef DEBUG if (debug) printf ("debugging on\n"); #endif DEBUG XErrorHandler(xerror); XIOErrorHandler(xioerror); for( ; ; ) if(screen->TekEmu) TekRun(); else VTRun(); } char *basename(name) char *name; { register char *cp; char *rindex(); return((cp = rindex(name, '/')) ? cp + 1 : name); } static struct argstr { char *arg; int val; } arg[] = { {"132", ARG_132}, #ifdef TIOCCONS {"C", ARG__C}, #endif TIOCCONS {"L", ARG__L}, {"S", ARG__S}, {"ai", ARG_AI}, {"ar", ARG_AR}, {"b", ARG_B}, {"bd", ARG_BD}, {"bg", ARG_BG}, {"bw", ARG_BW}, {"cr", ARG_CR}, {"cu", ARG_CU}, #ifdef DEBUG {"d", ARG_D}, #endif DEBUG {"dw", ARG_DW}, {"e", ARG_E}, {"fb", ARG_FB}, {"fg", ARG_FG}, {"fi", ARG_FI}, {"fn", ARG_FN}, {"ft", ARG_FT}, {"i", ARG_I}, {"ib", ARG_IB}, {"it", ARG_IT}, {"j", ARG_J}, #ifdef KEYBD {"k", ARG_K}, #endif KEYBD {"l", ARG_L}, {"lf", ARG_LF}, {"ls", ARG_LS}, {"mb", ARG_MB}, {"ms", ARG_MS}, {"n", ARG_N}, {"nb", ARG_NB}, {"po", ARG_PO}, {"ps", ARG_PS}, {"r", ARG_RV}, {"rv", ARG_RV}, {"rw", ARG_RW}, {"s", ARG_S}, {"sb", ARG_SB}, {"si", ARG_SI}, {"sk", ARG_SK}, {"sl", ARG_SL}, {"sn", ARG_SN}, {"st", ARG_ST}, {"t", ARG_T}, {"tb", ARG_TB}, {"ti", ARG_TI}, {"vb", ARG_VB}, {"w", ARG_BW}, }; argument(s) register char *s; { register int i, low, high, com; low = 0; high = sizeof(arg) / sizeof(struct argstr) - 1; while(low <= high) {/* use binary search, arg in lexigraphic order */ i = (low + high) / 2; if ((com = strcmp(s, arg[i].arg)) == 0) return(arg[i].val); if(com > 0) low = i + 1; else high = i - 1; } return(-1); } static char *ustring[] = { "Usage: xterm [-132] [-ai] [-ar] [-b margin_width] [-bd border_color] \\\n", #ifdef ARG__C " [-bg backgrnd_color] [-bw border_width] [-C] [-cr cursor_color] [-cu] \\\n", #else ARG__C " [-bg backgrnd_color] [-bw border_width] [-cr cursor_color] [-cu] \\\n", #endif ARG__C " [-dw] [-fb bold_font] [-fg foregrnd_color] [-fi icon_font] [-fn norm_font] \\\n", " [-ft title_font] [-i] [-ib iconbitmap] [-it tekiconbitmap] [-j] \\\n", #ifdef ARG_K " [-k keybd] [-l] [-lf logfile] [-ls] [-mb] [-ms mouse_color] \\\n", #else ARG_K " [-l] [-lf logfile] [-ls] [-mb] [-ms mouse_color] \\\n", #endif ARG_K " [-n name] [-nb bell_margin] [-po] [-ps] [-rv] [-rw] [-s] \\\n", " [-sb] [-si] [-sk] [-sl save_lines] [-sn] [-st] [-t] [-tb] \\\n", " [-ti] [-vb] [=[width]x[height][[+-]xoff[[+-]yoff]]] \\\n", " [%[width]x[height][[+-]xoff[[+-]yoff]]] [#[+-]xoff[[+-]yoff]] \\\n", " [-e command_to_exec]\n\n", "Fonts must be of fixed width and of same size;\n", "If only one font is specified, it will be used for normal and bold text\n", "The -132 option allows 80 <-> 132 column escape sequences\n", "The -ai option turns on miniature (active) icons\n", "The -ar option turns auto raise window mode on\n", #ifdef ARG__C "The -C option forces output to /dev/console to appear in this window\n", #endif ARG__C "The -cu option turns a curses bug fix on\n", "The -dw option warps the mouse on deiconify\n", "The -i option enables icon startup\n", "The -j option enables jump scroll\n", "The -l option enables logging\n", "The -ls option makes the shell a login shell\n", "The -mb option turns the margin bell on\n", "The -ps option turns page scroll on\n", "The -rv option turns reverse video on\n", "The -rw option turns reverse wraparound on\n", "The -s option enables asynchronous scrolling\n", "The -sb option enables the scrollbar\n", "The -si option enables re-positioning the scrollbar at the bottom on input\n", "The -sk option causes the scrollbar to position at the bottom on a key\n", "The -sn option makes the status line normal video \n", "The -st option enables the status line\n", "The -t option starts Tektronix mode\n", "The -tb option enables the titlebar\n", "The -ti option places the window name under the icon\n", "The -vb option enables visual bell\n", 0 }; Syntax () { register char **us = ustring; while (*us) fputs(*us++, stderr); exit (1); } get_pty (pty, tty) /* opens a pty, storing fildes in pty and tty. */ int *pty, *tty; { int devindex, letter = 0; while (letter < 4) { ttydev [8] = ptydev [8] = "pqrs" [letter++]; devindex = 0; while (devindex < 16) { ttydev [9] = ptydev [9] = "0123456789abcdef" [devindex++]; if ((*pty = open (ptydev, O_RDWR)) < 0) continue; if ((*tty = open (ttydev, O_RDWR)) < 0) { close(*pty); continue; } return; } } fprintf (stderr, "%s: Not enough available pty's\n", xterm_name); exit (ERROR_PTYS); } get_terminal () /* * sets up X and initializes the terminal structure except for term.buf.fildes. */ { register Screen *screen = &term.screen; register int try; Color cdef; char *malloc(); for (try = 10 ; ; ) { if (screen->display = XOpenDisplay(display)) break; if (!get_ty) { fprintf(stderr, "%s: No such display server %s\n", xterm_name, XDisplayName(display)); exit(ERROR_NOX); } if (--try <= 0) { fprintf (stderr, "%s: Can't connect to display server %s\n", xterm_name, XDisplayName(display)); exit (ERROR_NOX2); } sleep (5); } if(re_verse) { B_Pixel = WhitePixel; B_Pixmap = WhitePixmap; W_Pixel = BlackPixel; W_Pixmap = BlackPixmap; } else { B_Pixel = BlackPixel; B_Pixmap = BlackPixmap; W_Pixel = WhitePixel; W_Pixmap = WhitePixmap; } if (brdr_color && DisplayCells() > 2 && XParseColor(brdr_color, &cdef) && XGetHardwareColor(&cdef)) { if(!(screen->bordertile = XMakeTile(cdef.pixel))) Error(ERROR_BORDER); } else screen->bordertile = B_Pixmap; screen->graybordertile = make_gray(); screen->foreground = B_Pixel; screen->background = W_Pixel; screen->cursorcolor = B_Pixel; screen->mousecolor = B_Pixel; if (DisplayCells() > 2 && (fore_color || back_color || curs_color)) { if (fore_color && XParseColor(fore_color, &cdef) && XGetHardwareColor(&cdef)) { screen->foreground = cdef.pixel; screen->color |= C_FOREGROUND; } if (back_color && XParseColor(back_color, &cdef) && XGetHardwareColor(&cdef)) { screen->background = cdef.pixel; screen->color |= C_BACKGROUND; } if (curs_color && XParseColor(curs_color, &cdef) && XGetHardwareColor(&cdef)) { screen->cursorcolor = cdef.pixel; screen->color |= C_CURSOR; } else screen->cursorcolor = screen->foreground; } if (mous_color && DisplayCells() > 2 && XParseColor(mous_color, &cdef) && XGetHardwareColor(&cdef)) { screen->mousecolor = cdef.pixel; screen->color |= C_MOUSE; } else screen->mousecolor = screen->cursorcolor; if(screen->color & C_BACKGROUND) { if(!(screen->bgndtile = XMakeTile(screen->background))) Error(ERROR_BACK); } else screen->bgndtile = W_Pixmap; screen->arrow = make_arrow(screen->mousecolor, screen->background, GXcopy); XAutoRepeatOn(); if((screen->titlefont = XOpenFont(f_t)) == NULL) { fprintf(stderr, "%s: Can't get title font %s\n", xterm_name, f_t); exit(ERROR_TITLEFONT); } screen->title_n_size= XQueryWidth("m", screen->titlefont->id); screen->titleheight = screen->titlefont->height + 2 * TITLEPAD + 1; if(screen->fullVwin.titlebar) screen->fullVwin.titlebar = screen->fullTwin.titlebar = screen->titleheight; IconInit(screen, iconbitmap, tekiconbitmap); } static char *tekterm[] = { "tek4015", "tek4014", "tek4013", "tek4010", "dumb", 0 }; static char *vtterm[] = { "xterms", "xterm", "vt102", "vt100", "ansi", "dumb", 0 }; spawn () /* * Inits pty and tty and forks a login process. * Does not close fd Xsocket. * If getty, execs getty rather than csh and uses std fd's rather * than opening a pty/tty pair. * If slave, the pty named in passedPty is already open for use */ { register Screen *screen = &term.screen; int Xsocket = screen->display->fd; int index1, tty = -1; int discipline; unsigned lmode; struct tchars tc; struct ltchars ltc; struct sgttyb sg; char termcap [1024]; char newtc [1024]; char *ptr, *shname; int i, no_dev_tty = FALSE; char **envnew; /* new environment */ char buf[32]; char *TermName = NULL; int ldisc = 0; #ifdef sun #ifdef TIOCSSIZE struct ttysize ts; #endif TIOCSSIZE #else sun #ifdef TIOCSWINSZ struct winsize ws; #endif TIOCSWINSZ #endif sun struct passwd *pw = NULL; #ifdef UTMP struct utmp utmp; #endif UTMP extern int Exit(); struct passwd *getpwuid(); char *getenv(); char *index (), *rindex (), *strindex (); screen->uid = getuid(); screen->gid = getgid(); #ifdef UTMP added_utmp_entry = FALSE; #endif UTMP /* so that TIOCSWINSZ || TIOCSIZE doesn't block */ signal(SIGTTOU,SIG_IGN); if(!(screen->TekEmu ? TekInit() : VTInit())) exit(ERROR_INIT); if(screen->TekEmu) { envnew = tekterm; ptr = newtc; } else { /* * Special case of a 80x24 window, use "xterms" */ envnew = (screen->max_col == 79 && screen->max_row == 23) ? vtterm : &vtterm[1]; ptr = termcap; } while(*envnew) { if(tgetent(ptr, *envnew) == 1) { TermName = *envnew; if(!screen->TekEmu) resize(screen, TermName, termcap, newtc); break; } envnew++; } if (get_ty) { screen->respond = loginpty; if((tslot = ttyslot()) <= 0) SysError(ERROR_TSLOT); #ifdef TIOCCONS if (Console) { int on = 1; if (ioctl (0, TIOCCONS, &on) == -1) SysError(ERROR_TIOCCONS); } #endif TIOCCONS } else if (am_slave) { screen->respond = am_slave; ptydev[8] = ttydev[8] = passedPty[0]; ptydev[9] = ttydev[9] = passedPty[1]; if((tslot = ttyslot()) <= 0) SysError(ERROR_TSLOT2); setgid (screen->gid); setuid (screen->uid); } else { if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) { if (errno != ENXIO) SysError(ERROR_OPDEVTTY); else { no_dev_tty = TRUE; sg = d_sg; tc = d_tc; discipline = d_disipline; ltc = d_ltc; lmode = d_lmode; } } else { /* get a copy of the current terminal's state */ if(ioctl(tty, TIOCGETP, &sg) == -1) SysError (ERROR_TIOCGETP); if(ioctl(tty, TIOCGETC, &tc) == -1) SysError (ERROR_TIOCGETC); if(ioctl(tty, TIOCGETD, &discipline) == -1) SysError (ERROR_TIOCGETD); if(ioctl(tty, TIOCGLTC, <c) == -1) SysError (ERROR_TIOCGLTC); if(ioctl(tty, TIOCLGET, &lmode) == -1) SysError (ERROR_TIOCLGET); close (tty); /* close all std file descriptors */ for (index1 = 0; index1 < 3; index1++) close (index1); if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) SysError (ERROR_OPDEVTTY2); if (ioctl (tty, TIOCNOTTY, 0) == -1) SysError (ERROR_NOTTY); close (tty); } get_pty (&screen->respond, &tty); if (screen->respond != Xsocket + 1) { dup2 (screen->respond, Xsocket + 1); close (screen->respond); screen->respond = Xsocket + 1; } /* change ownership of tty to real group and user id */ chown (ttydev, screen->uid, screen->gid); /* change protection of tty */ chmod (ttydev, 0622); if (tty != Xsocket + 2) { dup2 (tty, Xsocket + 2); close (tty); tty = Xsocket + 2; } /* set the new terminal's state to be the old one's with minor modifications for efficiency */ sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW); sg.sg_flags |= ECHO | CRMOD; /* make sure speed is set on pty so that editors work right*/ sg.sg_ispeed = B9600; sg.sg_ospeed = B9600; /* reset t_brkc to default value */ tc.t_brkc = -1; if (ioctl (tty, TIOCSETP, &sg) == -1) SysError (ERROR_TIOCSETP); if (ioctl (tty, TIOCSETC, &tc) == -1) SysError (ERROR_TIOCSETC); if (ioctl (tty, TIOCSETD, &discipline) == -1) SysError (ERROR_TIOCSETD); if (ioctl (tty, TIOCSLTC, <c) == -1) SysError (ERROR_TIOCSLTC); if (ioctl (tty, TIOCLSET, &lmode) == -1) SysError (ERROR_TIOCLSET); #ifdef TIOCCONS if (Console) { int on = 1; if (ioctl (tty, TIOCCONS, &on) == -1) SysError(ERROR_TIOCCONS); } #endif TIOCCONS close (open ("/dev/null", O_RDWR, 0)); for (index1 = 0; index1 < 3; index1++) dup2 (tty, index1); if((tslot = ttyslot()) <= 0) SysError(ERROR_TSLOT3); #ifdef UTMP if((pw = getpwuid(screen->uid)) && (i = open(etc_utmp, O_WRONLY)) >= 0) { bzero((char *)&utmp, sizeof(struct utmp)); (void) strcpy(utmp.ut_line, &ttydev[5]); (void) strcpy(utmp.ut_name, pw->pw_name); (void) strcpy(utmp.ut_host, DisplayName()); time(&utmp.ut_time); lseek(i, (long)(tslot * sizeof(struct utmp)), 0); write(i, (char *)&utmp, sizeof(struct utmp)); close(i); added_utmp_entry = TRUE; } #endif UTMP } #ifdef sun #ifdef TIOCSSIZE /* tell tty how big window is */ if(screen->TekEmu) { ts.ts_lines = 38; ts.ts_cols = 81; } else { ts.ts_lines = screen->max_row + 1; ts.ts_cols = screen->max_col + 1; } ioctl (screen->respond, TIOCSSIZE, &ts); #endif TIOCSSIZE #else sun #ifdef TIOCSWINSZ /* tell tty how big window is */ if(screen->TekEmu) { ws.ws_row = 38; ws.ws_col = 81; ws.ws_xpixel = TFullWidth(screen); ws.ws_ypixel = TFullHeight(screen); } else { ws.ws_row = screen->max_row + 1; ws.ws_col = screen->max_col + 1; ws.ws_xpixel = FullWidth(screen); ws.ws_ypixel = FullHeight(screen); } ioctl (screen->respond, TIOCSWINSZ, &ws); #endif TIOCSWINSZ #endif sun if (!am_slave) { if ((screen->pid = fork ()) == -1) SysError (ERROR_FORK); if (screen->pid == 0) { extern char **environ; int pgrp = getpid(); char shell_name[64]; close (Xsocket); close (screen->respond); if(fileno(stderr) >= 3) close (fileno(stderr)); if (tty >= 0) close (tty); signal (SIGCHLD, SIG_DFL); signal (SIGHUP, SIG_IGN); /* copy the environment before Setenving */ for (i = 0 ; environ [i] != NULL ; i++) ; /* * The `4' is the number of Setenv() calls which may add * a new entry to the environment. The `1' is for the * NULL terminating entry. */ envnew = (char **) calloc (i + (4 + 1), sizeof(char *)); bcopy((char *)environ, (char *)envnew, i * sizeof(char *)); environ = envnew; Setenv ("TERM=", TermName); if(!TermName) *newtc = 0; Setenv ("TERMCAP=", newtc); sprintf(buf, "%d", screen->TekEmu ? (int)TWindow(screen) : (int)VWindow(screen)); Setenv ("WINDOWID=", buf); /* put the display into the environment of the shell*/ if (display[0] != '\0') Setenv ("DISPLAY=", screen->display->displayname); signal(SIGTERM, SIG_DFL); ioctl(0, TIOCSPGRP, &pgrp); setpgrp (0, 0); close(open(ttyname(0), O_WRONLY, 0)); setpgrp (0, pgrp); setgid (screen->gid); setuid (screen->uid); if (command_to_exec) { execvp(*command_to_exec, command_to_exec); /* print error message on screen */ fprintf(stderr, "%s: Can't execvp %s\n", xterm_name, *command_to_exec); } signal(SIGHUP, SIG_IGN); if (get_ty) { ioctl (0, TIOCNOTTY, 0); execl ("/etc/getty", "+", "Xwindow", get_ty, 0); } signal(SIGHUP, SIG_DFL); #ifdef UTMP if(((ptr = getenv("SHELL")) == NULL || *ptr == 0) && ((pw == NULL && (pw = getpwuid(screen->uid)) == NULL) || *(ptr = pw->pw_shell) == 0)) #else UTMP if(((ptr = getenv("SHELL")) == NULL || *ptr == 0) && ((pw = getpwuid(screen->uid)) == NULL || *(ptr = pw->pw_shell) == 0)) #endif UTMP ptr = "/bin/sh"; if(shname = rindex(ptr, '/')) shname++; else shname = ptr; i = strlen(shname) - 3; ldisc = (strcmp("csh", shname + i) == 0 || strcmp("ksh", shname + i) == 0) ? NTTYDISC : 0; ioctl(0, TIOCSETD, &ldisc); if(login_shell) strcpy(shell_name, "-"); else *shell_name = 0; strcat(shell_name, shname); execl (ptr, shell_name, 0); fprintf (stderr, "%s: Could not exec %s!\n", xterm_name, ptr); sleep(5); exit(ERROR_EXEC); } } if(tty >= 0) close (tty); signal(SIGHUP,SIG_IGN); if (!no_dev_tty) { if ((tty = open ("/dev/tty", O_RDWR, 0)) < 0) SysError(ERROR_OPDEVTTY3); for (index1 = 0; index1 < 3; index1++) dup2 (tty, index1); if (tty > 2) close (tty); } signal(SIGINT, Exit); signal(SIGQUIT, Exit); signal(SIGTERM, Exit); } Exit(n) int n; { register Screen *screen = &term.screen; #ifdef UTMP register int i; struct utmp utmp; if(added_utmp_entry && (i = open(etc_utmp, O_WRONLY)) >= 0) { bzero((char *)&utmp, sizeof(struct utmp)); lseek(i, (long)(tslot * sizeof(struct utmp)), 0); write(i, (char *)&utmp, sizeof(struct utmp)); close(i); } #endif UTMP if(screen->logging) CloseLog(screen); if(!get_ty && !am_slave) { /* restore ownership of tty */ chown (ttydev, 0, 0); /* restore modes of tty */ chmod (ttydev, 0666); } exit(n); } resize(screen, TermName, oldtc, newtc) Screen *screen; char *TermName; register char *oldtc, *newtc; { register char *ptr1, *ptr2; register int i; register int li_first = 0; register char *temp; char *index(), *strindex(); if ((ptr1 = strindex (oldtc, "co#")) == NULL){ fprintf(stderr, "%s: Can't find co# in termcap string %s\n", xterm_name, TermName); exit (ERROR_NOCO); } if ((ptr2 = strindex (oldtc, "li#")) == NULL){ fprintf(stderr, "%s: Can't find li# in termcap string %s\n", xterm_name, TermName); exit (ERROR_NOLI); } if(ptr1 > ptr2) { li_first++; temp = ptr1; ptr1 = ptr2; ptr2 = temp; } ptr1 += 3; ptr2 += 3; strncpy (newtc, oldtc, i = ptr1 - oldtc); newtc += i; sprintf (newtc, "%d", li_first ? screen->max_row + 1 : screen->max_col + 1); newtc += strlen(newtc); ptr1 = index (ptr1, ':'); strncpy (newtc, ptr1, i = ptr2 - ptr1); newtc += i; sprintf (newtc, "%d", li_first ? screen->max_col + 1 : screen->max_row + 1); ptr2 = index (ptr2, ':'); strcat (newtc, ptr2); } static reapchild () { union wait status; register int pid; #ifdef DEBUG if (debug) fputs ("Exiting\n", stderr); #endif DEBUG pid = wait3 (&status, WNOHANG, NULL); if (!pid) return; if (pid != term.screen.pid) return; Cleanup(0); } consolepr(string) char *string; { extern int errno; extern char *sys_errlist[]; int oerrno; int f; oerrno = errno; f = open("/dev/console",O_WRONLY); write(f, "xterm: ", 7); write(f, string, strlen(string)); write(f, ": ", 2); write(f, sys_errlist[oerrno],strlen(sys_errlist[oerrno])); write(f, "\n", 1); close(f); if ((f = open("/dev/tty", 2)) >= 0) { ioctl(f, TIOCNOTTY, 0); close(f); } } checklogin() { register int i, j; register struct passwd *pw; struct utmp utmp; if((i = open(etc_utmp, O_RDONLY)) < 0) return(FALSE); lseek(i, (long)(tslot * sizeof(struct utmp)), 0); j = read(i, (char *)&utmp, sizeof(utmp)); close(i); if(j != sizeof(utmp) || strcmp(get_ty, utmp.ut_line) != 0 || !*utmp.ut_name || (pw = getpwnam(utmp.ut_name)) == NULL) return(FALSE); chdir(pw->pw_dir); setgid(pw->pw_gid); setuid(pw->pw_uid); L_flag = 0; return(TRUE); } RAZZLE!DAZZLE fi # End main.c if test -f menu.c then echo shar: will not overwrite existing file "'menu.c'" else echo 'x - menu.c' cat << \RAZZLE!DAZZLE > menu.c /* * $Source: /u1/X/xterm/RCS/menu.c,v $ * $Header: menu.c,v 10.101 86/12/01 17:52:43 swick Rel $ */ #ifdef MODEMENU #include "X/Xlib.h" #include "menu.h" #ifndef lint static char sccs_id[] = "@(#)menu.c\tX10/6.6B\t12/26/86"; #endif lint #define FALSE 0 #define TRUE 1 #define InvertPlane 1 #define SetStateFlags(item) item->itemFlags = (item->itemFlags &\ ~(itemStateMask | itemChanged)) |\ ((item->itemFlags & itemSetMask) >>\ itemSetMaskShift) static short Check_MarkBits[] = { 0x0100, 0x0180, 0x00c0, 0x0060, 0x0031, 0x001b, 0x000e, 0x0004 }; static short Check_GrayBits[] = { 0x0100, 0x0080, 0x0040, 0x0020, 0x0011, 0x000a, 0x0004, 0x0000 }; static short Default_CursorBits[] = { 0x0000, 0x0002, 0x0006, 0x000e, 0x001e, 0x003e, 0x007e, 0x00fe, 0x01fe, 0x003e, 0x0036, 0x0062, 0x0060, 0x00c0, 0x00c0, 0x0000 }; static short Default_GrayBits[] = { 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, }; static short Default_MaskBits[] = { 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x007f, 0x00f7, 0x00f3, 0x01e1, 0x01e0, 0x01c0 }; static char def_menu_font[] = "vtsingle"; Pixmap Gray_Tile; Menu Menu_Default; Cursor Menu_DefaultCursor; char *Menu_DefaultFont; FontInfo *Menu_DefaultFontInfo; /* * AddMenuItem() adds a menu item to an existing menu, at the end of the * list, which are number sequentially from zero. The menuitem index is * return, or -1 if failed. */ AddMenuItem(menu, text) register Menu *menu; register char *text; { register MenuItem *menuitem, **next; register int i; extern char *malloc(); if(!menu || !text || (menuitem = (MenuItem *)malloc(sizeof(MenuItem))) == (MenuItem *)0) return(-1); bzero((char *)menuitem, sizeof(MenuItem)); menuitem->itemText = text; menuitem->itemTextLength = strlen(text); for(i = 0, next = &menu->menuItems ; *next ; i++) next = &(*next)->nextItem; *next = menuitem; menu->menuFlags |= menuChanged; return(i); } /* * DisposeItem() releases the memory allocated for the given indexed * menuitem. Nonzero is returned if an item was actual disposed of. */ DisposeItem(menu, i) register Menu *menu; register int i; { register MenuItem **next, **last, *menuitem; if(!menu || i < 0) return(0); next = &menu->menuItems; do { if(!*next) return(0); last = next; next = &(*next)->nextItem; } while(i-- > 0); menuitem = *last; *last = *next; free(menuitem); return(1); } /* * DisposeMenu() releases the memory allocated for the given menu. */ DisposeMenu(menu) register Menu *menu; { static Unmap_Menu(); if(!menu) return; if(menu->menuFlags & menuMapped) Unmap_Menu(menu); while(DisposeItem(menu, 0)); if(menu->menuWindow) XDestroyWindow(menu->menuWindow); if(menu->menuSaved) XFreePixmap(menu->menuSaved); free(menu); } InitMenu(name) register char *name; { register char *cp; register Bitmap bit; /* * If the gray tile hasn't been set up, do it now. */ if(!Gray_Tile) { if(!(bit = XStoreBitmap(grayWidth, grayHeight, Default_GrayBits))) return; Gray_Tile = XMakePixmap(bit, WhitePixel, BlackPixel); XFreeBitmap(bit); } Menu_Default.menuFlags = menuChanged; if((cp = XGetDefault(name, "MenuFreeze")) && strcmp(cp, "on") == 0) Menu_Default.menuFlags |= menuFreeze; if((cp = XGetDefault(name, "MenuSave")) && strcmp(cp, "on") == 0) Menu_Default.menuFlags |= menuSaveMenu; Menu_Default.menuInitialItem = -1; Menu_Default.menuBorderWidth = (cp = XGetDefault(name, "MenuBorder")) ? atoi(cp) : 2; Menu_Default.menuItemPad = (cp = XGetDefault(name, "MenuPad")) ? atoi(cp) : 3; Menu_DefaultFont = (cp = XGetDefault(name, "MenuFont")) ? cp : def_menu_font; }; /* * ItemFlags returns the state of item "n" of the menu. */ ItemFlags(menu, n) register Menu *menu; register int n; { register MenuItem *item; if(!menu || !menu->menuItems || n < 0) return(-1); for(item = menu->menuItems ; n > 0 ; n--) if(!(item = item->nextItem)) return(0); return((item->itemFlags & itemSetMask) >> itemSetMaskShift); } /* * ItemText changes the text of item "n" of the menu. */ ItemText(menu, n, text) register Menu *menu; register int n; char *text; { register MenuItem *item; if(!menu || !menu->menuItems || n < 0 || !text) return(0); for(item = menu->menuItems ; n > 0 ; n--) if(!(item = item->nextItem)) return(0); item->itemText = text; menu->menuFlags |= menuChanged; return(1); } /* * NewMenu() returns a pointer to an initialized new Menu structure, or NULL * if failed. * * The Menu structure _menuDefault contains the default menu settings. */ Menu *NewMenu(name, reverse) char *name; int reverse; { register Menu *menu; register int fg, bg; extern char *malloc(); /* * If the GrayTile hasn't been defined, InitMenu() was never * run, so exit. */ if(!Gray_Tile) return((Menu *)0); /* * Allocate the memory for the menu structure. */ if((menu = (Menu *)malloc(sizeof(Menu))) == (Menu *)0) return((Menu *)0); /* * Initialize to default values. */ *menu = Menu_Default; /* * If the menu font hasn't yet been gotten, go get it. */ if(!menu->menuFontInfo) { if(!Menu_DefaultFontInfo && !(Menu_DefaultFontInfo = XOpenFont(Menu_DefaultFont))) return((Menu *)0); menu->menuFontInfo = Menu_DefaultFontInfo; } /* * If the menu cursor hasn't been given, make a default one. */ if(!menu->menuCursor) { if(!Menu_DefaultCursor) { if(reverse) { fg = WhitePixel; bg = BlackPixel; } else { fg = BlackPixel; bg = WhitePixel; } if(!(Menu_DefaultCursor = XCreateCursor(defaultCursorWidth, defaultCursorHeight, Default_CursorBits, Default_MaskBits, defaultCursorX, defaultCursorY, fg, bg, GXcopy))) return((Menu *)0); } menu->menuCursor = Menu_DefaultCursor; } /* * Initialze the default background and border pixmaps and foreground * and background colors (black and white). */ if(reverse) { menu->menuBgTile = BlackPixmap; menu->menuFgColor = WhitePixel; menu->menuBgColor = BlackPixel; } else { menu->menuBgTile = WhitePixmap; menu->menuFgColor = BlackPixel; menu->menuBgColor = WhitePixel; } /* * Set the menu title. If name is NULL or is an empty string, no * title will be displayed. */ if(name && *name) { menu->menuTitleLength = strlen(menu->menuTitle = name); menu->menuTitleWidth = XStringWidth(name, menu->menuFontInfo, 0, 0); menu->menuItemTop = menu->menuFontInfo->height + 2 * menu->menuItemPad + 1; } else menu->menuTitleLength = menu->menuTitleWidth = menu->menuItemTop = 0; return(menu); } /* * SetItemCheck sets the check state of item "n" of the menu to "state". */ SetItemCheck(menu, n, state) register Menu *menu; register int n; int state; { register MenuItem *item; if(!menu || !menu->menuItems || n < 0) return(0); for(item = menu->menuItems ; n > 0 ; n--) if(!(item = item->nextItem)) return(0); if(state) item->itemFlags |= itemSetChecked; else item->itemFlags &= ~itemSetChecked; if(((item->itemFlags & itemSetMask) >> itemSetMaskShift) != (item->itemFlags & itemStateMask)) { item->itemFlags |= itemChanged; menu->menuFlags |= menuItemChanged; } else item->itemFlags &= ~itemChanged; return(1); } /* * SetItemDisable sets the disable state of item "n" of the menu to "state". */ SetItemDisable(menu, n, state) register Menu *menu; register int n; int state; { register MenuItem *item; if(!menu || !menu->menuItems || n < 0) return(0); for(item = menu->menuItems ; n > 0 ; n--) if(!(item = item->nextItem)) return(0); if(state) item->itemFlags |= itemSetDisabled; else item->itemFlags &= ~itemSetDisabled; if(((item->itemFlags & itemSetMask) >> itemSetMaskShift) != (item->itemFlags & itemStateMask)) { item->itemFlags |= itemChanged; menu->menuFlags |= menuItemChanged; } else item->itemFlags &= ~itemChanged; return(1); } /* * TrackMenu does most of the work of displaying the menu and tracking the * mouse. */ TrackMenu(menu, event) register Menu *menu; register XButtonPressedEvent *event; { register MenuItem *item; register int i, button; register MenuItem *hilited_item = (MenuItem *)0; register int drawn; XButtonReleasedEvent ev; register int changed; int y, n, hilited_y, hilited_n, in_window; static MenuItem *Mouse_InItem(), *Y_InItem(); static Unmap_Menu(); /* * Check that things are reasonable. */ if(!menu || !event || !menu->menuItems || event->type != ButtonPressed) return(-1); /* * Set the changed flag and clear the menu changed flags. */ changed = menu->menuFlags & (menuChanged | menuItemChanged); /* * If the entire menu has changed, throw away any saved pixmap and * then call RecalcMenu(). */ if(changed & menuChanged) { if(menu->menuSaved) XFreePixmap(menu->menuSaved); menu->menuSaved = (Pixmap)0; if(!Recalc_Menu(menu)) return(-1); changed &= ~menuItemChanged; } /* * Now if the window was never created, go ahead and make it. Otherwise * if the menu has changed, resize the window. */ if(!menu->menuWindow) { if((menu->menuWindow = XCreateWindow(RootWindow, 0, 0, menu->menuWidth, menu->menuHeight, menu->menuBorderWidth, Gray_Tile, menu->menuBgTile)) == (Window)0) return(-1); XDefineCursor(menu->menuWindow, menu->menuCursor); XSelectInput(menu->menuWindow, ExposeWindow | EnterWindow | LeaveWindow | MouseMoved | ButtonReleased); } else if(changed & menuChanged) XChangeWindow(menu->menuWindow, menu->menuWidth, menu->menuHeight); /* * Figure out where the menu is supposed to go, from the initial button * press, and move the window there. Then map the menu. */ if(!Move_Menu(menu, event) || !Map_Menu(menu)) return(-1); /* * Try to grab the mouse, over a period of 10 seconds. */ for(i = 10 ; ; ) { if(XGrabMouse(menu->menuWindow, menu->menuCursor, ButtonReleased | EnterWindow | LeaveWindow | MouseMoved)) break; if(--i <= 0) { Unmap_Menu(menu); return(-1); } sleep(1); } /* * Save away the button that was pressed and use it to match a * corresponding ButtonReleased event. */ button = event->detail & 03; /* * Now process events for the menu window. */ drawn = 0; for( ; ; ) { XNextEvent(&ev); if(ev.type != ButtonReleased && ev.window != menu->menuWindow) { if(menu->menuEventHandler) (*menu->menuEventHandler)(&ev); continue; } switch(ev.type) { case ExposeWindow: /* * If we have a saved pixmap, display it. Otherwise * redraw the menu and save it away. */ if(menu->menuSaved) { XPixmapPut(menu->menuWindow, 0, 0, 0, 0, menu->menuWidth, menu->menuHeight, menu->menuSaved, GXcopy, AllPlanes); /* * If the menuItemChanged flag is still set, * then we need to redraw certain menu items. * ("i" is the vertical position of the top * of the current item.) */ if(changed & menuItemChanged) { i = menu->menuItemTop; for(item = menu->menuItems ; item ; item = item->nextItem) { if(item->itemFlags & itemChanged) Modify_Item(menu, item, i); i += item->itemHeight; } } } else Draw_Menu(menu); /* * If the menu has changed in any way and we want to * save the menu, throw away any existing save menu * image and make a new one. */ XFlush(); if(changed && (menu->menuFlags & menuSaveMenu)) { if(menu->menuSaved) XFreePixmap(menu->menuSaved); menu->menuSaved = XPixmapSave(menu->menuWindow, 0, 0, menu->menuWidth, menu->menuHeight); } /* * See which item the cursor may currently be in. If * it is in a non-disabled item, hilite it. */ if(hilited_item = Mouse_InItem(menu, &hilited_y, &hilited_n, &in_window)) XPixFill(menu->menuWindow, 0, hilited_y, menu->menuWidth, hilited_item->itemHeight, BlackPixmap, (Bitmap)0, GXinvert, InvertPlane); drawn++; break; case EnterWindow: in_window = TRUE; /* drop through */ case MouseMoved: if(!drawn || !in_window) break; /* * See which item the cursor may currently be in. If * the item has changed, unhilite the old one and * then hilited the new one. */ y = ((XEnterWindowEvent *)&ev)->y; if((item = Y_InItem(menu, &y, &n)) != hilited_item) { if(hilited_item) XPixFill(menu->menuWindow, 0, hilited_y, menu->menuWidth, hilited_item->itemHeight, BlackPixmap, (Bitmap)0, GXinvert, InvertPlane); if(hilited_item = item) { XPixFill(menu->menuWindow, 0, hilited_y = y, menu->menuWidth, item->itemHeight, BlackPixmap, (Bitmap)0, GXinvert, InvertPlane); hilited_n = n; } } break; case LeaveWindow: if(!drawn) break; /* * Unhilite any window that is currently hilited. */ if(hilited_item) { XPixFill(menu->menuWindow, 0, hilited_y, menu->menuWidth, hilited_item->itemHeight, BlackPixmap, (Bitmap)0, GXinvert, InvertPlane); hilited_item = (MenuItem *)0; } in_window = FALSE; break; case ButtonReleased: /* * If the correct button was released, ungrab the mouse * and return the index number of any selected menu * item. */ if((ev.detail & 0x3) == button) { if(in_window) { y = ((XButtonReleasedEvent *)&ev)->y; if((item = Y_InItem(menu, &y, &n)) != hilited_item) { if(hilited_item) XPixFill(menu->menuWindow, 0, hilited_y, menu->menuWidth, hilited_item->itemHeight, BlackPixmap, (Bitmap)0, GXinvert, InvertPlane); if(hilited_item = item) { XPixFill(menu->menuWindow, 0, hilited_y = y, menu->menuWidth, hilited_item->itemHeight, BlackPixmap, (Bitmap)0, GXinvert, InvertPlane); hilited_n = n; } } } XUngrabMouse(); menu->menuFlags &= ~(menuChanged | menuItemChanged); Unmap_Menu(menu); XFlush(); if(hilited_item) return(menu->menuInitialItem = hilited_n); return(-1); } break; } } } /* * Recalculate all of the various menu and item variables. */ static Recalc_Menu(menu) register Menu *menu; { register MenuItem *item; register int max, i, height, fontheight; /* * We must have already gotten the menu font. */ if(!menu->menuFontInfo) return(0); /* * Initialize the various max width variables. */ fontheight = menu->menuFontInfo->height; height = menu->menuItemTop; menu->menuMaxTextWidth = menu->menuTitleWidth; /* * The item height is the maximum of the font height and the * checkbox height. */ max = fontheight; if(checkMarkHeight > max) max = checkMarkHeight; /* * Go through the menu item list. */ for(item = menu->menuItems ; item ; item = item->nextItem) { /* * If the item text is a single dash, we assume this is * a line separator and treat it special. */ if(strcmp(item->itemText, "-") == 0) height += (item->itemHeight = lineSeparatorHeight); else { height += (item->itemHeight = max); /* * Check the text width with the max value stored in * menu. */ if((item->itemTextWidth = XStringWidth(item->itemText, menu->menuFontInfo, 0, 0)) > menu->menuMaxTextWidth) menu->menuMaxTextWidth = item->itemTextWidth; } /* * If the itemChanged flag is set, set the state bits. */ if(item->itemFlags & itemChanged) { item->itemFlags = (item->itemFlags & ~itemStateMask) | ((item->itemFlags & itemSetMask) >> itemSetMaskShift); item->itemFlags &= ~itemChanged; } } /* * Set the menu height and then set the menu width. */ menu->menuHeight = height; menu->menuWidth = 3 * menu->menuItemPad + menu->menuMaxTextWidth + checkMarkWidth; return(1); } /* * Figure out where to popup the menu, relative to the where the button was * pressed. */ static Move_Menu(menu, ev) register Menu *menu; XButtonPressedEvent *ev; { register MenuItem *item; register int n, x, y; int ev_x, ev_y; int total_width; Window subw; /* * Get the coordinates of the mouse when the button was pressed. */ XInterpretLocator(RootWindow, &ev_x, &ev_y, &subw, ev->location); /* * Try to popup the menu so that the cursor is centered within the * width of the menu, but compensate if that would run it outside * the display area. */ total_width = menu->menuWidth + 2 * menu->menuBorderWidth; if((x = ev_x - total_width / 2) < 0) x = 0; else if(x + total_width > DisplayWidth()) x = DisplayWidth() - total_width; #ifdef DROPMENUS y = 0; #else DROPMENUS /* * If we have an inital item, try to popup the menu centered * vertically within this item. */ if(menu->menuInitialItem >= 0) { /* * Look through the item list. "y" is the vertical position * of the top of the current item and "n" is the item number. */ y = menu->menuItemTop + menu->menuBorderWidth; for(n = 0, item = menu->menuItems ; ; n++) { /* * On finding the intial item, center within this item. */ if(n == menu->menuInitialItem) { y += item->itemHeight / 2; break; } y += item->itemHeight; /* * If we run out of items, turn off the initial item * and treat this as if no initial item. */ if(!(item = item->nextItem)) { menu->menuInitialItem = -1; goto noInitial; } } /* * If no initial item, try to popup the menu centered in the item * nearest the center of the menu. */ } else { noInitial: /* * Look through the item list. "y" is the vertical position * of the top of the current item and "n" is the vertical * position of the center of the menu. */ y = menu->menuItemTop + menu->menuBorderWidth; for(n = menu->menuHeight / 2, item = menu->menuItems ; item ; item = item->nextItem) /* * If the center of the menu is in this item, we * center within this item. */ if((y += item->itemHeight) > n) { y -= item->itemHeight / 2; break; } } #endif DROPMENU /* * If the menu extends above outside of the display, warp * the mouse vertically so the menu will all show up. */ if((y = ev_y - y) < 0) { XWarpMouse(RootWindow, ev_x, ev_y - y); y = 0; } else if((n = y + menu->menuHeight + 2 * menu->menuBorderWidth - DisplayHeight()) > 0) { XWarpMouse(RootWindow, ev_x, ev_y - n); y -= n; } XMoveWindow(menu->menuWindow, x, y); /* * If we are in freeze mode, save what will be the coordinates of * the save image. */ if(menu->menuFlags & menuFreeze) { menu->menuSavedImageX = x; menu->menuSavedImageY = y; } return(1); } /* * Map the menu window. */ static Map_Menu(menu) register Menu *menu; { register int i; /* * If we are in freeze mode, save the pixmap underneath where the menu * will be (including the border). */ if(menu->menuFlags & menuFreeze) { XGrabServer(); i = 2 * menu->menuBorderWidth; if((menu->menuSavedImage = XPixmapSave(RootWindow, menu->menuSavedImageX, menu->menuSavedImageY, menu->menuWidth + i, menu->menuHeight + i)) == (Pixmap)0) return(0); } /* * Actually map the window. */ XMapWindow(menu->menuWindow); menu->menuFlags |= menuMapped; return(1); } /* * Draw the entire menu in the blank window. */ static Draw_Menu(menu) register Menu *menu; { register MenuItem *item; register int top = menu->menuItemTop; register int x = menu->menuItemPad; register int y, dim; /* * If we have a menu title, draw it first, centered and hilited. */ if(menu->menuTitleLength) { XPixSet(menu->menuWindow, 0, 0, menu->menuWidth, top - 1, menu->menuFgColor); XText(menu->menuWindow, (menu->menuWidth - menu->menuTitleWidth) / 2, menu->menuItemPad, menu->menuTitle, menu->menuTitleLength, menu->menuFontInfo->id, menu->menuBgColor, menu->menuFgColor); } /* * For each item in the list, first draw any check mark and then * draw the rest of it. */ for(item = menu->menuItems ; item ; item = item->nextItem) { SetStateFlags(item); dim = (item->itemFlags & itemDisabled); /* * Draw the check mark, possibly dimmed, wherever is necessary. */ if(item->itemFlags & itemChecked) { XBitmapBitsPut(menu->menuWindow, x, y = top + (item->itemHeight - checkMarkHeight) / 2, checkMarkWidth, checkMarkHeight, dim ? Check_GrayBits : Check_MarkBits, menu->menuFgColor, menu->menuBgColor, (Bitmap)0, GXcopy, AllPlanes); } /* * Draw the item, possibly dimmed. */ Draw_Item(menu, item, top, dim); top += item->itemHeight; } } /* * Modify the item at vertical position y. This routine is table driven and * the state and set bits are each 2 bits long, contiguous, the least * significant bits in the flag word and with the state bits in bits 0 & 1. */ #define drawCheck 0x10 #define removeCheck 0x08 #define dimCheck 0x04 #define drawItem 0x02 #define dimItem 0x01 static char Modify_Table[] = { 0x00, 0x02, 0x08, 0x0a, 0x01, 0x00, 0x09, 0x08, 0x10, 0x12, 0x00, 0x12, 0x15, 0x14, 0x05, 0x00 }; static Modify_Item(menu, item, top) register Menu *menu; register MenuItem *item; int top; { register int x = menu->menuItemPad; register int y; register int center = top + item->itemHeight / 2; register int func = Modify_Table[item->itemFlags & (itemStateMask | itemSetMask)]; /* * If we really won't be making a change, return. */ if(func == 0) return; /* * Draw the check mark if needed, possibly dimmed. */ y = center - (checkMarkHeight / 2); if(func & (drawCheck | dimCheck)) XBitmapBitsPut(menu->menuWindow, x, y, checkMarkWidth, checkMarkHeight, (func & dimCheck) ? Check_GrayBits : Check_MarkBits, menu->menuFgColor, menu->menuBgColor, (Bitmap)0, GXcopy, AllPlanes); /* * Remove the check mark if needed. */ if(func & removeCheck) XTileSet(menu->menuWindow, x, y, checkMarkWidth, checkMarkHeight, menu->menuBgTile); /* * Call Draw_Item if we need to draw or dim the item. */ if((x = func & dimItem) || (func & drawItem)) Draw_Item(menu, item, top, x); /* * Update state flags. */ SetStateFlags(item); } /* * Draw the item (less check mark) at vertical position y. * Dim the item if "dim" is set. */ static Draw_Item(menu, item, y, dim) register Menu *menu; register MenuItem *item; register int y; int dim; { register int x = 2 * menu->menuItemPad + checkMarkWidth; register int center = y + item->itemHeight / 2; /* * If the item text is a single dash, draw a separating line. */ if(strcmp(item->itemText, "-") == 0) { XLine(menu->menuWindow, 0, center, menu->menuWidth, center, 1, 1, menu->menuFgColor, GXcopy, AllPlanes); return; } /* * Draw and/or dim the text, centered vertically. */ y = center - (menu->menuFontInfo->height / 2); if(dim) { XTileSet(menu->menuWindow, x, y, item->itemTextWidth, menu->menuFontInfo->height, Gray_Tile); XTextPad(menu->menuWindow, x, y, item->itemText, item->itemTextLength, menu->menuFontInfo->id, 0, 0, menu->menuFgColor, menu->menuBgColor, menu->menuFgColor ? GXand : GXor, AllPlanes); } else XText(menu->menuWindow, x, y, item->itemText, item->itemTextLength, menu->menuFontInfo->id, menu->menuFgColor, menu->menuBgColor); } /* * Determine which enabled menu item the mouse is currently in. Return the * top position of this item and its item number. Set inwindow to whether * we are or not. */ static MenuItem *Mouse_InItem(menu, top, n, inwindow) register Menu *menu; int *top, *n, *inwindow; { int x, y; Window subw; static MenuItem *Y_InItem(); /* * Find out where the mouse is. If its not in the menu window, * return NULL. */ XQueryMouse(RootWindow, &x, &y, &subw); if(subw != menu->menuWindow) { *inwindow = FALSE; return((MenuItem *)0); } *inwindow = TRUE; /* * Now get the coordinates relative to the menu window. */ XInterpretLocator(menu->menuWindow, &x, &y, &subw, (x << 16) | y); /* * Call Y_InItem(). */ *top = y; return(Y_InItem(menu, top, n)); } /* * Return which enabled item the locator is in. Also return the * top position of this item and its item number. Initial y passed * in top. */ static MenuItem *Y_InItem(menu, top, n) register Menu *menu; int *top, *n; { register MenuItem *item; register int t, i; register int y = *top; Window subw; /* * Go through the item list. "t" is the vertical position of the * current item and "i" is its item number. */ t = menu->menuItemTop; /* * If the mouse is before the first item, return. */ if(y < t) return((MenuItem *)0); for(i = 0, item = menu->menuItems ; item ; i++, item = item->nextItem) { /* * If the y coordinate is within this menu item, then return. * But don't return disable items. */ if(t + item->itemHeight > y) { if(item->itemFlags & itemDisabled) return((MenuItem *)0); *top = t; *n = i; return(item); } t += item->itemHeight; } /* * Should never get here. */ return((MenuItem *)0); } /* * Unmap_Menu() unmaps a menu, if it is currently mapped. */ static Unmap_Menu(menu) register Menu *menu; { register int i; if(!menu || !(menu->menuFlags & menuMapped)) return; if(menu->menuFlags & menuFreeze) { XUnmapTransparent(menu->menuWindow); i = 2 * menu->menuBorderWidth; XPixmapPut(RootWindow, 0, 0, menu->menuSavedImageX, menu->menuSavedImageY, menu->menuWidth + i, menu->menuHeight + i, menu->menuSavedImage, GXcopy, AllPlanes); XFreePixmap(menu->menuSavedImage); XUngrabServer(); } else XUnmapWindow(menu->menuWindow); menu->menuFlags &= ~menuMapped; } #endif MODEMENU RAZZLE!DAZZLE fi # End menu.c echo '***** End of' xterm 6.6B - Part 5 of 7 '*****' exit