v04i083: xconf -- X-based conferencing tool, Part01/05

Dan Heller argv at island.uu.net
Tue Jul 25 18:10:51 AEST 1989


Submitted-by: Jon Crowcroft <J.Crowcroft at Cs.Ucl.AC.UK>
Posting-number: Volume 4, Issue 83
Archive-name: xconf/part01



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
#		"End of archive 2 (of 5)."
# Contents:  xconf/AsciiSink.c xconf/GCManager.c xconf/Makefile
#   xconf/Text.c.ab
# Wrapped by argv at sumatra on Tue Jul 25 01:01:05 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'xconf/AsciiSink.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xconf/AsciiSink.c'\"
else
echo shar: Extracting \"'xconf/AsciiSink.c'\" \(15302 characters\)
sed "s/^X//" >'xconf/AsciiSink.c' <<'END_OF_FILE'
X#ifndef lint
Xstatic char Xrcsid[] = "$XConsortium: AsciiSink.c,v 1.26 88/10/19 20:08:51 swick Exp $";
X#endif lint
X
X
X/***********************************************************
XCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
Xand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
X
X                        All Rights Reserved
X
XPermission to use, copy, modify, and distribute this software and its 
Xdocumentation for any purpose and without fee is hereby granted, 
Xprovided that the above copyright notice appear in all copies and that
Xboth that copyright notice and this permission notice appear in 
Xsupporting documentation, and that the names of Digital or MIT not be
Xused in advertising or publicity pertaining to distribution of the
Xsoftware without specific, written prior permission.  
X
XDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
XDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
XSOFTWARE.
X
X******************************************************************/
X
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X#ifdef JON
X#include "TextP.h"
X#else JON
X#include <X11/TextP.h>
X#endif JON
X
X
X#define GETLASTPOS (*source->Scan)(source, 0, XtstAll, XtsdRight, 1, TRUE)
X/* Private Ascii TextSink Definitions */
X
Xstatic unsigned bufferSize = 200;
X
Xtypedef struct _AsciiSinkData {
X    Pixel foreground;
X    GC normgc, invgc, xorgc;
X    XFontStruct *font;
X    int em;
X    Pixmap insertCursorOn;
X    XtTextInsertState laststate;
X    int tab_count;
X    Position *tabs;
X} AsciiSinkData, *AsciiSinkPtr;
X
Xstatic char *buf = NULL;
X
X/* XXX foreground default should be XtDefaultFGPixel. How do i do that?? */
X
Xstatic XtResource SinkResources[] = {
X    {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
X        XtOffset(AsciiSinkPtr, font), XtRString, "Fixed"},
X    {XtNforeground, XtCForeground, XtRPixel, sizeof (int),
X        XtOffset(AsciiSinkPtr, foreground), XtRString, "Black"},    
X};
X
X/* Utilities */
X
Xstatic int CharWidth (w, x, c)
X  Widget w;
X  int x;
X  char c;
X{
X    AsciiSinkData *data = (AsciiSinkData*) ((TextWidget)w)->text.sink->data;
X    int     width, nonPrinting;
X    XFontStruct *font = data->font;
X
X    if (c == '\t') {
X	int i;
X	Position *tab;
X	if (x >= w->core.width) return 0;
X	for (i=0, tab=data->tabs; i<data->tab_count; i++, tab++) {
X	    if (x < *tab) {
X		if (*tab < w->core.width)
X		    return *tab - x;
X		else
X		    return 0;
X	    }
X	}
X	return 0;
X    }
X    if (c == LF)
X	c = SP;
X    nonPrinting = (c < SP);
X    if (nonPrinting) c += '@';
X
X    if (font->per_char &&
X	    (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
X	width = font->per_char[c - font->min_char_or_byte2].width;
X    else
X	width = font->min_bounds.width;
X
X    if (nonPrinting)
X	width += CharWidth(w, x, '^');
X
X    return width;
X}
X
X/* Sink Object Functions */
X
Xstatic int AsciiDisplayText (w, x, y, pos1, pos2, highlight)
X  Widget w;
X  Position x, y;
X  int highlight;
X  XtTextPosition pos1, pos2;
X{
X    XtTextSink sink = ((TextWidget)w)->text.sink;
X    XtTextSource source = ((TextWidget)w)->text.source;
X    AsciiSinkData *data = (AsciiSinkData *) sink->data ;
X
X    XFontStruct *font = data->font;
X    int     j, k;
X    Dimension width;
X    XtTextBlock blk;
X    GC gc = highlight ? data->invgc : data->normgc;
X    GC invgc = highlight ? data->normgc : data->invgc;
X
X    y += font->ascent;
X    j = 0;
X    while (pos1 < pos2) {
X	pos1 = (*source->Read)(source, pos1, &blk, pos2 - pos1);
X	for (k = 0; k < blk.length; k++) {
X	    if (j >= bufferSize - 5) {
X		bufferSize *= 2;
X		buf = XtRealloc(buf, bufferSize);
X	    }
X	    buf[j] = blk.ptr[k];
X	    if (buf[j] == LF)
X		buf[j] = ' ';
X	    else if (buf[j] == '\t') {
X	        XDrawImageString(XtDisplay(w), XtWindow(w),
X			gc, x, y, buf, j);
X		buf[j] = 0;
X		x += XTextWidth(data->font, buf, j);
X		width = CharWidth(w, x, '\t');
X		XFillRectangle(XtDisplay(w), XtWindow(w), invgc, x,
X			       y - font->ascent, width,
X			       (Dimension) (data->font->ascent +
X					    data->font->descent));
X		x += width;
X		j = -1;
X	    }
X	    else
X		if (buf[j] < ' ') {
X		    buf[j + 1] = buf[j] + '@';
X		    buf[j] = '^';
X		    j++;
X		}
X	    j++;
X	}
X    }
X    XDrawImageString(XtDisplay(w), XtWindow(w), gc, x, y, buf, j);
X}
X
X
X#define insertCursor_width 6
X#define insertCursor_height 3
Xstatic char insertCursor_bits[] = {0x0c, 0x1e, 0x33};
X
X#ifdef SERVERNOTBROKEN
Xstatic Pixmap CreateInsertCursor(s)
XScreen *s;
X{
X    return (XCreateBitmapFromData (DisplayOfScreen(s), RootWindowOfScreen(s),
X        insertCursor_bits, insertCursor_width, insertCursor_height));
X}
X#endif
X
X/*
X * The following procedure manages the "insert" cursor.
X */
X
Xstatic AsciiInsertCursor (w, x, y, state)
X  Widget w;
X  Position x, y;
X  XtTextInsertState state;
X{
X    XtTextSink sink = ((TextWidget)w)->text.sink;
X    AsciiSinkData *data = (AsciiSinkData *) sink->data;
X
X/*
X    XCopyArea(sink->dpy,
X	      (state == XtisOn) ? data->insertCursorOn : data->insertCursorOff,
X	      w, data->normgc, 0, 0, insertCursor_width, insertCursor_height,
X	      x - (insertCursor_width >> 1), y - (insertCursor_height));
X*/
X
X    if (state != data->laststate && XtIsRealized(w)) {
X#ifdef SERVERNOTBROKEN
X	XCopyPlane(XtDisplay(w),
X		  data->insertCursorOn, XtWindow(w),
X		  data->xorgc, 0, 0, insertCursor_width, insertCursor_height,
X		  x - (insertCursor_width >> 1), y - (insertCursor_height), 1);
X#else /* SERVER is BROKEN */
X	/*
X	 * See the comment down at the bottom where the pixmap gets built
X	 * for why we are doing this this way.
X	 */
X	XCopyArea (XtDisplay(w), data->insertCursorOn, XtWindow (w),
X		   data->xorgc, 0, 0, insertCursor_width, insertCursor_height,
X		   x - (insertCursor_width >> 1), y - (insertCursor_height));
X#endif /* SERVERNOTBROKEN */
X    }
X    data->laststate = state;
X}
X
X/*
X * Clear the passed region to the background color.
X */
X
Xstatic AsciiClearToBackground (w, x, y, width, height)
X  Widget w;
X  Position x, y;
X  Dimension width, height;
X{
X#ifndef USE_CLEAR_AREA
X    XFillRectangle(XtDisplay(w), XtWindow(w),
X		   ((AsciiSinkData*)((TextWidget)w)->text.sink->data)->invgc,
X		   x, y, width, height);
X#else
X    XClearArea(XtDisplay(w), XtWindow(w), x, y, width, height, False);
X#endif /*USE_CLEAR_AREA*/
X}
X
X/*
X * Given two positions, find the distance between them.
X */
X
Xstatic AsciiFindDistance (w, fromPos, fromx, toPos,
X			  resWidth, resPos, resHeight)
X  Widget w;
X  XtTextPosition fromPos;	/* First position. */
X  int fromx;			/* Horizontal location of first position. */
X  XtTextPosition toPos;		/* Second position. */
X  int *resWidth;		/* Distance between fromPos and resPos. */
X  XtTextPosition *resPos;	/* Actual second position used. */
X  int *resHeight;		/* Height required. */
X{
X    XtTextSink sink = ((TextWidget)w)->text.sink;
X    XtTextSource source = ((TextWidget)w)->text.source;
X
X    AsciiSinkData *data;
X    register    XtTextPosition index, lastPos;
X    register char   c;
X    XtTextBlock blk;
X
X    data = (AsciiSinkData *) sink->data;
X    /* we may not need this */
X    lastPos = GETLASTPOS;
X    (*source->Read)(source, fromPos, &blk, toPos - fromPos);
X    *resWidth = 0;
X    for (index = fromPos; index != toPos && index < lastPos; index++) {
X	if (index - blk.firstPos >= blk.length)
X	    (*source->Read)(source, index, &blk, toPos - fromPos);
X	c = blk.ptr[index - blk.firstPos];
X	if (c == LF) {
X	    *resWidth += CharWidth(w, fromx + *resWidth, SP);
X	    index++;
X	    break;
X	}
X	*resWidth += CharWidth(w, fromx + *resWidth, c);
X    }
X    *resPos = index;
X    *resHeight = data->font->ascent + data->font->descent;
X}
X
X
Xstatic AsciiFindPosition(w, fromPos, fromx, width, stopAtWordBreak, 
X			 resPos, resWidth, resHeight)
X  Widget w;
X  XtTextPosition fromPos; 	/* Starting position. */
X  int fromx;			/* Horizontal location of starting position. */
X  int width;			/* Desired width. */
X  int stopAtWordBreak;		/* Whether the resulting position should be at
X				   a word break. */
X  XtTextPosition *resPos;	/* Resulting position. */
X  int *resWidth;		/* Actual width used. */
X  int *resHeight;		/* Height required. */
X{
X    XtTextSink sink = ((TextWidget)w)->text.sink;
X    XtTextSource source = ((TextWidget)w)->text.source;
X    AsciiSinkData *data;
X    XtTextPosition lastPos, index, whiteSpacePosition;
X    int     lastWidth, whiteSpaceWidth;
X    Boolean whiteSpaceSeen;
X    char    c;
X    XtTextBlock blk;
X    data = (AsciiSinkData *) sink->data;
X    lastPos = GETLASTPOS;
X
X    (*source->Read)(source, fromPos, &blk, bufferSize);
X    *resWidth = 0;
X    whiteSpaceSeen = FALSE;
X    c = 0;
X    for (index = fromPos; *resWidth <= width && index < lastPos; index++) {
X	lastWidth = *resWidth;
X	if (index - blk.firstPos >= blk.length)
X	    (*source->Read)(source, index, &blk, bufferSize);
X	c = blk.ptr[index - blk.firstPos];
X	if (c == LF) {
X	    *resWidth += CharWidth(w, fromx + *resWidth, SP);
X	    index++;
X	    break;
X	}
X	*resWidth += CharWidth(w, fromx + *resWidth, c);
X	if ((c == SP || c == TAB) && *resWidth <= width) {
X	    whiteSpaceSeen = TRUE;
X	    whiteSpacePosition = index;
X	    whiteSpaceWidth = *resWidth;
X	}
X    }
X    if (*resWidth > width && index > fromPos) {
X	*resWidth = lastWidth;
X	index--;
X	if (stopAtWordBreak && whiteSpaceSeen) {
X	    index = whiteSpacePosition + 1;
X	    *resWidth = whiteSpaceWidth;
X	}
X    }
X    if (index == lastPos && c != LF) index = lastPos + 1;
X    *resPos = index;
X    *resHeight = data->font->ascent + data->font->descent;
X}
X
X
Xstatic int AsciiResolveToPosition (w, pos, fromx, width,
X				   leftPos, rightPos)
X  Widget w;
X  XtTextPosition pos;
X  int fromx,width;
X  XtTextPosition *leftPos, *rightPos;
X{
X    int     resWidth, resHeight;
X    XtTextSource source = ((TextWidget)w)->text.source;
X
X    AsciiFindPosition(w, pos, fromx, width, FALSE,
X	    leftPos, &resWidth, &resHeight);
X    if (*leftPos > GETLASTPOS)
X	*leftPos = GETLASTPOS;
X    *rightPos = *leftPos;
X}
X
X
Xstatic int AsciiMaxLinesForHeight (w, height)
X  Widget w;
X  Dimension height;
X{
X    AsciiSinkData *data;
X    XtTextSink sink = ((TextWidget)w)->text.sink;
X
X    data = (AsciiSinkData *) sink->data;
X    return(height / (data->font->ascent + data->font->descent));
X}
X
X
Xstatic int AsciiMaxHeightForLines (w, lines)
X  Widget w;
X  int lines;
X{
X    AsciiSinkData *data;
X    XtTextSink sink = ((TextWidget)w)->text.sink;
X
X    data = (AsciiSinkData *) sink->data;
X    return(lines * (data->font->ascent + data->font->descent));
X}
X
X
Xstatic void AsciiSetTabs (w, offset, tab_count, tabs)
X  Widget w;			/* for context */
X  Position offset;		/* from left, for margin */
X  int tab_count;		/* count of entries in tabs */
X  Position *tabs;		/* list of character positions */
X{
X    AsciiSinkData *data = (AsciiSinkData*)((TextWidget)w)->text.sink->data;
X    int i;
X
X    if (tab_count > data->tab_count) {
X	data->tabs = (Position*)XtRealloc(data->tabs,
X				    (unsigned)tab_count * sizeof(Position*));
X    }
X    
X    for (i=0; i < tab_count; i++) {
X	data->tabs[i] = offset + tabs[i] * data->em;
X    }
X    data->tab_count = tab_count;
X}
X
X/***** Public routines *****/
X
XXtTextSink XtAsciiSinkCreate (parent, args, num_args)
X    Widget	parent;
X    ArgList 	args;
X    Cardinal 	num_args;
X{
X    XtTextSink sink;
X    AsciiSinkData *data;
X    unsigned long valuemask = (GCFont | GCGraphicsExposures |
X			       GCForeground | GCBackground | GCFunction);
X    XGCValues values;
X    long wid;
X    XFontStruct *font;
X
X    if (!buf) buf = XtMalloc(bufferSize);
X
X    sink = XtNew(XtTextSinkRec);
X    sink->Display = AsciiDisplayText;
X    sink->InsertCursor = AsciiInsertCursor;
X    sink->ClearToBackground = AsciiClearToBackground;
X    sink->FindPosition = AsciiFindPosition;
X    sink->FindDistance = AsciiFindDistance;
X    sink->Resolve = AsciiResolveToPosition;
X    sink->MaxLines = AsciiMaxLinesForHeight;
X    sink->MaxHeight = AsciiMaxHeightForLines;
X    sink->SetTabs = AsciiSetTabs;
X    data = XtNew(AsciiSinkData);
X    sink->data = (caddr_t)data;
X
X    XtGetSubresources (parent, (caddr_t)data, XtNtextSink, XtCTextSink, 
X		       SinkResources, XtNumber(SinkResources),
X		       args, num_args);
X
X    font = data->font;
X    values.function = GXcopy;
X    values.font = font->fid;
X    values.graphics_exposures = (Bool) FALSE;
X    values.foreground = data->foreground;
X    values.background = parent->core.background_pixel;
X    data->normgc = XtGetGC(parent, valuemask, &values);
X    values.foreground = parent->core.background_pixel;
X    values.background = data->foreground;
X    data->invgc = XtGetGC(parent, valuemask, &values);
X    values.function = GXxor;
X    values.foreground = data->foreground ^ parent->core.background_pixel;
X    values.background = 0;
X    data->xorgc = XtGetGC(parent, valuemask, &values);
X
X
X    wid = -1;
X    if ((!XGetFontProperty(font, XA_QUAD_WIDTH, &wid)) || wid <= 0) {
X	if (font->per_char && font->min_char_or_byte2 <= '0' &&
X	    		      font->max_char_or_byte2 >= '0')
X	    wid = font->per_char['0' - font->min_char_or_byte2].width;
X	else
X	    wid = font->max_bounds.width;
X    }
X    if (wid <= 0)
X	data->em = 1;
X    else
X	data->em = wid;
X
X    data->font = font;
X#ifdef SERVERNOTBROKEN
X    data->insertCursorOn = CreateInsertCursor(XtScreen(parent));
X#else
X    /*
X     * This is the work around for not being able to do CopyPlane with XOR.
X     * However, there is another bug which doesn't let us use the new
X     * CreatePixmapFromBitmapData routine to build the pixmap that we will
X     * use CopyArea with.
X     */
X#ifdef SERVERNOTBROKEN2
X    data->insertCursorOn =
X      XCreatePixmapFromBitmapData (XtDisplay (parent), 
X				   RootWindowOfScreen(XtScreen(parent)),
X				   insertCursor_bits, insertCursor_width,
X				   insertCursor_height, data->foreground,
X				   parent->core.background_pixel,
X				   parent->core.depth);
X#else /* SERVER is BROKEN the second way */
X    {
X	Screen *screen = XtScreen (parent);
X	Display *dpy = XtDisplay (parent);
X	Window root = RootWindowOfScreen(screen);
X	Pixmap bitmap = XCreateBitmapFromData (dpy, root, insertCursor_bits,
X					       insertCursor_width,
X					       insertCursor_height);
X	Pixmap pixmap = XCreatePixmap (dpy, root, insertCursor_width,
X				       insertCursor_height,
X				       DefaultDepthOfScreen (screen));
X	XGCValues gcv;
X	GC gc;
X
X	gcv.function = GXcopy;
X	gcv.foreground = data->foreground ^ parent->core.background_pixel;
X	gcv.background = 0;
X	gcv.graphics_exposures = False;
X	gc = XtGetGC (parent, (GCFunction | GCForeground | GCBackground |
X			       GCGraphicsExposures), &gcv);
X	XCopyPlane (dpy, bitmap, pixmap, gc, 0, 0, insertCursor_width,
X		    insertCursor_height, 0, 0, 1);
X	XtDestroyGC (gc);
X	data->insertCursorOn = pixmap;
X    }
X#endif /* SERVERNOTBROKEN2 */
X#endif /* SERVERNOTBROKEN */
X    data->laststate = XtisOff;
X    data->tab_count = 0;
X    data->tabs = NULL;
X    return sink;
X}
X
Xvoid XtAsciiSinkDestroy (sink)
X    XtTextSink sink;
X{
X    AsciiSinkData *data;
X
X    data = (AsciiSinkData *) sink->data;
X    XtFree((char *) data->tabs);
X    XtFree((char *) data);
X    XtFree((char *) sink);
X}
END_OF_FILE
if test 15302 -ne `wc -c <'xconf/AsciiSink.c'`; then
    echo shar: \"'xconf/AsciiSink.c'\" unpacked with wrong size!
fi
# end of 'xconf/AsciiSink.c'
fi
if test -f 'xconf/GCManager.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xconf/GCManager.c'\"
else
echo shar: Extracting \"'xconf/GCManager.c'\" \(6869 characters\)
sed "s/^X//" >'xconf/GCManager.c' <<'END_OF_FILE'
X#ifndef lint
Xstatic char Xrcsid[] = "$XConsortium: GCManager.c,v 1.31 88/09/06 16:27:54 jim Exp $";
X/* $oHeader: GCManager.c,v 1.4 88/08/19 14:19:51 asente Exp $ */
X#endif lint
X
X/***********************************************************
XCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
Xand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
X
X                        All Rights Reserved
X
XPermission to use, copy, modify, and distribute this software and its 
Xdocumentation for any purpose and without fee is hereby granted, 
Xprovided that the above copyright notice appear in all copies and that
Xboth that copyright notice and this permission notice appear in 
Xsupporting documentation, and that the names of Digital or MIT not be
Xused in advertising or publicity pertaining to distribution of the
Xsoftware without specific, written prior permission.  
X
XDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
XDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
XSOFTWARE.
X
X******************************************************************/
X
X#include <stdio.h>
X#include "IntrinsicI.h"
X
X
Xtypedef struct _GCrec {
X    Display	*dpy;		/* Display for GC */
X    Screen	*screen;	/* Screen for GC */
X    Cardinal	depth;		/* Depth for GC */
X    Cardinal    ref_count;      /* # of shareholders */
X    GC 		gc;		/* The GC itself. */
X    XtValueMask	valueMask;	/* What fields are being used right now. */
X    XGCValues 	values;		/* What values those fields have. */
X    struct _GCrec *next;	/* Next GC for this widgetkind. */
X} GCrec, *GCptr;
X
Xstatic Drawable GCparents[256]; /* static initialized to zero, K&R ss 4.9 */
Xstatic GCrec    *GClist = NULL;
X
Xstatic Bool Matches(ptr, valueMask, v)
X	     GCptr	    ptr;
X    register XtValueMask    valueMask;
X    register XGCValues      *v;
X{
X    register XGCValues      *p = &(ptr->values);
X
X#define CheckGCField(MaskBit,fieldName) \
X    if ((valueMask & MaskBit) && (p->fieldName != v->fieldName)) return False
X
X    /* Check most common fields specified for GCs first */
X    CheckGCField( GCForeground,		foreground);
X    CheckGCField( GCBackground,		background);
X    CheckGCField( GCFont,		font);
X    CheckGCField( GCFillStyle,		fill_style);
X    CheckGCField( GCLineWidth,		line_width);
X    /* Are we done yet ? */
X    if (! (valueMask
X        & ~(GCForeground | GCBackground | GCFont | GCFillStyle | GCLineWidth)))
X	return True;
X
X    /* Check next most common */
X    CheckGCField( GCFunction,		function);
X    CheckGCField( GCGraphicsExposures,	graphics_exposures);
X    CheckGCField( GCTile,		tile);
X    CheckGCField( GCSubwindowMode,	subwindow_mode);
X    CheckGCField( GCPlaneMask,		plane_mask);
X    /* Now are we done ? */
X    if (! (valueMask
X         & ~(GCForeground | GCBackground | GCFont | GCFillStyle | GCLineWidth
X	    | GCFunction | GCGraphicsExposures | GCTile | GCSubwindowMode
X	    | GCPlaneMask))) return True;
X
X    CheckGCField( GCLineStyle,		line_style);
X    CheckGCField( GCCapStyle,		cap_style);
X    CheckGCField( GCJoinStyle,		join_style);
X    CheckGCField( GCFillRule,		fill_rule);
X    CheckGCField( GCArcMode,		arc_mode);
X    CheckGCField( GCStipple,		stipple);
X    CheckGCField( GCTileStipXOrigin,	ts_x_origin);
X    CheckGCField( GCTileStipYOrigin,	ts_y_origin);
X    CheckGCField( GCClipXOrigin,	clip_x_origin);
X    CheckGCField( GCClipYOrigin,	clip_y_origin);
X    CheckGCField( GCClipMask,		clip_mask);
X    CheckGCField( GCDashOffset,		dash_offset);
X    CheckGCField( GCDashList,		dashes);
X#undef CheckGCField
X    return True;
X} /* Matches */
X
X
X/* 
X * Return a read-only GC with the given values.  
X */
X
XGC XtGetGC(widget, valueMask, values)
X	     Widget	widget;
X    register XtGCMask	valueMask;
X	     XGCValues	*values;
X{
X	     GCptr      prev;
X    register GCptr      cur;
X    register Cardinal   depth   = widget->core.depth;
X    register Screen     *screen = XtScreen(widget);
X	     Drawable   drawable;
X    register Display 	*dpy = XtDisplay(widget);
X
X    /* Search for existing GC that matches exactly */
X    for (cur = GClist, prev = NULL; cur != NULL; prev = cur, cur = cur->next) {
X	if (cur->valueMask == valueMask && cur->depth == depth
X		&& cur->screen == screen && cur->dpy == dpy
X		&& Matches(cur, valueMask, values)) {
X            cur->ref_count++;
X	    /* Move this GC to front of list if not already there */
X	    if (prev != NULL) {
X		prev->next = cur->next;
X		cur->next = GClist;
X		GClist = cur;
X	    }
X	    return cur->gc;
X	}
X    }
X
X    /* No matches, have to create a new one */
X    cur		= XtNew(GCrec);
X    cur->next   = GClist;
X    GClist      = cur;
X
X    cur->dpy	    = XtDisplay(widget);
X    cur->screen     = screen;
X    cur->depth      = depth;
X    cur->ref_count  = 1;
X    cur->valueMask  = valueMask;
X    cur->values     = *values;
X    if (XtWindow(widget) == NULL) {
X	/* Have to create a bogus pixmap for the GC.  Stupid X protocol. */
X#ifdef JON
X	if (depth == DefaultDepthOfScreen(screen))
X                drawable = RootWindowOfScreen(screen);
X            else
X                drawable = XCreatePixmap(cur->dpy, screen->root, 1, 1,
Xdepth);
X#else
X	if (GCparents[depth] != 0) {
X	    drawable = GCparents[depth];
X        } else {
X	    if (depth == DefaultDepthOfScreen(screen))
X		drawable = RootWindowOfScreen(screen);
X	    else 
X		drawable = XCreatePixmap(cur->dpy, screen->root, 1, 1, depth);
X           GCparents[depth] = drawable;
X        }
X#endif
X    } else {
X	drawable = XtWindow(widget);
X    }
X    cur->gc = XCreateGC(cur->dpy, drawable, valueMask, values);
X    return cur->gc;
X} /* XtGetGC */
X
Xvoid  XtReleaseGC(widget, gc)
X    Widget   widget;
X    GC      gc;
X{
X    register GCptr cur, prev;
X    
X    for (cur = GClist, prev = NULL; cur != NULL; prev = cur, cur = cur->next) {
X	if (cur->gc == gc && cur->dpy == XtDisplay(widget)) {
X	    if (--(cur->ref_count) == 0) {
X		if (prev != NULL) prev->next = cur->next;
X		else GClist = cur->next;
X		XFreeGC(cur->dpy, gc);
X		XtFree((char *) cur);
X		break;
X	    }
X	}
X    }
X} /* XtReleaseGC */
X
X/*  The following interface is broken and supplied only for backwards
X *  compatibility.  It will work properly in all cases only if there
X *  is exactly 1 Display created by the application.
X */
X
Xvoid XtDestroyGC(gc)
X    GC      gc;
X{
X    register GCptr cur, prev;
X    
X    for (cur = GClist, prev = NULL; cur != NULL; prev = cur, cur = cur->next) {
X	if (cur->gc == gc) {
X	    if (--(cur->ref_count) == 0) {
X		if (prev != NULL) prev->next = cur->next;
X		else GClist = cur->next;
X		XFreeGC(cur->dpy, gc);
X		XtFree((char *) cur);
X		break;
X	    }
X	}
X    }
X} /* XtDestroyGC */
END_OF_FILE
if test 6869 -ne `wc -c <'xconf/GCManager.c'`; then
    echo shar: \"'xconf/GCManager.c'\" unpacked with wrong size!
fi
# end of 'xconf/GCManager.c'
fi
if test -f 'xconf/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xconf/Makefile'\"
else
echo shar: Extracting \"'xconf/Makefile'\" \(437 characters\)
sed "s/^X//" >'xconf/Makefile' <<'END_OF_FILE'
XH = AsciiText.h Text.h TextSrcP.h AsciiTextP.h TextP.h xconf.h
XS = xconf.c ru.c Text.c AsciiText.c
XO = xconf.o ru.o Text.o AsciiText.o AsciiSink.o  \
X	StringSrc.o DiskSrc.o \
X	Dialog.o  \
X	GCManager.o Converters.o 
XL = -lXaw -lXt -lXmu -lX11 -lrpcsvc
XCFLAGS = -I/usr/src/X11R3/lib/Xt -DJON -DDEBUG -DJOKE -DEXPTL -DSUNRPC -g
X
Xall:	xconf
X
Xxconf:	$O $H
X	cc $(CFLAGS) -o xconf $O $L
X
Xlint:	$S
X	lint -I/usr/ucl/include -DJON -DDEBUG xconf.c
END_OF_FILE
if test 437 -ne `wc -c <'xconf/Makefile'`; then
    echo shar: \"'xconf/Makefile'\" unpacked with wrong size!
fi
# end of 'xconf/Makefile'
fi
if test -f 'xconf/Text.c.ab' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xconf/Text.c.ab'\"
else
echo shar: Extracting \"'xconf/Text.c.ab'\" \(29444 characters\)
sed "s/^X//" >'xconf/Text.c.ab' <<'END_OF_FILE'
X    if (visible) {
X	XtTextLineTableEntry *thisLine, *nextLine = ctx->text.lt.info + line1;
X	Boolean resizeable = ctx->text.options & resizeWidth;
X	Boolean wordwrap = ctx->text.options & wordBreak;
X	int (*FindPosition)() = ctx->text.sink->FindPosition;
X	int (*ClearToBackground)() = ctx->text.sink->ClearToBackground;
X	register XtTextPosition lastPos = ctx->text.lastPos;
X	for (i = line1; i < ctx->text.lt.lines; i++) {/* fixup line table */
X	    thisLine = nextLine++;
X	    width = resizeable ? BIGNUM : ctx->core.width - x;
X	    if (startPos <= lastPos) {
X		(*FindPosition)(ctx, startPos, x, width, wordwrap,
X				&endPos, &realW, &realH);
X		if (!wordwrap && endPos < lastPos) {
X		    /* if not wordBreak, skip remainder of this line */
X		    endPos = (*Scan)(ctx->text.source, startPos,
X				     XtstEOL, XtsdRight, 1, TRUE);
X		    if (endPos == startPos)
X			endPos = lastPos + 1;
X		}
X		thisLine->endX = x + realW;
X		nextLine->y = thisLine->y + realH;
X		if ((endPos > pos1) && (endPos == nextLine->position))
X		    break;	/* %%% why not update remaining y's? */
X		startPos = endPos;
X	    }
X	    if (startPos > lastPos) {
X		if (nextLine->position <= lastPos) {
X		    (*ClearToBackground) (ctx, nextLine->x, nextLine->y,
X					  nextLine->endX,
X					  (nextLine+1)->y - nextLine->y);
X		}
X		nextLine->endX = ctx->text.leftmargin;
X	    }
X	    nextLine->position = startPos;
X	    x = nextLine->x;
X	}
X	if (delta >= lastPos)
X	    endPos = lastPos;
X	if (endPos < pos2)	/* might scroll if word wrapped off bottom */
X	    endPos = pos2;
X	if (endPos > lastPos && delta > 0)
X	    endPos = lastPos;	/* optimize insert at end; don't clear below */
X	if (pos2 >= ctx->text.lt.top || delta >= lastPos)
X	    _XtTextNeedsUpdating(ctx, updateFrom, endPos);
X    }
X    SetScrollBar(ctx);
X    return error;
X}
X
X
X/*
X * This routine will display text between two arbitrary source positions.
X * In the event that this span contains highlighted text for the selection, 
X * only that portion will be displayed highlighted.
X */
Xstatic void DisplayText(w, pos1, pos2)
X  Widget w;
X  XtTextPosition pos1, pos2;
X  /* it is illegal to call this routine unless there is a valid line table! */
X{
X    TextWidget ctx = (TextWidget)w;
X    Position x, y;
X    int height;
X    int line, i, visible;
X    XtTextPosition startPos, endPos;
X    int lastPos = ctx->text.lastPos;
X    Boolean clear_eol;
X    Boolean clear_eos = True;
X
X    if (pos1 < ctx->text.lt.top)
X	pos1 = ctx->text.lt.top;
X    if (pos2 > ctx->text.lastPos)
X	pos2 = ctx->text.lastPos;
X    else if (pos2 == ctx->text.lastPos)
X	clear_eos = False;
X    if (pos1 >= pos2) return;
X    visible = LineAndXYForPosition(ctx, pos1, &line, &x, &y);
X    if (!visible)
X	return;
X    startPos = pos1;
X    for (i = line; i < ctx->text.lt.lines; i++) {
X	endPos = ctx->text.lt.info[i + 1].position;
X	if (endPos > pos2) {
X	    if (endPos >= lastPos)
X		clear_eol = True;
X	    else
X		clear_eol = False;
X	    endPos = pos2;
X	}
X	else clear_eol = True;
X	height = ctx->text.lt.info[i + 1].y - ctx->text.lt.info[i].y;
X	if (endPos > startPos) {
X	    if (x == ctx->text.leftmargin)
X                (*ctx->text.sink->ClearToBackground)
X		    (w, 0, y, ctx->text.leftmargin, height);
X	    if (startPos >= ctx->text.s.right || endPos <= ctx->text.s.left) {
X		(*ctx->text.sink->Display) (w, x, y, startPos, endPos, FALSE);
X	    } else if (startPos >= ctx->text.s.left && endPos <= ctx->text.s.right) {
X		(*ctx->text.sink->Display) (w, x, y, startPos, endPos, TRUE);
X	    } else {
X		DisplayText(w, startPos, ctx->text.s.left);
X		DisplayText(w, max(startPos, ctx->text.s.left), 
X			    min(endPos, ctx->text.s.right));
X		DisplayText(w, ctx->text.s.right, endPos);
X	    }
X	}
X	startPos = endPos;
X	if (clear_eol)
X	    (*ctx->text.sink->ClearToBackground)(ctx,
X		ctx->text.lt.info[i].endX, y, (int)ctx->core.width, height);
X	x = ctx->text.leftmargin;
X	y = ctx->text.lt.info[i + 1].y;
X	if ((endPos == pos2) && !clear_eos)
X	    break;
X    }
X}
X
X/*
X * This routine implements multi-click selection in a hardwired manner.
X * It supports multi-click entity cycling (char, word, line, file) and mouse
X * motion adjustment of the selected entitie (i.e. select a word then, with
X * button still down, adjust wich word you really meant by moving the mouse).
X * [NOTE: This routine is to be replaced by a set of procedures that
X * will allows clients to implements a wide class of draw through and
X * multi-click selection user interfaces.]
X*/
Xstatic void DoSelection (ctx, position, time, motion)
X  TextWidget ctx;
X  XtTextPosition position;
X  Time time;
X  Boolean motion;
X{
X    int     delta;
X    XtTextPosition newLeft, newRight;
X    XtTextSelectType newType;
X    XtTextSelectType *sarray;
X
X    delta = (time < ctx->text.lasttime) ?
X	ctx->text.lasttime - time : time - ctx->text.lasttime;
X    if (motion)
X	newType = ctx->text.s.type;
X    else {
X	if ((delta < 500) && ((position >= ctx->text.s.left)
X		    && (position <= ctx->text.s.right))) { /* multi-click event */
X	    for (sarray = ctx->text.sarray;
X		*sarray != XtselectNull && *sarray != ctx->text.s.type;
X		sarray++) ;
X	    if (*sarray != XtselectNull) sarray++;
X	    if (*sarray == XtselectNull) sarray = ctx->text.sarray;
X	    newType = *sarray;
X	} else {			/* single-click event */
X	    newType = *(ctx->text.sarray);
X	}
X        ctx->text.lasttime = time;
X    }
X    switch (newType) {
X	case XtselectPosition: 
X            newLeft = newRight = position;
X	    break;
X	case XtselectChar: 
X            newLeft = position;
X            newRight = (*ctx->text.source->Scan)(
X                    ctx->text.source, position, position, XtsdRight, 1, FALSE);
X	    break;
X	case XtselectWord: 
X	    newLeft = (*ctx->text.source->Scan)(
X		    ctx->text.source, position, XtstWhiteSpace, XtsdLeft, 1, FALSE);
X	    newRight = (*ctx->text.source->Scan)(
X		    ctx->text.source, position, XtstWhiteSpace, XtsdRight, 1, FALSE);
X	    break;
X	case XtselectLine: 
X	case XtselectParagraph:  /* need "para" scan mode to implement pargraph */
X 	    newLeft = (*ctx->text.source->Scan)(
X		    ctx->text.source, position, XtstEOL, XtsdLeft, 1, FALSE);
X	    newRight = (*ctx->text.source->Scan)(
X		    ctx->text.source, position, XtstEOL, XtsdRight, 1, FALSE);
X	    break;
X	case XtselectAll: 
X	    newLeft = (*ctx->text.source->Scan)(
X		    ctx->text.source, position, XtstAll, XtsdLeft, 1, FALSE);
X	    newRight = (*ctx->text.source->Scan)(
X		    ctx->text.source, position, XtstAll, XtsdRight, 1, FALSE);
X	    break;
X    }
X    if ((newLeft != ctx->text.s.left) || (newRight != ctx->text.s.right)
X	    || (newType != ctx->text.s.type)) {
X	_XtTextSetNewSelection(ctx, newLeft, newRight, NULL, ZERO);
X	ctx->text.s.type = newType;
X	if (position - ctx->text.s.left < ctx->text.s.right - position)
X	    ctx->text.insertPos = newLeft;
X	else 
X	    ctx->text.insertPos = newRight;
X    }
X    if (!motion) { /* setup so we can freely mix select extend calls*/
X	ctx->text.origSel.type = ctx->text.s.type;
X	ctx->text.origSel.left = ctx->text.s.left;
X	ctx->text.origSel.right = ctx->text.s.right;
X	if (position >= ctx->text.s.left + ((ctx->text.s.right - ctx->text.s.left) / 2))
X	    ctx->text.extendDir = XtsdRight;
X	else
X	    ctx->text.extendDir = XtsdLeft;
X    }
X}
X
X/*
X * This routine implements extension of the currently selected text in
X * the "current" mode (i.e. char word, line, etc.). It worries about
X * extending from either end of the selection and handles the case when you
X * cross through the "center" of the current selection (e.g. switch which
X * end you are extending!).
X * [NOTE: This routine will be replaced by a set of procedures that
X * will allows clients to implements a wide class of draw through and
X * multi-click selection user interfaces.]
X*/
Xstatic void ExtendSelection (ctx, position, motion)
X  TextWidget ctx;
X  XtTextPosition position;
X  Boolean motion;
X{
X    XtTextPosition newLeft, newRight;
X	
X
X    if (!motion) {		/* setup for extending selection */
X	ctx->text.origSel.type = ctx->text.s.type;
X	ctx->text.origSel.left = ctx->text.s.left;
X	ctx->text.origSel.right = ctx->text.s.right;
X	if (position >= ctx->text.s.left + ((ctx->text.s.right - ctx->text.s.left) / 2))
X	    ctx->text.extendDir = XtsdRight;
X	else
X	    ctx->text.extendDir = XtsdLeft;
X    }
X    else /* check for change in extend direction */
X	if ((ctx->text.extendDir == XtsdRight && position < ctx->text.origSel.left) ||
X		(ctx->text.extendDir == XtsdLeft && position > ctx->text.origSel.right)) {
X	    ctx->text.extendDir = (ctx->text.extendDir == XtsdRight)? XtsdLeft : XtsdRight;
X	    _XtTextSetNewSelection(ctx, ctx->text.origSel.left, ctx->text.origSel.right, NULL, ZERO);
X	}
X    newLeft = ctx->text.s.left;
X    newRight = ctx->text.s.right;
X    switch (ctx->text.s.type) {
X	case XtselectPosition: 
X	    if (ctx->text.extendDir == XtsdRight)
X		newRight = position;
X	    else
X		newLeft = position;
X	    break;
X	case XtselectWord: 
X	    if (ctx->text.extendDir == XtsdRight)
X		newRight = position = (*ctx->text.source->Scan)(
X			ctx->text.source, position, XtstWhiteSpace, XtsdRight, 1, FALSE);
X	    else
X		newLeft = position = (*ctx->text.source->Scan)(
X			ctx->text.source, position, XtstWhiteSpace, XtsdLeft, 1, FALSE);
X	    break;
X        case XtselectLine:
X	case XtselectParagraph: /* need "para" scan mode to implement pargraph */
X	    if (ctx->text.extendDir == XtsdRight)
X		newRight = position = (*ctx->text.source->Scan)(
X			ctx->text.source, position, XtstEOL, XtsdRight, 1, TRUE);
X	    else
X		newLeft = position = (*ctx->text.source->Scan)(
X			ctx->text.source, position, XtstEOL, XtsdLeft, 1, FALSE);
X	    break;
X	case XtselectAll: 
X	    position = ctx->text.insertPos;
X	    break;
X    }
X    _XtTextSetNewSelection(ctx, newLeft, newRight, NULL, ZERO);
X    ctx->text.insertPos = position;
X}
X
X
X/*
X * Clear the window to background color.
X */
Xstatic ClearWindow (w)
X  Widget w;
X{
X    if (XtIsRealized(w))
X	(*((TextWidget)w)->text.sink->
X	 ClearToBackground) (w, 0, 0, (int)w->core.width, (int)w->core.height);
X}
X
X
X/*
X * Internal redisplay entire window.
X * Legal to call only if widget is realized.
X */
XDisplayTextWindow (w)
X  Widget w;
X{
X    TextWidget ctx = (TextWidget) w;
X    ClearWindow(w);
X    BuildLineTable(ctx, ctx->text.lt.top);
X    _XtTextNeedsUpdating(ctx, zeroPosition, ctx->text.lastPos);
X    SetScrollBar(ctx);
X}
X
X/*
X * This routine checks to see if the window should be resized (grown or
X * shrunk) or scrolled when text to be painted overflows to the right or
X * the bottom of the window. It is used by the keyboard input routine.
X*/
Xstatic CheckResizeOrOverflow(ctx)
X  TextWidget ctx;
X{
X    XtTextPosition posToCheck;
X    int     visible, line, width;
X    XtWidgetGeometry rbox;
X    XtGeometryResult reply;
X    register int options = ctx->text.options;
X
X    if (options & resizeWidth) {
X	XtTextLineTableEntry *lt;
X	width = 0;
X	for (line=0, lt=ctx->text.lt.info; line<ctx->text.lt.lines; line++) {
X	    if (width < lt->endX)
X		width = lt->endX;
X	    lt++;
X	}
X	if (width > ctx->core.width) {
X	    rbox.request_mode = CWWidth;
X	    rbox.width = width;
X	    reply = XtMakeGeometryRequest((Widget)ctx, &rbox, &rbox);
X	    if (reply == XtGeometryAlmost)
X	        reply = XtMakeGeometryRequest((Widget)ctx, &rbox, NULL);
X	}
X    }
X    if ((options & resizeHeight) || (options & scrollOnOverflow)) {
X	if (options & scrollOnOverflow)
X	    posToCheck = ctx->text.insertPos;
X	else
X	    posToCheck = ctx->text.lastPos;
X	visible = IsPositionVisible(ctx, posToCheck);
X	if (visible)
X	    line = LineForPosition(ctx, posToCheck);
X	else
X	    line = ctx->text.lt.lines;
X	if ((options & scrollOnOverflow) && (line + 1 > ctx->text.lt.lines)) {
X	    BuildLineTable(ctx, ctx->text.lt.info[1].position);
X	    XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx),
X		      ctx->text.gc, (int)ctx->text.leftmargin, 
X		      (int)ctx->text.lt.info[1].y,
X		      (int)ctx->core.width, (int)ctx->core.height,
X		      (int)ctx->text.leftmargin, ctx->text.lt.info[0].y);
X	}
X	else
X	    if ((options & resizeHeight) && (line + 1 != ctx->text.lt.lines)) {
X		int oldHeight = ctx->core.height;
X		rbox.request_mode = CWHeight;
X		rbox.height = (*ctx->text.sink->MaxHeight)
X				(ctx, line + 1) + (2*yMargin)+2;
X		reply = XtMakeGeometryRequest(ctx, &rbox, &rbox);
X		if (reply == XtGeometryAlmost)
X		    reply = XtMakeGeometryRequest((Widget)ctx, &rbox, NULL);
X		if (reply == XtGeometryYes) {
X		    BuildLineTable(ctx, ctx->text.lt.top);
X		    if (!(options & wordBreak) /* if NorthEastGravity */
X			&& rbox.height < oldHeight) {
X			/* clear cruft from bottom margin */
X			(*ctx->text.sink->ClearToBackground)
X			    (ctx, ctx->text.leftmargin,
X			     ctx->text.lt.info[ctx->text.lt.lines].y,
X			     (int)ctx->core.width, oldHeight - rbox.height);
X		    }
X		}
X	    }
X    }
X}
X
Xstatic Atom* _SelectionList(ctx, params, num_params)
X  TextWidget ctx;
X  String *params;
X  Cardinal num_params;
X{
X    /* converts (params, num_params) to a list of atoms & caches the
X     * list in the TextWidget instance.
X     */
X
X    if (num_params > ctx->text.s.array_size) {
X	ctx->text.s.selections =
X	    (Atom*)XtRealloc(ctx->text.s.selections, num_params*sizeof(Atom));
X	ctx->text.s.array_size = num_params;
X    }
X    XmuInternStrings( XtDisplay((Widget)ctx), params, num_params,
X		      ctx->text.s.selections );
X    ctx->text.s.atom_count = num_params;
X    return ctx->text.s.selections;
X}
X
X
X/*
X * This routine is used to perform various selection functions. The goal is
X * to be able to specify all the more popular forms of draw-through and
X * multi-click selection user interfaces from the outside.
X */
Xvoid AlterSelection (ctx, mode, action, params, num_params)
X    TextWidget     ctx;
X    XtTextSelectionMode   mode;	/* {XtsmTextSelect, XtsmTextExtend} */
X    XtTextSelectionAction action; /* {XtactionStart, XtactionAdjust, XtactionEnd} */
X    String	*params;
X    Cardinal	*num_params;
X{
X    XtTextPosition position;
X
X    position = PositionForXY (ctx, (int) ctx->text.ev_x, (int) ctx->text.ev_y);
X    if (action == XtactionStart) {
X	switch (mode) {
X	case XtsmTextSelect: 
X	    DoSelection (ctx, position, ctx->text.time, FALSE);
X	    break;
X	case XtsmTextExtend: 
X	    ExtendSelection (ctx, position, FALSE);
X	    break;
X	}
X    }
X    else {
X	switch (mode) {
X	case XtsmTextSelect: 
X	    DoSelection (ctx, position, ctx->text.time, TRUE);
X	    break;
X	case XtsmTextExtend: 
X	    ExtendSelection (ctx, position, TRUE);
X	    break;
X	}
X    }
X    if (action == XtactionEnd) {
X	if (ctx->text.s.left < ctx->text.s.right) {
X	    Cardinal count = *num_params;
X	    if (count == 0) {
X		static String defaultSelection = "CUT_BUFFER0";
X		params = &defaultSelection;
X		count = 1;
X	    }
X	    _XtTextSetNewSelection(
X		   ctx, ctx->text.s.left, ctx->text.s.right,
X		   _SelectionList(ctx, params, count),
X		   count );
X	}
X	else XtTextUnsetSelection((Widget)ctx);
X    }
X}
X
X/*
X * This routine processes all "expose region" XEvents. In general, its job
X * is to the best job at minimal re-paint of the text, displayed in the
X * window, that it can.
X*/
Xstatic void ProcessExposeRegion(w, event)
X  Widget w;
X  XEvent *event;
X{
X    TextWidget ctx = (TextWidget) w;
X    XtTextPosition pos1, pos2, resultend;
X    int line;
X    int x = event->xexpose.x;
X    int y = event->xexpose.y;
X    int width = event->xexpose.width;
X    int height = event->xexpose.height;
X    XtTextLineTableEntry *info;
X
X   _XtTextPrepareToUpdate(ctx);
X    if (x < ctx->text.leftmargin) /* stomp on caret tracks */
X        (*ctx->text.sink->ClearToBackground)(ctx, x, y, width, height);
X   /* figure out starting line that was exposed */
X    line = LineForPosition(ctx, PositionForXY(ctx, x, y));
X    while (line < ctx->text.lt.lines && ctx->text.lt.info[line + 1].y < y)
X	line++;
X    while (line < ctx->text.lt.lines) {
X	info = &(ctx->text.lt.info[line]);
X	if (info->y >= y + height)
X	    break;
X	(*ctx->text.sink->Resolve)(ctx, 
X                                info->position, info->x,
X			        x - info->x, &pos1, &resultend);
X	(*ctx->text.sink->Resolve)(ctx, 
X                                info->position, info->x,
X			        x + width - info->x, &pos2, 
X                                &resultend);
X	pos2 = (*ctx->text.source->Scan)(ctx->text.source, pos2, XtstPositions, 
X                                      XtsdRight, 1, TRUE);
X	_XtTextNeedsUpdating(ctx, pos1, pos2);
X	line++;
X    }
X    _XtTextExecuteUpdate(ctx);
X}
X
X/*
X * This routine does all setup required to syncronize batched screen updates
X*/
Xint _XtTextPrepareToUpdate(ctx)
X  TextWidget ctx;
X{
X    if (ctx->text.old_insert < 0) {
X	InsertCursor((Widget)ctx, XtisOff);
X	ctx->text.numranges = 0;
X	ctx->text.showposition = FALSE;
X	ctx->text.old_insert = ctx->text.insertPos;
X    }
X}
X
X
X/*
X * This is a private utility routine used by _XtTextExecuteUpdate. It
X * processes all the outstanding update requests and merges update
X * ranges where possible.
X*/
Xstatic void FlushUpdate(ctx)
X  TextWidget ctx;
X{
X    int     i, w;
X    XtTextPosition updateFrom, updateTo;
X    if (!XtIsRealized((Widget)ctx)) {
X	ctx->text.numranges = 0;
X	return;
X    }
X    while (ctx->text.numranges > 0) {
X	updateFrom = ctx->text.updateFrom[0];
X	w = 0;
X	for (i=1 ; i<ctx->text.numranges ; i++) {
X	    if (ctx->text.updateFrom[i] < updateFrom) {
X		updateFrom = ctx->text.updateFrom[i];
X		w = i;
X	    }
X	}
X	updateTo = ctx->text.updateTo[w];
X	ctx->text.numranges--;
X	ctx->text.updateFrom[w] = ctx->text.updateFrom[ctx->text.numranges];
X	ctx->text.updateTo[w] = ctx->text.updateTo[ctx->text.numranges];
X	for (i=ctx->text.numranges-1 ; i>=0 ; i--) {
X	    while (ctx->text.updateFrom[i] <= updateTo && i < ctx->text.numranges) {
X		updateTo = ctx->text.updateTo[i];
X		ctx->text.numranges--;
X		ctx->text.updateFrom[i] = ctx->text.updateFrom[ctx->text.numranges];
X		ctx->text.updateTo[i] = ctx->text.updateTo[ctx->text.numranges];
X	    }
X	}
X	DisplayText((Widget)ctx, updateFrom, updateTo);
X    }
X}
X
X
X/*
X * This is a private utility routine used by _XtTextExecuteUpdate. This routine
X * worries about edits causing new data or the insertion point becoming
X * invisible (off the screen). Currently it always makes it visible by
X * scrolling. It probably needs generalization to allow more options.
X*/
X_XtTextShowPosition(ctx)
X  TextWidget ctx;
X{
X    XtTextPosition top, first, second;
X    if (!XtIsRealized((Widget)ctx)) return;
X    if (ctx->text.insertPos < ctx->text.lt.top ||
X	ctx->text.insertPos >= ctx->text.lt.info[ctx->text.lt.lines].position) {
X	if (ctx->text.lt.lines > 0 && (ctx->text.insertPos < ctx->text.lt.top 
X	    || ctx->text.lt.info[ctx->text.lt.lines].position <= ctx->text.lastPos)) {
X	    first = ctx->text.lt.top;
X	    second = ctx->text.lt.info[1].position;
X	    if (ctx->text.insertPos < first)
X		top = (*ctx->text.source->Scan)(
X			ctx->text.source, ctx->text.insertPos, XtstEOL,
X			XtsdLeft, 1, FALSE);
X	    else
X		top = (*ctx->text.source->Scan)(
X			ctx->text.source, ctx->text.insertPos, XtstEOL,
X			XtsdLeft, ctx->text.lt.lines, FALSE);
X	    BuildLineTable(ctx, top);
X	    while (ctx->text.insertPos >= ctx->text.lt.info[ctx->text.lt.lines].position) {
X		if (ctx->text.lt.info[ctx->text.lt.lines].position > ctx->text.lastPos)
X		    break;
X		BuildLineTable(ctx, ctx->text.lt.info[1].position);
X	    }
X	    if (ctx->text.lt.top == second) {
X	        BuildLineTable(ctx, first);
X		_XtTextScroll(ctx, 1);
X	    } else if (ctx->text.lt.info[1].position == first) {
X		BuildLineTable(ctx, first);
X		_XtTextScroll(ctx, -1);
X	    } else {
X		ctx->text.numranges = 0;
X		if (ctx->text.lt.top != first)
X		    DisplayTextWindow((Widget)ctx);
X	    }
X	}
X    }
X}
X
X
X
X/*
X * This routine causes all batched screen updates to be performed
X*/
X_XtTextExecuteUpdate(ctx)
X  TextWidget ctx;
X{
X    if (ctx->text.update_disabled) return;
X
X    if (ctx->text.old_insert >= 0) {
X	if (ctx->text.old_insert != ctx->text.insertPos
X	    || ctx->text.showposition)
X	    _XtTextShowPosition(ctx);
X	FlushUpdate(ctx);
X	InsertCursor((Widget)ctx, XtisOn);
X	ctx->text.old_insert = -1;
X    }
X}
X
X
Xstatic void TextDestroy(w)
X    Widget w;
X{
X    TextWidget ctx = (TextWidget)w;
X    register struct _dialog *dialog, *next;
X
X    for (dialog = ctx->text.dialog; dialog; dialog = next) {
X	/* no need to destroy the widgets here; they should go automatically */
X	next = dialog->next;
X	XtFree( dialog );
X    }
X    if (ctx->text.outer)
X	(void) XtDestroyWidget(ctx->text.outer);
X    if (ctx->text.sbar)
X	(void) XtDestroyWidget(ctx->text.sbar);
X    XtFree((char *)ctx->text.updateFrom);
X    XtFree((char *)ctx->text.updateTo);
X}
X
X
X/* by the time we are managed (and get this far),
X * we had better have both a source and a sink */
Xstatic void Resize(w)
X    Widget          w;
X{
X    TextWidget ctx = (TextWidget) w;
X
X    if (ctx->text.sbar) {
X	Widget sbar = ctx->text.sbar;
X	XtResizeWidget( sbar, sbar->core.width, ctx->core.height,
X		        sbar->core.border_width );
X    }
X    _XtTextPrepareToUpdate(ctx);
X    ForceBuildLineTable(ctx);
X    _XtTextExecuteUpdate(ctx);
X}
X
X
X/*
X * This routine allow the application program to Set attributes.
X */
X
X/*ARGSUSED*/
Xstatic Boolean SetValues(current, request, new)
XWidget current, request, new;
X{
X    TextWidget oldtw = (TextWidget) current;
X    TextWidget newtw = (TextWidget) new;
X    Boolean    redisplay = FALSE;
X
X    _XtTextPrepareToUpdate(newtw);
X    
X    if ((oldtw->text.options & scrollVertical)
X		!= (newtw->text.options & scrollVertical)) {
X	newtw->text.leftmargin = newtw->text.client_leftmargin;
X	if (newtw->text.options & scrollVertical)
X	    CreateScrollbar(newtw);
X	else {
X	    XtDestroyWidget(oldtw->text.sbar);
X	    newtw->text.sbar = NULL;
X	}
X    }
X    else if (oldtw->text.client_leftmargin != newtw->text.client_leftmargin) {
X	newtw->text.leftmargin = newtw->text.client_leftmargin;
X	if (newtw->text.options & scrollVertical) {
X	    newtw->text.leftmargin +=
X		    newtw->text.sbar->core.width +
X		    newtw->text.sbar->core.border_width;
X	}
X    }
X
X    if (oldtw->text.source != newtw->text.source ||
X	oldtw->text.sink != newtw->text.sink ||
X	oldtw->text.lt.top != newtw->text.lt.top ||
X	oldtw->text.leftmargin != newtw->text.leftmargin ||
X	((oldtw->text.options & wordBreak)
X			!= (newtw->text.options & wordBreak)))
X    {
X	ForceBuildLineTable(newtw);
X	SetScrollBar(newtw);
X	redisplay = TRUE;
X    }
X
X    if (oldtw->text.insertPos != newtw->text.insertPos)
X	newtw->text.showposition = TRUE;
X
X    if (XtIsRealized(newtw)
X	&& ((oldtw->text.options & wordBreak)
X	    != (newtw->text.options & wordBreak))) {
X	XSetWindowAttributes attributes;
X	Mask valueMask;
X	valueMask = CWBitGravity;
X	attributes.bit_gravity =
X	  (newtw->text.options & wordBreak) ? ForgetGravity : NorthWestGravity;
X	XChangeWindowAttributes(XtDisplay(newtw), XtWindow(newtw),
X				valueMask, &attributes);
X	redisplay = TRUE;
X    }
X
X
X    if (!redisplay)
X	_XtTextExecuteUpdate(newtw);
X
X    return redisplay;
X}
X
X
X
Xvoid XtTextDisplay (w)
X    Widget w;
X{
X    TextWidget ctx = (TextWidget) w;
X
X    if (!XtIsRealized(w)) return;
X
X	_XtTextPrepareToUpdate(ctx);
X	DisplayTextWindow(w);
X	_XtTextExecuteUpdate(ctx);
X}
X
X/*******************************************************************
XThe following routines provide procedural interfaces to Text window state
Xsetting and getting. They need to be redone so than the args code can use
Xthem. I suggest we create a complete set that takes the context as an
Xargument and then have the public version lookup the context and call the
Xinternal one. The major value of this set is that they have actual application
Xclients and therefore the functionality provided is required for any future
Xversion of Text.
X********************************************************************/
X
Xvoid XtTextSetSelectionArray(w, sarray)
X    Widget w;
X    XtTextSelectType *sarray;
X{
X    ((TextWidget)w)->text.sarray = sarray;
X}
X
X#ifdef JON
XXtTextPosition XtTextGetLastPos(w)
X   Widget w;
X{
X   TextWidget ctx = (TextWidget) w;;
X	return GETLASTPOS;
X}
X#endif JON
X
Xvoid XtTextSetLastPos (w, lastPos)
X    Widget w;
X    XtTextPosition lastPos;
X{
X    TextWidget  ctx = (TextWidget) w;
X
X	_XtTextPrepareToUpdate(ctx);
X	(*ctx->text.source->SetLastPos)(ctx->text.source, lastPos);
X	ctx->text.lastPos = GETLASTPOS;
X	ForceBuildLineTable(ctx);
X        if (XtIsRealized(w))
X	    DisplayTextWindow(w);
X	_XtTextExecuteUpdate(ctx);
X}
X
X
Xvoid XtTextGetSelectionPos(w, left, right)
X  Widget w;
X  XtTextPosition *left, *right;
X{
X    TextWidget ctx = (TextWidget) w;
X    *left = ctx->text.s.left;
X    *right = ctx->text.s.right;
X}
X
X
Xvoid XtTextSetSource(w, source, startPos)
X    Widget w;
X    XtTextSource   source;
X    XtTextPosition startPos;
X{
X    TextWidget ctx = (TextWidget) w;
X
X	ctx->text.source = source;
X	ctx->text.lt.top = startPos;
X	ctx->text.s.left = ctx->text.s.right = 0;
X	ctx->text.insertPos = startPos;
X	ctx->text.lastPos = GETLASTPOS;
X
X	ForceBuildLineTable(ctx);
X        if (XtIsRealized(w)) {
X	    _XtTextPrepareToUpdate(ctx);
X	    DisplayTextWindow(w);
X	    _XtTextExecuteUpdate(ctx);
X	}
X}
X
X/*
X * This public routine deletes the text from startPos to endPos in a source and
X * then inserts, at startPos, the text that was passed. As a side effect it
X * "invalidates" that portion of the displayed text (if any), so that things
X * will be repainted properly.
X */
Xint XtTextReplace(w, startPos, endPos, text)
X    Widget	    w;
X    XtTextPosition  startPos, endPos;
X    XtTextBlock     *text;
X{
X    TextWidget ctx = (TextWidget) w;
X    int result;
X
X    _XtTextPrepareToUpdate(ctx);
X    if (endPos > ctx->text.lastPos) endPos = ctx->text.lastPos;
X    if (startPos > ctx->text.lastPos) startPos = ctx->text.lastPos;
X    if ((result = ReplaceText(ctx, startPos, endPos, text)) == EditDone) {
X	if (ctx->text.insertPos >= endPos) {
X	    int delta = text->length - (endPos - startPos);
X	    XtTextScanDirection sd;
X	    if (delta < 0) {
X		sd = XtsdLeft;
X		delta = -delta;
X	    }
X	    else
X		sd = XtsdRight;
X
X	    ctx->text.insertPos =
X		(*ctx->text.source->Scan)(ctx->text.source,
X					  ctx->text.insertPos,
X					  XtstPositions, sd,
X					  delta, TRUE);
X	}
X	else if (ctx->text.insertPos > startPos)
X	    ctx->text.insertPos =
X		(*ctx->text.source->Scan)(ctx->text.source, startPos,
X					  XtstPositions, XtsdRight,
X					  text->length, TRUE);
X    }
X    CheckResizeOrOverflow(ctx);
X    _XtTextExecuteUpdate(ctx);
X
X    return result;
X}
X
X
XXtTextPosition XtTextTopPosition(w)
X    Widget	    w;
X{
X    TextWidget ctx = (TextWidget) w;
X
X     return ctx->text.lt.top;
X}
X
X
Xvoid XtTextSetInsertionPoint(w, position)
X    Widget	    w;
X    XtTextPosition position;
X{
X    TextWidget ctx = (TextWidget) w;
X
X	_XtTextPrepareToUpdate(ctx);
X	ctx->text.insertPos = (position > ctx->text.lastPos)
X			       ? ctx->text.lastPos : position;
X	ctx->text.showposition = TRUE;
X	_XtTextExecuteUpdate(ctx);
X}
X
X
XXtTextPosition XtTextGetInsertionPoint(w)
X    Widget	    w;
X{
X    TextWidget ctx = (TextWidget) w;
X
X    return(ctx->text.insertPos);
X}
X
X
Xvoid XtTextUnsetSelection(w)
X    Widget	    w;
X{
X    register TextWidget ctx = (TextWidget)w;
X    int i;
X    void (*nullProc)() = NULL;
X
X    ctx->text.s.left = ctx->text.s.right = ctx->text.insertPos;
X    if (ctx->text.source->SetSelection != nullProc) {
X	(*ctx->text.source->SetSelection) (ctx->text.source, ctx->text.s.left,
X					   ctx->text.s.right,
X					   ctx->text.s.atom_count ? 
X					   ctx->text.s.selections[0] : NULL);
X    }
X
X    for (i = ctx->text.s.atom_count; i;) {
X	Atom selection = ctx->text.s.selections[--i];
X	switch (selection) {
X	  case XA_CUT_BUFFER0:
X	  case XA_CUT_BUFFER1:
X	  case XA_CUT_BUFFER2:
X	  case XA_CUT_BUFFER3:
X	  case XA_CUT_BUFFER4:
X	  case XA_CUT_BUFFER5:
X	  case XA_CUT_BUFFER6:
X	  case XA_CUT_BUFFER7: continue;
X	}
X	XtDisownSelection(w, selection);
X	LoseSelection(w, &selection); /* in case it wasn't just called */
X    }
X}
X
X
Xvoid XtTextChangeOptions(w, options)
X    Widget	    w;
X    int    options;
X{
X    TextWidget ctx = (TextWidget) w;
X
X	ctx->text.options = options;
X}
X
X
Xint XtTextGetOptions(w)
X    Widget	    w;
X{
X    TextWidget ctx = (TextWidget) w;
X
X 	return ctx->text.options;
X}
X
Xvoid XtTextSetSelection (w, left, right)
X    Widget	    w;
X    XtTextPosition left, right;
X{
X    TextWidget ctx = (TextWidget) w;
X    Atom selection = XA_PRIMARY;
X
X	_XtTextPrepareToUpdate(ctx);
X        if (left == right)
X	    XtTextUnsetSelection(w);
X	else
X	    _XtTextSetNewSelection(ctx, left, right, &selection, ONE);
X	_XtTextExecuteUpdate(ctx);
X}
X
Xvoid XtTextInvalidate(w, from, to)
X    Widget	    w;
X    XtTextPosition from,to;
X{
X    TextWidget ctx = (TextWidget) w;
X
X        ctx->text.lastPos = (*ctx->text.source->GetLastPos)(ctx->text.source);
X        _XtTextPrepareToUpdate(ctx);
X        _XtTextNeedsUpdating(ctx, from, to);
X        ForceBuildLineTable(ctx);
X        _XtTextExecuteUpdate(ctx);
X}
X
X/*ARGSUSED*/
Xvoid XtTextDisableRedisplay(w, d)
X    Widget w;
X    int d;
X{
X    register TextWidget ctx = (TextWidget)w;
X
X    ctx->text.update_disabled = True;
X    _XtTextPrepareToUpdate(ctx);
X}
X
Xvoid XtTextEnableRedisplay(w)
X    Widget w;
X{
X    register TextWidget ctx = (TextWidget)w;
X    register XtTextPosition lastPos;
X
X    if (!ctx->text.update_disabled) return;
X
X    ctx->text.update_disabled = False;
X    lastPos = ctx->text.lastPos = GETLASTPOS;
X    if (ctx->text.lt.top > lastPos)    ctx->text.lt.top = ctx->text.lastPos;
X    if (ctx->text.insertPos > lastPos) ctx->text.insertPos = ctx->text.lastPos;
X    if (ctx->text.s.left > lastPos ||
X	ctx->text.s.right > lastPos)  ctx->text.s.left = ctx->text.s.right = 0;
X
X    ForceBuildLineTable(ctx);
X    if (XtIsRealized(w))
X	DisplayTextWindow(w);
X    _XtTextExecuteUpdate(ctx);
X}
X
XXtTextSource XtTextGetSource(w)
X    Widget w;
X{
X    return ((TextWidget)w)->text.source;
X}
X
X
END_OF_FILE
if test 29444 -ne `wc -c <'xconf/Text.c.ab'`; then
    echo shar: \"'xconf/Text.c.ab'\" unpacked with wrong size!
fi
# end of 'xconf/Text.c.ab'
fi
echo shar: End of archive 2 \(of 5\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0



More information about the Comp.sources.x mailing list