guido@cwi.nl (Guido van Rossum) (03/04/91)
Archive-name: stdwin/part09 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 9 (of 19)." # Contents: Packs/vt/vtansi.c Ports/alfa/stdwin.c Ports/mac/draw.c # Ports/x11/menu.c Ports/x11/timer.c # Wrapped by guido@voorn.cwi.nl on Mon Mar 4 12:37:27 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Packs/vt/vtansi.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Packs/vt/vtansi.c'\" else echo shar: Extracting \"'Packs/vt/vtansi.c'\" \(11653 characters\) sed "s/^X//" >'Packs/vt/vtansi.c' <<'END_OF_FILE' X/* ANSI escape sequence interpreter */ X X/* There is some ugly code here, since I assume that code looking X at the input a character at a time is very time-critical. X Action functions are called with the start of the text to process, X and return a pointer to where they left off. X When an action function hits the end of the string, X it returns NULL and sets the action pointer to the function to X call next (often itself), or to NULL for the default. X A non-NULL return implies that the default action function must X be called next and the action pointer is irrelevant. X Remember that the general form of most ANSI escape sequences is X ESC [ <n1> ; <n2> ; ... <c> X where <c> is the command code and <n1>, <n2> etc. are optional X numerical parameters. X*/ X X#include "vtimpl.h" X X#ifdef DEBUG X /* Let it be heard that a command was not recognized */ X#define FAIL() wfleep() X#else X/* Silently ignore unrecognized commands */ X#define FAIL() 0 X#endif X X/* Function prototypes */ X XSTATIC char *def_action _ARGS((VT *vt, char *text, char *end)); XSTATIC char *esc_action _ARGS((VT *vt, char *text, char *end)); XSTATIC char *ansi_params _ARGS((VT *vt, char *text, char *end)); XSTATIC char *ansi_execute _ARGS((VT *vt, char *text)); XSTATIC void vtsetoptions _ARGS((VT *vt, bool flag)); XSTATIC void vtsetattrlist _ARGS((VT *vt)); X X/* Output a string, interpreting ANSI escapes */ X Xvoid Xvtansiputs(vt, text, len) X VT *vt; X char *text; X int len; X{ X char *end; X X#ifndef NDEBUG X if (vt->scr_top < 0 || vt->scr_top > vt->rows) { X fprintf(stderr, "vtansiputs: scr_top = %d\n", vt->scr_top); X vtpanic("vtansiputs: bad scr_top"); X } X#endif X X if (len < 0) X len = strlen(text); X end = text + len; X X D( printf("vtansiputs %d chars\n", len) ); X X /* Pick up where the last call left us behind */ X if (vt->action != NULL) X text = (*vt->action)(vt, text, end); X X /* Start in default state until text exhausted */ X while (text != NULL) X text = def_action(vt, text, end); X X /* Execute delayed scrolling */ X vtsync(vt); X D( printf("vtansiputs returns\n") ); X} X X/* Default action function */ X XSTATIC char * Xdef_action(vt, text, end) X VT *vt; X char *text, *end; X{ Xagain: X for (;;) { X if (text >= end) { X vt->action = NULL; X return NULL; X } X if (PRINTABLE(*text)) X break; X switch (*text++) { X X case ESC: /* ESC */ X return esc_action(vt, text, end); X X case BEL: /* Bell */ X if (vt->visualbell) { X VTBEGINDRAWING(vt); X vtinvert(vt, 0, 0, vt->rows, vt->cols); X VTENDDRAWING(vt); X VTBEGINDRAWING(vt); X vtinvert(vt, 0, 0, vt->rows, vt->cols); X VTENDDRAWING(vt); X } X else { X wfleep(); X } X break; X X case BS: /* Backspace -- move 1 left */ X /* Rely on vtsetcursor's clipping */ X vtsetcursor(vt, vt->cur_row, vt->cur_col - 1); X /* Don't erase -- X that's part of intelligent echoing */ X break; X X case TAB: /* Tab -- move to next tab stop */ X /* Rely on vtsetcursor's clipping */ X /* TO DO: use programmable tab stops! */ X vtsetcursor(vt, vt->cur_row, X (vt->cur_col & ~7) + 8); X /* Normalize cursor (may cause scroll!) */ X vtputstring(vt, "", 0); X break; X X case LF: /* Linefeed -- move down one line */ X if (vt->nlcr) /* First a \r? */ X vtsetcursor(vt, vt->cur_row, 0); X vtlinefeed(vt, 1); X break; X X case FF: /* Formfeed */ X /* vtreset(vt); */ X break; X X case CR: /* Return -- to col 0 on same line */ X vtsetcursor(vt, vt->cur_row, 0); X break; X X case ' ': /* In case isprint(c) fails for space */ X vtputstring(vt, " ", 1); X break; X X default: X D( printf("Unrecognized unprintable character 0x%x\n", X text[-1]) ); X FAIL(); X break; X } X } X X /* We fall through the previous loop when we get a printable X character */ X X { X char *p = text; X X while (PRINTABLE(*++p)) { X /* At least one character guaranteed! */ X if (p >= end) X break; X } X vtputstring(vt, text, (int)(p-text)); X text = p; X goto again; X } X} X X/* Action function called after ESC seen */ X XSTATIC char * Xesc_action(vt, text, end) X VT *vt; X char *text, *end; X{ X if (text >= end) { X vt->action = esc_action; X return NULL; X } X switch (*text++) { X/* X case '(': X case ')': X case '*': X case '+': X return cset_action(vt, text, end); X*/ X case '=': X vt->keypadmode = TRUE; X break; X case '>': X vt->keypadmode = FALSE; X break; X case '7': X vtsavecursor(vt); X break; X case '8': X vtrestorecursor(vt); X break; X case 'D': X vtlinefeed(vt, 1); X break; X case 'E': X /* Next Line */ X break; X case 'H': X /* Tab set */ X break; X case 'M': X vtrevlinefeed(vt, 1); X break; X case '[': X vt->nextarg = vt->args; X *vt->nextarg = -1; X vt->modarg = '\0'; X return ansi_params(vt, text, end); X case 'c': X vtreset(vt); X break; X default: X D( printf("Urecognized: esc-%c (0x%x)\n", X text[-1], text[-1]) ); X FAIL(); X break; X } X return text; X} X X/* Action function called after ESC-[ plus possible parameters seen */ X XSTATIC char * Xansi_params(vt, text, end) X VT *vt; X char *text, *end; X{ Xagain: X if (text >= end) { X vt->action = ansi_params; X return NULL; X } X if (isdigit(*text)) { X long a = *vt->nextarg; X if (a < 0) /* Still unused? */ X a = 0; X do { X a = a*10 + (*text - '0'); X CLIPMAX(a, 0x7fff); /* Avoid overflow */ X } while (++text < end && isdigit(*text)); X *vt->nextarg = a; /* Remember arg under construction */ X if (text >= end) X goto again; X } X switch (*text) { X X case ';': /* Arg no longer under construction */ X ++text; X if (vt->nextarg < &vt->args[VTNARGS-1]) X ++vt->nextarg; /* Else: overflow; who cares? */ X *vt->nextarg = -1; /* Mark unused */ X goto again; X X case '?': X ++text; X if (vt->nextarg == vt->args && /* No arguments yet */ X *vt->nextarg < 0 && vt->modarg == '\0') { X vt->modarg = '?'; X goto again; X } X else { /* Illegal here */ X D( printf("Wrong argcount in DEC private mode\n") ); X FAIL(); X return text; X } X X default: X return ansi_execute(vt, text); X } X} X X/* Called after complete ESC [ ? <number> h is parsed. X This is called DEC private mode set. Most stuff is not X implemented. The vt is guarantueed to contain the one X and only argument allowed here. */ X XSTATIC void Xvtprivset(vt) X VT *vt; X{ X switch (vt->args[0]) { X case 1: /* Application cursor keys */ X if (!vt->keypadmode) { X vt->keypadmode = 1; X vt->flagschanged = 1; X } X break; X#if 0 X case 3: /* 132 column mode */ X case 4: /* Smooth (slow) scroll */ X#endif X case 5: /* Reverse video */ X wfleep(); X break; X#if 0 X case 6: /* Origin mode */ X case 7: /* Wraparound mode */ X case 8: /* Autorepeat keys */ X#endif X case 9: /* Send MIT mouse row & column on Button Press */ X if (!vt->mitmouse) { /* If not already so */ X vt->mitmouse = 1; X vt->flagschanged = 1; X } X break; X#if 0 X case 38: /* Enter Tektronix Mode */ X case 40: /* Allow 80 <-> 132 mode */ X case 41: /* Curses(5) fix */ X case 44: /* Turn on margin bell */ X case 45: /* Reverse wraparound mode */ X case 46: /* Start logging */ X case 47: /* Use alternate screen buffer */ X case 1000: /* Send vt200 mouse row & column on Button Press */ X case 1003: /* Send vt200 Hilite mouse row & column on Button Press */ X#endif X default: X D( printf("Unsupported DEC private mode set:") ); X D( printf("esc [ ? %d h\n", vt->args[0]) ); X wfleep(); X } X} X X/* Called after complete ESC [ ? <number> l is parsed. X This is called DEC private mode reset. The vt is guarantueed X to contain the one and only argument allowed here. */ X XSTATIC void Xvtprivreset(vt) X VT *vt; X{ X switch (vt->args[0]) { X case 1: /* Normal cursor keys */ X if (vt->keypadmode) { X vt->keypadmode = 0; X vt->flagschanged = 1; X } X break; X#if 0 /* These are not supprted: */ X case 3: /* 80 column mode */ X case 4: /* Jumpscroll */ X#endif X case 5: /* Normal video (i.e. not reverse) */ X /* XXX Why this beep? */ X wfleep(); X break; X#if 0 X case 6: /* Normal cursor mode */ X case 7: /* No wraparound */ X case 8: /* No autorepeat */ X break; X#endif X case 9: /* Don't send mouse row & column on button press */ X case 1000: /* Same */ X case 1003: /* Same */ X if (vt->mitmouse) { /* If not already so */ X vt->mitmouse = 0; X vt->flagschanged = 1; X } X break; X#if 0 X case 40: /* Disallow 80 <-> 132 mode */ X case 41: /* No curses(5) fix */ X case 44: /* Turn off Margin bell */ X case 45: /* No reverse wraparound */ X case 46: /* Stop logging */ X case 47: /* Use normal screen buffer (opposed to alternate buffer) */ X break; X#endif X default: X D( printf("Unsupported DEC private mode reset:") ); X D( printf("esc [ ? %d l\n", vt->args[0]) ); X wfleep(); X break; X } X} X X/* Action function called at last char of ANSI sequence. X (This is only called when the char is actually seen, X so there is no need for an 'end' parameter). */ X XSTATIC char * Xansi_execute(vt, text) X VT *vt; X char *text; X{ X int a1 = vt->args[0]; X int a2 = (vt->nextarg > vt->args) ? vt->args[1] : -1; X X if (vt->modarg == '?') { X /* These escape sequences have exactly one numeric parameter */ X if (a1 < 0 || a2 > 0) { X wfleep(); X return text+1; X } X switch (*text++) { X case 'h': /* DEC Private mode Set */ X vtprivset(vt); X break; X case 'l': /* DEC Private mode Reset */ X vtprivreset(vt); X break; X /* To do: add private mode memory to vt-descriptor? */ X case 'r': /* DEC Private mode Restore */ X case 's': /* DEC Private mode Save */ X default: X /* Not supported or simply wrong */ X wfleep(); X } X return text; X } X X CLIPMIN(a1, 1); X CLIPMIN(a2, 1); X X switch (*text++) { X case '@': vtinschars(vt, a1); break; X case 'A': vtarrow(vt, WC_UP, a1); break; X case 'B': vtarrow(vt, WC_DOWN, a1); break; X case 'C': vtarrow(vt, WC_RIGHT, a1); break; X case 'D': vtarrow(vt, WC_LEFT, a1); break; X case 'H': X case 'f': if (vt->nextarg > &vt->args[0]) X vtsetcursor(vt, vt->topterm + a1 - 1, a2 - 1); X else vtsetcursor(vt, vt->topterm, 0); X break; X case 'J': X switch (vt->args[0]) { X case -1: X case 0: X vteosclear(vt, vt->topterm, 0); X break; X case 1: X /* clear above cursor */ X break; X case 2: X vteosclear(vt, vt->cur_row, vt->cur_col); X break; X default: X FAIL(); X break; X } X break; X case 'K': X switch (vt->args[0]) { X case -1: X case 0: X vteolclear(vt, vt->cur_row, vt->cur_col); X break; X case 1: X /* Clear left of cursor */ X break; X case 2: X vteolclear(vt, vt->cur_row, 0); X break; X default: X FAIL(); X break; X } X break; X case 'L': vtinslines(vt, a1); break; X case 'M': vtdellines(vt, a1); break; X case 'P': vtdelchars(vt, a1); break; X case 'S': vtlinefeed(vt, a1); break; X case 'T': vtrevlinefeed(vt, a1); break; X case 'c': vtsendid(vt); break; X case 'g': /* Tab clear */ break; X /* 0: current col; 3: all */ X case 'h': vtsetoptions(vt, TRUE); break; X case 'l': vtsetoptions(vt, FALSE); break; X case 'm': vtsetattrlist(vt); break; X case 'n': X if (a1 == 6) vtsendpos(vt); X /* 5: echo 'ESC [ 0 n' */ X break; X case 'r': X vtsetscroll(vt, vt->topterm+vt->args[0]-1, vt->topterm+a2); X break; X case 'x': /* Send terminal params */ X break; X default: X FAIL(); X break; X } X X return text; X} X X/* Set/reset numbered options given in args array */ X XSTATIC void Xvtsetoptions(vt, flag) X VT *vt; X bool flag; /* Set/reset */ X{ X short *a; X for (a = vt->args; a <= vt->nextarg; ++a) { X switch (*a) { X case 4: X vtsetinsert(vt, flag); X break; X case -1: X /* Empty parameter, don't beep */ X break; X default: X FAIL(); X break; X } X } X} X X/* Set/reset output mode attributes given in args array */ X XSTATIC void Xvtsetattrlist(vt) X VT *vt; X{ X short *a; X for (a = vt->args; a <= vt->nextarg; ++a) { X switch (*a) { X case -1: X if (a == vt->args) X vtresetattr(vt); X break; X case 0: X vtresetattr(vt); X break; X default: X vtsetattr(vt, *a); X break; X } X } X} END_OF_FILE if test 11653 -ne `wc -c <'Packs/vt/vtansi.c'`; then echo shar: \"'Packs/vt/vtansi.c'\" unpacked with wrong size! fi # end of 'Packs/vt/vtansi.c' fi if test -f 'Ports/alfa/stdwin.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Ports/alfa/stdwin.c'\" else echo shar: Extracting \"'Ports/alfa/stdwin.c'\" \(9984 characters\) sed "s/^X//" >'Ports/alfa/stdwin.c' <<'END_OF_FILE' X/* TERMCAP STDWIN -- BASIC ROUTINES. */ X X#include "alfa.h" X X#if defined(unix) || defined(AMOEBA) X#define DO_SIGNAL X#define DO_SYSTEM X#endif X X#ifdef DO_SIGNAL X#include <sys/types.h> X#include <signal.h> X#include "sigtype.h" Xstatic SIGTYPE handler(); /* Forward */ X#endif X Xint lines, columns; X X/* Initialization call. X Should be called only once, before any others. X Will exit when the initialization fails. */ X Xvoid Xwinit() X{ X winitargs((int*)NULL, (char***)NULL); X} X X/*ARGSUSED*/ Xvoid Xwinitargs(pargc, pargv) X int *pargc; X char ***pargv; X{ X int flags; X int err; X X#ifdef DO_SIGNAL X (void) signal(SIGINT, handler); X#ifdef NDEBUG X (void) signal(SIGQUIT, handler); X#endif X (void) signal(SIGILL, handler); X (void) signal(SIGIOT, handler); X (void) signal(SIGEMT, handler); X (void) signal(SIGFPE, handler); X (void) signal(SIGBUS, handler); X (void) signal(SIGSEGV, handler); X (void) signal(SIGSYS, handler); X (void) signal(SIGTERM, handler); X#endif /* DO_SIGNAL */ X X getttykeydefs(0); /* File descriptor 0 */ X err= trmstart(&lines, &columns, &flags); X if (err != 0) { X fprintf(stderr, "STDWIN: trmstart error %d\n", err); X exit(2); X } X gettckeydefs(); X if (lines > MAXLINES) X lines= MAXLINES; X trmputdata(0, lines-1, 0, ""); X initsyswin(); X _winitmenus(); X} X X/* Termination call. X Should be called before the program exits X (else the terminal will be left in almost raw mode). */ X Xvoid Xwdone() X{ X if (lines > 0) { X /* Move cursor to last screen line. */ X trmputdata(lines-1, lines-1, 0, ""); X trmsync(lines-1, 0); X } X lines= 0; X trmend(); X} X X#ifdef DO_SIGNAL X X/* Signal handler. X Print a message and exit. */ X Xstatic SIGTYPE Xhandler(sig) X int sig; X{ X wdone(); X signal(sig, SIG_DFL); X kill(0, sig); /* Kill all others in our process group */ X kill(getpid(), sig); /* Commit suicide */ X /* (On BSD, the signal is delivered to us only after we return.) */ X} X X#endif /* DO_SIGNAL */ X X/* Essential data structures. */ X XWINDOW winlist[MAXWINDOWS] /* = {FALSE, ...}, ... */; X XWINDOW *wasfront; /* What the application thinks is active */ XWINDOW *front; /* The window that is really active */ X /* If these are not equal, an activate or deactivate event X will be generated by wevent before anything else. */ X Xchar uptodate[MAXLINES] /* = FALSE, ... */; X X/* Open a window. */ X XWINDOW * Xwopen(title, drawproc) X char *title; X void (*drawproc)(); X{ X int id; X WINDOW *win; X X for (win= &winlist[0]; win < &winlist[MAXWINDOWS]; ++win) { X if (!win->open) X break; X } X id= win - &winlist[0]; X if (id >= MAXWINDOWS) X return NULL; /* Too many windows open */ X win->open= TRUE; X _wreshuffle(); X win->resized = FALSE; /* Don't begin with a redraw event */ X win->tag= 0; X win->drawproc= drawproc; X win->title= strdup(title); X win->attr= wattr; X X win->offset= -win->top; X win->curh= win->curv= -1; X win->timer= 0; X X initmenubar(&win->mbar); X X front= win; X return win; X} X X/* Divide the available lines over the available windows. X Line 0 is for window 0, the system window, and is different: X it has no title, and is always one line high, except when it's X the only window. */ X Xvoid X_wreshuffle() X{ X int nwins= 0; X int nlines= lines; X int top= 0; X WINDOW *win; X X /* Count open windows. */ X for (win= winlist; win < &winlist[MAXWINDOWS]; ++win) { X if (win->open) X ++nwins; X } X /* Assign each open window its share of the screen. */ X for (win= winlist; win < &winlist[MAXWINDOWS]; ++win) { X if (win->open) { X int i= nlines/nwins; /* This window's share */ X int id= win - winlist; X#ifdef LM_S_PROB X int oldtop= win->top, oldbot= win->bottom; X int dv, scrbot; X#endif X /* Cause redraw event for old title position: */ X if (win->top > 0) X uptodate[win->top-1]= FALSE; X if (id == 0) { /* System window */ X win->top= top; X if (nwins > 1) X i=1; X } X else X win->top= top+1; X win->bottom= top + i; X nlines -= i; X --nwins; X#ifndef LM_S_PROB X /* This is overkill; X we should try not cause a redraw of all lines! */ X for (i= top; i < win->bottom; ++i) { X uptodate[i]= FALSE; X } X#else X /* LM's probeersel */ X dv= oldtop-win->top; X scrbot=win->bottom; X if (oldbot-dv < scrbot) scrbot=oldbot-dv; X scrollupdate(win->top, scrbot, dv); X trmscrollup(win->top, scrbot-1, dv); X for (i= top; i < win->bottom; ++i) X if (!(win->top <= i && i < scrbot || X win->top <= i+dv && i+dv < scrbot)) X uptodate[i]= FALSE; X#endif X top= win->bottom; X /* Cause redraw event for new title position: */ X if (win->top > 0) X uptodate[win->top-1]= FALSE; X /* Cause resize event: */ X win->resized= TRUE; X /* Scroll back if negative line numbers visible: */ X if (win->top + win->offset < 0) X wshow(win, 0, 0, X columns, win->bottom - win->top); X#if 0 /* We don't really want to for showing the caret... */ X /* Show caret: */ X if (win->curv >= 0) X wshow(win, win->curh, win->curv, X win->curh, win->curv); X#endif X } X } X} X X/* Close a window. */ X Xvoid Xwclose(win) X WINDOW *win; X{ X int id= win - winlist; X X if (id < 0 || id >= MAXWINDOWS || !win->open) X return; X killmenubar(&win->mbar); X if (win == wasfront) X wasfront= NULL; X if (win == front) X front= NULL; X win->open= FALSE; X if (win->title != NULL) { X free(win->title); X win->title= NULL; X } X _wreshuffle(); X /* Select another window. */ X if (front == NULL) { X /* Search below the window we just closed. */ X for (; win < &winlist[MAXWINDOWS]; ++win) { X if (win->open) { X front= win; X break; /* First hit is OK */ X } X } X if (front == NULL) { X /* Try searching above it. */ X for (win= winlist+1; win < &winlist[MAXWINDOWS]; X ++win) { X if (win->open) X front= win; X /* NO break -- we need the last hit */ X } X } X if (front == NULL) { X /* Exasperation time. */ X front= &winlist[0]; /* The system window */ X } X _wnewtitle(front); /* Make sure the title is redrawn */ X } X} X X/* Dummies for functions not supported by this version. */ X X/*ARGSUSED*/ Xvoid Xwsetdefwinpos(h, v) X int h, v; X{ X} X X/*ARGSUSED*/ Xvoid Xwsetdefwinsize(width, height) X int width, height; X{ X} X X/*ARGSUSED*/ Xvoid Xwsetmaxwinsize(width, height) X int width, height; X{ X} X X/* Make a window the active window. */ X Xvoid Xwsetactive(win) X WINDOW *win; X{ X int id= win - winlist; X X if (id < 0 || id >= MAXWINDOWS || !win->open) X return; X _wnewtitle(front); X front= win; X _wnewtitle(front); X} X X/* Select next, previous window. X Note: these will never select the system window unless it is already X selected (which can only occur if there are no other windows open). */ X Xvoid X_wselnext() X{ X WINDOW *win; X X for (win= front+1; win < &winlist[MAXWINDOWS]; ++win) { X if (win->open) { X wsetactive(win); X return; X } X } X for (win= winlist+1; win < front; ++win) { X if (win->open) { X wsetactive(win); X return; X } X } X} X Xvoid X_wselprev() X{ X WINDOW *win; X X for (win= front-1; win > winlist; --win) { X if (win->open) { X wsetactive(win); X return; X } X } X for (win= &winlist[MAXWINDOWS-1]; win > front; --win) { X if (win->open) { X wsetactive(win); X return; X } X } X} X X/* Force a redraw of the entire screen. X (This routine only sets 'invalid' bits for all lines; X the actual redraw is done later in wgetevent or wupdate.) */ X Xvoid X_wredraw() X{ X int i; X X for (i= 0; i < lines; ++i) X uptodate[i]= FALSE; X _wreshuffle(); X trmundefined(); X trmputdata(0, lines-1, 0, ""); X} X X/* Temporarily restore cooked tty mode. */ X X_wcooked() X{ X trmputdata(lines-1, lines-1, 0, ""); X trmsync(lines-1, 0); X trmend(); X} X X/* Back to window mode. X If 'wait' flag is set, wait until a character is typed before X continuing. clearing the screen. */ X X_wstdwin(wait) X bool wait; X{ X int flags; X X if (wait) { X printf("\nCR to continue... "); X fflush(stdout); X } X (void) trmstart(&lines, &columns, &flags); X if (wait) X (void) trminput(); X _wredraw(); X wmessage((char *)NULL); /* Reset menu bar */ X} X X/* Suspend the process (BSD Unix only). */ X Xvoid X_wsuspend() X{ X _wcooked(); X trmsuspend(); X _wstdwin(FALSE); X} X X/* Execute a shell command, if possible and necessary outside the window X manager. If the 'wait' parameter is set, the window manager pauses X until a character is typed before continuing. */ X Xint Xwsystem(cmd, wait) X char *cmd; X bool wait; X{ X#ifdef DO_SYSTEM X int status; X _wcooked(); X status= system(cmd); X _wstdwin(wait); X return status; X#else X return -1; X#endif X} X X/* Return active window. */ X XWINDOW * Xwgetactive() X{ X return front; X} X X/* Change a window's title. */ X Xvoid Xwsettitle(win, title) X WINDOW *win; X char *title; X{ X if (win->title != NULL) X free(win->title); X win->title= strdup(title); X _wnewtitle(win); X} X X/* Change the mouse cursor -- dummy */ X X/*ARGSUSED*/ Xvoid Xwsetwincursor(win, cursor) X WINDOW *win; X CURSOR *cursor; X{ X} X X/* Fetch a mouse cursor -- always return NULL */ X X/*ARGSUSED*/ XCURSOR * Xwfetchcursor(name) X char *name; X{ X return NULL; X} X X/* Set a window's extent (document size). Not implemented here. */ X X/*ARGSUSED*/ Xvoid Xwsetdocsize(win, width, height) X WINDOW *win; X int width, height; X{ X} X X/*ARGSUSED*/ Xvoid Xwgetdocsize(win, pwidth, pheight) X WINDOW *win; X int *pwidth, *pheight; X{ X *pwidth = *pheight = 0; X} X X/* Get a window's origin with respect to document. */ X Xvoid Xwgetorigin(win, ph, pv) X WINDOW *win; X int *ph, *pv; X{ X *ph= 0; X *pv= win->top + win->offset; X} X X/* Get a window's origin with respect to screen. */ X Xvoid Xwgetwinpos(win, ph, pv) X WINDOW *win; X int *ph, *pv; X{ X *ph= 0; X *pv= win->top; X} X X/* Get a window's window size. */ X Xvoid Xwgetwinsize(win, pwidth, pheight) X WINDOW *win; X int *pwidth, *pheight; X{ X *pwidth= columns; X *pheight= win->bottom - win->top; X} X X/* Get the screen size in pixels. */ X Xvoid Xwgetscrsize(ph, pv) X int *ph, *pv; X{ X *ph= columns; X *pv= lines; X} X X/* Get the screen size in mm. X Of course we don't know it; we pretend that the average character X is 3 mm wide and 6 mm high, which is a reasonable approximation X of reality on my terminal (an HP2621). */ X Xvoid Xwgetscrmm(ph, pv) X int *ph, *pv; X{ X *ph= columns * 3; X *pv= lines * 6; X} X Xvoid Xwfleep() X{ X trmbell(); X} END_OF_FILE if test 9984 -ne `wc -c <'Ports/alfa/stdwin.c'`; then echo shar: \"'Ports/alfa/stdwin.c'\" unpacked with wrong size! fi # end of 'Ports/alfa/stdwin.c' fi if test -f 'Ports/mac/draw.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Ports/mac/draw.c'\" else echo shar: Extracting \"'Ports/mac/draw.c'\" \(10989 characters\) sed "s/^X//" >'Ports/mac/draw.c' <<'END_OF_FILE' X/* MAC STDWIN -- DOCUMENT DRAWING. */ X X/* Contents of this file: X X wchange, wscroll; X wbegindrawing, wenddrawing, _wupdate, wupdate; X text attribute manipulation (internal and external); X text measuring; X text drawing; X coordinate conversion tools; X ordinary drawing. X X XXX Should be split, only things used between w{begin,end}drawing X belong here. X X BEWARE OF COORDINATE SYSTEMS! X X The window's origin is not always the same. X When the aplication isn't drawing (i.e., outside w{begin,end}drawing), X the origin is (0, 0); this is necessary because the control mgr X doesn't like it otherwise. X When the application is drawing, the origin is set to win->(orgh, orgv) X so the drawing primitives don't need to do their own coordinate X transformation. X Routines called while not drawing must do their own transformations. X X XXX Routines that may be called any time are in trouble! X (There shouldn't be any.) X*/ X X#include "macwin.h" X#ifdef MPW X#include <Fonts.h> X#endif X Xstatic WINDOW *drawing; Xstatic TEXTATTR drawsaveattr; Xstatic int baseline; Xstatic int lineheight; X X/* Function prototypes */ X XSTATIC void getwattr _ARGS((GrafPtr port, TEXTATTR *attr)); XSTATIC void setwattr _ARGS((TEXTATTR *attr)); XSTATIC void getfinfo _ARGS((void)); X Xvoid Xwchange(win, left, top, right, bottom) X WINDOW *win; X int left, top, right, bottom; X{ X Rect r; X X SetPort(win->w); X X if (drawing) dprintf("warning: wchange called while drawing"); X makerect(win, &r, left, top, right, bottom); X InvalRect(&r); X} X Xvoid Xwscroll(win, left, top, right, bottom, dh, dv) X WINDOW *win; X int left, top, right, bottom; X int dh, dv; X{ X Rect r; X X if (drawing) dprintf("warning: wchange called while drawing"); X makerect(win, &r, left, top, right, bottom); X scrollby(win, &r, dh, dv); X} X X/* Scroll a rectangle (given in window coordinates) by dh, dv. X Also used from scroll.c. */ X/* XXX need less visible name */ X Xvoid Xscrollby(win, pr, dh, dv) X WINDOW *win; X Rect *pr; X int dh, dv; X{ X RgnHandle rgn= NewRgn(); X X SetPort(win->w); X X rmcaret(win); X X if (!EmptyRgn(( (WindowPeek)win->w )->updateRgn)) { X RgnHandle ur= NewRgn(); X int left, top; X Rect r; X X /* Scroll the part of the update region that intersects X the scrolling area. */ X CopyRgn(( (WindowPeek)win->w )->updateRgn, ur); X /* portBits.bounds is the screen in local coordinates! */ X left= win->w->portBits.bounds.left; X top= win->w->portBits.bounds.top; X OffsetRgn(ur, left, top); /* Global to Local */ X RectRgn(rgn, pr); X SectRgn(rgn, ur, ur); X if (!EmptyRgn(ur)) { X ValidRgn(ur); X OffsetRgn(ur, dh, dv); X SectRgn(rgn, ur, ur); X InvalRgn(ur); X } X DisposeRgn(ur); X } X X ScrollRect(pr, dh, dv, rgn); X InvalRgn(rgn); X X DisposeRgn(rgn); X} X X X/* Internal version of wupdate -- also used from event.c */ X Xvoid X_wupdate(win, pr) X WINDOW *win; X Rect *pr; X{ X RgnHandle rgn= NewRgn(); X X SetPort(win->w); X X rmcaret(win); X BeginUpdate(win->w); X EraseRect(&win->w->portRect); X DrawGrowIcon(win->w); X DrawControls(win->w); X getwinrect(win, pr); X RectRgn(rgn, pr); X SectRgn(rgn, win->w->visRgn, rgn); X *pr= (*rgn)->rgnBBox; X OffsetRect(pr, win->orgh, win->orgv); X if (win->drawproc != NULL && !EmptyRect(pr)) { X wbegindrawing(win); X (*win->drawproc)(win, pr->left, pr->top, pr->right, pr->bottom); X wenddrawing(win); X } X EndUpdate(win->w); X DisposeRgn(rgn); X} X X/* Process an update event -- call the window's draw procedure. */ X/* XXX This function shouldn't be in the stdwin spec (why was it ever?) */ X Xvoid Xwupdate(win) X WINDOW *win; X{ X if (win->drawproc != NULL) { X Rect r; X _wupdate(win, &r); X } X} X Xvoid Xwbegindrawing(win) X WINDOW *win; X{ X Rect r; X X if (drawing != NULL) { X dprintf("warning: recursive call to wbegindrawing"); X /* Fix it */ X wenddrawing(drawing); X } X if (win == NULL) { X dprintf("warning: wbegindrawing(NULL) ignored"); X return; X } X drawing= win; X SetPort(win->w); X SetOrigin(win->orgh, win->orgv); X rmcaret(win); X getwinrect(win, &r); X ClipRect(&r); X PenNormal(); X wgettextattr(&drawsaveattr); X wsettextattr(&win->attr); X} X Xvoid Xwenddrawing(win) X WINDOW *win; X{ X Rect r; X X if (drawing == NULL) { X dprintf("warning: wenddrawing ignored while not drawing"); X return; X } X if (drawing != win) { X dprintf("warning: wenddrawing ignored for wrong window"); X return; X } X SetOrigin(0, 0); X SetRect(&r, -32000, -32000, 32000, 32000); X ClipRect(&r); X wsettextattr(&drawsaveattr); X drawing= NULL; X} X X/* Get the current text attributes of a GrafPort. */ X Xstatic void Xgetwattr(port, attr) X GrafPtr port; X TEXTATTR *attr; X{ X SetPort(port); /* XXX Is this necessary to validate txFont etc.? */ X X attr->font= port->txFont; X attr->style= port->txFace; X attr->size= port->txSize; X} X X/* Start using the given text attributes in the current grafport. */ X Xstatic void Xsetwattr(attr) X TEXTATTR *attr; X{ X TextFont(attr->font); X TextFace(attr->style & ~TX_INVERSE); X TextSize(attr->size); X} X X/* Get font info and baseline from current GrafPort */ X Xstatic void Xgetfinfo() X{ X FontInfo finfo; X GetFontInfo(&finfo); X baseline= finfo.ascent + finfo.leading; X lineheight= baseline + finfo.descent; X} X X/* Initialize 'wattr'. Uses the screen's grafport. */ X Xint _w_font= applFont; Xint _w_size= 9; X Xvoid Xinitwattr() X{ X TEXTATTR saveattr; X X SetPort(screen); X X getwattr(screen, &saveattr); X TextFont(_w_font); X TextSize(_w_size); X getwattr(screen, &wattr); X getfinfo(); X setwattr(&saveattr); X} X X/* TEXT ATTRIBUTES. */ X Xvoid Xwgettextattr(attr) X TEXTATTR *attr; X{ X *attr= wattr; X} X Xvoid Xwsettextattr(attr) X TEXTATTR *attr; X{ X wattr= *attr; X if (drawing != NULL) { X setwattr(attr); X getfinfo(); X } X} X Xvoid Xwgetwintextattr(win, attr) X WINDOW *win; X TEXTATTR *attr; X{ X *attr= win->attr; X} X Xvoid Xwsetwintextattr(win, attr) X WINDOW *win; X TEXTATTR *attr; X{ X win->attr= *attr; X if (drawing != NULL) X dprintf("warning: wsetwintextattr called while drawing"); X} X Xvoid Xwsetfont(fontname) X char *fontname; X{ X if (fontname == NULL || *fontname == EOS) X wattr.font= _w_font; X else { X short fnum= 0; X GetFNum(PSTRING(fontname), &fnum); X if (fnum == 0) X dprintf("can't find font %s", fontname); X wattr.font= fnum; X } X if (drawing != NULL) { X TextFont(wattr.font); X getfinfo(); X } X X} X Xvoid Xwsetsize(size) X int size; X{ X wattr.size= size; X if (drawing != NULL) { X TextSize(size); X getfinfo(); X } X} X Xvoid Xwsetstyle(face) X Style face; X{ X wattr.style= face; X if (drawing != NULL) { X TextFace(face & ~TX_INVERSE); X getfinfo(); X } X} X Xvoid Xwsetplain() X{ X wsetstyle(0); X} X Xvoid Xwsetinverse() X{ X wattr.style |= TX_INVERSE; X} X Xvoid Xwsetbold() X{ X wsetstyle(bold); X} X Xvoid Xwsetitalic() X{ X wsetstyle(italic); X} X Xvoid Xwsetbolditalic() X{ X wsetstyle(bold|italic); X} X Xvoid Xwsetunderline() X{ X wsetstyle(underline); X} X Xvoid Xwsethilite() X{ X wsetstyle(TX_INVERSE); X} X X/* TEXT MEASURING. */ X Xint Xwlineheight() X{ X if (drawing == NULL) { X TEXTATTR saveattr; X getwattr(screen, &saveattr); X setwattr(&wattr); X getfinfo(); X setwattr(&saveattr); X } X return lineheight; X} X Xint Xwbaseline() X{ X if (drawing == NULL) X (void) wlineheight(); X return baseline; X} X Xint Xwtextwidth(str, len) X char *str; X int len; X{ X TEXTATTR saveattr; X int width; X X if (drawing == NULL) { X getwattr(screen, &saveattr); X setwattr(&wattr); X } X if (len < 0) X len= strlen(str); X width= TextWidth(str, 0, len); X if (drawing == NULL) X setwattr(&saveattr); X return width; X} X Xint Xwcharwidth(c) X int c; X{ X char cbuf[1]; X cbuf[0]= c; X return wtextwidth(cbuf, 1); X} X X/* TEXT DRAWING. */ X Xvoid Xwdrawtext(h, v, str, len) X int h, v; X char *str; X int len; X{ X Point pen; X X if (len < 0) X len= strlen(str); X MoveTo(h, v + baseline); X DrawText(str, 0, len); X GetPen(&pen); X if (wattr.style & TX_INVERSE) { X Rect r; X SetRect(&r, h, v, pen.h, v + lineheight); X InvertRect(&r); X } X} X Xvoid Xwdrawchar(h, v, c) X int h, v; X int c; X{ X if ((wattr.style & TX_INVERSE) == 0) { X /* Attempt to optimize for appls. like dpv */ X MoveTo(h, v + baseline); X DrawChar(c); X } X else { X char cbuf[1]; X cbuf[0]= c; X wdrawtext(h, v, cbuf, 1); X } X} X X/* COORDINATE CONVERSIONS ETC. */ X X/* Create a rect in current window coordinates (as for getwinrect) X from a rectangle given in document coordinates. X This works both while drawing and while not drawing. X The resulting rectangle is clipped to the winrect. */ X Xvoid Xmakerect(win, pr, left, top, right, bottom) X WINDOW *win; X Rect *pr; X int left, top, right, bottom; X{ X Rect r; X SetRect(pr, left, top, right, bottom); X if (!drawing) X OffsetRect(pr, - win->orgh, - win->orgv); X getwinrect(win, &r); X (void) SectRect(&r, pr, pr); X} X X/* Retrieve the 'winrect', i.e., the contents area exclusive X of the scroll bars and grow icon. X Coordinates are in window coordinates, i.e., X the origin is (0, 0) outside w{begin,end}drawing, X but (win->orgh, win->orgv) between calls to these routines. */ X Xvoid Xgetwinrect(win, pr) X WINDOW *win; X Rect *pr; X{ X *pr= win->w->portRect; X pr->right -= BAR; X pr->bottom -= BAR; X} X X/* ACTUAL DRAW ROUTINES. */ X Xvoid Xwdrawline(h1, v1, h2, v2) X{ X MoveTo(h1, v1); X Line(h2-h1, v2-v1); X} X Xvoid Xwxorline(h1, v1, h2, v2) X{ X MoveTo(h1, v1); X PenMode(patXor); X Line(h2-h1, v2-v1); X PenNormal(); X} X Xvoid Xwdrawbox(left, top, right, bottom) X int left, top, right, bottom; X{ X Rect r; X X SetRect(&r, left, top, right, bottom); X FrameRect(&r); X} X Xvoid Xwerase(left, top, right, bottom) X int left, top, right, bottom; X{ X Rect r; X X SetRect(&r, left, top, right, bottom); X EraseRect(&r); X} X Xvoid Xwinvert(left, top, right, bottom) X int left, top, right, bottom; X{ X Rect r; X X SetRect(&r, left, top, right, bottom); X InvertRect(&r); X} X Xvoid Xwpaint(left, top, right, bottom) X int left, top, right, bottom; X{ X Rect r; X X SetRect(&r, left, top, right, bottom); X FillRect(&r, QD(black)); X} X Xvoid Xwshade(left, top, right, bottom, perc) X int left, top, right, bottom; X int perc; X{ X Rect r; X unsigned char *p; /* really Pattern * or PatPtr */ X X perc= (perc + 12)/25; X CLIPMIN(perc, 0); X X switch (perc) { X case 0: p= &QD(white)[0]; break; X case 1: p= &QD(ltGray)[0]; break; X case 2: p= &QD(gray)[0]; break; X case 3: p= &QD(dkGray)[0]; break; X default: p= &QD(black)[0]; break; X } X X SetRect(&r, left, top, right, bottom); X X FillRect(&r, p); X} X Xvoid Xwdrawcircle(h, v, radius) X int h, v; X int radius; X{ X Rect r; X X /* XXX Isn't there an off-by-one error here? */ X SetRect(&r, h-radius, v-radius, h+radius, v+radius); X FrameOval(&r); X} X X/* Draw counterclockwise elliptical arc. X h, v are center; hrad, vrad are half axes; ang1 and ang2 are start X and stop angles in degrees, with respect to 3 o'clock. */ X Xvoid Xwdrawelarc(h, v, hrad, vrad, ang1, ang2) X{ X Rect r; X /* XXX Does this work? No off-by-one errors? */ X SetRect(&r, h-hrad, v-vrad, h+hrad, v+vrad); X FrameArc(&r, 90-ang1, ang1-ang2); /* ??? */ X} X X/* CLIPPING */ X Xvoid Xwcliprect(left, top, right, bottom) X int left, top, right, bottom; X{ X Rect r1, r2; X SetRect(&r1, left, top, right, bottom); X getwinrect(drawing, &r2); X SectRect(&r1, &r2, /*dst:*/ &r2); X ClipRect(&r2); X X} X Xvoid Xwnoclip() X{ X Rect r; X getwinrect(drawing, &r); X ClipRect(&r); X} END_OF_FILE if test 10989 -ne `wc -c <'Ports/mac/draw.c'`; then echo shar: \"'Ports/mac/draw.c'\" unpacked with wrong size! fi # end of 'Ports/mac/draw.c' fi if test -f 'Ports/x11/menu.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Ports/x11/menu.c'\" else echo shar: Extracting \"'Ports/x11/menu.c'\" \(11775 characters\) sed "s/^X//" >'Ports/x11/menu.c' <<'END_OF_FILE' X/* X11 STDWIN -- Menu handling */ X X#include "x11.h" X#include "llevent.h" /* For _w_dirty */ X Xstatic bool local; /* When zero, menus are created global */ X Xstatic int nmenus; Xstatic MENU **menulist; /* Only global menus */ X Xstatic MENU *sysmenu; /* System menu, included in each window's mbar */ X Xstatic Xmbardirty(win) X WINDOW *win; X{ X _w_dirty= win->mbar.dirty= TRUE; X} X Xvoid Xwmenusetdeflocal(flag) X bool flag; X{ X local= flag; X} X Xvoid Xwmenuattach(win, mp) X WINDOW *win; X MENU *mp; X{ X int i; X X for (i= 0; i < win->nmenus; ++i) { X if (win->menulist[i] == mp) X return; /* Already attached */ X } X L_APPEND(win->nmenus, win->menulist, MENU *, mp); X mbardirty(win); X} X Xvoid Xwmenudetach(win, mp) X WINDOW *win; X MENU *mp; X{ X int i; X X for (i= 0; i < win->nmenus; ++i) { X if (win->menulist[i] == mp) { X L_REMOVE(win->nmenus, win->menulist, MENU *, i); X mbardirty(win); X break; X } X } X} X X_waddmenus(win) X WINDOW *win; X{ X int i; X X /* Create system menu if first time here */ X if (sysmenu == NULL) { X bool savelocal= local; X wmenusetdeflocal(TRUE); X sysmenu= wmenucreate(0, "X"); X if (sysmenu != NULL) X wmenuadditem(sysmenu, "Close", -1); X wmenusetdeflocal(savelocal); X } X X /* Initialize the nonzero variables used by the menu module */ X win->curmenu= win->curitem= -1; X X /* Add system menu and all global menus to the menu list */ X if (sysmenu != NULL) { X L_APPEND(win->nmenus, win->menulist, MENU *, sysmenu); X } X for (i= 0; i < nmenus; ++i) { X L_APPEND(win->nmenus, win->menulist, MENU *, menulist[i]); X } X if (nmenus > 0) X mbardirty(win); X} X X_w_delmenus(win) X WINDOW *win; X{ X /* Delete the menu list before closing a window */ X L_DEALLOC(win->nmenus, win->menulist); X} X XMENU * Xwmenucreate(id, title) X int id; X char *title; X{ X MENU *mp= ALLOC(MENU); X X if (mp == NULL) X return NULL; X mp->id= id; X mp->title= strdup(title); X mp->nitems= 0; X mp->itemlist= NULL; X if (!local) { X L_APPEND(nmenus, menulist, MENU *, mp); X _waddtoall(mp); X } X return mp; X} X Xvoid Xwmenudelete(mp) X MENU *mp; X{ X int i; X X for (i= 0; i < nmenus; ++i) { X if (menulist[i] == mp) { X L_REMOVE(nmenus, menulist, MENU *, i); X break; X } X } X _wdelfromall(mp); X X for (i= 0; i < mp->nitems; ++i) X FREE(mp->itemlist[i].text); X FREE(mp->itemlist); X FREE(mp); X} X Xint Xwmenuadditem(mp, text, shortcut) X MENU *mp; X char *text; X int shortcut; X{ X struct item it; X X it.text= strdup(text); X if (shortcut < 0) X it.sctext= NULL; X else { X char buf[50]; X sprintf(buf, "M-%c", shortcut); X it.sctext= strdup(buf); X } X it.shortcut= shortcut; X it.enabled= it.text != NULL && it.text[0] != EOS; X it.checked= FALSE; X L_APPEND(mp->nitems, mp->itemlist, struct item, it); X return mp->nitems - 1; X} X Xvoid Xwmenusetitem(mp, i, text) X MENU *mp; X int i; X char *text; X{ X if (i < 0 || i >= mp->nitems) X return; X FREE(mp->itemlist[i].text); X mp->itemlist[i].text= strdup(text); X} X Xvoid Xwmenuenable(mp, i, flag) X MENU *mp; X int i; X bool flag; X{ X if (i < 0 || i >= mp->nitems) X return; X mp->itemlist[i].enabled= flag; X} X Xvoid Xwmenucheck(mp, i, flag) X MENU *mp; X int i; X bool flag; X{ X if (i < 0 || i >= mp->nitems) X return; X mp->itemlist[i].checked= flag; X} X X/* --- system-dependent code starts here --- */ X X/* XXXX Stuff recomputed more than I like: X - length of menu titles and menu item texts X - menu item text widths X*/ X X#define NOITEM (-1) X#define NOMENU (-1) X X/* Precomputed values (assume _wdrawmbar is always called first) */ Xstatic int baseline; Xstatic int lineheight; Xstatic int halftitledist; X#define titledist (2*halftitledist) Xstatic int shortcutdist; X Xstatic X_wmenusetup() X{ X shortcutdist= XTextWidth(_wmf, " ", 4); X halftitledist= XTextWidth(_wmf, "0", 1); X baseline= _wmf->ascent; X lineheight= _wmf->ascent + _wmf->descent; X} X X/* Draw the menu bar. X Called via the normal exposure event mechanism. */ X X_wdrawmbar(win) X WINDOW *win; X{ X int i; X int x; X int y; X X _wmenusetup(); X x= titledist; X y= baseline - 1 + (win->mbar.height - lineheight) / 2; X X XClearWindow(_wd, win->mbar.wid); X for (i= 0; i < win->nmenus; ++i) { X char *title= win->menulist[i]->title; X int len= strlen(title); X XDrawString(_wd, win->mbar.wid, win->gc, x, y, title, len); X x += XTextWidth(_wmf, title, len) + titledist; X } X} X Xstatic Xinverttitle(win, it) X WINDOW *win; X int it; X{ X int x= leftedge(win, it); X MENU *mp= win->menulist[it]; X char *title= mp->title; X int len= strlen(title); X int width= XTextWidth(_wmf, title, len); X X _winvert(win->mbar.wid, win->gc, X x-halftitledist, 0, width+titledist, win->mbar.height); X} X Xstatic int Xleftedge(win, it) X WINDOW *win; X int it; X{ X int i; X int x= titledist; X X for (i= 0; i < it; ++i) { X char *title= win->menulist[i]->title; X int len= strlen(title); X int width= XTextWidth(_wmf, title, len); X x += width + titledist; X } X X return x; X} X X/* Draw the current menu */ X Xstatic Xdrawmenu(win) X WINDOW *win; X{ X int i; X int x= halftitledist; X int y= baseline; X MENU *mp= win->menulist[win->curmenu]; X X for (i= 0; i < mp->nitems; ++i) { X char *text= mp->itemlist[i].text; X int len= strlen(text); X char *marker= NULL; X if (!mp->itemlist[i].enabled) { X if (len > 0) X marker= "-"; X } X else if (mp->itemlist[i].checked) X marker= "*"; X if (marker != NULL) { X int width= XTextWidth(_wmf, marker, 1); X XDrawString(_wd, win->mwin.wid, win->gc, X (x-width)/2, y, marker, 1); X } X XDrawString(_wd, win->mwin.wid, win->gc, x, y, text, len); X text= mp->itemlist[i].sctext; X if (text != NULL) { X int width; X len= strlen(text); X width= XTextWidth(_wmf, text, len); X XDrawString(_wd, win->mwin.wid, win->gc, X win->mwin.width - width - halftitledist, y, X text, len); X } X y += lineheight; X } X} X X/* Create the window for the menu. X It is a direct child of the outer window, but aligned with the X top of the inner window */ X Xstatic Xmakemenu(win) X WINDOW *win; X{ X int i; X int maxwidth= 0; X MENU *mp= win->menulist[win->curmenu]; X Window child_dummy; X X /* Compute the maximum item width. X Item width is the sum of: X - 1/2 title width (left margin, also used for tick marks) X - text width of item text X - if there is a shortcut: X - shortcutdist (some space between text and shortcut) X - text width of shortcut text X - 1/2 title width (right margin) X */ X X for (i= 0; i < mp->nitems; ++i) { X char *text= mp->itemlist[i].text; X int len= strlen(text); X int width= XTextWidth(_wmf, text, len); X text= mp->itemlist[i].sctext; X if (text != NULL) { X len= strlen(text); X width += XTextWidth(_wmf, text, len) + shortcutdist; X } X if (width > maxwidth) X maxwidth= width; X } X X win->mwin.width= maxwidth + titledist; X win->mwin.height= mp->nitems * lineheight + 1; X CLIPMAX(win->mwin.width, WidthOfScreen(_ws)); X CLIPMAX(win->mwin.height, HeightOfScreen(_ws)); X X if (!XTranslateCoordinates(_wd, win->wo.wid, X RootWindowOfScreen(_ws), X leftedge(win, win->curmenu) -halftitledist + win->mbar.x, X win->wi.y, X &win->mwin.x, X &win->mwin.y, X &child_dummy)) { X X _wwarning("makemenu: XTranslateCoordinates failed"); X win->mwin.x = win->mwin.y = 0; X } X X CLIPMAX(win->mwin.x, WidthOfScreen(_ws) - win->mwin.width); X CLIPMAX(win->mwin.y, HeightOfScreen(_ws) - win->mwin.height); X CLIPMIN(win->mwin.x, 0); X CLIPMIN(win->mwin.y, 0); X X win->mwin.dirty= TRUE; X win->mwin.border= IBORDER; X X (void) _wcreate1(&win->mwin, RootWindowOfScreen(_ws), XC_arrow, FALSE, X win->fgo, win->bgo, 1); X _wsaveunder(&win->mwin, True); X XMapWindow(_wd, win->mwin.wid); X i = XGrabPointer(_wd, /* display */ X win->mwin.wid, /* grab_window */ X False, /* owner_events */ X ButtonMotionMask | ButtonReleaseMask, X /* event_masks */ X GrabModeAsync, /* pointer_mode */ X GrabModeAsync, /* keyboard_mode */ X None, /* confine_to */ X None, /* cursor */ X _w_lasttime /* timestamp */ X ); X if (i != GrabSuccess) { X _wwarning("makemenu: XGrabPointer failed (err %d)", i); X /* Didn't get the grab -- forget about it */ X } X} X X/* Handle mouse state change in menu bar */ X X_whitmbar(bsp, ep) X struct button_state *bsp; X EVENT *ep; X{ X WINDOW *win= bsp->win; X X if (win->curmenu >= 0) { X /* We already created a menu. X This is probably an event that was queued before X the menu window was created. */ X _wdebug(1, "_whitmbar: mouse in mwin"); X } X X if (!bsp->down) X hidemenu(win); X else if (bsp->y >= 0 && bsp->y <= win->mbar.height && X bsp->x >= 0 && bsp->x <= win->mbar.width) X showmenu(win, whichmenu(win, bsp->x)); X} X X/* Handle mouse state change in menu. X (This is called with a fake button state from _whitmbar, X since the menu bar has grabbed the pointer) */ X X/*static*/ /* Now called from event.c */ X_whitmwin(bsp, ep) X struct button_state *bsp; X EVENT *ep; X{ X WINDOW *win= bsp->win; X MENU *mp= win->menulist[win->curmenu]; X int it; X X if (bsp->x >= 0 && bsp->x <= win->mwin.width) X it= whichitem(mp, bsp->y); X else X it= NOITEM; X _wdebug(5, "_whitmwin: hit item %d", it); X hiliteitem(win, it); X X if (!bsp->down) { X hidemenu(win); X XFlush(_wd); /* Show it right now */ X if (it >= 0) { X if (mp->id == 0) { X ep->type= WE_COMMAND; X ep->u.command= WC_CLOSE; X ep->window= win; X } X else { X ep->type= WE_MENU; X ep->u.m.id= mp->id; X ep->u.m.item= it; X ep->window= win; X } X } X } X} X X/* Show and hide menus */ X Xstatic Xshowmenu(win, newmenu) X WINDOW *win; X int newmenu; X{ X if (newmenu != win->curmenu) { X hidemenu(win); X if (newmenu >= 0) { X win->curmenu= newmenu; X win->curitem= NOITEM; X inverttitle(win, win->curmenu); X makemenu(win); X drawmenu(win); X } X } X} X Xstatic Xhidemenu(win) X WINDOW *win; X{ X if (win->curmenu >= 0) { X hiliteitem(win, NOITEM); X XDestroyWindow(_wd, win->mwin.wid); X win->mwin.wid= 0; X inverttitle(win, win->curmenu); X win->curmenu= NOMENU; X } X} X X/* Compute which menu was hit */ X Xstatic int Xwhichmenu(win, xhit) X WINDOW *win; X int xhit; X{ X int i; X int x= halftitledist; X X if (xhit < x) X return NOMENU; X X for (i= 0; i < win->nmenus; ++i) { X char *title= win->menulist[i]->title; X int len= strlen(title); X x += XTextWidth(_wmf, title, len) + titledist; X if (xhit < x) X return i; X } X X return NOMENU; X} X X/* (Un)hilite the given menu item */ X Xstatic Xhiliteitem(win, it) X WINDOW *win; X int it; X{ X if (it != win->curitem) { X if (win->curitem >= 0) X invertitem(win, win->curitem); X if (it >= 0) X invertitem(win, it); X win->curitem= it; X } X} X Xstatic Xinvertitem(win, it) X WINDOW *win; X int it; X{ X int top, size; X X size= lineheight; X top= it*size; X _winvert(win->mwin.wid, win->gc, 0, top, win->mwin.width, size); X} X X/* Compute which item was hit */ X Xstatic int Xwhichitem(mp, yhit) X MENU *mp; X int yhit; X{ X int it= yhit < 0 ? NOITEM : yhit / lineheight; X X _wdebug(4, "whichitem: yhit=%d, it=%d", yhit, it); X if (it >= 0 && it < mp->nitems && mp->itemlist[it].enabled) X return it; X else X return NOITEM; X} X X/* Generate a menu selection event from a meta-key press. X *ep has the window already filled in. */ X Xbool X_w_menukey(c, ep) X int c; X EVENT *ep; X{ X WINDOW *win= ep->window; X int i; X int altc; X bool althit= FALSE; X X c &= 0xff; X X if (islower(c)) X altc= toupper(c); X else if (isupper(c)) X altc= tolower(c); X else X altc= 0; X X for (i= 0; i < win->nmenus; ++i) { X MENU *mp= win->menulist[i]; X int j; X for (j= 0; j < mp->nitems; ++j) { X if (mp->itemlist[j].shortcut == c) { X ep->type= WE_MENU; X ep->u.m.id= mp->id; X ep->u.m.item= j; X return TRUE; X } X else if (altc != 0 && !althit && X mp->itemlist[j].shortcut == altc) { X ep->u.m.id= mp->id; X ep->u.m.item= j; X althit= TRUE; X } X } X } X if (althit) X ep->type= WE_MENU; X return althit; X} X X/* Delete all menus -- called by wdone(). X (In fact local menus aren't deleted since they aren't in the menu list). */ X X_wkillmenus() X{ X while (nmenus > 0) X wmenudelete(menulist[nmenus-1]); X if (sysmenu != NULL) { X wmenudelete(sysmenu); X sysmenu= NULL; X } X} END_OF_FILE if test 11775 -ne `wc -c <'Ports/x11/menu.c'`; then echo shar: \"'Ports/x11/menu.c'\" unpacked with wrong size! fi # end of 'Ports/x11/menu.c' fi if test -f 'Ports/x11/timer.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Ports/x11/timer.c'\" else echo shar: Extracting \"'Ports/x11/timer.c'\" \(5523 characters\) sed "s/^X//" >'Ports/x11/timer.c' <<'END_OF_FILE' X/* X11 STDWIN -- Alarm timers (BSD-specific) */ X X#ifdef AMOEBA X#include "amtimer.c" X#else /* !AMOEBA */ X X#include "x11.h" X X#include <errno.h> X X/* Alarm timer values must be stored as absolute times, X but since they are in tenths of a second and stored in a long, X there isn't enough space to store the true absolute time. X Therefore, they are stored relative to the second when the X first call to wsettimer was made, which is saved in torigin */ X Xstatic long torigin; /* Seconds */ Xstatic long nexttimer; /* Deciseconds */ X X/* Compute a new value for nexttimer. X Return the relevant window as a convenience */ X Xstatic WINDOW * Xsetnexttimer() X{ X WINDOW *win= _wnexttimer(); X X if (win == NULL) X nexttimer= 0; X else X nexttimer= win->timer; X _wdebug(3, "setnexttimer: nexttimer at %d for %x", nexttimer, win); X return win; X} X X/* Set the alarm timer for a given window */ X Xvoid wsettimer(win, deciseconds) X WINDOW *win; X int deciseconds; X{ X _wdebug(3, "wsettimer: deciseconds=%d", deciseconds); X win->timer= 0; X if (deciseconds > 0) { X struct timeval tv; X struct timezone tz; X X if (gettimeofday(&tv, &tz) < 0) { X _wwarning("wsettimer: can't get time of day"); X } X else { X if (torigin == 0) { X torigin= tv.tv_sec; X _wdebug(3, "wsettimer: torigin %d", torigin); X } X win->timer= deciseconds + 10 * (tv.tv_sec - torigin) + X tv.tv_usec/100000; X _wdebug(4, "wsettimer(%d): timer set to %d", X deciseconds, win->timer); X } X } X (void) setnexttimer(); X} X X/* Return a pointer suitable as timeout parameter for BSD select(2). X If no alarms are currently set, return a NULL pointer */ X Xstatic struct timeval * Xtimeout() X{ X if (nexttimer == 0) { X _wdebug(4, "timeout: no timers set"); X return NULL; X } X else { X static struct timeval tv; X struct timezone tz; X X if (gettimeofday(&tv, &tz) < 0) { X _wwarning("timeout: can't get time of day"); X return NULL; X } X else { X long tout; X tout= nexttimer X - (tv.tv_sec - torigin) * 10 X - tv.tv_usec / 100000; X if (tout <= 0) X tv.tv_sec= tv.tv_usec= 0; X else { X tv.tv_sec= tout / 10; X tv.tv_usec= (tout % 10) * 100000; X } X _wdebug(4, "timeout: delay %d sec %d usec", X tv.tv_sec, tv.tv_usec); X return &tv; X } X } X} X X/* Check if an alarm has gone off, and if so, generate an appropriate event. X This can be called at any time, but for efficiency reasons it should X only be called when an alarm has actually gone of (i.e., select has X timed out). If an alarm has gone off, it will always be found by X this function */ X Xstatic bool Xdotimer(ep) X EVENT *ep; X{ X WINDOW *win= setnexttimer(); X struct timeval *tp; X X if (win == NULL) { X _wdebug(1, "dotimer: no event found (spurious call)"); X return FALSE; X } X tp= timeout(); X if (tp == NULL) { X _wdebug(1, "dotimer: unexpected NULL timeout()"); X return FALSE; X } X if (tp->tv_sec == 0 && tp->tv_usec == 0) { X _wdebug(3, "dotimer: reporting timer event"); X ep->type= WE_TIMER; X ep->window= win; X win->timer= 0; X (void) setnexttimer(); X return TRUE; X } X else { X _wdebug(1, "dotimer: it is not yet time"); X return FALSE; X } X} X X/* Check for timer events. X Call this after XPending returns 0, just before calling XNextEvent */ X Xbool X_w_checktimer(ep, mayblock) X EVENT *ep; X bool mayblock; X{ X for (;;) { X struct timeval *tp= timeout(); X /* This is naive. BSD 4.3 really uses an array of longs X as arguments to select. Hope there aren't >32 fds, or X the socket and pipe are among the first 32 files opened */ X unsigned long rd, wd, xd; X int fd, nfd; X int nfound; X if (tp != NULL) X _wdebug(4, "_wchecktimer: sec=%d, usec=%d", X tp->tv_sec, tp->tv_usec); X if (!mayblock) { X if (tp != NULL) X _wdebug(4, "_wchecktimer: !mayblock"); X return tp != NULL && X tp->tv_sec == 0 && tp->tv_usec == 0 && X dotimer(ep); X } X fd= _wd->fd; X rd= 1 << fd; X nfd= fd+1; X#ifdef PIPEHACK X if (_wpipe[0] >= 0) { X rd |= (1 << _wpipe[0]); X if (_wpipe[0]+1 > nfd) X nfd= _wpipe[0]+1; X } X#endif X wd= xd= 0; X if (tp == NULL) X _wdebug(4, "wchecktimer: select w/o timeout"); X else X _wdebug(4, X "_wchecktimer: select call, sec=%d, usec=%d", X tp->tv_sec, tp->tv_usec); X#ifdef AMOEBA X /* Amoeba is far superior to unix: X we don't need something as silly as select... */ X nfound= EIO; X#else X nfound= select(nfd, &rd, &wd, &xd, tp); X#endif X _wdebug(4, "_wchecktimer: select returned %d", nfound); X /* Note: if select returns negative, we also break X out of the loop -- better drop a timer event than X loop forever on a select error. X The only exception is EINTR, which may have been caused X by an application's signal handler */ X if (nfound < 0) { X if (errno == EINTR) { X _wdebug(4, "_wchecktimer: select interrupted"); X continue; X } X else { X#ifdef AMOEBA X if (errno != EIO) X#endif X _wwarning( X "_wchecktimer: select failed, errno=%d", X errno); X } X } X if (nfound != 0) X break; X if (dotimer(ep)) X return TRUE; X } X _wdebug(4, "_wchecktimer: returning FALSE"); X return FALSE; X} X X/* P.S.: It is not necessary to recompute nextalarm when windows are X deleted. This can at most cause a spurious time-out, after which X dotimeout() is called again which recomputes nextalarm as a side X effect (twice, even). Applications incur a slight overhead if they X delete a window with a timer set and no other windows have timers X set; in this case a larger part of the timeout code is called until X the alarm goes off (which is then ignored!). */ X X#endif /* !AMOEBA */ END_OF_FILE if test 5523 -ne `wc -c <'Ports/x11/timer.c'`; then echo shar: \"'Ports/x11/timer.c'\" unpacked with wrong size! fi # end of 'Ports/x11/timer.c' fi echo shar: End of archive 9 \(of 19\). cp /dev/null ark9isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 19 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0