Path: utzoo!utgpu!cs.utexas.edu!uunet!mcsun!hp4nl!charon!guido From: guido@cwi.nl (Guido van Rossum) Newsgroups: alt.sources Subject: STDWIN 0.9.5, Part 08/19 Keywords: Standard Window System Interface, Macintosh, X11 Message-ID: <3072@charon.cwi.nl> Date: 4 Mar 91 11:57:58 GMT Sender: news@cwi.nl Lines: 2263 Archive-name: stdwin/part08 #! /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 'Appls/dpv/dpvfonts.c' <<'END_OF_FILE' X/* dpv -- ditroff previewer. Font translation. */ X X#include "dpv.h" X#include "dpvmachine.h" X#include "dpvoutput.h" X X/* Font translation table, to map ditroff font names to font names X STDWIN (really the underlying window system) understands. X This information should really be read from a configuration file. X For now, we know to map some ditroff names for Harris and PostScript X fonts to more or less equivalent X11 and Mac fonts. X (The X fonts used are to be found in the Andrew distribution). X Because the current font scheme in STDWIN for X doesn't know about X wsetsize and wsetbold c.s., the translation process is different X for X than for the Macintosh. */ X X#define NSIZES 10 X X#define R 0 X#define B 1 X#define I 2 X#define BI 3 X Xstatic struct _translate { X char *harname; X char *xname; X int style; X int sizes[NSIZES+1]; X} default_translate[]= { X#ifdef macintosh X {"R", "Times", R}, X {"I", "Times", I}, X {"B", "Times", B}, X {"BI", "Times", BI}, X X {"H", "Helvetica", R}, X {"HO", "Helvetica", I}, X {"HB", "Helvetica", B}, X {"HD", "Helvetica", BI}, X X {"C", "Courier", R}, X {"CO", "Courier", I}, X {"CB", "Courier", B}, X {"CD", "Courier", BI}, X X {"lp", "Courier", R}, X X {"Vl", "Helvetica", R}, X {"vl", "Helvetica", R}, X {"V", "Helvetica", R}, X {"v", "Helvetica", R}, X X /* Font used by funny character translation */ X X {"Symbol", "Symbol", R}, X#else X#ifdef X11R2 X /* X11 Release 2, using fonts from Andrew */ X X /* PostScript font names */ X X {"R", "times%d", R, 8, 10, 12, 16, 22, 0}, X {"I", "times%di", R, 8, 10, 12, 16, 22, 0}, X {"B", "times%db", R, 8, 10, 12, 16, 22, 0}, X {"BI", "times%dbi", R, 8, 10, 12, 16, 22, 0}, X X {"H", "helvetica%d", R, 8, 10, 12, 16, 22, 0}, X {"HO", "helvetica%di", R, 8, 10, 12, 16, 22, 0}, X {"HB", "helvetica%db", R, 8, 10, 12, 16, 22, 0}, X {"HD", "helvetica%dbi",R, 8, 10, 12, 16, 22, 0}, X X {"C", "courier%df", R, 8, 10, 12, 16, 22, 0}, X {"CO", "courier%dif", R, 8, 10, 12, 16, 22, 0}, X {"CB", "courier%dbf", R, 8, 10, 12, 16, 22, 0}, X {"CD", "courier%dbif", R, 8, 10, 12, 16, 22, 0}, X X /* CWI Harris font names (also R, I, B, BI) */ X X /* Vega light, Vega, Vega medium (Helvetica look-alike) */ X {"Vl", "helvetica%d", R, 8, 10, 12, 16, 22, 0}, X {"vl", "helvetica%di", R, 8, 10, 12, 16, 22, 0}, X {"V", "helvetica%d", R, 8, 10, 12, 16, 22, 0}, X {"v", "helvetica%di", R, 8, 10, 12, 16, 22, 0}, X {"Vm", "helvetica%db", R, 8, 10, 12, 16, 22, 0,}, X {"vm", "helvetica%dbi",R, 8, 10, 12, 16, 22, 0,}, X X /* Baskerville (see also small caps) */ X {"br", "times%d", R, 8, 10, 12, 16, 22, 0,}, X {"bi", "times%di", R, 8, 10, 12, 16, 22, 0,}, X {"bb", "times%db", R, 8, 10, 12, 16, 22, 0,}, X {"bI", "times%dbi", R, 8, 10, 12, 16, 22, 0,}, X X /* Century Schoolbook */ X {"cr", "times%d", R, 8, 10, 12, 16, 22, 0,}, X {"ci", "times%di", R, 8, 10, 12, 16, 22, 0,}, X {"cb", "times%db", R, 8, 10, 12, 16, 22, 0,}, X {"cI", "times%dbi", R, 8, 10, 12, 16, 22, 0,}, X X /* Laurel */ X {"lr", "times%d", R, 8, 10, 12, 16, 22, 0,}, X {"li", "times%di", R, 8, 10, 12, 16, 22, 0,}, X {"lb", "times%db", R, 8, 10, 12, 16, 22, 0,}, X {"lI", "times%dbi", R, 8, 10, 12, 16, 22, 0,}, X X /* Funny fonts mapped to Helvetica, at least they differ from Times */ X {"G3", "helvetica%d", R, 8, 10, 12, 16, 22, 0,}, /* German no 3 */ X {"fs", "helvetica%d", R, 8, 10, 12, 16, 22, 0,}, /* French Script */ X {"RS", "helvetica%di", R, 8, 10, 12, 16, 22, 0,}, /* Rose Script */ X {"SO", "helvetica%db", R, 8, 10, 12, 16, 22, 0,}, /* Scitype Open */ X X /* OCR-B (line printer font) */ X {"lp", "courier%dbf", R, 8, 10, 12, 0}, X X /* Small caps fonts mapped to normal fonts */ X {"Rs", "times%d", R, 8, 10, 12, 16, 22, 0,}, /* Times */ X {"Bs", "times%db", R, 8, 10, 12, 16, 22, 0,}, /* Times bold */ X {"bs", "times%d", R, 8, 10, 12, 16, 22, 0,}, /* Baskerville */ X {"bS", "times%db", R, 8, 10, 12, 16, 22, 0,}, /* Baskerv. bold */ X X /* Fonts used by funny character translation */ X X {"symbol", "symbol%d", R, 8, 10, 12, 16, 22, 0}, X {"symbola","symbola%d", R, 8, 10, 12, 16, 22, 0}, X#else /* ! X11R3 */ X /* X11 Release 3 fonts */ X /* Also works for Release 4 */ X X /* PostScript font names */ X X {"R", "-*-times-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"I", "-*-times-medium-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"B", "-*-times-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"BI", "-*-times-bold-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X X {"H", "-*-helvetica-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"HO", "-*-helvetica-medium-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"HB", "-*-helvetica-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"HD", "-*-helvetica-bold-o-*--%d-*",R, 8, 10, 12, 14, 18, 24, 0}, X X {"C", "-*-courier-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"CO", "-*-courier-medium-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"CB", "-*-courier-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"CD", "-*-courier-bold-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X X /* CW is a common alias for C */ X {"CW", "-*-courier-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X X /* CWI Harris font names (also R, I, B, BI) */ X X /* Vega light, Vega, Vega medium (Helvetica look-alike) */ X {"Vl", "-*-helvetica-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"vl", "-*-helvetica-medium-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"V", "-*-helvetica-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"v", "-*-helvetica-medium-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X {"Vm", "-*-helvetica-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X {"vm", "-*-helvetica-bold-o-*--%d-*",R, 8, 10, 12, 14, 18, 24, 0,}, X X /* Baskerville (see also small caps) */ X {"br", "-*-times-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X {"bi", "-*-times-medium-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X {"bb", "-*-times-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X {"bI", "-*-times-bold-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X X /* Century Schoolbook */ X {"cr", "-*-new century schoolbook-medium-r-*--%d-*", X R, 8, 10, 12, 14, 18, 24, 0,}, X {"ci", "-*-new century schoolbook-medium-i-*--%d-*", X R, 8, 10, 12, 14, 18, 24, 0,}, X {"cb", "-*-new century schoolbook-bold-r-*--%d-*", X R, 8, 10, 12, 14, 18, 24, 0,}, X {"cI", "-*-new century schoolbook-bold-i-*--%d-*", X R, 8, 10, 12, 14, 18, 24, 0,}, X X /* Laurel */ X {"lr", "-*-times-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X {"li", "-*-times-medium-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X {"lb", "-*-times-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X {"lI", "-*-times-bold-i-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X X /* Funny fonts mapped to Helvetica, at least they differ from Times */ X {"G3", "-*-helvetica-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X /* German no 3 */ X {"fs", "-*-helvetica-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X /* French Script */ X {"RS", "-*-helvetica-medium-o-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X /* Rose Script */ X {"SO", "-*-helvetica-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X /* Scitype Open */ X X /* OCR-B (line printer font) */ X {"lp", "-*-courier-bold-r-*--%d-*", R, 8, 10, 12, 0}, X X /* Small caps fonts mapped to normal fonts */ X {"Rs", "-*-times-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X /* Times */ X {"Bs", "-*-times-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X /* Times bold */ X {"bs", "-*-times-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X /* Baskerville */ X {"bS", "-*-times-bold-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0,}, X /* Baskerville bold */ X X /* Fonts used by funny character translation */ X X {"r3symbol", "*-*-symbol-medium-r-*--%d-*", R, 8, 10, 12, 14, 18, 24, 0}, X#endif /* ! X11R2 */ X#endif /* ! macintosh */ X X {NULL, NULL} X}; X Xstatic struct _translate *translate = default_translate; X X/* Tell STDWIN to use the desired font and size. X Call at start of page and after each font or size change. */ X Xusefont() X{ X char *fontname; X X if (showpage != ipage) X return; X X fontname= fonts.name[font]; X if (fontname != NULL) X fonthack(fontname); X /* Else, font not loaded -- assume in initialization phase */ X baseline= wbaseline(); X lineheight= wlineheight(); X recheck(); X} X Xfonthack(fontname) X char *fontname; X{ X int i; X int havesize; X char *harname; X char buf[256]; X struct _translate *t; X X for (t= translate; t->harname != NULL; ++t) { X if (strcmp(t->harname, fontname) == 0) X break; X } X if (t->harname == NULL) { X fontwarning(fontname); X } X else { X#ifdef macintosh X wsetfont(t->xname); X wsetsize(size); X wsetplain(); X switch (t->style) { X case I: wsetitalic(); break; X case B: wsetbold(); break; X case BI: wsetbolditalic(); break; X } X#else X havesize= size; X for (i= 0; ; ++i) { X if (t->sizes[i] >= havesize || t->sizes[i+1] == 0) { X havesize= t->sizes[i]; X break; X } X } X sprintf(buf, t->xname, havesize); X wsetfont(buf); X#endif X } X} X X/* Issue a warning. X Avoid warning many times in a row about the same font. */ X Xfontwarning(fontname) X char *fontname; X{ X static char lastwarning[200]; X char buf[256]; X X if (strncmp(lastwarning, fontname, sizeof lastwarning) != 0) { X strncpy(lastwarning, fontname, sizeof lastwarning); X sprintf(buf, "mapping for font %s unknown", fontname); X error(WARNING, buf); X } X} X X/* Get a token */ X Xstatic char * Xgettok(pp) X char **pp; X{ X char *p = *pp; X char *start; X char c; X X while (isspace(c = *p++)) /* Skip to start of token */ X ; X if (c == '\0' || c == '\n' || c == '#') { X if (dbg > 2) X if (c == '#') X fprintf(stderr, "next token is comment\n"); X else if (c == '\n') X fprintf(stderr, "next token is newline\n"); X else X fprintf(stderr, "next token is EOS\n"); X return NULL; /* End of line of comment */ X } X start = p-1; /* Remember start of token */ X while (!isspace(c = *p++) && c != '\0') /* Skip to end of token */ X ; X if (c == '\0') X p--; X else X p[-1] = '\0'; /* Zero-terminate token */ X *pp = p; /* Start point for next token */ X if (dbg > 2) X fprintf(stderr, "next token: %s\n", start); X return start; X} X Xstatic void Xaddtrans(pnt, pt, harname, xname, style, sizes) X int *pnt; X struct _translate **pt; X char *harname; X char *xname; X int style; X int sizes[]; X{ X int i = (*pnt)++; X struct _translate *t = *pt; X X if (i == 0) X t = (struct _translate *) malloc(sizeof(struct _translate)); X else X t = (struct _translate *) X realloc((char *)t, sizeof(struct _translate) * *pnt); X if (t == NULL) X error(FATAL, "not enough memory for font translations"); X *pt = t; X t += i; X t->harname = strdup(harname); X t->xname = strdup(xname); X t->style = style; X for (i = 0; i <= NSIZES; i++) X t->sizes[i] = sizes[i]; X} X X/* Read a file of alternative font translations. */ X Xreadtrans(filename) X char *filename; X{ X struct _translate *t; X int nt; X FILE *fp; X int line; X char buf[1000]; X char *p; X char *harname; X char *xname; X char *sizetemp; X int sizes[NSIZES+1]; X static int defsizes[NSIZES+1] = {8, 10, 12, 14, 18, 24, 0}; X int nsizes; X X fp = fopen(filename, "r"); X if (fp == NULL) X error(FATAL, "can't find font translations file %s", filename); X if (dbg > 0) X fprintf(stderr, "reading translations from %s\n", filename); X t = NULL; X nt = 0; X line = 0; X while (fgets(buf, sizeof buf, fp) != NULL) { X line++; X if (dbg > 1) X fprintf(stderr, "line %d: %s\n", line, buf); X p = buf; X harname = gettok(&p); X if (harname == NULL) X continue; /* Blank line or comment */ X xname = gettok(&p); X if (xname == NULL) { X error(WARNING, "%s(%d): incomplete line (only '%s')", X filename, line, harname); X continue; X } X /* Style is always R */ X nsizes = 0; X while (nsizes < NSIZES && (sizetemp = gettok(&p)) != NULL) { X sizes[nsizes] = atoi(sizetemp); X if (sizes[nsizes] <= 0 || X nsizes > 0 && X sizes[nsizes] <= sizes[nsizes-1]) { X error(WARNING, X "%s(%d): bad or non-increasing size '%s'", X filename, line, sizetemp); X } X else X nsizes++; X } X if (nsizes > 0) X while (nsizes <= NSIZES) X sizes[nsizes++] = 0; X addtrans(&nt, &t, harname, xname, R, X nsizes == 0 ? defsizes : sizes); X } X if (dbg > 0) X fprintf(stderr, "done reading translations.\n"); X fclose(fp); X if (nt == 0) X error(FATAL, "%s: no valid font translations", filename); X addtrans(&nt, &t, (char *)NULL, (char *)NULL, R, defsizes); X translate = t; X} END_OF_FILE if test 12151 -ne `wc -c <'Appls/dpv/dpvfonts.c'`; then echo shar: \"'Appls/dpv/dpvfonts.c'\" unpacked with wrong size! fi # end of 'Appls/dpv/dpvfonts.c' fi if test -f 'Doc/seldoc.ms' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Doc/seldoc.ms'\" else echo shar: Extracting \"'Doc/seldoc.ms'\" \(12081 characters\) sed "s/^X//" >'Doc/seldoc.ms' <<'END_OF_FILE' X.\" To format, use (di)troff -ms; and make sure macros.ms is around! X.so macros.ms X.SH XUsing X11 Selections and Cut Buffers in STDWIN X.LP XThe C STDWIN interface has been extended to support the X.I selection Xmechanism used by X11. XSupport for the ring of 8 cut buffers is also provided. X.PP XThis document assumes you are familiar with STDWIN as a programmer and Xwith X11 as an end user (at least xterm experience and some idea of the Xclient-server model). X.NH XWhat are Selections? X.LP XX11 supports an arbitrary number of selections, but version 1.0 of the XICCCM (Inter-Client Communication Conventions Manual, by David Rosenthal) Xrequires only that clients support three selections called PRIMARY, XSECONDARY and CLIPBOARD. XI will further reference these in lower case. X.PP XThe X.I "primary selection" Xis the mechanism you normally use to transfer data interactively Xbetween clients (or within one client). XIn xterm and text-oriented toolkit clients, you make a primary Xselection by dragging with the left mouse button. XThe contents of the selection are highlighted using inverse video. XThe contents of the primary selection can be pasted into the same or Xanother (toolkit) client by pressing the middle mouse button. X.PP XConventions for use of the X.I "secondary selection" Xare less well-known. XIt is used as the second argument of operations with two arguments, Xsuch as swap or replace operations. XThere is no default support for it in the toolkit, but it is Xpossible to customize toolkit clients to use it. X.PP XThe X.I clipboard Xis intended to hold data that the user has deleted and wants to insert Xsomewhere later. XIt is supported by the standard X11 client X.I xclipboard , Xwhich displays the current contents of the clipboard. XOther toolkit clients can be customized to use it. X.NH XSelections From the Client's Point of View X.LP XIt is important to realize that the contents of selections are Xtransferred between clients at the time they are pasted; selections are Xnot normally stored by the server. XAt any time, a selection is ``owned'' by at most one client, the X.I "selection owner" . XDifferent selections may be owned by different clients. XThe server keeps track of selection owners. XWhen a client wants to become owner of a particular selection, it tells Xthe server so, and the server will send the previous owner an event to Xtell it that it no longer owns the selection. X.PP XThe protocol to transfer the contents of a selection between clients is Xfairly involved. XSomewhat simplified, it works as follows: X.IP \(bu XA client requests the contents of a selection from the server. X.IP \(bu 2 XThe server sends the owner an event asking ``please give me this Xselection.'' X.IP \(bu 2 XThe owner stores the contents of the selection as a X.I property\(dg X.FS X\(dg XA window X.I property Xis a named arbitrary piece of data associated with a window, stored by Xthe server. X.FE Xon the requestor's window, and sends an event back (via the server) Xtelling the requestor that the selection is stored. X.IP \(bu 2 XThe requestor fetches the contents of the property, and deletes Xthe property. X.PP XVarious complications are possible: X.IP \(bu 2 XRace conditions: a client may be slow to respond to a mouse click, and Xthe impatient user may have clicked again in another client's window. XWhen the first client finally decides it wants to become selection Xowner, the second client may already own it. X.IP \(bu XCrashes: a selection owner may crash before it has responded to a Xrequest for the selection's contents. X.IP \(bu XSpace limitations on the server. X.IP \(bu XNegotiations about the type of the selection: a string could be stored Xin simple ASCII or in a special format that retains font information, Xand in fact a selection may contain a picture or an arbitrarily Xcomplicated data structure that only a few clients know about. X.NH XThe STDWIN Interface to Selections X.LP XSTDWIN simplifies the concept of a selection somewhat and takes care of Xmost details of communicating with other clients. XIn STDWIN, selections are always ASCII strings and only the three Xstandard selections are supported. XThe strings are null-terminated but may also contain embedded null Xcharacters, so a length is always provided. X.PP XThe header X.cW Xdefines constants that identify the selections: X.cW WS_PRIMARY , X.cW WS_SECONDARY , Xand X.cW WS_CLIPBOARD . XThe application calls the function X.cW wsetselection() Xto become owner of a selection. XIt may later receive an event of type X.cW WE_LOST_SEL Xtelling it that it lost ownership again. XIt is also possible to voluntarily give up selection ownership by Xcalling X.cW wresetselection() . XTo access the contents of a selection, whether you own it or not, call Xthe function X.cW wgetselection() . XTransfer of selection contents to other clients is done automatically by X.cW wgetevent() Xand X.cW wpollevent() . XDetailed descriptions of the new functions follow: X.NH 2 XFunction \* X.LP X.sC L Xbool wsetselection(win, sel, data, len) XWINDOW *win; Xint sel; Xchar *data; Xint len; X.eC X.LP XParameters: X.IP \* 6n XSpecifies a window that will be associated with the selection. XThis has no other meaning that limiting the lifetime of the selection to Xthe lifetime of the window. XIt will not be reported in X.cW WE_LOST_SEL Xevents. X.IP \* XSpecifies which selection should be set. XIt should be one of the codes X.cW WS_PRIMARY , X.cW WS_SECONDARY , Xor X.cW WS_CLIPBOARD . X.IP \* XSpecifies the data comprising the selection's contents. XThis need not be null-terminated. XIt is copied to a safe place by the function so it can be sent to Xother clients later. X.IP \* XSpecifies the length of the data, not including a terminating null byte. X.LP XThis function attempts to acquirpe ownership of the specified selection. XThis may fail because of race conditions. XThe function returns nonzero if it succeeds. XIf it fails, the application should give the user visual feedback of the Xfailure, X.I e.g. , Xby not inverting the selected text. X.NH 2 XFunction \* X.LP X.sC L Xvoid wresetselection(sel) Xint sel; X.eC X.LP XParameters: X.IP \* 6n XSpecifies which selection should be reset. XIt should be one of the codes X.cW WS_PRIMARY , X.cW WS_SECONDARY , Xor X.cW WS_CLIPBOARD . X.LP XIf the application owns the specified selection, this function cancels Xownership. XNo X.cW WE_LOST_SEL Xevents are generated for the selection. X.NH 2 XFunction \* X.LP X.sC L Xchar *wgetselection(sel, plen) Xint sel; Xint *plen; X.eC XParameters: X.IP \* 6n XSpecifies which selection should be retrieved. XIt should be one of the codes X.cW WS_PRIMARY , X.cW WS_SECONDARY , Xor X.cW WS_CLIPBOARD . X.IP \* XInto this parameter, the length of the data is returned, excluding the Xterminating null byte. X.LP XThis function retrieves the contents of the specified selection. XIf it succeeds, a pointer to its data is returned. XThe data is terminated by a null byte but may contain null bytes, so the Xlength is returned separately. XThe data pointer points to space internal to the STDWIN library. XIt remains valid until the next call involving selections. XIf the selection could not be retrieved somehow, a NULL pointer is Xreturned. XSelections longer that 32K may be truncated. XSince the transfer mechanism requires the use of a window, a NULL Xpointer is returned when the application currently has no windows open. X.NH 2 XThe \* event type X.LP XA STDWIN application receives this event type when it owns a selection X(a call to X.cW wsetselection() Xhas succeeded) and another client has become the new owner. XThe X.cW window Xmember of the X.cW EVENT Xis set to X.cW NULL . XThe X.cW u.sel Xunion member is set to the code for the selection. XThis event is not generated when selection ownership is given up by Xcalling X.cW wresetselection() Xor by deleting its window. X.NH XThe STDWIN Interface to Cut Buffers X.LP XFor compatibility with old STDWIN or X11 clients and Andrew clients, Xan interface to the cut buffer interface is also provided. XThis is a ring of 8 buffers maintained at the server. XThe following functions are available: X.NH 2 XFunction \* X.LP X.sC L Xvoid wsetcutbuffer(ibuffer, data, len) Xint ibuffer; Xchar *data; Xint len; X.eC X.LP XParameters: X.IP \* 10n XSpecifies which buffer should be set, in the range [0 ... 7]. X.IP \* XSpecifies the data. XIt need not be null-terminated. X.IP \* XSpecifies the length of the data, excluding a terminating null byte. X.LP XThis function sets the contents of the specified cut buffer to the given Xdata. XNo indication of success or failure is given. X.NH 2 XFunction \* X.LP X.sC L Xchar *wgetcutbuffer(ibuffer, plen) Xint ibuffer; Xint *plen; X.eC X.LP XParameters: X.IP \* 10n XSpecifies which buffer should be retrieved, in the range [0 ... 7]. X.IP \* XReturns the length of the data, excluding the terminating null byte. X.LP XThis function returns the contents of the specified cut buffer, Xterminated by a null byte. XIf the cut buffer is not accessible, it returns X.cW NULL . X.NH 2 XFunction \* X.LP X.sC L Xvoid wrotatecutbuffers(n) Xint n; X.eC X.LP XParameters: X.IP \* 4n XSpecifies the amount of rotation. XThis may be negative. X.LP XThe cut buffers are rotated as follows: Xbuffer n gets the contents of buffer 0, buffer n+1 (mod 8) gets the Xcontents of buffer 1, etc. X.NH 2 XFunction \* X.LP X.sC L Xvoid wsetclip(data, len) Xchar *data; Xint len; X.eC XThis function is equivalent to X.sC Xwsetcutbuffer(0, data, len); Xwrotatecutbuffers(1); X.eC X.NH 2 XFunction \* X.LP X.sC L Xchar *wgetclip() X.eC XThis function is equivalent to X.sC Xint len; Xreturn wgetcutbuffer(0, &len); X.eC X(It throws away the length.) X.NH XSuggested Usage X.LP XTo conform to X11 conventions, STDWIN applications should normally use Xthe primary selection, but use the cut buffers as a ``fall-back'' Xmechanism. X.PP XWhen the user has selected some text, the application should transfer Xthe text to cut buffer 0 and rotate the buffers (the easiest way to do Xthis is to call X.cW wsetclip() ), Xand then call X.cW wsetselection() Xto set the primary selection to the text. XIf the latter call fails, the inverse video on the selected text should Xbe removed. XThe inverse video should also be removed when a X.cW WE_LOST_SEL Xevent is received. XIf there is a text insertion point associated with the selection, it Xshould be left at the position indicated by the last mouse click, or to Xthe beginning of the selected text. X.PP XWhen the user desires to paste some text, the applcation should first Xget the contents of the primary selection, and if this returns a NULL Xpointer, it should get the contents of cut buffer 0. XIf this returns a NULL pointer as well, the paste request should be Xrefused (with a beep, or something similar). X.PP XThe conventions for selecting and pasting text are: X.IP \(bu 2 XDragging with the left (first) mouse button is used to make a selection. XDouble-clicking selects ``words.'' X.IP \(bu XClicking with the middle mouse button requests a ``paste'' operation. XIt does not move the insert point to the position of the click. X.IP \(bu XClicking with the right mouse button extends the selection at the end Xclosest to the button click. X.NH XSelections and Macintosh STDWIN X.LP XThe Macintosh user interface standards prescribe only a single cut Xbuffer, called the Clipboard. XFor source compatibility with STDWIN applications developed for X11, Xdummy versions of the selection functions are provided: X.cW wsetselection() Xand X.cW wgetselection() Xalways fail, and X.cW wresetselection() Xis ignored. XVersions of the cut buffer functions are provided that identify cut Xbuffer 0 with the Macintosh Clipboard and ignore the other cut buffers. X.PP XThe net effect is that STDWIN applications written for X11 selections Xthat use the cut buffers as a fall-back mechanism will support the XMacintosh Clipboard, albeit with an X11-like interface. XMacintosh applications are encouraged to provide a standard Edit menu Xwith the operations Cut, Copy and Paste and the standard shortcuts for Xthem: Command-X, Command-C and Command-V. END_OF_FILE if test 12081 -ne `wc -c <'Doc/seldoc.ms'`; then echo shar: \"'Doc/seldoc.ms'\" unpacked with wrong size! fi # end of 'Doc/seldoc.ms' fi if test -f 'Packs/textedit/textlow.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Packs/textedit/textlow.c'\" else echo shar: Extracting \"'Packs/textedit/textlow.c'\" \(12558 characters\) sed "s/^X//" >'Packs/textedit/textlow.c' <<'END_OF_FILE' X/* Text Edit, low-level routines */ X X/* CONVENTION: X routines beginning with te... have a first parameter 'tp'; X routines beginning with z... don't, or are macros that X implicitly use a variable or parameter 'tp' X*/ X X#include "text.h" X X/* Variants on wtextwidth, wtextbreak, wdrawtext taking the gap in account. X These have two buffer offsets as parameters instead of a text pointer X and a length; tetextbreak also returns a buffer offset */ X X/* These routines now also take tabs into account. X They should now only be called with a line start for 'pos' ! */ X Xint Xtetextwidth(tp, pos, end) X register TEXTEDIT *tp; X bufpos pos, end; X{ X char *p= tp->buf + pos; X register char *e= tp->buf + X (tp->gap >= pos && tp->gap < end ? tp->gap : end); X int w= 0; X register char *k; X X zcheckpos(pos); X zcheckpos(end); X zassert(pos <= end); X X /* This do loop is executed once or twice only! */ X do { X for (k= p; k < e; ++k) { X if (*k == '\t') { X if (k > p) X w += wtextwidth(p, (int)(k-p)); X w= znexttab(w); X p= k+1; X } X } X if (k > p) X w += wtextwidth(p, (int)(k-p)); X if (tp->gap >= pos) { X p= tp->buf + zgapend; X e= tp->buf + end; X } X } while (k < e); X X return w; X} X Xbufpos Xtetextbreak(tp, pos, end, width) X register TEXTEDIT *tp; X bufpos pos, end; X int width; X{ X char *p= tp->buf + pos; X register char *e= tp->buf + X (tp->gap >= pos && tp->gap < end ? tp->gap : end); X int w= 0; X register char *k; X X zcheckpos(pos); X zcheckpos(end); X zassert(pos <= end); X X /* This do loop is executed once or twice only! */ X do { X for (k= p; k < e; ++k) { X if (*k == '\t') { X if (k > p) { X int n= wtextbreak(p, (int)(k-p), X width-w); X if (n < k-p) X return p - tp->buf + n; X w += wtextwidth(p, (int)(k-p)); X } X w= znexttab(w); X if (w > width) X return k - tp->buf; X p= k+1; X } X } X if (k > p) { X int n= wtextbreak(p, (int)(k-p), width-w); X if (n < k-p) X return p - tp->buf + n; X w += wtextwidth(p, (int)(k-p)); X } X if (tp->gap >= pos) { X p= tp->buf + zgapend; X e= tp->buf + end; X } X } while (k < e); X X return end; X} X Xhcoord Xtedrawtext(tp, h, v, pos, end) X register TEXTEDIT *tp; X int h, v; X bufpos pos, end; X{ X char *p= tp->buf + pos; X register char *e= tp->buf + X (tp->gap >= pos && tp->gap < end ? tp->gap : end); X int w= 0; X register char *k; X X zcheckpos(pos); X zcheckpos(end); X zassert(pos <= end); X X /* This do loop is executed once or twice only! */ X do { X for (k= p; k < e; ++k) { X if (*k == '\t') { X if (k > p) X wdrawtext(h+w, v, p, (int)(k-p)); X w += wtextwidth(p, (int)(k-p)); X w= znexttab(w); X p= k+1; X } X } X if (k > p) { X wdrawtext(h+w, v, p, (int)(k-p)); X w += wtextwidth(p, (int)(k-p)); X } X if (tp->gap >= pos) { X p= tp->buf + zgapend; X e= tp->buf + end; X } X } while (k < e); X X return h+w; X} X X/* Safe memory allocation - these abort instead of returning NULL */ X Xchar * Xzmalloc(n) X int n; X{ X char *p= malloc((unsigned)n); X X if (p == NULL) { X dprintf("zmalloc(%d): out of mem", n); X exit(1); X } X return p; X} X Xchar * Xzrealloc(p, n) X char *p; X int n; X{ X char *q= realloc(p, (unsigned)n); X if (q == NULL) { X dprintf("zrealloc(0x%lx, %d): out of mem", (long)p, n); X exit(1); X } X return q; X} X X/* Create/destroy a text-edit record */ X XTEXTEDIT * Xtealloc(win, left, top, width) X WINDOW *win; X{ X return tesetup(win, left, top, left+width, top, TRUE); X} X XTEXTEDIT * Xtecreate(win, left, top, right, bottom) X WINDOW *win; X int left, top, right, bottom; X{ X return tesetup(win, left, top, right, bottom, TRUE); X} X X/*ARGSUSED*/ XTEXTEDIT * Xtesetup(win, left, top, right, bottom, drawing) X WINDOW *win; X int left, top, right, bottom; X bool drawing; X{ X TEXTEDIT *tp= (TEXTEDIT*) zmalloc(sizeof(TEXTEDIT)); X TEXTATTR saveattr; X X tp->win= win; X tp->left= left; X tp->top= top; X tp->right= right; X tp->width= right-left; X X wgettextattr(&saveattr); X if (win != NULL) { X wgetwintextattr(win, &tp->attr); X wsettextattr(&tp->attr); X } X else X tp->attr = saveattr; X tp->vspace= wlineheight(); X tp->tabsize= 8*wcharwidth(' '); X if (win != NULL) X wsettextattr(&saveattr); X X tp->bottom= tp->top + tp->vspace; X X tp->foc= tp->foclen= 0; X X tp->buflen= 1; X tp->buf= zmalloc(tp->buflen); X X tp->gap= 0; X tp->gaplen= tp->buflen; X X tp->nlines= 1; X tp->nstart= STARTINCR; X tp->start= (bufpos*) zmalloc(tp->nstart*sizeof(bufpos)); X tp->start[0]= tp->start[1]= tp->buflen; X X tp->aim= UNDEF; X tp->focprev= FALSE; X tp->hilite= FALSE; X tp->mdown= FALSE; X tp->drawing= tp->active= drawing; X tp->opt_valid= FALSE; X X if (tp->active) X tesetcaret(tp); X X zcheck(); X X return tp; X} X X Xvoid Xtedestroy(tp) X register TEXTEDIT *tp; X{ X wchange(tp->win, tp->left, tp->top, tp->right, tp->bottom); X tefree(tp); X} X Xvoid Xtefree(tp) X register TEXTEDIT *tp; X{ X if (tp->active) { X wnocaret(tp->win); X tehidefocus(tp); X } X if (tp->buf != NULL) X free(tp->buf); X if (tp->start != NULL) X free((char*)tp->start); X free((char*)tp); X} X Xvoid Xtesetactive(tp, active) X register TEXTEDIT *tp; X bool active; X{ X if (!tp->drawing || tp->active == active) X return; X tp->active = active; X if (active) { X tesetcaret(tp); X } X else { X wnocaret(tp->win); X tehidefocus(tp); X } X} X X/* Show/hide the focus highlighting. X The boolean hilite is set when highlighting is visible. X teshowfocus ensures the highlighting is visible (if applicable); X tehidefocus ensures it is invisible. X teinvertfocus does the hard work (it is also called from zdraw) */ X Xteshowfocus(tp) X register TEXTEDIT *tp; X{ X if (tp->active && !tp->hilite && tp->foclen > 0) { X wbegindrawing(tp->win); X teinvertfocus(tp); X wenddrawing(tp->win); X tp->hilite= TRUE; X } X} X Xtehidefocus(tp) X register TEXTEDIT *tp; X{ X if (tp->hilite) { X wbegindrawing(tp->win); X teinvertfocus(tp); X wenddrawing(tp->win); X tp->hilite= FALSE; X } X} X Xstatic Xteinvertfocus(tp) X register TEXTEDIT *tp; X{ X teinvert(tp, tp->foc, zfocend); X} X X/* Change to a new focus. X Sometimes this may keep the focus visible, sometimes not. */ X Xtechangefocus(tp, f1, f2) X register TEXTEDIT *tp; X int f1, f2; X{ X if (tp->hilite) { X wbegindrawing(tp->win); X if (f1 == tp->foc) X teinvert(tp, zfocend, f2); X else if (f2 == zfocend) X teinvert(tp, f1, tp->foc); X else { X teinvert(tp, tp->foc, zfocend); X tp->hilite= FALSE; X } X wenddrawing(tp->win); X } X tp->foc= f1; X tp->foclen= f2-f1; X} X X/* Low-level interface: invert the area between f1 and f2 */ X Xstatic Xteinvert(tp, f1, f2) X register TEXTEDIT *tp; X int f1, f2; X{ X coord h, v, hlast, vlast; X X if (f1 == f2) X return; X if (f2 < f1) { X int temp= f1; X f1= f2; X f2= temp; X } X X tewhichpoint(tp, f1, &h, &v); X tewhichpoint(tp, f2, &hlast, &vlast); X X if (v == vlast) X winvert(h, v, hlast, v + tp->vspace); X else { X winvert(h, v, tp->right, v + tp->vspace); X winvert(tp->left, v + tp->vspace, tp->right, vlast); X winvert(tp->left, vlast, hlast, vlast + tp->vspace); X } X} X X/* Draw procedure */ X Xvoid Xtedraw(tp) X register TEXTEDIT *tp; X{ X tedrawnew(tp, tp->left, tp->top, tp->right, tp->bottom); X} X X/*ARGSUSED*/ Xvoid Xtedrawnew(tp, left, top, right, bottom) X register TEXTEDIT *tp; X coord left, top, right, bottom; X{ X lineno ifirst, ilast, i; X X /* Compute first, last line to be drawn */ X ifirst= (top - tp->top)/tp->vspace; X if (ifirst < 0) X ifirst= 0; X ilast= (bottom - tp->top + tp->vspace - 1)/tp->vspace; X if (ilast > tp->nlines) X ilast= tp->nlines; X X /* Draw lines ifirst...ilast-1 */ X for (i= ifirst; i < ilast; ++i) { X bufpos pos= tp->start[i]; X bufpos end= tp->start[i+1]; X if (end > pos && zcharbefore(end) == EOL) X zdecr(&end); X while (end > pos && zcharbefore(end) == ' ') X zdecr(&end); X (void) tedrawtext(tp, tp->left, tp->top + i*tp->vspace, X pos, end); X } X if (tp->hilite) X teinvertfocus(tp); X} X X/* Move the gap to a new position */ X Xtemovegapto(tp, newgap) X register TEXTEDIT *tp; X bufpos newgap; X{ X zcheck(); X zassert(0<=newgap && newgap+tp->gaplen<=tp->buflen); X X if (newgap < tp->gap) X teshift(tp, tp->gaplen, newgap, tp->gap); X else if (newgap > tp->gap) X teshift(tp, -tp->gaplen, zgapend, newgap+tp->gaplen); X tp->gap= newgap; X X zcheck(); X} X X/* Extend the gap */ X Xtegrowgapby(tp, add) X register TEXTEDIT *tp; X int add; X{ X zcheck(); X zassert(add>=0); X X tp->buf= zrealloc(tp->buf, tp->buflen + add); X teshift(tp, add, zgapend, tp->buflen); X tp->gaplen += add; X if (tp->start[tp->nlines-1] == tp->buflen) X tp->start[tp->nlines-1]= tp->buflen+add; X tp->start[tp->nlines]= (tp->buflen += add); X X zcheck(); X} X X/* Shift buf[first..last-1] n bytes (positive right, negative left) */ X Xstatic Xteshift(tp, n, first, last) X register TEXTEDIT *tp; X int n; X bufpos first, last; X{ X teoffset(tp, n, first, last); X if (n < 0) X temovedown(tp, last-first, tp->buf+first, tp->buf+first+n); X else if (n > 0) X temoveup(tp, last-first, tp->buf+first, tp->buf+first+n); X} X Xstatic Xteoffset(tp, n, first, last) X register TEXTEDIT *tp; X int n; X int first, last; X{ X int i; X X zassert(0<=first&&first<=last&&last<=tp->buflen); X X i= 0; X while (tp->start[i] < first) X ++i; X while (tp->start[i] < last) { X tp->start[i] += n; X ++i; X } X} X X/*ARGSUSED*/ Xstatic Xtemoveup(tp, n, from, to) X TEXTEDIT *tp; X int n; X char *from, *to; X{ X zassert(from <= to); X X from += n, to += n; X while (--n >= 0) X *--to = *--from; X} X X/*ARGSUSED*/ Xstatic Xtemovedown(tp, n, from, to) X TEXTEDIT *tp; X int n; X char *from, *to; X{ X zassert(from >= to); X X while (--n >= 0) X *to++ = *from++; X} X X/* Make all start entries pointing into the gap point to beyond it X TO DO: replace by a routine to delete the focus??? */ X Xteemptygap(tp) X register TEXTEDIT *tp; X{ X lineno i; X X for (i= 0; tp->start[i] < tp->gap; ++i) X ; X for (; tp->start[i] < zgapend; ++i) X tp->start[i]= zgapend; X} X X/* Set the caret at the new focus position, X or display the focus highlighting, if applicable. X Also call wshow() of the focus. X As a side effect, the optimization data is invalidated */ X Xtesetcaret(tp) X register TEXTEDIT *tp; X{ X coord h, v, hlast, vlast; X X tp->opt_valid = FALSE; X if (!tp->active) X return; X X tewhichpoint(tp, tp->foc, &h, &v); X X if (tp->foclen == 0) { X wsetcaret(tp->win, h, v); X hlast= h; X vlast= v; X } X else { X tewhichpoint(tp, zfocend, &hlast, &vlast); X wnocaret(tp->win); X teshowfocus(tp); X } X wshow(tp->win, h, v, hlast, vlast + tp->vspace); X} X X/* Coordinate transformations. X The following coordinate systems exist; X a position in the text can be expressed in any of these: X X A) offset in buffer with gap removed (used for focus) X B) offset in buffer (used for start[] array) X C) (line number, offset in line taking gap into account) X D) (h, v) on screen X X Conversions exist between successive pairs: X X A -> B: pos= zaddgap(foc) X B -> A: foc= zsubgap(pos) X X B -> C: line= zwhichline(pos, prev); offset= pos-start[line] X C -> B: pos= offset + start[line] X X C -> D: v= i*vspace; h= ztextwidth(start[i], start[i]+offset) X D -> C: i= v/wlh; offset= ztextround(i, h) - start[i] X*/ X X/* Find (h, v) corresponding to focus position */ X Xtewhichpoint(tp, f, h_ret, v_ret) X TEXTEDIT *tp; X focpos f; X coord *h_ret, *v_ret; X{ X bufpos pos= zaddgap(f); X lineno i= tewhichline(tp, pos, f == tp->foc && tp->focprev); X hcoord h= tetextwidth(tp, tp->start[i], pos); X X *h_ret= h + tp->left; X *v_ret= i*tp->vspace + tp->top; X} X X/* To which line does the given buffer position belong? */ X Xlineno Xtewhichline(tp, pos, prev) X register TEXTEDIT *tp; X bufpos pos; X bool prev; /* Cf. focprev */ X{ X lineno i; X X for (i= 0; pos > tp->start[i+1]; ++i) X ; X if (pos == tp->start[i+1] && i+1 < tp->nlines) { X ++i; X if (prev && zcharbefore(tp->start[i]) != EOL) X --i; X } X X return i; X} X X/* Convert point in window to buffer position, X possibly taking double-clicking into account. X If required, the line number is also returned. */ X Xbufpos Xtewhereis(tp, h, v, line_return) X register TEXTEDIT *tp; X coord h, v; X int *line_return; X{ X bufpos pos; X lineno i; X X i= (v - tp->top)/tp->vspace; X if (i >= tp->nlines) { X i= tp->nlines; X pos= tp->buflen; X } X else if (i < 0) { X i= 0; X pos= 0; X } X else X pos= tetextround(tp, i, h); X if (line_return != NULL) X *line_return= i; X return pos; X} X X/* Find the buffer position nearest to the given h coordinate, X in the given line */ X Xbufpos Xtetextround(tp, i, h) X register TEXTEDIT *tp; X lineno i; X hcoord h; X{ X bufpos pos; X bufpos end= tp->start[i+1]; X X h -= tp->left; X if (end > tp->start[i] && zcharbefore(end) == EOL) X zdecr(&end); X pos= tetextbreak(tp, tp->start[i], end, h); X X if (pos < end) { X if (h - tetextwidth(tp, tp->start[i], pos) >= X tetextwidth(tp, tp->start[i], znext(pos)) - h) X zincr(&pos); X } X X return pos; X} END_OF_FILE if test 12558 -ne `wc -c <'Packs/textedit/textlow.c'`; then echo shar: \"'Packs/textedit/textlow.c'\" unpacked with wrong size! fi # end of 'Packs/textedit/textlow.c' fi if test -f 'Ports/mac/event.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Ports/mac/event.c'\" else echo shar: Extracting \"'Ports/mac/event.c'\" \(12997 characters\) sed "s/^X//" >'Ports/mac/event.c' <<'END_OF_FILE' X/* MAC STDWIN -- EVENT HANDLING. */ X X#include "macwin.h" X#ifdef MPW X#include X#include X#include X#include X#endif X#ifdef THINK_C X#include X#endif X Xvoid (*_w_idle_proc)(); /* Function to call in idle loop */ X XWINDOW *active= NULL; /* The active window */ X /* XXX should be a less obvious name */ Xbool _wm_down; /* Set if mouse is down in content rect */ X Xstatic EventRecord e; /* Global, so it's accessible to all subroutines */ X /* XXX the name is too short */ X X/* Function prototypes */ X XSTATIC void make_mouse_event _ARGS((EVENT *ep, Point *pwhere)); XSTATIC void do_idle _ARGS((EVENT *ep)); XSTATIC void do_update _ARGS((EVENT *ep)); XSTATIC void do_mouse_down _ARGS((EVENT *ep)); XSTATIC void do_mouse_up _ARGS((EVENT *ep)); XSTATIC void do_key _ARGS((EVENT *ep)); XSTATIC void do_activate _ARGS((EVENT *ep)); XSTATIC void do_disk _ARGS((EVENT *ep)); XSTATIC void activate _ARGS((WINDOW *win)); XSTATIC void deactivate _ARGS((void)); X XSTATIC void do_click _ARGS((EVENT *ep, WindowPtr w)); XSTATIC void do_unclick _ARGS((EVENT *ep)); XSTATIC void do_drag _ARGS((WindowPtr w)); XSTATIC void do_grow _ARGS((EVENT *ep, WindowPtr w)); XSTATIC void do_goaway _ARGS((EVENT *ep, WindowPtr w)); XSTATIC void do_zoom _ARGS((EVENT *ep, WindowPtr w, int code)); XSTATIC void do_size _ARGS((EVENT *ep, WindowPtr w)); X X# ifndef NO_STDIO X/* Some applications (e.g., Python) want events passed to the stdio console. X They must call wsetstdio(1) before their first wgetevent() call. */ X Xstatic int pass_to_stdio = 0; X Xvoid Xwsetstdio(flag) X int flag; X{ X pass_to_stdio = flag; X} X#endif X Xstatic EVENT pushback= {WE_NULL}; X Xvoid Xwungetevent(ep) X EVENT *ep; X{ X pushback= *ep; X} X Xstatic void Xwwaitevent(ep, wait) X EVENT *ep; X bool wait; X{ X _wfreeclip(); X if (pushback.type != WE_NULL) { X *ep= pushback; X pushback.type= WE_NULL; X return; X } X X if (_wmenuhilite) { X HiliteMenu(0); X _wmenuhilite= FALSE; X } X X if (active == NULL) X set_arrow(); X X ep->type= WE_NULL; X ep->window= NULL; X X do { X if (!GetNextEvent(everyEvent, &e)) { X if (e.what == nullEvent) { X if (wait) do_idle(ep); X else return; X } X } X else { X#ifndef NO_STDIO X /* Give THINK C stdio a chance to handle the event. X Unfortunately it also eats up clicks in X title bars, so, to save our Option-click feature, X we don't feed it those. */ X if (pass_to_stdio && X !(e.what == mouseDown && X (e.modifiers & optionKey))) { X if (StdEvent(&e)) X continue; X } X#endif X switch (e.what) { X case mouseDown: X do_mouse_down(ep); X break; X case mouseUp: X do_mouse_up(ep); X break; X case keyDown: X case autoKey: X do_key(ep); X break; X case updateEvt: X do_update(ep); X break; X case diskEvt: X do_disk(ep); X break; X case activateEvt: X do_activate(ep); X break; X } X } X } while (ep->type == WE_NULL); X X if (ep->window == NULL) X ep->window= whichwin(FrontWindow()); X if (!_wm_down) X set_watch(); X} X Xint Xwpollevent(ep) X EVENT *ep; X{ X ep->type = WE_NULL; X wwaitevent(ep, FALSE); X return ep->type != WE_NULL; X} X Xvoid Xwgetevent(ep) X EVENT *ep; X{ X wwaitevent(ep, TRUE); X} X Xstatic void Xdo_idle(ep) X EVENT *ep; X{ X if (checktimer(ep)) X return; X X if (_w_idle_proc != NULL) X (*_w_idle_proc)(); X X /* The user idle proc may have called wungetevent: */ X if (pushback.type != WE_NULL) { X *ep= pushback; X pushback.type= WE_NULL; X return; X } X X SystemTask(); X X if (active != NULL) { X Point where; X Rect r; X X where= e.where; X SetPort(active->w); X GlobalToLocal(&where); X if (_wm_down) { X autoscroll(active, where.h, where.v); X make_mouse_event(ep, &where); X return; X } X getwinrect(active, &r); X if (PtInRect(PASSPOINT where, &r)) { X if (e.modifiers & optionKey) X set_hand(); X else X set_applcursor(); X } X else X set_arrow(); X blinkcaret(active); X } X} X Xstatic void Xdo_update(ep) X EVENT *ep; X{ X WINDOW *win; X Rect r; X X win= whichwin((WindowPtr) e.message); X if (win == NULL) { X /* dprintf("update evt for alien window"); */ X return; X } X _wupdate(win, &r); X if (win->drawproc == NULL && !EmptyRect(&r)) { X ep->type= WE_DRAW; X ep->window= win; X ep->u.area.left= r.left; X ep->u.area.top= r.top; X ep->u.area.right= r.right; X ep->u.area.bottom= r.bottom; X } X} X Xstatic void Xdo_mouse_down(ep) X EVENT *ep; X{ X WindowPtr w; X int code= FindWindow(PASSPOINT e.where, &w); X X /* XXX This doesn't look incredibly necessary: X if (active != NULL) { X SetPort(active->win); X rmcaret(active); X } X */ X X if (code != inContent && code != inSysWindow) X set_arrow(); X switch (code) { X case inMenuBar: X _wdo_menu(ep, MenuSelect(PASSPOINT e.where)); X break; X case inSysWindow: X SystemClick(&e, w); X break; X case inContent: X do_click(ep, w); X break; X case inDrag: X do_drag(w); X break; X case inGrow: X do_grow(ep, w); X break; X case inGoAway: X do_goaway(ep, w); X break; X case inZoomIn: X case inZoomOut: X do_zoom(ep, w, code); X break; X } X} X Xstatic void Xdo_mouse_up(ep) X EVENT *ep; X{ X do_unclick(ep); X} X Xstatic void Xdo_key(ep) X EVENT *ep; X{ X char c= e.message & charCodeMask; X X /* XXX shouldn't mess at all with non-stdwin windows */ X X if (e.modifiers & cmdKey) { X if (c == '.') { X ep->type= WE_COMMAND; X ep->u.command= WC_CANCEL; X } X else X _wdo_menu(ep, MenuKey(c)); X } X else { X ep->type= WE_COMMAND; X switch (c) { X X default: X ObscureCursor(); X ep->type= WE_CHAR; X ep->u.character= c; X break; X X case LEFT_ARROW: X case RIGHT_ARROW: X case UP_ARROW: X case DOWN_ARROW: X ep->u.command= c-LEFT_ARROW + WC_LEFT; X break; X X case '\b': X ObscureCursor(); X ep->u.command= WC_BACKSPACE; X break; X X case '\t': X ObscureCursor(); X ep->u.command= WC_TAB; X break; X X case '\r': X case ENTER_KEY: X ep->u.command= WC_RETURN; X break; X X } X } X} X Xstatic void Xdo_disk(ep) X EVENT *ep; X{ X /* XXX Disk events not implemented -- who cares. */ X} X X/* XXX Need to be easier for cases where we seem to have missed events */ X Xstatic void Xdo_activate(ep) X EVENT *ep; X{ X WINDOW *win= whichwin((WindowPtr)e.message); X X if (win == NULL) { X /* dprintf("(de)activate evt for alien window"); */ X return; X } X X if (e.modifiers & activeFlag) { /* Activation */ X if (active != NULL) { X /* Perhaps reactivation after modal dialog */ X#ifdef NO_STDIO X /* But perhaps THINK C stdio is fooling us */ X if (active == win) X return; X /* If we get here we've missed a X deactivate event... */ X dprintf("activate without deactivate"); X#endif X } X activate(win); X ep->type= WE_ACTIVATE; X ep->window= active; X } X else { /* Deactivation */ X if (win != active) { X /* Spurious deactivation event. X This always happens when we open X two or more windows without intervening X call to wgetevent(). X Perhaps an conscious hack in the X ROM to "help" programs that believe X windows are created active? */ X return; X } X ep->type= WE_DEACTIVATE; X ep->window= active; X deactivate(); X } X} X Xstatic void Xdeactivate() X{ X SetPort(active->w); X rmcaret(active); X hidescrollbars(active); X rmlocalmenus(active); X DrawGrowIcon(active->w); X active= NULL; X set_arrow(); X} X Xstatic void Xactivate(win) X WINDOW *win; X{ X if (active != NULL) X deactivate(); X if (win != NULL) { X SetPort(win->w); X active= win; X showscrollbars(win); X addlocalmenus(active); X valid_border(win->w); /* Avoid flicker when window pops up */ X } X} X Xstatic void Xdo_click(ep, w) X EVENT *ep; X WindowPtr w; X{ X WINDOW *win= whichwin(w); X Point where; X int pcode; X ControlHandle bar; X X if (win == NULL) { X /* dprintf("click in alien window"); */ X return; X } X if (win != active) { X set_arrow(); X if (e.modifiers & optionKey) { X /* Option-click sends a window behind. */ X SendBehind(w, (WindowPtr) NULL); X } X else X SelectWindow(win->w); X return; X /* Let activate events do the rest. */ X } X where= e.where; X SetPort(win->w); X GlobalToLocal(&where); X pcode= FindControl(PASSPOINT where, w, &bar); X if (pcode != 0) { X set_arrow(); X do_scroll(&where, win, bar, pcode); X } X else { X Rect r; X X getwinrect(win, &r); X if (PtInRect(PASSPOINT where, &r)) { X if (e.modifiers & optionKey) { X set_hand(); X dragscroll(win, X where.h, where.v, X e.modifiers & shiftKey); X } X else { X set_applcursor(); X make_mouse_event(ep, &where); X } X } X } X} X Xstatic void Xdo_unclick(ep) X EVENT *ep; X{ X if (active != NULL) { X Point where; X X where= e.where; X SetPort(active->w); X GlobalToLocal(&where); X make_mouse_event(ep, &where); X } X} X Xstatic void Xdo_drag(w) X WindowPtr w; X{ X if (e.modifiers & optionKey) { X /* Nonstandard: option-click sends a window behind. */ X SendBehind(w, (WindowPtr) NULL); X } X else { X Rect r; X X r= screen->portRect; X r.top += MENUBARHEIGHT; X InsetRect(&r, 4, 4); X DragWindow(w, PASSPOINT e.where, &r); X } X} X Xstatic void Xdo_grow(ep, w) X EVENT *ep; X WindowPtr w; X{ X Rect r; X long reply; X X /* XXX shouldn't mess at all with non-stdwin windows */ X X /* Set minimal window size */ X r.left= LSLOP + MIN_WIDTH + RSLOP + BAR; X r.top= MIN_HEIGHT + BAR; X X /* The max size is derived from the document size. X If there is no document size, it is unlimited. X (There is nothing wrong with windows larger than X the screen, really.) */ X r.right = r.bottom = 0x7fff; X { X /* Max size restriction based on doc size, if specified */ X WINDOW *win = whichwin(w); X int docwidth = win->docwidth; X int docheight = win->docheight; X if (win->docwidth > 0) { X CLIPMIN(docwidth, MIN_WIDTH); X r.right = LSLOP + docwidth + RSLOP + BAR + 1; X } X if (win->docheight > 0) { X CLIPMIN(docheight, MIN_HEIGHT); X r.bottom = docheight + BAR + 1; X } X /* For some reason 1 has to be added. Sigh. */ X } X X reply= GrowWindow(w, PASSPOINT e.where, &r); X if (reply != 0) { X SetPort(w); X inval_border(w); X SizeWindow(w, LoWord(reply), HiWord(reply), TRUE); X do_size(ep, w); X } X} X Xstatic void Xdo_goaway(ep, w) X EVENT *ep; X WindowPtr w; X{ X /* XXX shouldn't mess at all with non-stdwin windows */ X X if (TrackGoAway(w, PASSPOINT e.where)) { X ep->type= WE_COMMAND; X ep->window= whichwin(w); X ep->u.command= WC_CLOSE; X } X} X Xstatic void Xdo_zoom(ep, w, code) X EVENT *ep; X WindowPtr w; X int code; X{ X /* XXX shouldn't mess at all with non-stdwin windows */ X X /* This code will never be reached on a machine X with old (64K) ROMs, because FindWindow will X never return inZoomIn or inZoomOut. X Therefore, no check for new ROMs is necessary. X A warning in Inside Macintosh IV says that X it is necessary to make the zoomed window X the current GrafPort before calling ZoomWindow. X True enough, it fails spectacularly otherwise, X but still this looks like a bug to me - there X are no similar requirements for SizeWindow X or DragWindow. */ X X SetPort(w); X if (TrackBox(w, PASSPOINT e.where, code)) { X inval_border(w); X ZoomWindow(w, code, TRUE); X do_size(ep, w); X } X} X X/* do_size assumes w is already the current grafport */ X Xstatic void Xdo_size(ep, w) X EVENT *ep; X WindowPtr w; X{ X WINDOW *win= whichwin(w); X X if (win == NULL) { X /* dprintf("alien window resized"); */ X return; X } X inval_border(w); X movescrollbars(win); X ep->type= WE_SIZE; X ep->window= win; X _wfixorigin(win); X} X Xvoid Xinval_border(w) X WindowPtr w; X{ X Rect r; X X r= w->portRect; X r.left= r.right - BAR; X InvalRect(&r); X r= w->portRect; X r.top= r.bottom - BAR; X InvalRect(&r); X} X Xvoid Xvalid_border(w) X WindowPtr w; X{ X Rect r; X X r= w->portRect; X r.left= r.right - BAR; X ValidRect(&r); X r= w->portRect; X r.top= r.bottom - BAR; X ValidRect(&r); X} X X/* Variables needed in click and move detection. */ X Xstatic int m_h, m_v; /* Doc. coord. of last mouse evt. */ Xstatic long m_when; /* TickCount of last mouse evt. */ Xstatic int m_clicks; /* N-fold click stage */ Xstatic int m_button; /* Which 'button'; X 1=normal, 2=shift, 3=command. */ X Xstatic void Xmake_mouse_event(ep, pwhere) X EVENT *ep; X Point *pwhere; /* Mouse pos. in local coord. */ X{ X WINDOW *win= active; X int h= pwhere->h + win->orgh; X int v= pwhere->v + win->orgv; X int dh= h - m_h; X int dv= v - m_v; X X if (dh*dh + dv*dv > CLICK_DIST*CLICK_DIST) X m_clicks= 0; /* Moved too much for a click */ X X if (e.what == mouseDown) { X if (e.when > m_when + GetDblTime()) X m_clicks= 1; X else X ++m_clicks; X ep->type= WE_MOUSE_DOWN; X _wm_down= TRUE; X /* XXX Should swap buttons 2 & 3 (also in textedit) X since X11 (e.g., xterm) uses button 3 for extend */ X m_button= (e.modifiers & cmdKey) ? 3 : X (e.modifiers & shiftKey) ? 2 : 1; X } X else if (e.what == mouseUp) { X if (!_wm_down) X return; X ep->type= WE_MOUSE_UP; X _wm_down= FALSE; X } X else { X if (!_wm_down || m_clicks > 0 || (dh == 0 && dv == 0)) X return; X ep->type= WE_MOUSE_MOVE; X } X ep->u.where.h= m_h= h; X ep->u.where.v= m_v= v; X ep->u.where.clicks= m_clicks; X ep->u.where.button= m_button; X ep->u.where.mask= (ep->type == WE_MOUSE_UP) ? 0 : 1; X ep->window= win; X m_when= e.when; X} X X/* Reset the mouse state. X Called when a dialog is started. */ X Xvoid X_wresetmouse() X{ X _wm_down= FALSE; X} END_OF_FILE if test 12997 -ne `wc -c <'Ports/mac/event.c'`; then echo shar: \"'Ports/mac/event.c'\" unpacked with wrong size! fi # end of 'Ports/mac/event.c' fi if test -f 'Ports/mac/menu.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Ports/mac/menu.h'\" else echo shar: Extracting \"'Ports/mac/menu.h'\" \(354 characters\) sed "s/^X//" >'Ports/mac/menu.h' <<'END_OF_FILE' X/* MAC STDWIN -- MENU DEFINITIONS. */ X X/* Note -- struct menu isn't defined here. X MENU * is taken to be equivalent to MenuPtr, whenever appropriate. X I know this is a hack -- I'll fix it later. */ X Xstruct menubar { X int nmenus; /* Number of menus in the list */ X MENU **menulist; /* Pointer to list of MENU pointers */ X}; X X#define APPLE_MENU 32000 END_OF_FILE if test 354 -ne `wc -c <'Ports/mac/menu.h'`; then echo shar: \"'Ports/mac/menu.h'\" unpacked with wrong size! fi # end of 'Ports/mac/menu.h' fi echo shar: End of archive 8 \(of 19\). cp /dev/null ark8isdone 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