STDWIN 0.9.5, Part 09/19
Guido van Rossum
guido at cwi.nl
Mon Mar 4 21:58:02 AEST 1991
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 at 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
More information about the Alt.sources
mailing list