[alt.sources] STDWIN 0.9.5, Part 10/19

guido@cwi.nl (Guido van Rossum) (03/04/91)

Archive-name: stdwin/part10

#! /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 10 (of 19)."
# Contents:  Appls/dpv/choose.c Conf/README Doc/man/editwin.man
#   Packs/vt/vtselect.c Ports/alfa/draw.c Ports/x11/selection.c
# Wrapped by guido@voorn.cwi.nl on Mon Mar  4 12:37:28 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Appls/dpv/choose.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Appls/dpv/choose.c'\"
else
echo shar: Extracting \"'Appls/dpv/choose.c'\" \(8842 characters\)
sed "s/^X//" >'Appls/dpv/choose.c' <<'END_OF_FILE'
X/* Application to choose ditroff special character names
X   for glyphs in a given font.
X   Usage: choose [-f  glyphfont] [-s size] [-c columns]
X   Mac defaults: -f Symbol -s 24 -c 8
X   X defaults: -f '*-symbol-*--24-*' -c 8
X
X   TO DO:
X   	- start with font choosing dialog on Mac
X	- more object-like file interface (pretend we're editing
X	  a table object)
X	- more syntax checking on input
X	- check for duplicate names?
X*/
X
X#define CHARWIDTHBUG		/* wcharwidth(i) == 0 for all i >= 128 */
X
X#include <stdwin.h>
X#include <tools.h>
X
X/* Number of possible characters per font -- limited by char = 8 bit */
X#define NGLYPHS 256
X
X/* Table of names for each char -- 3rd is terminating zero */
Xchar namelist[NGLYPHS][3];
X
X/* Random global variables */
Xchar *progname= "choose";	/* Program name for error messages */
XWINDOW *win;			/* Where it all happens */
Xint selected= -1;		/* Glyph currently selected, -1 if none */
Xbool changed;			/* Set if any changes made */
Xchar *filename;			/* Namelist file name */
X
X/* Variables controlling the window lay-out */
Xchar *glyphfont, *namefont;	/* Fonts used for ditto */
Xint glyphsize, namesize;	/* Point sizes used for glyph and name */
Xint firstglyph, lastglyph;	/* First and last glyphs */
Xint ncols, nrows;		/* Matrix dimensions */
Xint colwidth, rowheight;	/* Cell dimensions */
X
X/* Parse the command line */
X
Xparse(argc, argv)
X	int argc;
X	char **argv;
X{
X	if (argc > 0 && argv[0] != NULL && argv[0][0] != EOS) {
X		progname= rindex(argv[0], '/');
X		if (progname == NULL)
X			progname= argv[0];
X		else
X			progname++;
X	}
X	
X	for (;;) {
X		int c= getopt(argc, argv, "c:f:s:");
X		if (c == EOF)
X			break;
X		switch (c) {
X		case 'c':
X			ncols= atoi(optarg);
X			break;
X		case 'f':
X			glyphfont= optarg;
X			break;
X		case 's':
X			glyphsize= atoi(optarg);
X			break;
X		default:
X			usage();
X			/*NOTREACHED*/
X		}
X	}
X	
X	if (optind < argc)
X		filename= argv[optind++];
X	
X	if (optind < argc)
X		usage();
X}
X
X/* Print usage message and exit */
X
Xusage()
X{
X	wdone();
X	fprintf(stderr, "usage: %s [-c columns] [-f font] [-s size]\n",
X		progname);
X	exit(2);
X}
X
X/* Initialize the control variables */
X
Xsetup()
X{
X	/* Fill in defaults */
X	if (ncols <= 0)
X		ncols= 8;
X	if (glyphfont == NULL || *glyphfont == EOS) {
X#ifdef macintosh
X		glyphfont= "Symbol";
X#else
X#ifdef X11R2
X		glyphfont= "symbol22";
X#else
X		glyphfont= "*-symbol-*--24-*";
X#endif
X#endif
X	}
X	
X	if (glyphsize <= 0)
X		glyphsize= 24;
X	if (namefont == NULL || *namefont == EOS) {
X#ifdef machintosh
X		namefont= "Courier";
X#else
X#ifdef X11R2
X		namefont= "courier12f";
X#else
X		namefont= "*-courier-*--12-*";
X#endif
X#endif
X	}
X	if (namesize <= 0)
X		namesize= 10;
X	
X	/* Find first and last existing character */
X	firstglyph= 0;
X	lastglyph= NGLYPHS-1;
X	wsetfont(glyphfont);
X	wsetsize(glyphsize);
X	while (firstglyph < lastglyph && wcharwidth(firstglyph) == 0)
X		++firstglyph;
X	firstglyph= (firstglyph/ncols) * ncols;
X#ifndef CHARWIDTHBUG
X	while (lastglyph > firstglyph && wcharwidth(lastglyph) == 0)
X		--lastglyph;
X	lastglyph= (lastglyph/ncols + 1) * ncols - 1;
X#endif
X	
X	/* Compute remaining variables */
X	nrows= (lastglyph - firstglyph + ncols) / ncols;
X	colwidth= 2*wcharwidth('M');
X	rowheight= wlineheight();
X	wsetfont(namefont);
X	wsetsize(namesize);
X	rowheight += 4 + wlineheight();
X	{
X		int cw= wtextwidth("MM  MM", -1) + 4;
X		if (colwidth < cw)
X			colwidth= cw;
X	}
X}
X
X/* Draw procedure */
X
Xvoid
Xdrawproc(win, left, top, right, bottom)
X	WINDOW *win;
X	int left, top, right, bottom;
X{
X	int i;
X	
X	/* Draw vertical grid lines */
X	for (i= 1; i < ncols; ++i)
X		wdrawline(i*colwidth-1, 0, i*colwidth-1, nrows*rowheight);
X	
X	/* Draw horizontal grid lines */
X	for (i= 1; i < nrows; ++i)
X		wdrawline(0, i*rowheight-1, ncols*colwidth, i*rowheight-1);
X	
X	/* Draw glyph cells */
X	for (i= firstglyph; i <= lastglyph; ++i) {
X		int h, v, h2, v2;
X		int glyphwidth;
X		cellbounds(i, &h, &v, &h2, &v2);
X		if (v >= bottom)
X			break;
X		if (!intersects(h, v, h2, v2, left, top, right, bottom))
X			continue;
X		wsetfont(glyphfont);
X		wsetsize(glyphsize);
X		glyphwidth= wcharwidth(i);
X#ifndef CHARWIDTHBUG
X		if (glyphwidth == 0)
X			continue;
X#endif
X		wdrawchar(h + (colwidth-glyphwidth) / 2, v+2, i);
X		wsetfont(namefont);
X		wsetsize(namesize);
X		{
X			char buf[10];
X			sprintf(buf, "%02X", i);
X			wdrawtext(h+2, v2 - 2 - wlineheight(), buf, -1);
X		}
X		if (namelist[i][0] != EOS) {
X			int namewidth;
X			namewidth= wtextwidth(namelist[i], -1);
X			wdrawtext(h + colwidth - namewidth - 2,
X				v2 - 2 - wlineheight(),
X				namelist[i], -1);
X		}
X		if (i == selected)
X			winvert(h+1, v+1, h2-2, v2-2);
X	}
X}
X	
X/* Main program */
X
Xmain(argc, argv)
X	int argc;
X	char **argv;
X{
X	winitargs(&argc, &argv);
X	parse(argc, argv);
X	setup();
X	readnamelist();
X	wsetdefwinsize(colwidth*ncols, 0);
X	win= wopen(glyphfont, drawproc);
X	if (win == NULL) {
X		wdone();
X		fprintf(stderr, "%s: can't create window\n", progname);
X	}
X	wsetdocsize(win, colwidth*ncols, rowheight*nrows);
X	eventloop();
X	/*NOTREACHED*/
X}
X
X/* Event loop.  Never returns. */
X
Xeventloop() {
X	for (;;) {
X		EVENT e;
X		wgetevent(&e);
X		switch (e.type) {
X		
X		case WE_MOUSE_DOWN:
X		case WE_MOUSE_MOVE:
X		case WE_MOUSE_UP:
X			do_select(&e);
X			break;
X		
X		case WE_CHAR:
X			do_char(e.u.character);
X			break;
X		
X		case WE_COMMAND:
X			switch (e.u.command) {
X			case WC_CLOSE:
X			case WC_CANCEL:
X		close_it:
X				if (changed) {
X					int ok;
X					ok= waskync("Save changes?", 1);
X					if (ok > 0) {
X						if (!writenamelist())
X							ok= -1;
X					}
X					if (ok < 0)
X						continue;
X				}
X				wclose(win);
X				wdone();
X				exit(0);
X				/*NOTREACHED*/
X			case WC_BACKSPACE:
X				do_char('\b');
X				break;
X			}
X			break;
X		
X		case WE_CLOSE:
X			goto close_it;
X
X		}
X	}
X	/*NOTREACHED*/
X}
X
X/* Handle mouse events */
X
Xdo_select(ep)
X	EVENT *ep;
X{
X	int left, top, right, bottom;
X	int col= ep->u.where.h / colwidth;
X	int row= ep->u.where.v / rowheight;
X	int i= firstglyph + col + ncols*row;
X	wsetfont(glyphfont);
X	wsetsize(glyphsize);
X	if (ep->u.where.h < 0 || ep->u.where.v < 0 ||
X		col >= ncols || row >= nrows ||
X		i < firstglyph || i > lastglyph ||
X		wcharwidth(i) == 0)
X		i= -1;
X	if (i != selected) {
X		wbegindrawing(win);
X		if (selected >= 0) {
X			cellbounds(selected, &left, &top, &right, &bottom);
X			winvert(left+1, top+1, right-2, bottom-2);
X		}
X		selected= i;
X		if (selected >= 0) {
X			cellbounds(selected, &left, &top, &right, &bottom);
X			winvert(left+1, top+1, right-2, bottom-2);
X		}
X		wenddrawing(win);
X	}
X	/* Must do this here because wshow may have no effect
X	   while the mouse is down. */
X	if (selected >= 0) {
X		cellbounds(selected, &left, &top, &right, &bottom);
X		wshow(win, left, top, right, bottom);
X	}
X		
X}
X
X/* Handle character events and backspace */
X
Xdo_char(c)
X	int c;
X{
X	int n;
X	int left, top, right, bottom;
X	if (selected < 0) {
X		wfleep();
X		return;
X	}
X	if (c == '\b') {
X		n= 0;
X	}
X	else {
X		n= strlen(namelist[selected]) % 2;
X		namelist[selected][n++]= c;
X	}
X	namelist[selected][n]= EOS;
X	wsetfont(namefont);
X	wsetsize(namesize);
X	cellbounds(selected, &left, &top, &right, &bottom);
X	wshow(win, left, top, right, bottom);
X	wchange(win,
X		right - 3*wcharwidth('m'), bottom - 2 - wlineheight(),
X		right-2, bottom-2);
X	changed= TRUE;
X}
X
X/* Subroutine to find a glyph's cell */
X
Xcellbounds(i, pleft, ptop, pright, pbottom)
X	int i;
X	int *pleft, *ptop, *pright, *pbottom;
X{
X	int row= (i - firstglyph) / ncols;
X	int col= (i - firstglyph) % ncols;
X	*pleft= col*colwidth;
X	*pright= *pleft + colwidth;
X	*ptop= row * rowheight;
X	*pbottom= *ptop + rowheight;
X}
X
X/* Predicate for rectangle intersection */
X
Xbool
Xintersects(l1, t1, r1, b1, l2, t2, r2, b2)
X{
X	if (l1 >= r2 || r1 <= l2)
X		return FALSE;
X	if (t1 >= b2 || b1 <= t2)
X		return FALSE;
X	return TRUE;
X}
X
X/* Read the namelist */
X
Xbool
Xreadnamelist()
X{
X	FILE *fp;
X	char buf[256];
X	if (filename == NULL) {
X		buf[0]= EOS;
X		if (!waskfile("Read file:", buf, sizeof buf, FALSE))
X			return FALSE;
X		filename= strdup(buf);
X	}
X	fp= fopen(filename, "r");
X	if (fp == NULL) {
X		char buf[256];
X		sprintf(buf, "Can't read file %s", filename);
X		wmessage(buf);
X		return FALSE;
X	}
X	while (fgets(buf, sizeof buf, fp) != NULL) {
X		int glyph;
X		char name[256];
X		if (sscanf(buf, "%s - 0x%x", name, &glyph) == 2 ||
X			sscanf(buf, "%s 0x%x", name, &glyph) == 2) {
X			if (glyph >= 0 && glyph < NGLYPHS)
X				strncpy(namelist[glyph], name, 2);
X		}
X	}
X	fclose(fp);
X}
X
X/* Write the namelist */
X
Xbool
Xwritenamelist()
X{
X	char name[256];
X	FILE *fp;
X	int i;
X	if (filename == NULL)
X		name[0]= EOS;
X	else
X		strcpy(name, filename);
X	if (!waskfile("Write to file:", name, sizeof name, TRUE))
X		return FALSE;
X	filename= strdup(name);
X	fp= fopen(filename, "w");
X	if (fp == NULL) {
X		sprintf(name, "Can't create file %s", filename);
X		wmessage(name);
X		filename= NULL;
X		return FALSE;
X	}
X	for (i= 0; i < NGLYPHS; ++i) {
X		if (namelist[i][0] != EOS)
X			fprintf(fp, "%-2s - 0x%02X\n", namelist[i], i);
X	}
X	fclose(fp);
X	changed= FALSE;
X	return TRUE;
X}
END_OF_FILE
if test 8842 -ne `wc -c <'Appls/dpv/choose.c'`; then
    echo shar: \"'Appls/dpv/choose.c'\" unpacked with wrong size!
fi
# end of 'Appls/dpv/choose.c'
fi
if test -f 'Conf/README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Conf/README'\"
else
echo shar: Extracting \"'Conf/README'\" \(5259 characters\)
sed "s/^X//" >'Conf/README' <<'END_OF_FILE'
XConf subdirectory
X-----------------
X
XThis directory contains tools (scrips) and data (Makefile fragments)
Xused to build various ports of stdwin and applications that use it on
Xvarious UNIX-based platforms.
X
XAn explanation of some of the terms used may be in order:
X
XA "port" of stdwin consists of code that implements the portable stdwin
Xinterface on top of a particular lower-level interface, e.g., there is a
Xport for X11, called "x11", and a port for ASCII terminals using the
Xtermcap library, called "alfa"; there are also ports to the Macintosh
Xand the Atari ST, etc.  Ports can share code; in particular, some
Xlibrary packages built on top of stdwin (like "textedit") are used with
Xall ports, and some low-level routines (like "strdup") are used by all
Xports.  Ports are structured as libraries that must be linked with
Xapplications.
X
XA "platform" is a combination of operating system and machine
Xarchitecture on which you might want to use stdwin.  The x11 and alfa
Xports work on many platforms, and most of those platforms support both
Xports.  The current set-up identifies platforms with architectures;
Xwhile several operating systems are used on multiple architectures
X(e.g., SunOS on sun3 and sun4 architectures), few architectures offer a
Xchoice of operating system.  (If this simplification becomes a real
Xproblem, we'll simply change the maning of architecture identifiers into
Xplatform identifiers, so we might have platforms "ultvax" and "bsdvax"
Xfor a VAX under Ultrix and a VAX under BSD, respectively.)
X
XA "component" is either a port library, a package library, or an
Xapplication program.  Components are the smallest units that have
XMakefiles.  There is one set of sources for a particular component, used
Xon all platforms.  Package and application components are also used with
Xdifferent ports, again using the same set of sources.
X
XObjects live in a different part of the stdwin tree than sources.  This
Xsubtree is rooted at the Build subdirectory of the tree.  We certainly
Xneed a subtree per port, since two or more ports can co-exist on most
Xplatforms; but we also need a subtree per platform, since, through the
Xwonders of NFS, a single file system containing the stdwin tree may be
Xmounted on totally different systems.  Hence, the Build subtree has two
Xlevels of subdirectories before we are getting to business, one per
Xarchitecture (really per platform), one per port.  The scripts have a
Xfew provisions to create build trees in nonstandard places if you need
Xmore freedom.
X
XThe subtree structure under Build is as follows:
X
XBuild/<arch>/			subtree for a particular architecture
X				or platform (<arch> can be sun3, sun4,
X				vax etc.)
X
XBuild/<arch>/<port>/		subtree for a particular port
X				(<port> can be alfa or x11)
X
XBuild/<arch>/<port>/lib/	the main library component for the port
X				is built here
X
XBuild/<arch>/<port>/lib/lib.a	library file to link with applications
X
XBuild/<arch>/<port>/<pack>/
XBuild/<arch>/<port>/<appl>/	each application or package library
X				component is built in its own
X				subdirectory
X
XThe Makefiles are all generated automatically by scripts that live in
Xthe Conf subdirectory.  They are created from four sources:
X
Xa)	The concatenation of Makefile fragments that contain definitions
X	specific to:
X		- the port
X		- the architecture (or platform)
X		- the operating system
X	These fragments live in the Conf subdirectory.  Fragments for
X	all supported ports, and platforms are provided, as well as
X	templates that can be used to create new fragments.  These serve
X	as documentation for the fragments as well.
X
Xb)	A Makefile fragment specific to the component being built.
X	It defines which sources are needed and how they must be
X	combined.  The sources can come form any number of directories
X	besides the component's main source directory.  The object names
X	are derived from the source names.  There are two methods of
X	combining objects right now: libraries are created with "ar"
X	(and optionally "ranlib"), applications are created by linking
X	all objects together.  These Makefile fragments live in the main
X	source directory of the component (library or application) being
X	built.  The actual rules for building and creating the objects
X	are not contained in the fragments; rather, a bit of "bootstrap
X	magic" is used.
X
Xc)	The bootstrap magic consists of a Make rule in the
X	component-specific fragment.  This rule calls a program
X	"putprogmf" or "putlibmf" (depending on the component type) with
X	the list of source files used; the output is concatenated with
X	the Makefile fragments listed previously to produce a Makefile
X	that can build the component on the given platform using the
X	given port library (in case of an application).
X
Xd)	Full dependencies are added to the Makefile later.  Each
X	Makefile contains a rule "depend" which updates the Makefile
X	(in place!) with the current dependencies.  This should be run
X	once after the Makefile is built, and later when the dependency
X	structure of the sources is changed.  The dependencies are not
X	added when the Makefile is created initially, since the script
X	that computes dependencies *must* run on the platform where the
X	component is actually being built, while the Makefile can be
X	created (through NFS) from another platform.
END_OF_FILE
if test 5259 -ne `wc -c <'Conf/README'`; then
    echo shar: \"'Conf/README'\" unpacked with wrong size!
fi
# end of 'Conf/README'
fi
if test -f 'Doc/man/editwin.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Doc/man/editwin.man'\"
else
echo shar: Extracting \"'Doc/man/editwin.man'\" \(8791 characters\)
sed "s/^X//" >'Doc/man/editwin.man' <<'END_OF_FILE'
X.TH EDITWIN 3
X.SH NAME
XEditwin \- editing windows package for STDWIN
X.SH SYNOPSIS
X.nf
X.ft C
X#include "stdwin.h"
X#include "editwin.h"
X
Xtypedef struct editwin {
X	WINDOW *win;
X	TEXTEDIT *tp;
X	char *filename;
X	char saved;
X} EDITWIN;
X
XEDITWIN *ewcreate(char *filename);
XEDITWIN *ewnew();
XEDITWIN *ewopen();
X
Xbool ewsave(EDITWIN *ew);
Xbool ewsaveas(EDITWIN *ew);
Xbool ewsavecopy(EDITWIN *ew);
Xbool ewsaveall();
Xbool ewrevert(EDITWIN *ew);
Xbool ewclose(EDITWIN *ew);
Xbool ewcloseall();
X
Xbool ewwritefile(EDITWIN *ew, char *filename);
Xbool ewreadfile(EDITWIN *ew, char *filename);
X
Xbool ewevent(EDITWIN *ew, EVENT *e, int *closed_return);
Xvoid ewreplace(EDITWIN *ew, char *str);
Xvoid ewundo(EDITWIN *ew); /* Not implemented */
Xvoid ewcopy(EDITWIN *ew);
Xvoid ewpaste(EDITWIN *ew);
X
XEDITWIN *ewfind(WINDOW *win);
Xint ewcount();
X.ft 1
X.fi
X.SH DESCRIPTION
X.I Editwin
Xis a package built on top of the
X.I textedit
Xpackage, to ease the construction of views on text files etc.
XMany calls exist to make it extremely simple to respond to standard
Xmenus of
X.B File
Xoperations (New, Open..., Save, etc.) and
X.B Edit
Xoperations (Cut, Copy, Paste).
X.PP
XBelow are descriptions of the individual functions.
XNote that when a reference is made to a window's contents, the entire
Xcontents of the edit buffer belonging to the window is meant, not just
Xthe part of it visible in the window.
X.IP ewcreate
XIf
X.I filename
Xis a nil pointer, this call creates an ``Untitled'' edit window.
XOtherwise, the specified file must exist, and an edit window showing
Xits contents is created.
XIn both cases, the window's `saved' flag is set initially.
XA pointer to a newly allocated EDITWIN struct is returned.
XIf something went wrong (e.g., insufficient memory, or an unreadable
Xfile was specified), a nil pointer is returned.
X.IP ewnew
XThis function can be called in response to the selection of the
X.B New
Xmenu item.
XIt is equivalent to a call to
X.I ewcreate((char*)0).
X.IP ewopen
XCall this function for the
X.B Open...
Xmenu item.
XIt asks the user for an existing file name (using
X.IR waskfile ),
Xand then calls
X.I ewcreate
Xwith that file name as parameter.
XIt returns nil if the dialog was cancelled or
X.I ewcreate
Xreturns nil.
X.IP ewsave
XCall this function for the
X.B Save
Xmenu item.
XIf the window's contents were modified since they were last read or
Xsaved, the function attempts to save the window to its file.
XIf the window was still ``Untitled'', the user is first asked to specify
Xa file name.
XThe function returns true (nonzero) if the contents were actually saved,
Xor didn't need saving.
X.IP ewsaveas
XCall this function for the
X.B Save As...
Xmenu item.
XIt asks the user for a new file name to save the window's contents, and
Xif the saving succeeds, sets this to be the file name to which future
Xsave operations are directed.
X.IP ewsavecopy
XCall this function for the
X.B Save a Copy...
Xmenu item.
XLike
X.IR ewsaveas ,
Xthis function asks file a new file name and saves the window's contents
Xto that file; but it does not change the file name used for future save
Xoperations.
X.IP ewsaveall
XCalls
X.I ewsave
Xfor all windows.
XIf any call returns false (zero),
X.I ewsaveall
Xskips further calls and returns false.
X.IP ewrevert
XCall this function for the
X.B Revert...
Xmenu item.
XIt attempts to undo any changes since the window was last read or
Xsaved, by re-reading the corresponding file.
XIf this is at all possible, the user is asked to confirm the operation
Xfirst (since it may destroy valuable changes).
XThe function returns true if the file was actually read back, or if the
Xwindow was unchanged with respect to the file.
X.IP ewclose
XCloses the window.
XIf the window was changed since it was last read or saved, the user is
Xfirst asked whether it should be saved, and if the answer is Yes,
X.I ewsave
Xis called.
XCancelling the dialog will prevent closing the window.
XReturns true if the window was actually closed.
X.IP ewcloseall
XCalls
X.I ewclose
Xfor all windows.
XIf any call returns false,
X.I ewcloseall
Xskips further calls and returns false.
X.IP ewwritefile
XWrites the contents of the edit window to the specified file.
XReturns true if the operation succeeded.
XThis does
X.I not
Xset the `saved' flag for the window (because it is used internally be
X.IR ewsavecopy ).
X.IP ewreadfile
XReads the contents of the given file into the edit window, discarding
Xits previous contents.
XReturns true if the operation succeeded.
XThis
X.I does
Xset the `saved' flag for the window.
X.IP ewevent
XCall this function in response to
X.I any
Xevent returned by
X.I wgetevent.
XIf the event is a non-menu event applicable to the specified window, it
Xis handled and the function returns true;
Xotherwise nothing is done and the function returns false.
X(Menu events cannot be handled this way because the editwin package
Xdoesn't create its own menus, and thus cannot know the menu IDs or the
Xnumbers of the menu items.)
XIf the first parameter is a nil pointer, the event is checked against
Xany edit window; otherwise, only events applying to the given window are
Xhandled.
XThe third parameter must be a pointer to an integer variable, which is
Xcleared normally when an event was handled, but set to true when a
Xwindow was closed as a consequence of the event (it is unchanged when
Xthe event was nbot handled at all).
XIn the latter case, the caller should check whether any windows are
Xstill open (see
X.IR ewcount ),
Xand if this is not the case, it should either exit or open a new window.
XThis function clears a window's `saved' flag whenever its contents are
Xmodified by the event's handling.
X.IP ewreplace
XReplaces the current text selection in the window by the given
X(null-terminated) string.
XThis will insert text if the text selection was an insert point.
X.IP ewundo
XReserved for future extension of the package with an Undo facility.
X.IP ewcopy
XCall this function for the
X.B Copy
Xmenu item.
XIt retrieves the contents of the window's text selection, if non-null,
Xand copies it in into the clipboard through a call to
X.I wsetclip.
XIt beeps if the text selection is empty.
X(To implement the
X.B Cut
Xmenu item, call
X.I ewcopy
Xfollowed by
X.IR "ewreplace(ew, ``'')" .)
X.IP ewpaste
XCall this function for the
X.B Paste
Xmenu item.
XIt retrieves the contents of the clipboard, if non-null,
Xand pastes it into the window through a call to
X.I ewreplace.
XIt beeps (and does not change the window's contents) if the clipboard is
Xempty.
X.IP ewfind
XReturns a pointer to the EDITWIN struct containing the given WINDOW
Xpointer; returns nil if none exists.
X.IP ewcount
XReturns the number of open edit windows.
X.SH EXAMPLE
XThe following program is a trivial but almost usable single-file text
Xeditor.
XUsage is ``program [file]''.
X.nf
X.ft C
X
X#include "stdwin.h"
X#include "editwin.h"
X
Xmain(argc, argv) int argc; char **argv; {
X	EDITWIN *ew;
X	winitnew(&argc, &argv);
X	if (argc <= 1) ewnew();
X	else           ewcreate(argv[1]);
X	for (;;) {
X		EVENT e;
X		int closed;
X		wgetevent(&e);
X		if (ewevent(ew, &e, &b) && closed) break;
X	}
X	wdone();
X	exit(0);
X}
X.ft 1
X.fi
X.SH HINTS
XThe members of the EDITWIN data structure are explicitly intended to be
Xaccessible to the caller.
XFunctionality which is not provided directly but which is available for
Xplain windows or for textedit data structures can be implemented by
Xapplying it to the
X.I win
Xor
X.I tp
Xmembers.
XNote that the
X.I filename
Xmember, when non-nil, points to memory allocated with
X.IR malloc (3).
X.PP
XChanges to the window's contents should preferably be made with
X.I ewreplace,
Xsince it manages the `saved' flag.
X.PP
XTo control the text attributes used in an EDITWIN window, you can set
Xthem globally before creating the window.
X.SH DIAGNOSTICS
X.I Ewcreate, ewnew
Xand
X.I ewopen
Xreturn nil when the user cancelled the operation or when they could not
Xget all the necessary memory.
XThe save, revert, close and read/write family of functions return FALSE
Xif the operation was canceled by the user or if the file I/O failed.
X.I Ewevent
Xreturns TRUE when it has processed the event.
X.PP
X.I Ewcreate
Xand
X.I ewopen
Xwarn the user if a file is larger than about 30K; the textedit package
Xwas not designed to operate on big files, and may be intolerably slow.
X.SH SEE ALSO
XSTDWIN documentation
X.br
Xtextedit(3)
X.SH AUTHOR
XGuido van Rossum
X.SH BUGS
X.I Editwin
Xinherits some bugs from the
X.I textedit
Xpackage.
X.br
XThe package doesn't detect the situation where the user opens the same
Xfile twice, edits both copies, and saves them, thus losing the
Xchanges to the copy saved first.
X.br
XIf the height of the document gets over 32K scan lines, you are
Xin trouble: most window systems limit coordinates to short integers.
X.br
XMissing functionality:
Xa way to specify an alternate title for an untitled window;
Xa way to create a non-file window, which isn't saved when closed.
X(These should be easy to add, given the simplicity of the source.)
END_OF_FILE
if test 8791 -ne `wc -c <'Doc/man/editwin.man'`; then
    echo shar: \"'Doc/man/editwin.man'\" unpacked with wrong size!
fi
# end of 'Doc/man/editwin.man'
fi
if test -f 'Packs/vt/vtselect.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Packs/vt/vtselect.c'\"
else
echo shar: Extracting \"'Packs/vt/vtselect.c'\" \(9625 characters\)
sed "s/^X//" >'Packs/vt/vtselect.c' <<'END_OF_FILE'
X/* Copy and paste operations for VT.
X   The selections here are not rectangles,
X   like in most other vt-stuff */
X
X/* XXX This must be redesigned.
X   In the new design, the event loop is in the caller and we remember
X   the state somehow in the vt structure.
X   This is necessary to make it independent of aterm (special semantics
X   of WE_EXTERN events) and to support extending the selection with the
X   third button.
X*/
X
X#include "vtimpl.h"
X
X
Xextern int extra_downs; /* For aterm */
X
X
X/* Data structure used by coord_sort */
X
Xstruct coord {		/* A coordinate */
X	int c, r;	/* Column and row */
X};
X
X/*
X *	Bubblesort an array of coordinates.
X */
Xstatic void
Xcoord_sort(coord, n)
X    struct coord coord[];
X    int n;
X{
X    int i, j, big;
X    /* Bubble */
X    for (j = n; --j > 0; ) {
X	/* Find biggest in 0..j */
X	for (big = i = 0; ++i <= j; ) { /* Compare big and i */
X	    if (coord[big].r < coord[i].r ||
X	    (coord[big].r == coord[i].r && coord[big].c < coord[i].c))
X		big = i; /* Found a bigger one */
X	}
X	if (big != j) {
X	    struct coord swap;
X	    swap = coord[big]; coord[big] = coord[j]; coord[j] = swap;
X	}
X    }
X}
X
X/*
X *	Delete double occurences in a sorted
X *	array of coordinates (Both of them!)
X */
Xstatic int
Xno_double(coord, n)
X    struct coord coord[];
X    int n;
X{
X    int i, j;
X    for (i = j = 0; i < n; ) {
X	if (i < n - 1 && coord[i].r == coord[i + 1].r
X	&& coord[i].c == coord[i + 1].c) {
X	    i += 2; /* Skip both */
X	}
X	else {
X	    if (i != j) coord[j] = coord[i]; /* Copy */
X	    ++i; ++j;
X	}
X    }
X    return j; /* Return # array elements */
X}
X
X/*
X *	Set the selection of a vt, update state variables
X */
Xstatic void
Xset_selection(vt, row1, col1, row2, col2)
X    VT *vt;
X    int row1, col1, row2, col2;
X{
X    /* Screen coordinates of begins/ends of selection */
X    struct coord coord[4];
X    int n_coord, i;
X
X    /* Above last remembered line; repair */
X    if (row1 < -vt->topterm) {
X	    row1 = -vt->topterm;
X	    col1 = 0;
X    }
X
X    /* Initialise array */
X    coord[0].r = vt->sel_row1;
X    coord[0].c = vt->sel_col1;
X    coord[1].r = vt->sel_row2;
X    coord[1].c = vt->sel_col2;
X    coord[2].r = row1;
X    coord[2].c = col1;
X    coord[3].r = row2;
X    coord[3].c = col2;
X
X    /* Sort, optimise */
X    coord_sort(coord, 4);
X    n_coord = no_double(coord, 4);
X
X    /* Blit */
X    if (n_coord > 0) {
X	VTBEGINDRAWING(vt);
X	for (i = 0; i < n_coord; i += 2)
X	    vtinvert(vt, coord[i].r, coord[i].c, coord[i+1].r, coord[i+1].c);
X	VTENDDRAWING(vt);
X    }
X
X    /* Save state */
X    vt->sel_row1 = row1;
X    vt->sel_col1 = col1;
X    vt->sel_row2 = row2;
X    vt->sel_col2 = col2;
X} /* set_selection */
X
X
X/* Pass the selection to STDWIN.
X   Always set cut buffer 0, also try primary selection.
X   Return success/failure of the latter. */
X
Xstatic int
Xpass_selection(vt, data, len)
X	VT *vt;
X	char *data;
X	int len;
X{
X	wsetcutbuffer(0, data, len);
X	return wsetselection(vt->win, WS_PRIMARY, data, len);
X}
X
X
X/* Interface to STDWIN selection and cut buffer: save the copied text.
X   Returns success/failure */
X
Xstatic int
Xextract_selection(vt, row1, col1, row2, col2)
X    VT *vt;
X{
X    /* Swap if needed to make sure (row1, col1) <= (row2, col2) */
X    if (row1 > row2 || row1 == row2 && col1 > col2) {
X	register int scratch;
X	scratch = row1; row1 = row2; row2 = scratch;
X	scratch = col1; col1 = col2; col2 = scratch;
X    }
X
X    /* Make sure (0, 0) <= (row1, col1) and (row2, col2) <= (vt->rows, 0) */
X    if (row1 < 0) { row1 = 0; col1 = 0; }
X    if (row2 > vt->rows) { row2 = vt->rows; col2 = 0; }
X
X    /* Now, if (row1, col1) >= (row2, col2), the selection is empty */
X    if (row1 > row2 || row1 == row2 && col1 >= col2) {
X	wresetselection(WS_PRIMARY); /* Clear any previous selection */
X	return 1;
X    }
X
X    /* Check for simple case -- everything on one line */
X    if (row1 == row2 && col2 <= vt->llen[row2])
X	return pass_selection(vt, vt->data[row1] + col1, col2 - col1);
X
X    /* Harder case: more lines, or one line + end-of-line */
X
X    {
X	char *str, *p;
X	int ok;
X
X	/* Get (more than) enough memory, fail if can't get it */
X	p = str = malloc((row2 - row1 + 1) * (vt->cols + 1));
X	if (p == NULL) return 0; /* Fail */
X
X	/* Copy first line, add a newline */
X	if (col1 < vt->llen[row1]) {
X	    strncpy(p, vt->data[row1] + col1, vt->llen[row1] - col1);
X	    p += vt->llen[row1] - col1;
X	}
X	*p++ = '\n';
X
X	/* Copy intermediate lines, adding newlines */
X	while (++row1 < row2) {
X	    strncpy(p, vt->data[row1], vt->llen[row1]);
X	    p += vt->llen[row1];
X	    *p++ = '\n';
X	}
X
X	/* Copy last line -- if this is not the first as well, nor too far */
X	if (row1 == row2 && row2 < vt->rows) {
X	    if (col2 <= vt->llen[row2]) {
X		strncpy(p, vt->data[row2], col2);
X		p += col2;
X	    }
X	    else {
X		/* Beyond last char, copy a \n as well */
X		strncpy(p, vt->data[row2], vt->llen[row2]);
X		p += vt->llen[row2];
X		*p++ = '\n';
X	    }
X	}
X
X	/* Pass the string to STDWIN, free it, and return success */
X	ok = pass_selection(vt, str, (int) (p - str));
X	free(str);
X	return ok;
X    }
X}
X
X
X/* Symbolic values for the modes we can be in while selecting: */
X
X#define SEL_CHARS	0	/* Selecting chars */
X#define SEL_WORDS	1	/* Selecting words */
X#define SEL_LINES	2	/* Selecting lines */
X#define SEL_KINDS	3	/* How many modes we know */
X
X/* Macros to distinguish between various "brands" of characters.
X   A "word" is a sequence of characters of the same brand */
X
X#define BRAND_LETTER	0
X#define BRAND_SPACE	1
X#define BRAND_PUNCT	2
X
X/* Determine the brand of a character */
X
Xstatic int
Xbrand(ch)
X    int ch;
X{
X    return (('a' <= ch && ch <= 'z') ||
X	 ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9') ||
X	 (ch == '_') ? BRAND_LETTER :
X	 (ch == ' ' || ch == '\t') ? BRAND_SPACE : BRAND_PUNCT);
X}
X
X
X/* Called by the mainloop upon a mouse-down. Exits when the mouse is
X   up again; any other intermediate events terminates the selection.
X   Returns whether the selection succeeded */
X
Xint
Xvtselect(vt, e)
X    VT *vt;
X    EVENT *e;
X{
X    int first_row, first_col; /* Coords save at mouse-down */
X    int was_lazy; /* Zapped because vtsetcursor is lazy as well */
X    int csr_row, csr_col; /* Cursor saved at mouse-down */
X    int button_down = 1; /* That's the reason we're called after all */
X    int sel_mode = SEL_CHARS; /* This one is not yet handled */
X    int timer_pending = 0;
X    int success = 1; /* We are optimists */
X
X    /* Save cursor position */
X    was_lazy = vt->lazy; vt->lazy = 0;
X    csr_row = vt->cur_row;
X    csr_col = vt->cur_col;
X
X    /* Init */
X    first_row = e->u.where.v / vt->cheight;
X    first_col = (e->u.where.h + vt->cwidth/2) / vt->cwidth;
X    if (first_col > vt->llen[first_row]) {
X	/* Clicked beyond eoln; use first char on next line instead */
X	++first_row;
X	first_col = 0;
X    }
X
X    vtsetcursor(vt, first_row, first_col);
X
X    do {
X	int row, col; /* Current mouse position */
X
X	wgetevent(e);
X	switch (e->type) {
X	case WE_MOUSE_UP:
X	    button_down = 0;
X	    wsettimer(vt->win, 2);
X	    timer_pending = 1;
X	    break;
X	case WE_MOUSE_MOVE:
X	    break;
X	case WE_MOUSE_DOWN:
X	    if (e->u.where.button != 1) {
X		/* E.g. paste-button; stop selection */
X		timer_pending = button_down = 0;
X		wungetevent(e);
X		break;
X	    }
X	    button_down = 1;
X	    sel_mode = (sel_mode + 1) % SEL_KINDS;
X	    break;
X	case WE_EXTERN:	/* Got output from child - save */
X	    ++extra_downs;
X	    continue;	/* Get next event */
X	case WE_TIMER:
X	    timer_pending = 0;
X	    break;
X	default:
X	    wungetevent(e);
X	    success = 0;
X	    goto reset;
X	}
X
X	/*
X	 * We only get here when we want
X	 * to draw the current selection;
X	 * Compute new coords
X	 */
X
X	row = e->u.where.v / vt->cheight;
X	col = (e->u.where.h + vt->cwidth/2) / vt->cwidth;
X	vtsetcursor(vt, row, col);
X
X#if 0	/* To do: Make sure everything in the neighbourhood can be seen: */
X	/* This does not work; it's far too fast */
X	if (vt->rows > 3 && vt->cols > 3)
X	    wshow(vt->win,
X		e->u.where.h - vt->cwidth, e->u.where.v - vt->cheight,
X		e->u.where.h + vt->cwidth, e->u.where.v + vt->cheight);
X#endif
X
X	switch (sel_mode) {
X	int rs, cs;
X	case SEL_CHARS:
X	case SEL_WORDS:
X	    /* Clip row and col */
X	    if (row > vt->rows) row = vt->rows;
X	    else if (row < 0) row = 0;
X	    if (col > vt->cols) col = vt->cols;
X	    else if (col < 0) col = 0;
X	    rs = first_row;
X	    cs = first_col;
X	    if (sel_mode == SEL_CHARS) {
X		/* Select including the eoln when beyond last char */
X		if (vt->llen[row] < col) col = vt->cols;
X	    } else {
X		/* Sort coordinates */
X		if (rs > row || (rs == row && cs > col)) {
X		    register tmp;
X		    tmp = row; row = rs; rs = tmp;
X		    tmp = col; col = cs; cs = tmp;
X		}
X		/* Expand */
X		while (cs > 0 &&
X		    brand(vt->data[rs][cs]) == brand(vt->data[rs][cs - 1]))
X			--cs;
X		if (col >= vt->llen[row]) col = vt->cols;
X		else while (++col < vt->llen[row] &&
X		    brand(vt->data[row][col - 1]) == brand(vt->data[row][col]))
X			;
X	    }
X	    /* Update screen */
X	    set_selection(vt, rs, cs, row, col);
X	    break;
X	case SEL_LINES:
X	    if (++row > vt->rows) row = vt->rows;
X	    set_selection(vt,
X		first_row >= row ? first_row + 1 : first_row, 0, row, 0);
X	    break;
X	}
X
X    } while (button_down || timer_pending);
X
X    /* Now pass the selection to STDWIN */
X    if (!extract_selection(vt,
X    		vt->sel_row1, vt->sel_col1, vt->sel_row2, vt->sel_col2))
X    	wfleep(); /* Give the user some indication that it failed */
X
Xreset:
X    /* Invert back to normal:	*/
X    set_selection(vt, 0, 0, 0, 0);
X    vtsetcursor(vt, csr_row, csr_col);
X    vt->lazy = was_lazy;
X    return success;
X}
X
X
X/* Extend the selection */
X
Xint
Xvtextendselection(vt, ep)
X	VT *vt;
X	EVENT *ep;
X{
X	/* XXX not yet implemented */
X	wfleep();
X	return 0;
X}
END_OF_FILE
if test 9625 -ne `wc -c <'Packs/vt/vtselect.c'`; then
    echo shar: \"'Packs/vt/vtselect.c'\" unpacked with wrong size!
fi
# end of 'Packs/vt/vtselect.c'
fi
if test -f 'Ports/alfa/draw.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Ports/alfa/draw.c'\"
else
echo shar: Extracting \"'Ports/alfa/draw.c'\" \(8748 characters\)
sed "s/^X//" >'Ports/alfa/draw.c' <<'END_OF_FILE'
X/* ALFA STDWIN -- DRAWING. */
X
X#include "alfa.h"
X
Xstatic char *textline[MAXLINES];
Xstatic short textlen[MAXLINES];
Xstatic char texttouched[MAXLINES];
X
Xstatic TEXTATTR draw_saveattr;
Xstatic WINDOW *draw_win;
X
X/* Cause a redraw of part of a window. */
X
X/*ARGSUSED*/
Xvoid
Xwchange(win, left, top, right, bottom)
X	WINDOW *win;
X	int left, top;
X	int right, bottom;
X{
X	int id= win - winlist;
X	int i;
X	
X	if (id < 0 || id >= MAXWINDOWS || !win->open)
X		return;
X	top -= win->offset;
X	bottom -= win->offset;
X	if (top < win->top)
X		top= win->top;
X	if (bottom > win->bottom)
X		bottom= win->bottom;
X	for (i= top; i < bottom; ++i)
X		uptodate[i]= FALSE;
X	_wnewtitle(win);
X}
X
X/* (Try to) make sure a particular part of a window is visible,
X   by scrolling in distant parts if necessary. */
X
Xvoid scrollupdate();
X
X/*ARGSUSED*/
Xvoid
Xwshow(win, left, top, right, bottom)
X	WINDOW *win;
X	int left, top;
X	int right, bottom;
X{
X	int id= win - winlist;
X	int offset;
X	int extra;
X	int dv;
X	
X	if (id < 0 || id >= MAXWINDOWS || !win->open)
X		return;
X	extra= ( (win->bottom - win->top) - (bottom - top) ) / 2;
X	if (extra < 0)
X		extra= 0;
X	offset= win->offset;
X	if (bottom > win->bottom + offset)
X		offset= bottom - win->bottom + extra;
X	if (top < win->top + offset)
X		offset= top - win->top - extra;
X	if (win->top + offset < 0)
X		offset= -win->top;
X	dv= offset - win->offset;
X	if (dv == 0)
X		return;
X	win->offset= offset;
X	/* Now we'll use top, bottom to indicate the changed part. */
X	top= win->top;
X	bottom= win->bottom;
X	scrollupdate(top, bottom, dv);
X	trmscrollup(top, bottom-1, dv);
X}
X
X/* Similar, but by giving an explicit new origin */
X
X/*ARGSUSED*/
Xvoid
Xwsetorigin(win, h, v)
X	WINDOW *win;
X	int h, v;
X{
X	int id= win - winlist;
X	int top, bottom;
X	int dv;
X
X	if (id < 0 || id >= MAXWINDOWS || !win->open)
X		return;
X	dv = (v - win->top) - win->offset;
X	if (dv == 0)
X		return;
X	win->offset += dv;
X	top = win->top;
X	bottom = win->bottom;
X	scrollupdate(top, bottom, dv);
X	trmscrollup(top, bottom-1, dv);
X}
X
X/* Scroll the update bits */
X
X/*ARGSUSED*/
Xvoid
Xscrollupdate(top, bottom, dv)
X	int top, bottom;
X	int dv;
X{
X	int i;
X
X#ifndef EUROGEMODDER
X	for (i= top; i < bottom; ++i)
X		uptodate[i] = FALSE;
X#else
X	char *p;
X
X	if(dv==0)
X		return;
X	if(dv > 0) {
X		for (i= top; i < bottom; ++i) {
X			if (uptodate[i+dv]) {
X				p=textline[i];
X				textline[i]=textline[i+dv];
X				textlen[i]=textlen[i+dv];
X				uptodate[i]= TRUE;
X				textline[i+dv]= p;
X				/*needed? textlen[i+dv]= 0; */
X				uptodate[i+dv]= FALSE;
X			} else {
X				uptodate[i]= FALSE;
X			}
X		}
X	} else {
X		for (i= bottom-1; i >= top; --i) {
X			if (uptodate[i+dv]) {
X				p=textline[i];
X				textline[i]=textline[i+dv];
X				textlen[i]=textlen[i+dv];
X				uptodate[i]= TRUE;
X				textline[i+dv]= p;
X				/*needed? textlen[i+dv]= 0; */
X				uptodate[i+dv]= FALSE;
X			} else {
X				uptodate[i]= FALSE;
X			}
X		}
X	}
X#endif
X}
X
X/* Set the caret (cursor) position. */
X
Xvoid
Xwsetcaret(win, h, v)
X	WINDOW *win;
X	int h, v;
X{
X	win->curh= h;
X	win->curv= v;
X	/* wshow(win, h, v, h+1, v+1); */
X	/* Shouldn't call wshow here -- it's not always desirable! */
X}
X
X/* Remove the caret altogether. */
X
Xvoid
Xwnocaret(win)
X	WINDOW *win;
X{
X	win->curh= win->curv= -1;
X}
X
X/* Cause a redraw of the window 's title bar. */
X
Xvoid
X_wnewtitle(win)
X	WINDOW *win;
X{
X	if (win->top > 0)
X		uptodate[win->top-1]= FALSE;
X}
X
X/* Compute the smallest rectangle that needs an update.
X   As a side effect, uptodate is set to TRUE for the affected lines,
X   and the lines are cleared and set to touched
X   (but no actual output is performed).
X   Return FALSE if the rectangle is empty. */
X
Xbool
Xwgetchange(win, pleft, ptop, pright, pbottom)
X	WINDOW *win;
X	int *pleft, *ptop, *pright, *pbottom;
X{
X	int top= win->bottom;
X	int bottom= win->top;
X	int i;
X	
X	for (i= win->top; i < win->bottom; ++i) {
X		if (!uptodate[i]) {
X			texttouched[i]= TRUE;
X			textlen[i]= 0;
X			uptodate[i]= TRUE;
X			if (top > i)
X				top= i;
X			bottom= i+1;
X		}
X	}
X	if (top > bottom) {
X		*pleft= *pright= *ptop= *pbottom= 0;
X		return FALSE;
X	}
X	else {
X		*pleft= 0;
X		*pright= columns;
X		*ptop= top + win->offset;
X		*pbottom= bottom + win->offset;
X		return TRUE;
X	}
X}
X
Xvoid
Xwupdate(win)
X	WINDOW *win;
X{
X	int left, top, right, bottom;
X	
X	wgetchange(win, &left, &top, &right, &bottom);
X	
X	wbegindrawing(win);
X	
X	if (win->drawproc != NULL)
X		(*win->drawproc)(win, 0, top, columns, bottom);
X	
X	wenddrawing(win);
X}
X
Xvoid
Xwbegindrawing(win)
X	WINDOW *win;
X{
X	int i;
X	
X	if (draw_win != NULL)
X		wenddrawing(draw_win); /* Finish previous job */
X	
X	/* Auto-initialization of the textline array.
X	   The other arrays needn't be initialized,
X	   since they are preset to zero. */
X	for (i= win->top; i < win->bottom; ++i) {
X		if (textline[i] == NULL)
X			textline[i]= malloc((unsigned) (columns+1));
X			/*uptodate[i]= FALSE;*/
X	}
X	
X	draw_saveattr= wattr;
X	wattr= win->attr;
X	draw_win= win;
X}
X
Xvoid
Xwenddrawing(win)
X	WINDOW *win;
X{
X	int i;
X	
X	if (draw_win != win) {
X		return; /* Bad call */
X	}
X	
X	for (i= win->top; i < win->bottom; ++i) {
X		if (texttouched[i]) {
X			texttouched[i]= FALSE;
X			textline[i][textlen[i]]= EOS;
X			trmputdata(i, i, 0, textline[i]);
X		}
X	}
X	
X	wattr= draw_saveattr;
X	draw_win= NULL;
X}
X
Xvoid
Xwdrawtitle(win)
X	WINDOW *win;
X{
X	int titline= win->top - 1;
X	char buf[256];
X	char *title= win->title == NULL ? "" : win->title;
X	int tlen= strlen(title);
X	int space= columns-tlen;
X	int mask= (win == front) ? 0200 : 0;
X	int k;
X	
X	for (k= 0; k < space/2 - 1; ++k)
X		buf[k]= '-'|mask;
X	buf[k++]= ' '|mask;
X	while (k < columns && *title != EOS)
X		buf[k++]= *title++|mask;
X	if (k < columns)
X		buf[k++]= ' '|mask;
X	while (k < columns)
X		buf[k++]= '-'|mask;
X	buf[k]= EOS;
X	trmputdata(titline, titline, 0, buf);
X	uptodate[titline]= TRUE;
X}
X
Xvoid
Xwdrawtext(h, v, str, len)
X	int h, v;
X	char *str;
X	int len;
X{
X	int k;
X	int mask= (wattr.style == 0) ? 0 : 0200;
X	char *text;
X	WINDOW *win= draw_win;
X	
X	if (len < 0)
X		len= strlen(str);
X	v -= win->offset;
X	if (v < win->top || v >= win->bottom || h >= columns || len == 0)
X		return;
X	text= textline[v];
X	k= textlen[v];
X	while (k < h)
X		text[k++]= ' ';
X	while (len > 0) {
X#define APPC(c) \
X	if (h >= 0) text[h]= (c) | mask; if (++h >= columns) break
X		unsigned char c= *str++;
X		--len;
X		if (c < ' ') {
X			APPC('^');
X			APPC(c | '@');
X		}
X		else  if (c < 0177) {
X			APPC(c);
X		}
X		else if (c < 0200) {
X			APPC('^');
X			APPC('?');
X		}
X		else {
X			APPC('\\');
X			APPC('0' | ((c>>6) & 07));
X			APPC('0' | ((c>>3) & 07));
X			APPC('0' | (c & 07));
X		}
X#undef APPC
X	}
X	if (h > textlen[v])
X		textlen[v]= h;
X	texttouched[v]= TRUE;
X}
X
Xvoid
Xwdrawchar(h, v, c)
X	int h, v;
X	int c;
X{
X	char cbuf[2];
X	cbuf[0]= c;
X	cbuf[1]= EOS;
X	wdrawtext(h, v, cbuf, 1);
X}
X
Xvoid
Xwgetwintextattr(win, attr)
X	WINDOW *win;
X	TEXTATTR *attr;
X{
X	*attr= win->attr;
X}
X
Xvoid
Xwsetwintextattr(win, attr)
X	WINDOW *win;
X	TEXTATTR *attr;
X{
X	win->attr= *attr;
X}
X
X/* Non-text drawing dummy functions: */
X
X/*ARGSUSED*/
Xvoid
Xwdrawline(h1, v1, h2, v2)
X	int h1, v1, h2, v2;
X{
X}
X
X/*ARGSUSED*/
Xvoid
Xwxorline(h1, v1, h2, v2)
X	int h1, v1, h2, v2;
X{
X}
X
X/*ARGSUSED*/
Xvoid
Xwdrawcircle(h, v, radius)
X	int h, v;
X	int radius;
X{
X}
X
X/*ARGSUSED*/
Xvoid
Xwdrawelarc(h, v, radh, radv, ang1, ang2)
X	int h, v;
X	int radh, radv;
X	int ang1, ang2;
X{
X}
X
X/*ARGSUSED*/
Xvoid
Xwdrawbox(left, top, right, bottom)
X	int left, top, right, bottom;
X{
X}
X
X/*ARGSUSED*/
Xvoid
Xwpaint(left, top, right, bottom)
X	int left, top, right, bottom;
X{
X}
X
X/*ARGSUSED*/
Xvoid
Xwshade(left, top, right, bottom, percentage)
X	int left, top, right, bottom;
X	int percentage;
X{
X}
X
X/*ARGSUSED*/
Xvoid
Xwinvert(left, top, right, bottom)
X	int left, top, right, bottom;
X{
X	WINDOW *win= draw_win;
X	int v;
X	
X	if (left < 0)
X		left= 0;
X	if (right >= columns)
X		right= columns;
X	if (left >= right)
X		return;
X	top -= win->offset;
X	bottom -= win->offset;
X	if (top < win->top)
X		top= win->top;
X	if (bottom > win->bottom)
X		bottom= win->bottom;
X	for (v= top; v < bottom; ++v) {
X		int k= textlen[v];
X		char *text= textline[v];
X		if (k < right) {
X			do {
X				text[k++]= ' ';
X			} while (k < right);
X			textlen[v]= k;
X		}
X		for (k= left; k < right; ++k)
X			text[k] ^= 0200;
X		texttouched[v]= TRUE;
X	}
X}
X
X/*ARGSUSED*/
Xvoid
Xwerase(left, top, right, bottom)
X	int left, top, right, bottom;
X{
X	WINDOW *win= draw_win;
X	int v;
X	
X	if (left < 0)
X		left= 0;
X	if (right >= columns)
X		right= columns;
X	if (left >= right)
X		return;
X	top -= win->offset;
X	bottom -= win->offset;
X	if (top < win->top)
X		top= win->top;
X	if (bottom > win->bottom)
X		bottom= win->bottom;
X	for (v= top; v < bottom; ++v) {
X		int k= textlen[v];
X		char *text= textline[v];
X		if (k > right)
X			k= right;
X		while (--k >= left)
X			text[k]= ' ';
X		texttouched[v]= TRUE;
X	}
X}
X
X/*ARGSUSED*/
Xvoid
Xwcliprect(left, top, right, bottom)
X	int left, top, right, bottom;
X{
X	/* XXX not implemented */
X}
X
X/*ARGSUSED*/
Xvoid
Xwnoclip()
X{
X	/* XXX not implemented */
X}
END_OF_FILE
if test 8748 -ne `wc -c <'Ports/alfa/draw.c'`; then
    echo shar: \"'Ports/alfa/draw.c'\" unpacked with wrong size!
fi
# end of 'Ports/alfa/draw.c'
fi
if test -f 'Ports/x11/selection.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Ports/x11/selection.c'\"
else
echo shar: Extracting \"'Ports/x11/selection.c'\" \(8353 characters\)
sed "s/^X//" >'Ports/x11/selection.c' <<'END_OF_FILE'
X/* Selection Interface, a la ICCCM */
X
X
X/*
X	Features:
X	
X	- supports CLIPBOARD, PRIMARY and SECONDARY selections
X	- only supports STRING as selection type
X	- XXX no required funny targets TARGETS, MULTIPLE, TIMESTAMP
X	- no side effect targets DELETE, INSERT_*
X	- no INCR targets (XXX should accept these when receiving?)
X	- XXX truncates large selections to 32 K
X	- fixed timeout 1 second or 10 requests
X	
X	XXX To do:
X	
X	- delete selection data when we delete its window
X	- report the selection's window in WE_LOST_SEL events
X*/
X
X
X#include "x11.h"
X#include "llevent.h" /* For _w_lasttime; */
X
X
X#ifndef AMOEBA
X
X/* Provide default definitions for FD_ZERO and FD_SET */
X
X#ifndef FD_ZERO
X#define FD_ZERO(p)	bzero((char *)(p), sizeof(*(p)))
X#endif
X
X#ifndef NFDBITS
X#define NFDBITS		(sizeof(long)*8)	/* Assume 8 bits/byte */
X#endif
X
X#ifndef FD_SET
X#define FD_SET(n, p)	((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
X#endif
X
X#endif /* AMOEBA */
X
X
X/* Data structure describing what we know about each selection */
X
Xstruct seldescr {
X	Atom atom;
X	char *data;
X	int len;
X	Time time;
X	int lost;
X};
X
Xstatic struct seldescr seldata[] = {
X	{None,		NULL,	0,	CurrentTime,	0},	/* CLIPBOARD */
X	{XA_PRIMARY,	NULL,	0,	CurrentTime,	0},
X	{XA_SECONDARY,	NULL,	0,	CurrentTime,	0},
X};
X
X#define NSEL ( sizeof(seldata) / sizeof(seldata[0]) )
X
Xstatic void
Xinitseldata()
X{
X	/* The CLIPBOARD atom is not predefined, so intern it here... */
X	if (seldata[0].atom == None)
X		seldata[0].atom = XInternAtom(_wd, "CLIPBOARD", False);
X}
X
X
X/* Attempt to acquire selection ownership.  Return nonzero if success. */
X
Xint
Xwsetselection(win, sel, data, len)
X	WINDOW *win;
X	int sel; /* WS_CLIPBOARD, WS_PRIMARY or WS_SECONDARY */
X	char *data;
X	int len;
X{
X	Window owner;
X	initseldata();
X	if (sel < 0 || sel >= NSEL) {
X		_wwarning("wsetselection: invalid selection number %d", sel);
X		return 0;
X	}
X	seldata[sel].lost = 0;
X	XSetSelectionOwner(_wd, seldata[sel].atom, win->wo.wid, _w_lasttime);
X	owner = XGetSelectionOwner(_wd, seldata[sel].atom);
X	if (owner != win->wo.wid)
X		return 0; /* Didn't get it */
X	/* Squirrel away the data value for other clients */
X	seldata[sel].len = 0;
X	seldata[sel].time = CurrentTime;
X	if (seldata[sel].data != NULL)
X		free(seldata[sel].data);
X	seldata[sel].data = malloc(len+1);
X	if (seldata[sel].data == NULL) {
X		_wwarning("wsetselection: no mem for data (%d bytes)", len);
X		return 0;
X	}
X	memcpy(seldata[sel].data, data, len);
X	seldata[sel].data[len] = '\0';
X				/* Trailing NULL byte for wgetselection */
X	seldata[sel].len = len;
X	seldata[sel].time = _w_lasttime;
X	return 1;
X}
X
X
X/* Give up selection ownership */
X
Xvoid
Xwresetselection(sel)
X	int sel;
X{
X	if (sel < 0 || sel >= NSEL) {
X		_wwarning("wresetselection: invalid selection number %d", sel);
X		return;
X	}
X	seldata[sel].lost = 0;
X	if (seldata[sel].data != NULL) {
X		XSetSelectionOwner(_wd, seldata[sel].atom, None,
X							seldata[sel].time);
X		free(seldata[sel].data);
X		seldata[sel].data = NULL;
X		seldata[sel].len = 0;
X		seldata[sel].len = CurrentTime;
X	}
X}
X
X
X/* Attempt to get the value of a selection */
X
Xchar *
Xwgetselection(sel, len_return)
X	int sel;
X	int *len_return;
X{
X	static char *prop;
X	WINDOW *win;
X	XEvent e;
X	int i;
X	
X	initseldata();
X	
X	/* Free data retrieved last time */
X	if (prop != NULL) {
X		XFree(prop);
X		prop = NULL;
X	}
X	
X	/* Check selection code */
X	if (sel < 0 || sel >= NSEL) {
X		_wwarning("wgetselection: invalid selection number %d", sel);
X		return NULL;
X	}
X	
X	/* We may own this selection ourself... */
X	if (seldata[sel].data != NULL) {
X		_wdebug(2, "wgetselection: we have it");
X		*len_return = seldata[sel].len;
X		return seldata[sel].data;
X	}
X	
X	/* Have to ask some other client (the selection owner) */
X	win = _w_get_last_active();
X	if (win == NULL) {
X		_wwarning("wgetselection: no window");
X		return NULL;
X	}
X	
X	/* Tell the server to ask the selection owner */
X	XConvertSelection(_wd,
X		seldata[sel].atom,	/* selection */
X		XA_STRING,		/* target */
X		XA_STRING,		/* property (why not?) */
X		win->wo.wid,		/* window */
X		_w_lasttime);		/* time */
X	
X	/* Now wait for a SelectionNotify event -- 10 times */
X	_wdebug(2, "waiting for SelectionNotify");
X	for (i = 0; i < 10; i++) {
X		e.xselection.property = None;
X		if (XCheckTypedWindowEvent(_wd, win->wo.wid,
X						SelectionNotify, &e)) {
X			_wdebug(2, "got a SelectionNotify");
X			break;
X		}
X		else {
X#ifdef AMOEBA
X			/* XXX For now, just sleep a bit -- there is a
X			   routine to do this, though */
X			millisleep(100);
X#else /* !AMOEBA */
X			/* Use select */
X			/* SGI/SYSV interface */
X			fd_set readfds;
X			struct timeval timeout;
X			int nfound;
X			FD_ZERO(&readfds);
X			FD_SET(_wd->fd, &readfds);
X			timeout.tv_sec = 0;
X			timeout.tv_usec = 100000;
X			nfound = select(_wd->fd+1, &readfds,
X				(fd_set *)NULL, (fd_set *)NULL, &timeout);
X			if (nfound < 0)
X				_wwarning("select failed, errno %d", errno);
X			else
X				_wdebug(3, "select: nfound=%d\n", nfound);
X#endif /* !AMOEBA */
X		}
X	}
X	
X	if (e.xselection.property != None) {
X		/* Got a reply, now fetch the property */
X		int status;
X		Atom actual_type;
X		int actual_format;
X		unsigned long nitems;
X		unsigned long bytes_after;
X		status = XGetWindowProperty(_wd,
X			win->wo.wid,
X			e.xselection.property,
X			0L,
X			8192L, /* Times sizeof(long) is 32K ! */
X			True,
X			AnyPropertyType,
X			&actual_type,
X			&actual_format,
X			&nitems,
X			&bytes_after,
X			(unsigned char **)&prop);
X		if (status != Success) {
X			_wdebug(1, "XGetWindowProperty failed (%d)", status);
X			return NULL;
X		}
X		if (bytes_after != 0) {
X			_wwarning("truncated %d property bytes", bytes_after);
X			/* XXX should fetch the rest as well */
X			XDeleteProperty(_wd, win->wo.wid,
X						e.xselection.property);
X		}
X		if (actual_type != XA_STRING) {
X			_wdebug(1, "bad property type: 0x%lx", actual_type);
X			if (prop != NULL) {
X				XFree(prop);
X				prop = NULL;
X			}
X			return NULL;
X		}
X		*len_return = nitems * (actual_format/8);
X		_wdebug(2, "got a selection, %d bytes", *len_return);
X		return prop;
X		/* Will be freed next time this function is called */
X	}
X	
X	_wdebug(1, "SelectionNotify with property=None");
X	return NULL;
X}
X
X
X/* Handle a SelectionClear event -- called from llevent.c */
X
Xvoid
X_w_selectionclear(selection)
X	Atom selection;
X{
X	int sel;
X	
X	_wdebug(2, "clearing a selection");
X	initseldata();
X	
X	for (sel = 0; sel < NSEL; sel++) {
X		if (seldata[sel].atom == selection) {
X			wresetselection(sel);
X			seldata[sel].lost = 1;
X			break;
X		}
X	}
X}
X
X
X/* Generate a WE_LOST_SEL event if one is pending -- called from event.c */
X
Xint
X_w_lostselection(ep)
X	EVENT *ep;
X{
X	int sel;
X	
X	for (sel = 0; sel < NSEL; sel++) {
X		if (seldata[sel].lost) {
X			seldata[sel].lost = 0;
X			ep->type = WE_LOST_SEL;
X			/* XXX Should we report the window?
X			   This is not easily available. */
X			ep->window = NULL;
X			ep->u.sel = sel;
X			return 1;
X		}
X	}
X	return 0;
X}
X
X
X/* Reply to a SelectionRequest event -- called from llevent.c */
X
Xvoid
X_w_selectionreply(owner, requestor, selection, target, property, time)
X	Window owner;
X	Window requestor;
X	Atom selection;
X	Atom target;
X	Atom property;
X	Time time;
X{
X	XSelectionEvent e;
X	int sel;
X	
X	_wdebug(2, "replying to selection request");
X	initseldata();
X	
X	/* Fill in the reply event */
X	e.type = SelectionNotify;
X	e.requestor = requestor;
X	e.selection = selection;
X	e.target = target;
X	e.property = None; /* Replaced by property type if OK */
X	e.time = time;
X	
X	if (property == None)
X		property = target; /* Obsolete client */
X	
X	for (sel = 0; sel < NSEL; sel++) {
X		if (seldata[sel].atom == selection) {
X			/* It's this selection */
X			if (seldata[sel].data != NULL &&
X				(time == CurrentTime ||
X				seldata[sel].time == CurrentTime ||
X				((long)time - (long)seldata[sel].time) >= 0)) {
X				
X				/* And we have it.  Store it as a property
X				   on the requestor window.  The requestor
X				   will eventually delete it (says ICCCM). */
X				
X				/* XXX Always convert to STRING, OK? */
X				XChangeProperty(_wd,
X					requestor,
X					property,
X					XA_STRING,
X					8,
X					PropModeReplace,
X					(unsigned char *)seldata[sel].data,
X					seldata[sel].len);
X				/* Tell requestor we stored the property */
X				e.property = property;
X			}
X			else {
X				/* But we don't have it or the time is wrong */
X				_wdebug(1, "stale selection request");
X			}
X			break;
X		}
X	}
X	
X	if (!XSendEvent(_wd, requestor, False, 0L, (XEvent*)&e))
X		_wdebug(1, "XSendEvent failed");
X}
END_OF_FILE
if test 8353 -ne `wc -c <'Ports/x11/selection.c'`; then
    echo shar: \"'Ports/x11/selection.c'\" unpacked with wrong size!
fi
# end of 'Ports/x11/selection.c'
fi
echo shar: End of archive 10 \(of 19\).
cp /dev/null ark10isdone
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