home *** CD-ROM | disk | FTP | other *** search
- From: guido@cwi.nl (Guido van Rossum)
- Newsgroups: alt.sources
- Subject: STDWIN 0.9.5, Part 07/19
- Message-ID: <3071@charon.cwi.nl>
- Date: 4 Mar 91 11:57:54 GMT
-
- Archive-name: stdwin/part07
-
- #! /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 7 (of 19)."
- # Contents: Doc/vtrmdoc.ms Ports/mac/scroll.c Ports/x11/general.c
- # Ports/x11/llevent.c
- # Wrapped by guido@voorn.cwi.nl on Mon Mar 4 12:37:26 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Doc/vtrmdoc.ms' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Doc/vtrmdoc.ms'\"
- else
- echo shar: Extracting \"'Doc/vtrmdoc.ms'\" \(14015 characters\)
- sed "s/^X//" >'Doc/vtrmdoc.ms' <<'END_OF_FILE'
- X.TL
- X.if n .po 0
- X.if n .ll 72
- X.if n .nr LL 72n
- X.if t .po 3.5c \" For LaserWriter only
- XInterfacing to Keyboard and Screen with VTRM
- X.br
- X(Draft)
- X.AU
- XGuido van Rossum
- X.AB
- XSince both groups of `interns' at the ABC project will soon need to
- Xinterface their editors to a terminal, here is a description of the VTRM
- Xpackage, together with some hints on writing a simple displayer using
- Xthis package. Footnotes are used to indicate portions of the interface
- Xthat may change in the future.
- X.AE
- X.SH
- X1. Introduction
- X.LP
- XThe VTRM package can significantly ease terminal-independent input and
- Xoutput for a screen-oriented program like a text editor, written in C.
- XThere are
- Xabout a dozen routines, with few and simple parameters, that allow
- Xoptimized output to almost any ASCII terminal designed in the Western
- Xhemisphere, and input of single characters without echoing. Features
- Xinclude adaptation to any screen size, scrolling, and inverse video or a
- Xsimilar `stand-out' mode of displaying selected characters. Screen
- Xrefreshes use available terminal features such as character insert or
- Xdelete to minimize the number of characters actually output to the
- Xterminal, thus obtaining reasonable performance even at low baud rates.
- X.PP
- XImplementations of the VTRM package are available for
- X.UX ,
- XMS-DOS and the Apple Macintosh, and the package can be ported to
- Xother similar micro-computers. It is also possible to write an
- Xinterface to windowing systems like those found on Sun or Whitechapel
- Xworkstations.
- X.SH
- X2. Theory of operation
- X.LP
- XVTRM is a set of subroutines callable from a C program. There is a
- Xcertain discipline required in calling these routines; there are
- Xan initialization call, several data manipulation and input calls, and a
- Xclean-up call. The C program that is making the calls to VTRM is
- Xfurther referred to as `the application'. In fact, on different
- Xsystems, different soubroutines are used; but they all conform to the
- Xsame interface, which is what is described in this document.
- X.PP
- XVTRM has a simple model for a terminal screen: there are YMAX lines,
- Xeach consisting XMAX characters. YMAX and XMAX are not constants,
- Xbut remain constant during one particular program run.*
- X.FS
- X*This causes problems with resizable windows as currently available
- Xunder 4.3 BSD. It is possible that future versions can adapt themselves
- Xto changing window sizes, but this will require adaptation of the
- Xprograms calling VTRM.
- X.FE
- X.PP
- XThe coordinate system used by VTRM is different from that normally used
- Xin geometry, but more convenient for referencing screen positions:
- Xwhereever a position on the screen is referenced, it has the form (Y, X)
- Xwhere Y is the line number and X is the column number. The top line is
- Xline 0, the bottom line is YMAX\-1. Likewise, the leftmost
- Xcolumn is column 0, the rightmost is XMAX\-1. (Note how this is
- Xcompatible with array indexing practices in C.) **
- X.FS
- X** This will get us into trouble with bit-mapped displays, where often
- Xthe preferred character set or `font' has characters of different
- Xwidths, so that the number of characters displayable on a line is not a
- Xconstant. This issue is ignored by VTRM; implementations on such
- Xsystems currently use a `fixed-width' font.
- X.FE
- X.PP
- XEach character position contains one character, which is in the ASCII
- Xrange SPACE to `~', i.e., SPACE and all printable characters. Each
- Xcharacter can be displayed in one of two modes: normal or `stand-out',
- Xwhich is usually inverse video or underlined (this is a choice made by
- Xthe VTRM package). `Empty' parts of the screen contain spaces in normal
- Xmode. ***
- X.FS
- X*** Eventually the character set allowed will have to be extended to all
- Xor most characters in the machine's standard character set that can be
- Xdisplayed. There is a tendency for systems to extend the 7-bit ASCII
- Xcode to an 8-bit code, where the characters in the range 128-255 are
- Xused for special graphics, accented characters etc. VTRM currently uses
- Xthe 8th bit to indicate stand-out mode; this will have to be changed in
- Xthe interface. Applications are discouraged to use the 8th bit of
- Xcharacters as a `stand-out' flag except in the immediate interface with
- XVTRM.
- X.FE
- X.PP
- XVTRM is strongly line-oriented. The application must offer data to VTRM
- Xin chunks of one or more lines, and scrolling operations can only be
- Xapplied to entire lines. This is not likely to change in the near
- Xfuture. VTRM does not necessarily send whole lines to the screen: only
- Xchanged parts of a line are actually transmitted. VTRM recognizes most
- Xcases of insertion or deletion of small strings in a line, which can
- Xoften be handled with character insertions and/or deletions.
- X.PP
- XVTRM may buffer its output. There is one routine which flushes the
- Xbuffer and moves the terminal's cursor to a given (Y, X) position;
- Xduring the screen update process the screen contents and cursor position
- Xmay temporarily be undefined. Not all implementations actually buffer
- Xtheir output; micro-computer screen operations are often fast enough.
- XIn all cases, the cursor position is undefined during the screen update.
- X.PP
- XVTRM does not automatically clear the screen when first called; it
- Xallows an application to be written in such a manner that its output
- Xappears at the bottom of the screen and gradually scrolls upwards,
- Xmimicking the behaviour of older programs, if it so wishes. On the
- Xother hand, it is trivial to clear the screen after the first call.
- X.PP
- XOn
- X.UX ,
- XVTRM sets the terminal in a special mode (formally: cbreak, no echo, no
- Xcr to nl mapping). This makes it
- Xnecessary that an application takes measures to call the VTRM clean-up
- Xroutine whenever it exits.
- X.PP
- XOn
- X.UX ,
- XVTRM uses the `termcap' database to find out the terminal's
- Xcapabilities. It requires that the <:TERM:> environment variable is
- Xset, and optionally acknowledges the <:TERMCAP:> variable. Information
- Xon the proper use of these variables should be readily accessible to all
- Xusers of the application.
- X.SH
- X3. Description of the interface
- X.SH
- X3.1 Set-up and clean-up calls
- X.SH
- XTRMSTART
- X.LP
- X.DS
- X<:int trmstart(p_lines, p_columns, p_flags)
- Xint *p_lines, *p_columns;
- Xint *p_flags;:>
- X.DE
- XThis call must be made before any of the other calls are allowed. The
- Xfunction result is 0 if initialization is successful, nonzero if an
- Xerror occurred. In the latter case the applications should usually
- Xprint an error message and exit; the terminal state has not been
- Xaltered. The meaning of the error codes is described in the appendix.
- X.PP
- XThe three arguments must be the addresses of three integer variables
- X(call as, e.g., <:trmstart(&lines, &columns, &flags):>).
- XIn <:*p_lines:> and <:*p_columns:>, YMAX and XMAX are returned.
- XIn <:*p_flags:>, some flag bits are returned, but these can usually be
- Xignored by the applications (some flag bits are defined but never used).
- X.SH
- XTRMEND
- X.LP
- X.DS
- X<:trmend();:>
- X.DE
- XThis function cleans up before the application exits. If it is not
- Xcalled (when <:trmstart:> has been called), the application may leave
- Xthe terminal in a weird mode, from which it is hard to recover for the
- Xuser (on
- X.UX -systems non-
- Xother weird things may happen).
- X.PP
- XSo that it can be safely called from within an interrupt handler,
- X<:trmend:> may be called at any time, before or even during a call to
- X<:trmstart:>. Calls at any other time than after a successful call
- Xto <:trmstart:> are ignored. After a call to <:trmend:>, as before a
- Xcall to <:trmstart:>, calls to all other routines of VTRM are forbidden
- X(this is not enforced by all implementations \- but your program may
- Xcrash).
- X.PP
- XAn application may engage in a sequence of interactive sessions, each
- Xbracketed between calls to <:trmstart:> and <:trmend:>. Outside these
- Xsessions, normal print-style output can safely be used, thusly:
- X.DS
- X<:trmstart(...);
- X\fIVTRM interaction 1\fP
- Xtrmend();
- Xprintf("Hello, world\\n"); /* Etc. */
- Xtrmstart(...);
- X\fIVTRM interaction 2\fP
- Xtrmend();
- X:><:...:>
- X.DE
- X.SH
- X3.2 Output calls
- X.SH
- XTRMPUTDATA
- X.LP
- X.DS
- X<:trmputdata(y0, y1, x, data)
- Xint y0, y1;
- Xint x;
- Xchar *data;:>
- X.DE
- XThe characters in `data' are placed on the screen, starting at line y0,
- Xposition x, and continuing up to the last position of line y1. If data
- Xis shorter than this space, the remaining positions are filled with
- Xspaces; if tdata is too long, it is truncated. The positions 0 through
- Xx\-1 on line y0 are left unchanged.
- X.PP
- XCharacters with their 8th bit on (or-ed with 0200 octal or 0x80 hex)
- Xare displayed in `stand-out' mode.
- X.PP
- XThe following is an easy way of clearing the screen:
- X.DS
- X<:trmputdata(0, YMAX-1, 0, "");:>
- X.DE
- X.SH
- XTRMSCROLLUP
- X.LP
- X.DS
- X<:trmscrollup(y0, y1, n)
- Xint y0, y1;
- Xint n;:>
- X.DE
- XScrolls the screen lines y0 to y1, inclusive, up by n lines.
- XIf n is negative, it scrolls down. When scrolling up, the top n lines
- Xstarting at y0 disappear, the lines from y0+n to y1 move up n lines,
- Xand n blank lines are `shifted in' at and above line y1. Scrolling down
- Xis similar. If abs(n) > y1\-y0, lines y0 to y1 are blanked.
- X.SH
- XTRMSYNC
- X.LP
- X.DS
- X<:trmsync(y, x)
- Xint y, x;:>
- X.DE
- XCompletes any pending operations, flushes the output buffer, and moves
- Xthe cursor to position (y, x) on the screen.
- X.SH
- XTRMUNDEFINED
- X.LP
- X.DS
- X<:trmundefined();:>
- X.DE
- XTells VTRM to forget whatever it has remembered about the current screen
- Xcontents. This is necessary before doing a complete screen refresh in
- Xresponse to a user command like control-L, since such a refresh is
- Xusually intended to correct the effect of transmission errors or other
- Xprocesses clobbering the screen.
- X.SH
- XTRMBELL
- X.LP
- X.DS
- X<:trmbell();:>
- X.DE
- XIssues an alarm to the user in a way most appropriate to the output
- Xdevice being used. This may either be an audible bell or beep,
- Xor a `visible bell', meaning a flash of (part of) the screen.
- X.PP
- X(On
- X.UX ,
- Xa control-G is sent to the terminal, unless the termcap entry specifies
- Xthe `vb' property (visible bell). On MS-DOS, the bell is sounded
- Xunconditionally. On the Macintosh, `SysBeep' is called, which gives a
- Xbeep with a level determined by the volume control on the Control Panel,
- Xor flashes the menu bar if the volume is set to 0.)
- X.SH
- X3.3 Input calls
- X.SH
- XTRMINPUT
- X.LP
- X.DS
- X<:int trminput();:>
- X.DE
- XReturns the next input character typed at the keyboard, waiting if
- Xnecessary until one is typed. When an error occurs, \-1 is returned;
- Xthis is usually permanent, so further input would be futile. This could
- Xhappen, for example, when the user `hangs up'.
- X.SH
- XTRMAVAIL
- X.LP
- X.DS
- X<:int trmavail();:>
- X.DE
- XReturns 1 if an input character is immediately available for
- X<:trminput:>; 0 if no such character is available; and \-1 if the system
- Xcan't find out (this is not an error condition; it means that the system
- Xcannot do a `non-blocking read').
- X.SH
- XTRMSENSE
- X.LP
- X.DS
- X<:int trmsense(p_y, p_x)
- Xint *p_y, *p_x;:>
- X.DE
- XSenses the current cursor or mouse position, and returns its position,
- Xconverted to screen coordinates, in <:*p_y:> and <:*p_x:>. If the
- Xterminal is not capable of sensing the cursor position, both values are
- Xset to \-1 and the functions returns 0; after a successful sense, the
- Xfunction returns 1.
- X.SH
- X3.4 Interrupt handling calls
- X.SH
- XTRMINTERRUPT
- X.LP
- X.DS
- X<:int trminterrupt();:>
- X.DE
- XChecks for keyboard-generated interrupt. Returns 1 if one is found, 0
- Xif not. This may set a signal handler for <:SIGINT:>, so it may
- Xinterfere with the application's signal handling.* It may also flush
- Xtype-ahead and (unfortunately enough) discard output buffers.
- X.FS
- X* This is an experimental feature. Use at own risk. Check the source
- Xcode to see if its actually implemented, and how.
- X.FE
- X.SH
- XTRMSUSPEND
- X.LP
- X.DS
- X<:trmsuspend();:>
- X.DE
- XThis call does nothing except on Berkeley
- X.UX
- Xsupporting job control. Because the terminal state and screen contents
- Xare not restored when a process is suspended or resumed, programs using
- XVTRM must be aware of suspension. The character control-Z is received
- Xas a normal input character by <:trminput:>, because <:trmstart:> turns
- Xoff most special character processing. When a control-Z is received,
- Xthe application should react as follows:
- X.DS
- X<:trmend();
- Xtrmsuspend();
- Xtrmstart(...);
- X\fIrepaint the screen\fR:>
- X.DE
- XThe <:trmsuspend:> call suspends the application and its `process group';
- Xthis includes any subprocesses, and possibly parent processes (if the
- Xapplication was run from a shell script or from another program, maybe
- Xusing a `shell escape'). It only returns when the process group is resumed
- Xagain (with the shell's `fg' command).
- X.SH
- X4. Examples
- X.LP
- XHere is a very small sample program:
- X.DS
- X<:main() {
- X int lines, columns, flags;
- X if (trmstart(&lines, &columns, &flags) != 0) exit(1);
- X trmputdata(0, lines-1, 0, "Hello, \\327orld!");
- X trmsync(1, 0);
- X trmend();
- X exit(0);
- X}:>
- X.DE
- XIt prints the text <:Hello, \fBW\fRorld!:> at the top of the screen,
- Xcleans the rest of the screen, and moves the cursor the the beginning of
- Xthe second line. The `W' is displayed in stand-out mode.
- X.TL
- XAppendix \- <:\fBtrmstart:> error codes and flags
- X.sp 2
- X.LP
- XThe file "trm.h" can be included to get definitions for the flags and
- Xerror codes returned by <:trmstart:>. It contains the following:
- X.sp 1
- X.nf
- X<:
- X.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n
- X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
- X
- X/*
- X * Terminal capabilities. These correspond to bits set by trmstart in its
- X * parameter flags parameter.
- X */
- X
- X#define HAS_STANDOUT 1 /* Terminal has inverse video or underline */
- X#define CAN_SCROLL 2 /* Terminal can insert/delete lines */
- X#define CAN_OPTIMISE 4 /* Terminal can insert/delete characters */
- X#define CAN_SENSE 8 /* Terminal can send cursor position */
- X
- X/*
- X * Error codes returned by trmstart.
- X */
- X
- X#define TE_OK 0 /* No errors */
- X#define TE_TWICE 1 /* Trmstart called again */
- X#define TE_NOTERM 2 /* $TERM not set or empty */
- X#define TE_BADTERM 3 /* $TERM not found in termcap database */
- X#define TE_DUMB 4 /* Terminal too dumb */
- X#define TE_NOTTY 5 /* Stdout not a tty device */
- X#define TE_NOMEM 6 /* Can't get enough memory */
- X#define TE_OTHER 7 /* This and higher are reserved errors */
- X:>
- X.fi
- END_OF_FILE
- if test 14015 -ne `wc -c <'Doc/vtrmdoc.ms'`; then
- echo shar: \"'Doc/vtrmdoc.ms'\" unpacked with wrong size!
- fi
- # end of 'Doc/vtrmdoc.ms'
- fi
- if test -f 'Ports/mac/scroll.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Ports/mac/scroll.c'\"
- else
- echo shar: Extracting \"'Ports/mac/scroll.c'\" \(13659 characters\)
- sed "s/^X//" >'Ports/mac/scroll.c' <<'END_OF_FILE'
- X/* MAC STDWIN -- SCROLLING. */
- X
- X/* All non-public functions here assume the current grafport is set */
- X
- X/* XXX The contents of this file should be organized more top-down */
- X
- X#include "macwin.h"
- X#ifdef MPW
- X#include <Events.h>
- X#endif
- X
- X/* I am using the fact here that the scroll bars of an inactive window
- X are invisible:
- X when a window's origin or its document size changes while it isn't the
- X active window, its controls get their new values but aren't redrawn. */
- X
- X/* Key repeat constants in low memory (set by the Control Panel),
- X in ticks (used here to control the continuous scrolling speed). */
- X
- X#define KeyThresh (* (short*)0x18e) /* Delay until repeat starts */
- X#define KeyRepThresh (* (short*)0x190) /* Repeat rate */
- X
- X#define JURJENBARPROC 48 /* CDEF id for Jurjen's proportional scrollbar */
- X
- XSTATIC void setscrollbarvalues _ARGS((WINDOW *win));
- XSTATIC void usescrollbarvalues _ARGS((WINDOW *win));
- XSTATIC void sizescrollbars _ARGS((WINDOW *win));
- XSTATIC void calcbar _ARGS((ControlHandle bar,
- X int org, int size, int begin, int end));
- XSTATIC void setbar _ARGS((ControlHandle bar, int winsize, int val, int max));
- XSTATIC void deltabar _ARGS((ControlHandle bar, int delta));
- XSTATIC void showbar _ARGS((ControlHandle bar));
- XSTATIC void hidebar _ARGS((ControlHandle bar));
- XSTATIC void movebar _ARGS((ControlHandle bar,
- X int left, int top, int right, int bottom));
- X
- Xvoid
- Xwsetorigin(win, orgh, orgv)
- X WINDOW *win;
- X int orgh, orgv;
- X{
- X Rect r;
- X
- X /* XXX wsetorigin is currently the only routine that allows
- X the application to show bits outside the document.
- X Is even this desirable? */
- X
- X CLIPMIN(orgh, 0);
- X CLIPMIN(orgv, 0);
- X getwinrect(win, &r);
- X orgh -= LSLOP;
- X if (orgh != win->orgh || orgv != win->orgv) {
- X SetPort(win->w);
- X scrollby(win, &r, win->orgh - orgh, win->orgv - orgv);
- X win->orgh= orgh;
- X win->orgv= orgv;
- X setscrollbarvalues(win);
- X }
- X}
- X
- Xvoid
- Xwgetorigin(win, ph, pv)
- X WINDOW *win;
- X int *ph, *pv;
- X{
- X *ph = win->orgh + LSLOP;
- X *pv = win->orgv;
- X}
- X
- Xvoid
- Xwshow(win, left, top, right, bottom)
- X WINDOW *win;
- X int left, top, right, bottom;
- X{
- X int orgh, orgv;
- X int winwidth, winheight;
- X int docwidth, docheight;
- X
- X /* Calls to wshow while the mouse is down are ignored,
- X because they tend to mess up auto-scrolling.
- X I presume it's harmless (even the right thing to do),
- X since wshow is usually called to make sure the object
- X being selected is visible, which isn't a problem while
- X the user is busy pointing at it.
- X The check must be here, not in wsetorigin, because
- X the latter is used internally by the auto-scroll code! */
- X if (_wm_down)
- X return;
- X
- X /* The code below is generic for all versions of stdwin */
- X
- X wgetorigin(win, &orgh, &orgv);
- X wgetwinsize(win, &winwidth, &winheight);
- X wgetdocsize(win, &docwidth, &docheight);
- X
- X orgh = calcneworigin(orgh, left, right, winwidth, docwidth);
- X orgv = calcneworigin(orgv, top, bottom, winheight, docheight);
- X
- X wsetorigin(win, orgh, orgv);
- X}
- X
- X/* Subroutine for wshow to calculate new origin in h or v direction */
- X
- Xstatic int
- Xcalcneworigin(org, low, high, winsize, docsize)
- X int org, low, high, winsize, docsize;
- X{
- X if (docsize <= 0)
- X return org;
- X
- X /* Ignore requests to show bits outside doc */
- X /* XXX Is this necessary? */
- X CLIPMIN(low, 0);
- X CLIPMAX(high, docsize);
- X
- X /* Ignore requests for empty range */
- X /* XXX Is this what we want? */
- X if (high <= low)
- X return org;
- X
- X if (org <= low && high <= org + winsize)
- X return org;
- X
- X if (high - low > winsize) { /* Range too big for window */
- X
- X /* Don't scroll if at least 1/3 of the window is in range */
- X /* XXX 1/3 is an arbitrary number! */
- X if (low <= org + winsize*2/3 && high >= org + winsize/3)
- X return org;
- X
- X /* Center the end of the range that's closest to the window */
- X if (low - org >= org + winsize - high) {
- X org = low - winsize/2;
- X CLIPMIN(org, 0);
- X return org;
- X }
- X else {
- X org = high - winsize/2;
- X CLIPMAX(org, docsize);
- X CLIPMIN(org, 0);
- X return org;
- X }
- X }
- X
- X /* The whole range will fit */
- X
- X /* See if it makes sense to scroll less than the window size */
- X if (low < org) {
- X if (org - low < winsize)
- X return low;
- X }
- X else if (high > org + winsize) {
- X if (high - (org + winsize) < winsize)
- X return high - winsize;
- X }
- X
- X /* Would have to scroll at least winsize -- center the range */
- X org = (low + high - winsize) / 2;
- X
- X /* Make sure we stay within the document */
- X CLIPMIN(org, 0);
- X CLIPMAX(org, docsize);
- X
- X return org;
- X}
- X
- Xvoid
- Xwsetdocsize(win, docwidth, docheight)
- X WINDOW *win;
- X int docwidth, docheight;
- X{
- X CLIPMIN(docwidth, 0);
- X CLIPMIN(docheight, 0);
- X if (docwidth == win->docwidth && docheight == win->docheight)
- X return;
- X win->docwidth= docwidth;
- X win->docheight= docheight;
- X SetPort(win->w);
- X setscrollbarvalues(win);
- X _wfixorigin(win);
- X
- X /* Make the zoomed window size the full document size,
- X or the full screen size if the document is bigger. */
- X
- X if (((WindowPeek)(win->w))->dataHandle != NULL) {
- X WStateData *data = (WStateData *)
- X *((WindowPeek)(win->w))->dataHandle;
- X if (data != NULL) {
- X if (docwidth > 0) {
- X CLIPMIN(docwidth, MIN_WIDTH);
- X data->stdState.right =
- X data->stdState.left
- X + LSLOP + docwidth + RSLOP + BAR;
- X }
- X else
- X data->stdState.right = 0x7fff;
- X CLIPMAX(data->stdState.right,
- X screen->portRect.right-3);
- X if (docheight > 0) {
- X CLIPMIN(docheight, MIN_HEIGHT);
- X data->stdState.bottom =
- X data->stdState.top
- X + docheight + BAR;
- X }
- X else
- X data->stdState.bottom = 0x7fff;
- X CLIPMAX(data->stdState.bottom,
- X screen->portRect.bottom-3);
- X }
- X }
- X}
- X
- Xvoid
- Xwgetdocsize(win, pwidth, pheight)
- X WINDOW *win;
- X int *pwidth, *pheight;
- X{
- X *pwidth = win->docwidth;
- X *pheight = win->docheight;
- X}
- X
- X/* Fix the window's origin after a document or window resize.
- X (Also used from do_size() in event.c) */
- X
- X_wfixorigin(win)
- X WINDOW *win;
- X{
- X int orgh, orgv;
- X int winwidth, winheight;
- X int docwidth, docheight;
- X wgetorigin(win, &orgh, &orgv);
- X wgetwinsize(win, &winwidth, &winheight);
- X wgetdocsize(win, &docwidth, &docheight);
- X
- X /* XXX Do we really want this?
- X This means that in a text edit window, if you are focused
- X at the bottom, every line deletion causes a scroll.
- X Oh well, I suppose that text edit windows could fix
- X their document size to include some blank lines at the
- X end...
- X */
- X
- X CLIPMAX(orgh, docwidth - winwidth);
- X CLIPMIN(orgh, 0);
- X CLIPMAX(orgv, docheight - winheight);
- X CLIPMIN(orgv, 0);
- X wsetorigin(win, orgh, orgv);
- X}
- X
- X/* do_scroll is called from event.c when a click in a scroll bar
- X is detected */
- X
- XSTATIC pascal trackbar(ControlHandle bar, short pcode); /* Forward */
- X
- Xstatic WINDOW *scrollwin; /* The window (needed by 'trackbar') */
- Xstatic int scrollstep; /* By how much we scroll */
- Xstatic long deadline; /* When the next step may happen */
- X
- Xvoid
- Xdo_scroll(pwhere, win, bar, pcode)
- X Point *pwhere;
- X WINDOW *win;
- X ControlHandle bar;
- X int pcode;
- X{
- X int step, page;
- X ProcPtr action;
- X int width, height;
- X
- X wgetwinsize(win, &width, &height);
- X
- X if (bar == win->hbar) {
- X step= width / 20;
- X CLIPMIN(step, 1);
- X page= width / 2;
- X }
- X else if (bar == win->vbar) {
- X step= wlineheight(); /* Should use current win's */
- X page= height - step;
- X }
- X else
- X return;
- X
- X page= (page/step) * step; /* Round down to multiple of step */
- X action= trackbar;
- X scrollwin= win;
- X
- X switch (pcode) {
- X case inUpButton:
- X scrollstep= -step;
- X break;
- X case inDownButton:
- X scrollstep= step;
- X break;
- X case inPageUp:
- X scrollstep= -page;
- X break;
- X case inPageDown:
- X scrollstep= page;
- X break;
- X default:
- X action= NULL;
- X break;
- X }
- X
- X deadline= 0;
- X if (TrackControl(bar, PASSPOINT *pwhere, action) == inThumb)
- X usescrollbarvalues(win);
- X}
- X
- Xstatic pascal
- Xtrackbar(bar, pcode)
- X ControlHandle bar;
- X short pcode;
- X{
- X long now= TickCount();
- X if (now >= deadline && pcode != 0) {
- X deltabar(bar, scrollstep);
- X usescrollbarvalues(scrollwin);
- X wupdate(scrollwin);
- X if (deadline == 0 && KeyThresh > KeyRepThresh)
- X deadline= now + KeyThresh;
- X /* Longer delay first time */
- X else
- X deadline= now + KeyRepThresh;
- X }
- X}
- X
- X/* Automatic scrolling when the mouse is pressed and moved outside
- X the application panel. */
- X
- Xvoid
- Xautoscroll(win, h, v)
- X WINDOW *win;
- X int h, v; /* Mouse location in local coordinates */
- X{
- X Rect r;
- X int dh= 0, dv= 0;
- X
- X getwinrect(win, &r);
- X if (h < r.left)
- X dh= h - r.left;
- X else if (h > r.right)
- X dh= h - r.right;
- X if (v < r.top)
- X dv= v - r.top;
- X else if (v > r.bottom)
- X dv= v - r.bottom;
- X if (dh != 0 || dv != 0) {
- X /* NOTE: assuming current grafport is win->w */
- X deltabar(win->hbar, dh);
- X deltabar(win->vbar, dv);
- X usescrollbarvalues(win);
- X }
- X}
- X
- X/* Alternative scrolling: Option-click produces a 'hand' cursor
- X and allows scrolling like in MacPaint. Called from event.c. */
- X
- Xvoid
- Xdragscroll(win, h, v, constrained)
- X WINDOW *win;
- X int h, v;
- X int constrained;
- X{
- X int do_h= !constrained, do_v= !constrained;
- X
- X while (StillDown()) {
- X Point mouse;
- X SetPort(win->w);
- X GetMouse(&mouse);
- X if (constrained) {
- X int ah= ABS(h - mouse.h);
- X int av= ABS(v - mouse.v);
- X if (ABS(ah - av) < 2)
- X continue;
- X if (ah > av)
- X do_h= TRUE;
- X else
- X do_v= TRUE;
- X constrained= FALSE;
- X }
- X if (do_h)
- X deltabar(win->hbar, h - mouse.h);
- X if (do_v)
- X deltabar(win->vbar, v - mouse.v);
- X usescrollbarvalues(win);
- X wupdate(win);
- X h= mouse.h;
- X v= mouse.v;
- X }
- X}
- X
- Xvoid
- Xmakescrollbars(win)
- X WINDOW *win;
- X{
- X Rect r;
- X int id= scrollBarProc;
- X
- X /* The scroll bars are initially created at a dummy location,
- X and then moved to their proper location.
- X They are not displayed here;
- X that's done only when an activate event arrives. */
- X
- X#ifdef JURJENBARPROC
- X /* If Jurjen's proportional scroll bar exists, use it.
- X (For the vertical bar only -- it doesn't understand
- X about horizontal bars...) */
- X if (cdefexists(JURJENBARPROC))
- X id= JURJENBARPROC;
- X#endif JURJENBARPROC
- X
- X SetRect(&r, 0, 0, 1, 1); /* Dummy rectangle */
- X win->hbar= NewControl(win->w,
- X &r, "", false, 0, 0, 0, scrollBarProc, 0L);
- X win->vbar= NewControl(win->w,
- X &r, "", false, 0, 0, 0, id, 0L);
- X sizescrollbars(win);
- X}
- X
- X#ifdef JURJENBARPROC
- Xstatic int
- Xcdefexists(id)
- X int id;
- X{
- X return GetResource('CDEF', id/16) != NULL;
- X}
- X#endif
- X
- Xvoid
- Xshowscrollbars(win)
- X WINDOW *win;
- X{
- X DrawGrowIcon(win->w);
- X showbar(win->hbar);
- X showbar(win->vbar);
- X}
- X
- Xvoid
- Xhidescrollbars(win)
- X WINDOW *win;
- X{
- X hidebar(win->hbar);
- X hidebar(win->vbar);
- X}
- X
- Xvoid
- Xmovescrollbars(win)
- X WINDOW *win;
- X{
- X hidescrollbars(win);
- X sizescrollbars(win);
- X showscrollbars(win);
- X}
- X
- Xstatic void
- Xsizescrollbars(win)
- X WINDOW *win;
- X{
- X Rect r;
- X
- X /* This should be done while the scroll bars are invisible. */
- X
- X r= win->w->portRect;
- X movebar(win->vbar, r.right - BAR, r.top - 1,
- X r.right + 1, r.bottom - BAR + 1);
- X movebar(win->hbar, r.left - 1, r.bottom - BAR,
- X r.right - BAR + 1, r.bottom + 1);
- X setscrollbarvalues(win);
- X}
- X
- Xstatic void
- Xsetscrollbarvalues(win)
- X WINDOW *win;
- X{
- X Rect r;
- X
- X getwinrect(win, &r);
- X calcbar(win->hbar,
- X win->orgh, win->docwidth, LSLOP, r.right - r.left - RSLOP);
- X calcbar(win->vbar,
- X win->orgv, win->docheight, 0, r.bottom - r.top);
- X if (win == active) {
- X /* XXX Should only draw those controls that have changed. */
- X DrawControls(win->w);
- X valid_border(win->w);
- X }
- X}
- X
- X/*
- X * Calculate (and set!) the new value of a scroll bar.
- X * Parameters (all pertaining to either h or v):
- X * org: origin of window (win->orgh or win->orgv)
- X * size: extent of document (win->docwidth or win->docheight)
- X * begin: position of document origin if bar is at its beginning
- X * end: position of document end if bar is at its end
- X * Situation sketch:
- X * 0 begin end winwidth
- X * +====+==============================+====+
- X * +--------------------------------------------------+
- X * +--------------------------------------------------+
- X * Window shown on top; min document position in the middle;
- X * max document position below. Org is (begin of win) - (begin of doc).
- X */
- X
- Xstatic void
- Xcalcbar(bar, org, size, begin, end)
- X ControlHandle bar;
- X int org, size;
- X int begin, end;
- X{
- X int range;
- X /* For the caller it's easier to remember to pass win->org{h,v};
- X but for our calculations it's easier to have the sign reversed! */
- X org= -org;
- X CLIPMIN(begin, org);
- X CLIPMIN(size, 0);
- X CLIPMAX(end, org + size);
- X range = size - (end - begin);
- X CLIPMIN(range, 0);
- X setbar(bar, end - begin, begin - org, range);
- X}
- X
- Xstatic void
- Xusescrollbarvalues(win)
- X WINDOW *win;
- X{
- X wsetorigin(win,
- X GetCtlValue(win->hbar) - GetCtlMin(win->hbar),
- X GetCtlValue(win->vbar) - GetCtlMin(win->vbar));
- X /* Implies setscrollbarvalues! */
- X}
- X
- Xstatic void
- Xsetbar(bar, winsize, val, max)
- X ControlHandle bar;
- X int winsize, val, max;
- X{
- X if (bar != NULL) {
- X ControlPtr p= *bar;
- X if (max < 0)
- X max= 0;
- X if (val > max)
- X val= max;
- X if (val < 0)
- X val= 0;
- X p->contrlMin= winsize;
- X p->contrlValue= val + winsize;
- X p->contrlMax= max + winsize;
- X /* Must be drawn by DrawControls or ShowControl. */
- X }
- X}
- X
- Xstatic void
- Xdeltabar(bar, delta)
- X ControlHandle bar;
- X int delta;
- X{
- X int min= GetCtlMin(bar);
- X int val= GetCtlValue(bar);
- X int max= GetCtlMax(bar);
- X int newval= val + delta;
- X
- X if (newval > max)
- X newval= max;
- X if (newval < min)
- X newval= min;
- X if (newval != val)
- X SetCtlValue(bar, newval);
- X}
- X
- Xstatic void
- Xshowbar(bar)
- X ControlHandle bar;
- X{
- X if (bar != NULL)
- X ShowControl(bar);
- X}
- X
- Xstatic void
- Xhidebar(bar)
- X ControlHandle bar;
- X{
- X if (bar != NULL)
- X HideControl(bar);
- X}
- X
- Xstatic void
- Xmovebar(bar, left, top, right, bottom)
- X ControlHandle bar;
- X int left, top, right, bottom;
- X{
- X if (bar != NULL) {
- X /* This works best while the scroll bar is invisible. */
- X MoveControl(bar, left, top);
- X SizeControl(bar, right-left, bottom-top);
- X }
- X}
- END_OF_FILE
- if test 13659 -ne `wc -c <'Ports/mac/scroll.c'`; then
- echo shar: \"'Ports/mac/scroll.c'\" unpacked with wrong size!
- fi
- # end of 'Ports/mac/scroll.c'
- fi
- if test -f 'Ports/x11/general.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Ports/x11/general.c'\"
- else
- echo shar: Extracting \"'Ports/x11/general.c'\" \(13917 characters\)
- sed "s/^X//" >'Ports/x11/general.c' <<'END_OF_FILE'
- X/* X11 STDWIN -- General initializations, enquiries and defaults */
- X
- X#include "x11.h"
- X
- X
- X/* Private globals */
- X
- XDisplay *_wd; /* The Display (== connection) */
- XScreen *_ws; /* The screen */
- XXFontStruct *_wf; /* The font */
- XXFontStruct *_wmf; /* The menu font */
- X#ifdef PIPEHACK
- Xint _wpipe[2]; /* Pipe used by wungetevent from handler */
- X#endif
- X#ifdef AMOEBA
- X#include <amoeba.h>
- X#include <semaphore.h>
- Xextern semaphore *_wsema; /* From amtimer.c */
- X#endif
- Xchar *_wprogname = "stdwin"; /* Program name from argv[0] */
- Xstatic char *_wdisplayname; /* Display name */
- X
- X/* Interned atoms */
- X
- XAtom _wm_protocols;
- XAtom _wm_delete_window;
- XAtom _wm_take_focus;
- X
- X/* Globals used to communicate hints to wopen() */
- X
- Xchar *_whostname;
- Xchar *_wm_command;
- Xint _wm_command_len;
- X
- X/* Copy the arguments away to _wm_command, and get the host name */
- X
- Xstatic void
- Xstoreargcargv(argc, argv)
- X int argc;
- X char **argv;
- X{
- X int i;
- X char *bp;
- X char buf[256];
- X
- X /* Calculate length of buffer to allocate */
- X _wm_command_len= 0;
- X for (i= 0; i < argc; i++)
- X _wm_command_len += strlen(argv[i]) + 1;
- X if (_wm_command_len != 0) {
- X _wm_command= bp= malloc((unsigned)_wm_command_len);
- X for (i= 0; i < argc; i++) {
- X strcpy(bp, argv[i]);
- X bp += strlen(argv[i]) + 1;
- X }
- X }
- X
- X buf[0]= EOS;
- X gethostname(buf, sizeof buf);
- X buf[(sizeof buf)-1]= EOS;
- X _whostname= strdup(buf);
- X}
- X
- X/* Function to get a default directly from a database */
- X
- Xstatic char *
- Xgetoption(db, name, classname)
- X XrmDatabase db;
- X char *name;
- X char *classname;
- X{
- X char namebuf[256], classnamebuf[256];
- X char *type;
- X XrmValue rmvalue;
- X
- X sprintf(namebuf, "%s.%s", _wprogname, name);
- X sprintf(classnamebuf, "Stdwin.%s", classname);
- X if (XrmGetResource(db, namebuf, classnamebuf, &type, &rmvalue))
- X return rmvalue.addr;
- X else
- X return NULL;
- X}
- X
- X/* Command line options tables */
- X
- X/* NOTE: To prevent stdwin eating user options scanned with getopt(3),
- X single-letter options must never be acceptable as abbreviations.
- X When necessary, this is ensured by adding dummy options, e.g., "-g:"
- X because there is only one option starting with "-g" ("-geometry").
- X (The colon is used as second character because getopt() uses it as a
- X delimiter.)
- X Watch out: if you remove the last option starting with a certain
- X letter, also remove the dummy option!
- X*/
- X
- X/* Table 1: command-line only options */
- X
- Xstatic XrmOptionDescRec options1[]= {
- X
- X{"-debuglevel", ".debugLevel", XrmoptionSepArg, NULL},
- X{"-display", ".display", XrmoptionSepArg, NULL},
- X
- X{"-n:", NULL, XrmoptionIsArg, NULL},
- X{"-name", ".name", XrmoptionSepArg, NULL},
- X
- X{"-s:", NULL, XrmoptionIsArg, NULL},
- X{"-synchronous", ".synchronous", XrmoptionNoArg, "on"},
- X
- X};
- X
- X/* Table 2: options to be merged with resources */
- X
- Xstatic XrmOptionDescRec options2[]= {
- X
- X/* Command line options to override resources.
- X All the options named in "man X" are supported, except those to
- X do with borders (-bd, -bw) or national language choice (-xnl*). */
- X
- X{"-background", ".background", XrmoptionSepArg, NULL},
- X{"-bg", ".background", XrmoptionSepArg, NULL},
- X
- X{"-font", ".font", XrmoptionSepArg, NULL},
- X{"-fn", ".font", XrmoptionSepArg, NULL},
- X{"-foreground", ".foreground", XrmoptionSepArg, NULL},
- X{"-fg", ".foreground", XrmoptionSepArg, NULL},
- X
- X{"-g:", NULL, XrmoptionIsArg, NULL},
- X{"-geometry", ".geometry", XrmoptionSepArg, NULL},
- X
- X{"-iconic", ".iconic", XrmoptionNoArg, "on"},
- X{"-iconbitmap", ".iconBitmap", XrmoptionSepArg, NULL},
- X{"-icongeometry", ".iconGeometry", XrmoptionSepArg, NULL},
- X{"-iconmask", ".iconMask", XrmoptionSepArg, NULL},
- X
- X{"-menubackground", ".menuBackground", XrmoptionSepArg, NULL},
- X{"-menufont", ".menuFont", XrmoptionSepArg, NULL},
- X{"-menufn", ".menuFont", XrmoptionSepArg, NULL},
- X{"-menuforeground", ".menuForeground", XrmoptionSepArg, NULL},
- X
- X{"-reversevideo", ".reverse", XrmoptionNoArg, "on"},
- X{"-rv", ".reverse", XrmoptionNoArg, "on"},
- X{"+rv", ".reverse", XrmoptionNoArg, "off"},
- X
- X{"-s:", NULL, XrmoptionIsArg, NULL},
- X{"-selectionTimeout", ".selectionTimeout", XrmoptionSepArg, NULL},
- X
- X{"-t:", NULL, XrmoptionIsArg, NULL},
- X{"-title", ".title", XrmoptionSepArg, NULL},
- X
- X{"-x:", NULL, XrmoptionIsArg, NULL},
- X{"-xrm", NULL, XrmoptionResArg, NULL},
- X
- X/* Options that end option processing completely:
- X "-" means <stdin>, "--" is a getopt(3) convention
- X to force the end of the option list. */
- X
- X{"-", NULL, XrmoptionSkipLine, NULL},
- X{"--", NULL, XrmoptionSkipLine, NULL},
- X
- X};
- X
- X#define NUM(options) (sizeof options / sizeof options[0])
- X
- X
- X/* Initialization is split in two parts -- wargs(&argc, &argv) to process
- X the command line, winit() to open the connection. The call
- X winitargs(&argc, &argv) calls wargs() and then winit().
- X
- X Programs that call winit() without callin wargs() will always
- X appear to have the name "stdwin", and you can't pass X command
- X line arguments on their command line. Defaults put in the server's
- X resource database for application name 'stdwin' will work, though.
- X You can also set the environment variable RESOURCE_NAME. */
- X
- X
- Xstatic XrmDatabase db = NULL; /* Passed between wargs() and winit() */
- Xstatic int wargs_called; /* Set when wargs is called */
- X
- X/* Part one of the initialization -- process command line arguments */
- X
- Xvoid
- Xwargs(pargc, pargv)
- X int *pargc;
- X char ***pargv;
- X{
- X char **argv= *pargv;
- X char *value;
- X
- X if (wargs_called)
- X _wfatal("wargs: called more than once");
- X wargs_called = 1;
- X
- X /* Get the program name (similar to basename(argv[0])) */
- X
- X if (*pargc > 0 && argv[0] != NULL && argv[0][0] != EOS) {
- X _wprogname= strrchr(argv[0], '/');
- X if (_wprogname != NULL && _wprogname[1] != EOS)
- X ++_wprogname;
- X else
- X _wprogname= argv[0];
- X }
- X
- X /* Save entire argument list for WM_COMMAND hint; plus hostname */
- X
- X storeargcargv(*pargc, argv);
- X
- X /* Get command-line-only X options */
- X
- X XrmParseCommand(&db, options1, NUM(options1),
- X _wprogname, pargc, *pargv);
- X
- X /* Get -debuglevel argument from temp database.
- X This is done first so calls to _wdebug will work. */
- X
- X if ((value= getoption(db, "debugLevel", "DebugLevel")) != NULL) {
- X _wtracelevel= _wdebuglevel= atoi(value);
- X setlinebuf(stderr);
- X _wwarning("wargs: -debuglevel %d", _wdebuglevel, value);
- X }
- X
- X /* Get -display argument from temp database */
- X
- X if ((_wdisplayname= getoption(db, "display", "Display")) != NULL)
- X _wdebug(1, "wargs: -display %s", _wdisplayname);
- X
- X /* Get -name argument from temp database.
- X This will override the command name used by _wgetdefault.
- X You can use this to pretend the command name is different,
- X so it gets its options from a different part of the defaults
- X database. (Try -name xmh. :-)
- X If -name is not set, getenv("RESOURCE_NAME") will override
- X _wprogname (if non-empty). */
- X
- X if ((value= getoption(db, "name", "Name")) != NULL) {
- X _wdebug(1, "wargs: -name %s", value);
- X _wprogname= strdup(value);
- X }
- X else if ((value = getenv("RESOURCE_NAME")) != NULL && *value != '\0') {
- X _wdebug(1, "wargs: RESOURCE_NAME=%s", value);
- X _wprogname = strdup(value);
- X }
- X
- X /* Get the remaining command line options.
- X Option parsing is done in two phases so that if the user
- X specifies -name and -geometry, the geometry is stored under
- X the new name (else it won't be found by _wgetdefault later). */
- X
- X XrmParseCommand(&db, options2, NUM(options2),
- X _wprogname, pargc, *pargv);
- X}
- X
- X
- X/* Part two of the initialization -- open the display */
- X
- Xvoid
- Xwinit()
- X{
- X char *value;
- X
- X /* Call wargs() with dummy arguments if not already called */
- X
- X if (!wargs_called) {
- X static char* def_args[]= {"stdwin", (char*)NULL};
- X int argc= 1;
- X char **argv= def_args;
- X wargs(&argc, &argv);
- X }
- X
- X /* Open the display, die if we can't */
- X
- X _wd= XOpenDisplay(_wdisplayname);
- X if (_wd == NULL) {
- X _wfatal("winit: can't open display (%s)",
- X _wdisplayname ? _wdisplayname :
- X getenv("DISPLAY") ? getenv("DISPLAY") : "<none>");
- X }
- X
- X#ifdef AMOEBA
- X /* Set the semaphore. This must be done before doing anything
- X else with the connection. */
- X if (_wsema != NULL)
- X XamSetSema(_wd, _wsema);
- X#endif
- X
- X /* Turn on synchronous mode if required.
- X This is not automatic when debuglevel is set,
- X since some bugs disappear in synchronous mode! */
- X
- X if (getoption(db, "synchronous", "Synchronous") != NULL)
- X XSynchronize(_wd, True);
- X
- X /* Call XGetDefault() once. We don't use it to get our
- X defaults, since it doesn't let the caller specify the class
- X name for the resource requested, but the first call to it
- X also initializes the resources database from various sources
- X following conventions defined by the X toolkit, and that code
- X is too convoluted (and X11-version specific?) to bother to
- X repeat it here. */
- X
- X (void) XGetDefault(_wd, _wprogname, "unused");
- X
- X /* From now on, use _wgetdefault() exclusively to get defaults */
- X
- X /* Get the debug level again, this time from the user's
- X defaults database. This value overrides only if larger. */
- X
- X value= _wgetdefault("debugLevel", "DebugLevel");
- X if (value != 0) {
- X int k= atoi(value);
- X if (k > _wdebuglevel) {
- X _wtracelevel= _wdebuglevel= k;
- X _wdebug(1, "winit: new debuglevel %d (%s)",
- X _wdebuglevel, value);
- X XSynchronize(_wd, True);
- X }
- X }
- X
- X /* Merge the command line options with the defaults database.
- X This must be done after the call to XGetDefault (above),
- X otherwise XGetDefault doesn't care to load the database.
- X I assume that the command line options get higher priority
- X than the user defaults in this way. */
- X
- X XrmMergeDatabases(db, &_wd->db);
- X db = NULL;
- X
- X /* Get the default screen (the only one we use) */
- X
- X _ws= DefaultScreenOfDisplay(_wd);
- X
- X _wdebug(1, "server does%s save-unders",
- X DoesSaveUnders(_ws) ? "" : "n't do");
- X
- X /* Intern some atoms (unconditionally) */
- X
- X _wm_protocols = XInternAtom(_wd, "WM_PROTOCOLS", False);
- X _wm_delete_window = XInternAtom(_wd, "WM_DELETE_WINDOW", False);
- X _wm_take_focus = XInternAtom(_wd, "WM_TAKE_FOCUS", False);
- X
- X /* Initialize font list */
- X
- X _winitfonts();
- X
- X#ifdef PIPEHACK
- X /* Create the pipe used to communicate wungetevent calls
- X from a signal handler to wgetevent */
- X
- X if (pipe(_wpipe) != 0) {
- X _wwarning("winit: can't create pipe");
- X _wpipe[0]= _wpipe[1]= -1;
- X }
- X#endif
- X}
- X
- X
- X/* Call both parts of the initialization together */
- X
- Xvoid
- Xwinitargs(pargc, pargv)
- X int *pargc;
- X char ***pargv;
- X{
- X wargs(pargc, pargv);
- X winit();
- X}
- X
- X
- X/* Return the name of the display, if known. (X11 stdwin only.) */
- X
- Xchar *
- Xwdisplayname()
- X{
- X return _wdisplayname ? _wdisplayname : getenv("DISPLAY");
- X}
- X
- X
- X/* Clean up */
- X
- Xvoid
- Xwdone()
- X{
- X /* This may be called when we are not initialized */
- X if (_wd) {
- X _wkillwindows();
- X _wkillmenus();
- X XFlush(_wd); /* Show possibly queued visual effects */
- X XCloseDisplay(_wd);
- X _wd = NULL;
- X }
- X}
- X
- X/* Flush server queue */
- X
- Xvoid
- Xwflush()
- X{
- X XFlush(_wd);
- X}
- X
- X
- X/* Get screen size */
- X
- Xvoid
- Xwgetscrsize(pwidth, pheight)
- X int *pwidth, *pheight;
- X{
- X *pwidth= WidthOfScreen(_ws);
- X *pheight= HeightOfScreen(_ws);
- X}
- X
- X
- X/* Get screen size in mm */
- X
- Xvoid
- Xwgetscrmm(pwidth, pheight)
- X int *pwidth, *pheight;
- X{
- X *pwidth= WidthMMOfScreen(_ws);
- X *pheight= HeightMMOfScreen(_ws);
- X}
- X
- X/* Subroutine to invert a rectangle.
- X On a colour display, we invert all planes that have a different
- X value in the foreground and background pixels, thus swapping
- X fg anbd bg colors.
- X Since we can't get the fg and bg pixels from a GC without cheating
- X (i.e., risking future incompatibility), we depend on the fact
- X that the plane mask is *always* set to the XOR of the fg and bg colors.
- X If the bg color for the window is the same as the bg for the GC,
- X this means all draw operations need only be concerned with those planes.
- X*/
- X
- X_winvert(d, gc, x, y, width, height)
- X Drawable d;
- X GC gc;
- X int x, y, width, height;
- X{
- X XSetFunction(_wd, gc, GXinvert);
- X XFillRectangle(_wd, d, gc, x, y, width, height);
- X XSetFunction(_wd, gc, GXcopy);
- X}
- X
- X/* Get a default (replaces XGetDefault calls) */
- X
- X#include <ctype.h>
- X
- Xchar *
- X_wgetdefault(name, classname)
- X char *name;
- X char *classname;
- X{
- X char namebuf[256], classnamebuf[256];
- X register char *p;
- X
- X p = getoption(_wd->db, name, classname);
- X if (p != NULL)
- X return p;
- X
- X /* XXX Compatibility hack. Previous versions of STDWIN used
- X a different resource format, where the name would be
- X <progname>.stdwin.<resname> and the classname was defaulted
- X by XGetDefault to Program.Name (or some such).
- X The resource names were also all lowercase. */
- X sprintf(namebuf, "stdwin.%s", name);
- X sprintf(classnamebuf, "Stdwin.%s", classname);
- X for (p = namebuf; *p != '\0'; p++) {
- X if (isupper(*p))
- X *p = tolower(*p);
- X }
- X _wdebug(1, "_wgetdefault(%s, %s): no luck, trying %s, %s",
- X name, classname, namebuf, classnamebuf);
- X return getoption(_wd->db, namebuf, classnamebuf);
- X}
- X
- X/* Get a Boolean default. May be 'on' or 'off', 'true' or 'false',
- X '1' or '0'. If not present, return the default value. */
- X
- Xint
- X_wgetbool(name, classname, def)
- X char *name;
- X char *classname;
- X int def;
- X{
- X register char *value;
- X static struct flags {
- X char *name;
- X int value;
- X };
- X static struct flags flags[] = {
- X {"on", 1},
- X {"true", 1},
- X {"yes", 1},
- X {"1", 1},
- X
- X {"off", 0},
- X {"false", 0},
- X {"no", 0},
- X {"0", 0},
- X
- X {NULL, 0} /* Sentinel */
- X };
- X struct flags *fp, *hit;
- X
- X value = _wgetdefault(name, classname);
- X if (value == NULL)
- X return def;
- X hit = NULL;
- X for (fp = flags; fp->name != NULL; fp++) {
- X if (matchname(fp->name, value)) {
- X if (hit != NULL)
- X _wwarning(
- X "ambiguous resource value for %s: %s",
- X name, value);
- X hit = fp;
- X }
- X }
- X if (hit != NULL)
- X def = hit->value;
- X else
- X _wwarning("unknown resource value for %s: %s", name, value);
- X return def;
- X}
- X
- Xstatic int
- Xmatchname(fullname, shortname)
- X char *fullname;
- X char *shortname;
- X{
- X register int c;
- X while ((c = *shortname++) != '\0') {
- X if (isupper(c))
- X c = tolower(c);
- X if (c != *fullname++)
- X return 0;
- X }
- X return 1;
- X}
- END_OF_FILE
- if test 13917 -ne `wc -c <'Ports/x11/general.c'`; then
- echo shar: \"'Ports/x11/general.c'\" unpacked with wrong size!
- fi
- # end of 'Ports/x11/general.c'
- fi
- if test -f 'Ports/x11/llevent.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Ports/x11/llevent.c'\"
- else
- echo shar: Extracting \"'Ports/x11/llevent.c'\" \(8971 characters\)
- sed "s/^X//" >'Ports/x11/llevent.c' <<'END_OF_FILE'
- X/* X11 STDWIN -- Low-level event handling */
- X
- X#include "x11.h"
- X#include "llevent.h"
- X#include <X11/keysym.h>
- X
- X/* Double-click detection parameters */
- X
- X#define DCLICKTIME 500
- X#define DCLICKDIST 5
- X
- X/* Events are handled in two phases.
- X There is low-level event handling which can be called at any time
- X and will only set various flags (global and in windows) indicating
- X changed circumstances. This kind of event handling goes on even
- X while we are locked in a dialog box.
- X There is high-level event handling which passes the results of the
- X low-level handling to the application in request to a call to
- X 'wgetevent'.
- X This file contains the low-level event handling. */
- X
- X
- X/* Low-level event handler.
- X Data items set for use by higher-level event handler include:
- X
- X - the 'new active window' pointer
- X - the 'dirty' flags for all windows and subwindows
- X - the 'size changed' flags for all top-level windows
- X
- X These can be accumulated; the net effect of all such events is
- X correctly remembered. The following data items are also set but need
- X to be checked after each call, since they are not queued:
- X
- X - the mouse button state
- X - the 'last-key-pressed' variable
- X
- X Mouse moves may be ignored, however.
- X The state change flags must be be reset by the higher-level event
- X handler after the changes have been noted. */
- X
- XWINDOW *_w_new_active; /* New active window */
- Xstruct button_state _w_bs; /* Mouse button state */
- XKeySym _w_keysym; /* Keysym of last non-modifier key pressed */
- Xint _w_state; /* Modifiers in effect at key press */
- X
- Xbool _w_moved; /* Set if button moved */
- Xbool _w_bs_changed; /* Set if button up/down state changed */
- Xbool _w_dirty; /* Set if any window needs a redraw */
- Xbool _w_resized; /* Set if any window resized */
- Xbool _w_focused; /* Set if between FocusIn and FocusOut */
- XTime _w_lasttime = CurrentTime; /* Last timestamp received in an event */
- XWINDOW *_w_close_this; /* Window to close (WM_DELETE_WINDOW) */
- X
- X_w_ll_event(e)
- X XEvent *e;
- X{
- X WINDOW *win;
- X
- X _wdebug(6, "_w_ll_event: event type %ld", e->type);
- X
- X win = _whichwin(e->xkey.window);
- X if (win == NULL) {
- X _wdebug(6, "_w_ll_event: event not for any window -- ignore");
- X return;
- X }
- X
- X switch (e->type) {
- X
- X /* Keyboard */
- X
- X case KeyPress:
- X _w_lasttime = e->xkey.time;
- X activate(win);
- X ll_key(&e->xkey, win);
- X break;
- X
- X case MappingNotify:
- X XRefreshKeyboardMapping(&e->xmapping);
- X break;
- X
- X /* Buttons */
- X
- X case MotionNotify:
- X#ifndef DONT_COMPRESS_MOTION /* XXX should be a resource option instead */
- X /* Compress motion events */
- X while (XPending(_wd) > 0) {
- X XEvent e2;
- X XPeekEvent(_wd, &e2);
- X if (e2.type == MotionNotify &&
- X e2.xmotion.window == e->xmotion.window &&
- X e2.xmotion.subwindow == e->xmotion.subwindow) {
- X /* replace current event with next one */
- X XNextEvent(_wd, e);
- X }
- X else
- X break;
- X }
- X#endif
- X /* Fall through */
- X case ButtonPress:
- X case ButtonRelease:
- X _w_lasttime = e->xbutton.time;
- X ll_button(&e->xbutton, win);
- X break;
- X
- X /* Exposures */
- X
- X case GraphicsExpose:
- X _wdebug(3, "GraphicsExpose event:");
- X case Expose:
- X ll_expose(&e->xexpose, win);
- X break;
- X
- X /* Structure changes */
- X
- X case ConfigureNotify:
- X ll_configure(&e->xconfigure, win);
- X break;
- X
- X /* Input focus changes */
- X
- X case FocusIn:
- X _w_focused= TRUE;
- X activate(win);
- X break;
- X
- X case FocusOut:
- X _w_focused= FALSE;
- X deactivate(win);
- X break;
- X
- X case EnterNotify:
- X _w_lasttime = e->xcrossing.time;
- X if (!_w_focused && e->xcrossing.focus)
- X activate(win);
- X break;
- X
- X case LeaveNotify:
- X _w_lasttime = e->xcrossing.time;
- X if (!_w_focused && e->xcrossing.detail != NotifyInferior &&
- X e->xcrossing.focus)
- X deactivate(win);
- X break;
- X
- X /* ICCCM */
- X
- X case ClientMessage:
- X _wdebug(2,
- X "ClientMessage, type=%ld, send_event=%ld, format=%ld",
- X e->xclient.message_type,
- X e->xclient.send_event,
- X e->xclient.format);
- X if (e->xclient.message_type == _wm_protocols) {
- X _wdebug(2, "It's a WM_PROTOCOLS ClientMessage (%ld)",
- X e->xclient.data.l[0]);
- X _w_lasttime = e->xclient.data.l[1];
- X }
- X else {
- X _wdebug(1, "Unexpected ClientMessage ignored (%ld)",
- X e->xclient.message_type);
- X break;
- X }
- X if (e->xclient.data.l[0] == _wm_delete_window) {
- X _wdebug(1, "WM_DELETE_WINDOW");
- X _w_close_this = win;
- X }
- X else {
- X _wdebug(1,
- X "Unexpected WM_PROTOCOLS ClientMessage (%ld)",
- X e->xclient.data.l[0]);
- X }
- X break;
- X
- X case SelectionRequest:
- X _w_selectionreply(
- X e->xselectionrequest.owner,
- X e->xselectionrequest.requestor,
- X e->xselectionrequest.selection,
- X e->xselectionrequest.target,
- X e->xselectionrequest.property,
- X e->xselectionrequest.time);
- X break;
- X
- X case SelectionClear:
- X _w_selectionclear(e->xselectionclear.selection);
- X break;
- X
- X case MapNotify:
- X /* Ignore this */
- X break;
- X
- X default:
- X _wdebug(1, "unexpected event type %d", e->type);
- X
- X }
- X}
- X
- Xstatic
- Xactivate(win)
- X WINDOW *win;
- X{
- X if (_w_new_active != win) {
- X if (_w_new_active != NULL)
- X deactivate(_w_new_active);
- X _w_new_active= win;
- X if (win != NULL)
- X XSetWindowBorder(_wd, win->wo.wid, win->fgo);
- X }
- X}
- X
- Xstatic
- Xdeactivate(win)
- X WINDOW *win;
- X{
- X if (win == _w_new_active) {
- X _w_new_active= NULL;
- X if (win != NULL)
- X _w_setgrayborder(win);
- X }
- X}
- X
- Xstatic
- Xll_key(e, win)
- X XKeyEvent *e;
- X WINDOW *win;
- X{
- X char sbuf[1];
- X
- X _wdebug(6, "keycode %d, state 0x%x", e->keycode, e->state);
- X if (XLookupString(e, sbuf, 1, &_w_keysym, (XComposeStatus*)NULL) > 0)
- X _w_keysym= sbuf[0];
- X else if (IsModifierKey(_w_keysym))
- X _w_keysym= 0;
- X _w_state= e->state;
- X}
- X
- X/* Update button status, given a Button or Motion event.
- X THIS ASSUMES BUTTON AND MOTION EVENTS HAVE THE SAME LAY-OUT! */
- X
- Xstatic
- Xll_button(e, win)
- X XButtonEvent *e;
- X WINDOW *win;
- X{
- X Window w= e->window;
- X
- X /* This code is ugly. I know. */
- X
- X if (!_w_bs.down) { /* New sequence */
- X if (e->type != ButtonPress) {
- X /* Button moved/release event while we've never
- X received a corresponding press event.
- X I suspect this is a server bug;
- X normally I never reach this code, but sometimes
- X it happens continually. Why?... */
- X _wdebug(5,
- X "ll_button: spurious button move/release %d",
- X e->type);
- X return;
- X }
- X else {
- X bool isdclick= FALSE;
- X _w_bs.down= TRUE;
- X _w_bs_changed= TRUE;
- X if (_w_bs.button == e->button &&
- X _w_bs.w == e->window) {
- X /* Multiple-click detection; must be done
- X before setting new values */
- X if (e->time <= _w_bs.time + DCLICKTIME) {
- X int dx= e->x - _w_bs.x;
- X int dy= e->y - _w_bs.y;
- X isdclick= (dx*dx + dy*dy <=
- X DCLICKDIST*DCLICKDIST);
- X }
- X }
- X if (!isdclick)
- X _w_bs.clicks= 0;
- X ++_w_bs.clicks;
- X _w_bs.mask= e->state / Button1Mask; /* XXX */
- X _w_bs.button= e->button;
- X _w_bs.time= e->time;
- X _w_bs.win= win;
- X _w_bs.w= w;
- X for (_w_bs.isub= NSUBS; --_w_bs.isub >= 0; ) {
- X if (w == win->subw[_w_bs.isub].wid)
- X break;
- X }
- X if (_w_bs.isub < 0) {
- X _wdebug(0, "ll_button: can't find subwin");
- X _w_bs.isub= 0;
- X return;
- X }
- X _w_bs.x= _w_bs.xdown= e->x;
- X _w_bs.y= _w_bs.ydown= e->y;
- X }
- X }
- X else { /* Continue existing sequence */
- X if (win == _w_bs.win && w != _w_bs.w) {
- X /* Maybe changed between mbar and mwin? */
- X if (_w_bs.isub == MBAR && w == win->mwin.wid) {
- X /* Change it -- because of XGrabPointer */
- X _wdebug(3, "MBAR grabbed button");
- X _w_bs.isub = MWIN;
- X _w_bs.w = w;
- X }
- X }
- X if (win != _w_bs.win || w != _w_bs.w) {
- X /* XXX This still happens -- why? */
- X _wdebug(0, "ll_button: inconsistent _w_bs");
- X _w_bs.down= FALSE;
- X _w_bs.mask= 0;
- X _w_bs_changed= TRUE;
- X }
- X else {
- X _w_bs.mask= e->state / Button1Mask; /* XXX */
- X _w_bs.x= e->x;
- X _w_bs.y= e->y;
- X _w_bs.time= e->time;
- X if (e->type == ButtonRelease &&
- X e->button == _w_bs.button) {
- X _w_bs.down= FALSE;
- X _w_bs_changed= TRUE;
- X }
- X else
- X _w_moved= TRUE;
- X }
- X }
- X _wdebug(5, "ll_button: xy=(%d, %d), down=%d, clicks=%d",
- X _w_bs.x, _w_bs.y, _w_bs.down, _w_bs.clicks);
- X}
- X
- Xstatic
- Xll_expose(e, win)
- X XExposeEvent *e;
- X WINDOW *win;
- X{
- X Window w= e->window;
- X
- X _wdebug(3, "ll_expose called, count=%d, x=%d,y=%d,w=%d,h=%d",
- X e->count, e->x, e->y, e->width, e->height);
- X if (w == win->wa.wid)
- X wchange(win, e->x, e->y, e->x + e->width, e->y + e->height);
- X else if (w == win->mbar.wid)
- X win->mbar.dirty= TRUE;
- X else if (w == win->hbar.wid)
- X win->hbar.dirty= TRUE;
- X else if (w == win->vbar.wid)
- X win->vbar.dirty= TRUE;
- X else {
- X _wdebug(3, "ll_expose: uninteresting event");
- X return;
- X }
- X if (e->count == 0)
- X _w_dirty= TRUE;
- X}
- X
- Xstatic
- Xll_configure(e, win)
- X XConfigureEvent *e;
- X WINDOW *win;
- X{
- X if (e->window != win->wo.wid) {
- X _wdebug(0, "ll_configure: not for wo.wid");
- X return;
- X }
- X win->wo.x= e->x + e->border_width;
- X win->wo.y= e->y + e->border_width;
- X win->wo.border= e->border_width;
- X if (win->wo.width != e->width || win->wo.height != e->height) {
- X /* Size changed */
- X win->wo.width= e->width;
- X win->wo.height= e->height;
- X _wmovesubwins(win);
- X win->resized= _w_resized= TRUE;
- X }
- X}
- END_OF_FILE
- if test 8971 -ne `wc -c <'Ports/x11/llevent.c'`; then
- echo shar: \"'Ports/x11/llevent.c'\" unpacked with wrong size!
- fi
- # end of 'Ports/x11/llevent.c'
- fi
- echo shar: End of archive 7 \(of 19\).
- cp /dev/null ark7isdone
- 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
-