[comp.sources.x] v08i081: chaos, Part05/10

ken@uunet.UU.NET (Ken Marks (x2425)) (08/21/90)

Submitted-by: balr!panasun!ken@uunet.UU.NET (Ken Marks (x2425))
Posting-number: Volume 8, Issue 81
Archive-name: chaos/part05

#! /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 5 (of 10)."
# Contents:  headers/LocalDefs.h widgets/Menu.c widgets/Slider.c
#   widgets/Text.c
# Wrapped by ken@panasun on Mon Jul 30 14:59:49 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'headers/LocalDefs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'headers/LocalDefs.h'\"
else
echo shar: Extracting \"'headers/LocalDefs.h'\" \(1813 characters\)
sed "s/^X//" >'headers/LocalDefs.h' <<'END_OF_FILE'
X/*
X * Copyright (c) Ken W. Marks 1989, 1990.
X */
X
X#ifndef _LocalDefs_h
X#define _LocalDefs_h
X
X/* Resource names */
X
X#define XtNbuffer		"buffer"
X#define XtNbufferLen		"bufferLen"
X#define XtNbuttonType		"buttonType"
X#define XtNcellSize		"cellSize"
X#define XtNcharsWide		"charsWide"
X#define XtNcursor		"cursor"
X#define XtNdefaultPos		"defaultPos"
X#define XtNdialogbox		"dialogbox"
X#define XtNdronePath		"dronePath"
X#define XtNfontNormal		"fontNormal"
X#define XtNfontReverse		"fontReverse"
X#define XtNhorizPad		"horizPad"
X#define XtNhosts		"hosts"
X#define XtNimageDir		"imageDir"
X#define XtNinitialText		"initialText"
X#define XtNiterationLimit	"iterationLimit"
X#define XtNkeepTasksSquare	"keepTasksSquare"
X#define XtNlistDefault		"listDefault"
X#define XtNlistItems		"listItems"
X#define XtNmapDir		"mapDir"
X#define XtNmaxValue		"maxValue"
X#define XtNminValue		"minValue"
X#define XtNmenuItems		"menuItems"
X#define XtNnumberVisible	"numberVisible"
X#define XtNradioDefault		"radioDefault"
X#define XtNradioItems		"radioItems"
X#define XtNretainAspectRatio	"retainAspectRatio"
X#define XtNshowValue		"showValue"
X#define XtNtaskHeight		"taskHeight"
X#define XtNtaskWidth		"taskWidth"
X#define XtNtoggleItems		"toggleItems"
X#define XtNunfocusedBorder	"unfocusedBorder"
X#define XtNvertPad		"vertPad"
X#define XtNzoomDir		"zoomDir"
X
X/* Class types */
X
X#define XtCBuffer		"Buffer"
X#define XtCButtonType		"ButtonType"
X#define XtCCellSize		"CellSize"
X#define XtCDefault		"Default"
X#define XtCExtent		"Extent"
X#define XtCHosts		"Hosts"
X#define XtCLimit		"Limit"
X#define XtCList			"List"
X#define XtCPath			"Path"
X#define XtCReserved		"Reserved"
X#define XtCShowValue		"ShowValue"
X#define XtCText			"Text"
X#define XtCUnfocused		"Unfocused"
X#define XtCWidget		"Widget"
X
X/* Resource types */
X
X#define XtRWidget		"Widget"
X
X#endif _LocalDefs_h
END_OF_FILE
if test 1813 -ne `wc -c <'headers/LocalDefs.h'`; then
    echo shar: \"'headers/LocalDefs.h'\" unpacked with wrong size!
fi
# end of 'headers/LocalDefs.h'
fi
if test -f 'widgets/Menu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'widgets/Menu.c'\"
else
echo shar: Extracting \"'widgets/Menu.c'\" \(16223 characters\)
sed "s/^X//" >'widgets/Menu.c' <<'END_OF_FILE'
X/*
X * Copyright (c) Ken W. Marks 1989, 1990.
X */
X
X#include <stdio.h>
X#include <X11/IntrinsicP.h>
X#include <X11/cursorfont.h>
X#include <X11/StringDefs.h>
X#include <Chaos.h>
X#include <LocalDefs.h>
X#include <MenuP.h>
X#include <Colormap.h>
X
X/* For debugging purposes, set allow_grabs to False.  This disallows
X * pointer and keyboard grabs so that menu code may be debugged
X * (breakpointed) without the possibility of interrupting the client
X * during a grab (rendering the workstation about as useful as a large
X * paperweight or perhaps a small end table). */
X
Xstatic allow_grabs = True;
X
X#define GET_ITEM(w, x, y)	(((x) < 0 || \
X				(x) >= w->core.width || \
X				(y) < 0 || \
X				(y) >= w->core.height) ? NO_ITEM : \
X				(y) / w->menu.item_height)
X
X/* internal padding for items in menu */
X#define VERTICAL_PAD		1
X#define HORIZONTAL_PAD		2
X
X/* modes for drawing an item */
X#define NORMAL			1
X#define REVERSE			2
X
Xstatic void MenuInitialize();
Xstatic void MenuRealize();
Xstatic void MenuResize();
Xstatic void MenuRedisplay();
Xstatic void MenuDestroy();
Xstatic void MenuBtnUp();
Xstatic void MenuMotion();
Xstatic void MenuLeave();
Xstatic void MenuDrawItem();
X
X#define offset(field) XtOffset(MenuWidget, menu.field)
X#define goffset(field) XtOffset(Widget,core.field)
X
Xstatic XtResource menu_resources[] = {
X    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
X    offset(foreground), XtRString, "Black"},
X    {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
X    goffset(background_pixel), XtRString, "White"},
X    {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
X    offset(font), XtRString, "lucidasans-bold-18"},
X    {XtNmenuItems, XtCList, XtRPointer, sizeof(char **),
X    offset(items), XtRString, NULL},
X    {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
X    offset(cursor), XtRString, "arrow"},
X    {XtNhorizPad, XtCMargin, XtRDimension, sizeof(Dimension),
X    offset(h_pad), XtRImmediate, (caddr_t) HORIZONTAL_PAD},
X    {XtNvertPad, XtCMargin, XtRDimension, sizeof(Dimension),
X    offset(v_pad), XtRImmediate, (caddr_t) VERTICAL_PAD},
X};
X
Xstatic XtActionsRec menu_actions[] =
X{
X    {"release", MenuBtnUp},
X    {"move", MenuMotion},
X    {"leave", MenuLeave},
X};
X
Xstatic char menu_translations[] =
X"<Btn3Up>:	release()\n\
X <Motion>:	move()\n\
X <Leave>:	leave()\n\
X";
X
X#define superclass		(&simpleClassRec)
X
XMenuClassRec menuClassRec = {
X    {
X	/* core fields 		 */
X	 /* superclass		 */ (WidgetClass) superclass,
X	 /* class_name		 */ "Menu",
X	 /* widget_size		 */ sizeof(MenuRec),
X	 /* class_initialize	 */ NULL,
X	 /* class_part_initialize */ NULL,
X	 /* class_inited	 */ FALSE,
X	 /* initialize		 */ MenuInitialize,
X	 /* initialize_hook	 */ NULL,
X	 /* realize		 */ MenuRealize,
X	 /* actions		 */ menu_actions,
X	 /* num_actions		 */ XtNumber(menu_actions),
X	 /* resources		 */ menu_resources,
X	 /* resource_count	 */ XtNumber(menu_resources),
X	 /* xrm_class		 */ NULLQUARK,
X	 /* compress_motion	 */ TRUE,
X	 /* compress_exposure	 */ TRUE,
X	 /* compress_enterleave	 */ TRUE,
X	 /* visible_interest	 */ FALSE,
X	 /* destroy		 */ MenuDestroy,
X	 /* resize		 */ MenuResize,
X	 /* expose		 */ MenuRedisplay,
X	 /* set_values		 */ NULL,
X	 /* set_values_hook	 */ NULL,
X	 /* set_values_almost	 */ XtInheritSetValuesAlmost,
X	 /* get_values_hook	 */ NULL,
X	 /* accept_focus	 */ NULL,
X	 /* version		 */ XtVersion,
X	 /* callback_private	 */ NULL,
X	 /* tm_table		 */ menu_translations,
X	 /* query_geometry       */ NULL,
X	 /* display_accelerator	 */ XtInheritDisplayAccelerator,
X	 /* extension		 */ NULL
X    },
X    {
X	/* Simple class fields initialization */
X	 /* change_sensitive	 */ XtInheritChangeSensitive
X    }
X};
X
X
XWidgetClass menuWidgetClass = (WidgetClass) & menuClassRec;
X
X
X/************************************************************/
X/******************** Private Procedures ********************/
X/************************************************************/
X
X
Xstatic void MenuGetGC(w)
XMenuWidget w;
X{
X    Screen *screen = XtScreen(w);
X    XGCValues values;
X
X    values.foreground = w->menu.foreground;
X    values.background = w->core.background_pixel;
X    values.font = w->menu.font->fid;
X    values.fill_style = FillTiled;
X    values.function = GXor;
X    values.tile = XmuCreateStippledPixmap(screen, w->menu.foreground,
X      w->core.background_pixel, (unsigned) DefaultDepthOfScreen(screen));
X
X
X    w->menu.normal_gc = XtGetGC((Widget) w, (unsigned) GCForeground |
X      GCBackground | GCFont, &values);
X
X    w->menu.gray_gc = XtGetGC((Widget) w, (unsigned) GCForeground |
X      GCBackground | GCFunction | GCFont | GCTile | GCFillStyle, &values);
X
X    values.foreground = values.background;
X
X    w->menu.clear_gc = XtGetGC((Widget) w, (unsigned) GCForeground |
X      GCBackground, &values);
X
X    values.background = w->menu.foreground;
X
X    w->menu.reverse_gc = XtGetGC((Widget) w, (unsigned) GCForeground |
X      GCBackground | GCFont, &values);
X}
X
X
Xstatic void MenuSetSize(w)
XMenuWidget w;
X{
X    XFontStruct *fs = w->menu.font;
X    MenuItem *item;
X    Cardinal height = fs->max_bounds.ascent + fs->max_bounds.descent;
X    Cardinal width;
X    Cardinal max_width = 0;
X    int ii = 0;
X
X    while (1)
X    {
X	item = &(w->menu.items[ii]);
X	if (item->label == NULL)
X	    break;
X	width = XTextWidth(fs, item->label, STRLEN(item->label));
X	max_width = MAX(max_width, width);
X	++ii;
X    }
X
X    w->menu.num_items = ii;
X    w->menu.item_width = max_width;
X    w->menu.item_height = height + 2 * w->menu.v_pad;
X    w->core.width = w->menu.item_width + 2 * w->menu.h_pad;
X    w->core.height = w->menu.item_height * w->menu.num_items;
X}
X
X
X/*ARGSUSED*/
Xstatic void MenuInitialize(request, new)
XWidget request;			/* unused */
XWidget new;
X{
X    MenuWidget w = (MenuWidget) new;
X    int ii;
X
X    w->menu.pixmap = NULL;
X    w->menu.current_item = NO_ITEM;
X    w->menu.mode = ModeUndecided;
X
X    MenuGetGC(w);
X    MenuSetSize(w);
X
X    /* After MenuSetSize is called, the number of menu items is stored in
X     * num_items.  Using this value, we allocate a private copy of the menu
X     * structure so that it doesn't change from under us. */
X
X    ii = w->menu.num_items;
X    w->menu.items = (MenuItem *) COPY(w->menu.items, ii * sizeof(MenuItem));
X
X    /* And don't forget to make private copies of all the labels in the menu
X     * structure. */
X    while (--ii >= 0)
X	w->menu.items[ii].label = STRCOPY(w->menu.items[ii].label);
X}
X
X
Xstatic void MenuRealize(widget, valueMask, attrs)
XWidget widget;
XXtValueMask *valueMask;
XXSetWindowAttributes *attrs;
X{
X    XtCreateWindow(widget, InputOutput, (Visual *) CopyFromParent,
X      *valueMask, attrs);
X
X    /* Call Resize() to initialize pixmap at creation time since the */
X    /* Redisplay() will generally be called before Resize() would.   */
X
X    (*XtClass(widget)->core_class.resize) (widget);
X}
X
X
X/*ARGSUSED*/
Xstatic void MenuRedisplay(widget, event, region)
XWidget widget;
XXEvent *event;
XRegion region;			/* unused */
X{
X    MenuWidget w = (MenuWidget) widget;
X    Window window = XtWindow(w);
X    Display *dpy = XtDisplay(w);
X    XExposeEvent *ev = (XExposeEvent *) event;
X
X    if (XtIsRealized(widget) == False)
X	return;
X
X    XCopyArea(dpy, w->menu.pixmap, window, w->menu.normal_gc,
X      ev->x, ev->y, (unsigned) ev->width, (unsigned) ev->height, ev->x, ev->y);
X}
X
X
Xstatic void MenuUpdatePixmap(widget, item)
XWidget widget;
Xint item;
X{
X    MenuWidget w = (MenuWidget) widget;
X    Display *dpy = XtDisplay(w);
X    Window window = XtWindow(w);
X    MenuItem *menu_item;
X    int ii;
X    int x, y;
X    int first_item = 0;
X    int last_item = w->menu.num_items - 1;
X
X    if (!XtIsRealized(widget))
X	return;
X
X    /* if the call was for a particular item */
X    if (item != NO_ITEM)
X	first_item = last_item = item;
X
X    for (ii = first_item; ii <= last_item; ++ii)
X    {
X	menu_item = &(w->menu.items[ii]);
X	x = (Position) w->menu.h_pad;
X	y = (Position) w->menu.item_height * ii + w->menu.v_pad +
X	  w->menu.font->max_bounds.ascent;
X
X	XFillRectangle(dpy, w->menu.pixmap,
X	  menu_item->sensitive ? w->menu.reverse_gc : w->menu.gray_gc,
X	  0, w->menu.item_height * ii, w->core.width, w->menu.item_height);
X
X	XDrawString(dpy, w->menu.pixmap, w->menu.normal_gc, x, y,
X	  menu_item->label, STRLEN(menu_item->label));
X    }
X
X    XCopyArea(dpy, w->menu.pixmap, window, w->menu.normal_gc,
X      0, w->menu.item_height * first_item, w->core.width,
X      (last_item - first_item + 1) * w->menu.item_height,
X      0, w->menu.item_height * first_item);
X}
X
X
Xstatic void MenuResize(widget)
XWidget widget;
X{
X    MenuWidget w = (MenuWidget) widget;
X    Display *dpy = XtDisplay(w);
X    Window window = XtWindow(w);
X    static unsigned int height = 0, width = 0;
X
X    if (XtIsRealized(widget) &&
X      (height != w->core.height || width != w->core.width))
X    {
X	height = w->core.height;
X	width = w->core.width;
X
X	if (w->menu.pixmap)
X	    XFreePixmap(dpy, w->menu.pixmap);
X
X	w->menu.pixmap = XCreatePixmap(dpy, window, width, height,
X	  w->core.depth);
X
X	if (!w->menu.pixmap)
X	{
X	    eprintf("Insufficient space for pixmap\n");
X	    abort();
X	}
X
X	/* clear the pixmap */
X	XFillRectangle(dpy, w->menu.pixmap, w->menu.clear_gc,
X	  0, 0, w->core.width, w->core.height);
X
X	MenuUpdatePixmap(widget, NO_ITEM);
X    }
X}
X
X
Xstatic void MenuDestroy(widget)
XWidget widget;
X{
X    MenuWidget w = (MenuWidget) widget;
X
X    XtReleaseGC(widget, w->menu.normal_gc);
X    XtReleaseGC(widget, w->menu.clear_gc);
X    XtReleaseGC(widget, w->menu.reverse_gc);
X    XtReleaseGC(widget, w->menu.gray_gc);
X}
X
X
Xstatic void MenuDrawItem(w, item, mode)
XMenuWidget w;
Xint item;
Xint mode;
X{
X    MenuItem *menu_item = &(w->menu.items[item]);
X    Display *dpy = XtDisplay(w);
X    Window window = XtWindow(w);
X    Position x, y;
X    GC fill_gc;
X    GC draw_gc;
X
X    x = (Position) w->menu.h_pad;
X    y = (Position) w->menu.item_height * item + w->menu.v_pad +
X      w->menu.font->max_bounds.ascent;
X
X    if (mode == REVERSE)
X    {
X	fill_gc = w->menu.normal_gc;
X	draw_gc = w->menu.reverse_gc;
X    }
X    else
X    {
X	fill_gc = w->menu.reverse_gc;
X	draw_gc = w->menu.normal_gc;
X    }
X
X    XFillRectangle(dpy, window, fill_gc, 0, w->menu.item_height * item,
X      w->core.width, w->menu.item_height);
X
X    XDrawString(dpy, window, draw_gc, x, y, menu_item->label,
X      STRLEN(menu_item->label));
X}
X
X
X/***********************************************************/
X/******************** Action Procedures ********************/
X/***********************************************************/
X
X
X/*ARGSUSED*/
Xstatic void MenuLeave(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    MenuWidget w = (MenuWidget) widget;
X
X    if (w->menu.current_item != NO_ITEM)
X    {
X	MenuDrawItem(w, w->menu.current_item, NORMAL);
X	w->menu.current_item = NO_ITEM;
X    }
X}
X
X
X/*ARGSUSED*/
Xstatic void MenuBtnUp(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    MenuWidget w = (MenuWidget) widget;
X    Display *dpy = XtDisplay(w);
X    XButtonEvent *ev = (XButtonEvent *) & event->xbutton;
X    int selected;
X
X    if (w->menu.mode == ModeUndecided)
X    {
X	/* We ignore the event and implement a click style interface */
X	w->menu.mode = ModeClick;
X	return;
X    }
X
X    MenuPopdown(widget);
X    XSync(dpy, False);
X    selected = GET_ITEM(w, ev->x, ev->y);
X    if (selected == NO_ITEM)
X	return;
X
X    /* Call function */
X    if (w->menu.items[selected].sensitive &&
X      w->menu.items[selected].func != NULL)
X	(*w->menu.items[selected].func) (widget, w->menu.items[selected].data,
X	  selected);
X}
X
X
X/*ARGSUSED*/
Xstatic void MenuMotion(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    MenuWidget w = (MenuWidget) widget;
X    XMotionEvent *ev = (XMotionEvent *) & event->xmotion;
X    int new_item;
X
X    if (w->menu.mode == ModeUndecided)
X	/* We implement a drag style interface */
X	w->menu.mode = ModeDrag;
X
X    new_item = GET_ITEM(w, ev->x, ev->y);
X
X    if (w->menu.current_item == new_item)
X	return;
X
X    if (w->menu.current_item != NO_ITEM)
X	MenuDrawItem(w, w->menu.current_item, NORMAL);
X
X    if (new_item != NO_ITEM && w->menu.items[new_item].sensitive == False)
X    {
X	/* save the current item which is now insensitive in case it should
X	 * change to sensitive while we are over it. */
X	w->menu.current_insensitive_item = new_item;
X	new_item = NO_ITEM;
X    }
X
X    w->menu.current_item = new_item;
X
X    if (new_item != NO_ITEM)
X    {
X	MenuDrawItem(w, w->menu.current_item, REVERSE);
X	w->menu.current_insensitive_item = NO_ITEM;
X    }
X}
X
X
X/***********************************************************/
X/******************** Public Procedures ********************/
X/***********************************************************/
X
X
XBoolean MenuChangeLabel(widget, item, label)
XWidget widget;
XCardinal item;
XString label;
X{
X    MenuWidget w = (MenuWidget) widget;
X
X    if (item >= w->menu.num_items || label == NULL)
X	return (False);
X
X    if (strcmp(w->menu.items[item].label, label) != SAME)
X    {
X	free(w->menu.items[item].label);
X	w->menu.items[item].label = STRCOPY(label);
X	MenuUpdatePixmap(widget, (int) item);
X    }
X    return (True);
X}
X
X
XBoolean MenuChangeFunction(widget, item, func)
XWidget widget;
XCardinal item;
Xvoid (*func) ();
X{
X    MenuWidget w = (MenuWidget) widget;
X
X    if (item >= w->menu.num_items)
X	return (False);
X
X    w->menu.items[item].func = func;
X    return (True);
X}
X
X
XBoolean MenuChangeClientData(widget, item, data)
XWidget widget;
XCardinal item;
Xcaddr_t data;
X{
X    MenuWidget w = (MenuWidget) widget;
X
X    if (item >= w->menu.num_items)
X	return (False);
X
X    w->menu.items[item].data = data;
X    return (True);
X}
X
X
XBoolean MenuChangeSensitivity(widget, item, sensitive)
XWidget widget;
XCardinal item;
XBoolean sensitive;
X{
X    MenuWidget w = (MenuWidget) widget;
X
X    if (item >= w->menu.num_items)
X	return (False);
X
X    if (w->menu.items[item].sensitive != sensitive)
X    {
X	w->menu.items[item].sensitive = sensitive;
X
X	if (XtIsRealized(widget) == False)
X	    return (True);
X
X	if (sensitive == True && item == w->menu.current_insensitive_item)
X	{
X	    /* we have re-sensitized the item that the pointer is parked on
X	     * therefore we should now highlight this item. */
X	    if (w->menu.current_item != NO_ITEM)
X	    {
X		MenuDrawItem(w, w->menu.current_item, NORMAL);
X	    }
X	    w->menu.current_item = item;
X	    MenuDrawItem(w, w->menu.current_item, REVERSE);
X	}
X	else
X	    MenuUpdatePixmap(widget, (int) item);
X    }
X    return (True);
X}
X
X
Xvoid MenuPopup(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X    Display *dpy = XtDisplay(widget);
X    Screen *screen = XtScreen(widget);
X    Widget popup_shell;
X    MenuWidget menu;
X    XButtonEvent *ev = (XButtonEvent *) & event->xbutton;
X    int popup_x, popup_y;
X    int max_popup_x, max_popup_y;
X    unsigned int mask;
X
X    if (*num_params != 1)
X    {
X	eprintf("MenuPopup must be called with the name of a menu\n");
X	return;
X    }
X
X    menu = (MenuWidget) XtNameToWidget(XtParent(widget), params[0]);
X
X    if (menu == NULL)
X    {
X	eprintf("Invalid menu name '%s'\n", params[0]);
X	return;
X    }
X
X    popup_shell = XtParent(menu);
X
X    popup_x = ev->x_root;
X    popup_y = ev->y_root;
X
X    max_popup_x = WidthOfScreen(screen) - menu->core.width;
X
X    if (popup_x > max_popup_x)
X	popup_x = max_popup_x;
X
X    max_popup_y = HeightOfScreen(screen) - menu->core.height;
X
X    if (popup_y > max_popup_y)
X	popup_y = max_popup_y;
X
X    menu->menu.current_item = NO_ITEM;
X    menu->menu.mode = ModeUndecided;
X    XtMoveWidget(popup_shell, popup_x, popup_y);
X    XtRealizeWidget(popup_shell);
X    XMapRaised(dpy, XtWindow(popup_shell));
X
X    if (!allow_grabs)
X	return;
X
X    mask = ButtonPressMask |
X      ButtonReleaseMask |
X      ButtonMotionMask |
X      PointerMotionMask |
X      EnterWindowMask |
X      LeaveWindowMask;
X
X    XGrabPointer(dpy, XtWindow(menu), False, mask, GrabModeAsync,
X      GrabModeAsync, None, menu->menu.cursor, ev->time);
X}
X
X
Xvoid MenuPopdown(widget)
XWidget widget;
X{
X    MenuWidget w = (MenuWidget) widget;
X    Display *dpy = XtDisplay(w);
X
X    XUngrabPointer(dpy, CurrentTime);
X    XtUnmapWidget(XtParent(widget));
X    XSync(dpy, False);
X}
END_OF_FILE
if test 16223 -ne `wc -c <'widgets/Menu.c'`; then
    echo shar: \"'widgets/Menu.c'\" unpacked with wrong size!
fi
# end of 'widgets/Menu.c'
fi
if test -f 'widgets/Slider.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'widgets/Slider.c'\"
else
echo shar: Extracting \"'widgets/Slider.c'\" \(16605 characters\)
sed "s/^X//" >'widgets/Slider.c' <<'END_OF_FILE'
X/*
X * Copyright (c) Ken W. Marks 1989, 1990.
X */
X
X#include <stdio.h>
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X#include <Chaos.h>
X#include <LocalDefs.h>
X#include <SliderP.h>
X#include <Colormap.h>
X#include <DlgShell.h>
X
X#define IN_LEFT_ARROW(w, x, y)	(((x) < (w)->slider.min_x && \
X				(x) >= (w)->slider.char_width && \
X				(y) >= 0 && \
X				(y) < (w)->slider.char_height) ? True : False)
X
X#define IN_RIGHT_ARROW(w, x, y)	(((x) < (w)->slider.bar_width && \
X				(x) >= (w)->slider.bar_width - \
X				(w)->slider.arrow_width && \
X				(y) >= 0 && \
X				(y) < (w)->slider.char_height) ? True : False)
X
X#define IN_SCROLLBAR(w, x, y)	(((x) >= (w)->slider.min_x && \
X				(x) < (w)->slider.bar_width - \
X				(w)->slider.arrow_width \
X				&& (y) >= 0 && \
X				(y) < (w)->slider.char_height) ? True : False)
X
X#define LEFT_ARROW_STRING	"\007\010"
X#define RIGHT_ARROW_STRING	"\011\012"
X#define SLOT_STRING		"\013\013"
X#define KNOB_STRING		"\014\015"
X
X#define ARROW			'\037'
X#define BLANK			'\036'
X
Xstatic void SliderInitialize();
Xstatic void SliderRealize();
Xstatic void SliderRedisplay();
Xstatic void SliderDestroy();
Xstatic void SliderDrawArrow();
Xstatic void SliderMoveKnob();
Xstatic void SliderMark();
Xstatic void SliderGoto();
Xstatic void SliderSlide();
Xstatic void SliderFocusIn();
Xstatic void SliderFocusOut();
Xstatic void SliderBtnUp();
Xstatic void SliderLeave();
Xstatic void SliderMotion();
X
X#define offset(field) XtOffset(SliderWidget, slider.field)
X#define goffset(field) XtOffset(Widget,core.field)
X
Xstatic XtResource slider_resources[] = {
X    {XtNdefaultPos, XtCDefault, XtRInt, sizeof(int),
X    offset(position), XtRImmediate, (caddr_t) 0},
X    {XtNminValue, XtCExtent, XtRInt, sizeof(int),
X    offset(min_value), XtRImmediate, (caddr_t) 0},
X    {XtNmaxValue, XtCExtent, XtRInt, sizeof(int),
X    offset(max_value), XtRImmediate, (caddr_t) 0},
X    {XtNshowValue, XtCShowValue, XtRBool, sizeof(Boolean),
X    offset(show_value), XtRImmediate, (caddr_t) True},
X    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
X    offset(foreground), XtRString, "Black"},
X    {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
X    goffset(background_pixel), XtRString, "White"},
X    {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
X    offset(font), XtRString, "chaos-bold"},
X    {XtNcallback, XtCCallback, XtRCallback, sizeof(caddr_t),
X    offset(callbacks), XtRCallback, (caddr_t) NULL},
X    {XtNdialogbox, XtCWidget, XtRWidget, sizeof(Widget),
X    offset(dialogbox), XtRWidget, (caddr_t) NULL},
X    {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
X    offset(cursor), XtRString, "arrow"},
X};
X
Xstatic XtActionsRec slider_actions[] =
X{
X    {"mark", SliderMark},
X    {"goto", SliderGoto},
X    {"slide", SliderSlide},
X    {"focus_in", SliderFocusIn},
X    {"focus_out", SliderFocusOut},
X    {"release", SliderBtnUp},
X    {"leave", SliderLeave},
X    {"move", SliderMotion},
X};
X
Xstatic char slider_translations[] =
X"<BtnDown>:		mark()\n\
X <BtnUp>:		release()\n\
X <Motion>:		move()\n\
X <Leave>:		leave()\n\
X Shift<Key>Tab:		goto(PREV)\n\
X <Key>Tab:		goto(NEXT)\n\
X <Key>Right:		slide(RIGHT)\n\
X <Key>Left:		slide(LEFT)\n\
X <FocusIn>:		focus_in()\n\
X <FocusOut>:		focus_out()\n\
X";
X
X#define superclass		(&simpleClassRec)
X
XSliderClassRec sliderClassRec = {
X    {
X	/* core fields 		 */
X	 /* superclass		 */ (WidgetClass) superclass,
X	 /* class_name		 */ "Slider",
X	 /* widget_size		 */ sizeof(SliderRec),
X	 /* class_initialize	 */ NULL,
X	 /* class_part_initialize */ NULL,
X	 /* class_inited	 */ FALSE,
X	 /* initialize		 */ SliderInitialize,
X	 /* initialize_hook	 */ NULL,
X	 /* realize		 */ SliderRealize,
X	 /* actions		 */ slider_actions,
X	 /* num_actions		 */ XtNumber(slider_actions),
X	 /* resources		 */ slider_resources,
X	 /* resource_count	 */ XtNumber(slider_resources),
X	 /* xrm_class		 */ NULLQUARK,
X	 /* compress_motion	 */ TRUE,
X	 /* compress_exposure	 */ TRUE,
X	 /* compress_enterleave	 */ TRUE,
X	 /* visible_interest	 */ FALSE,
X	 /* destroy		 */ SliderDestroy,
X	 /* resize		 */ NULL,
X	 /* expose		 */ SliderRedisplay,
X	 /* set_values		 */ NULL,
X	 /* set_values_hook	 */ NULL,
X	 /* set_values_almost	 */ XtInheritSetValuesAlmost,
X	 /* get_values_hook	 */ NULL,
X	 /* accept_focus	 */ NULL,
X	 /* version		 */ XtVersion,
X	 /* callback_private	 */ NULL,
X	 /* tm_table		 */ slider_translations,
X	 /* query_geometry       */ NULL,
X	 /* display_accelerator	 */ XtInheritDisplayAccelerator,
X	 /* extension		 */ NULL
X    },
X    {
X	/* Simple class fields initialization */
X	 /* change_sensitive	 */ XtInheritChangeSensitive
X    }
X};
X
X
XWidgetClass sliderWidgetClass = (WidgetClass) & sliderClassRec;
X
X
X/************************************************************/
X/******************** Private Procedures ********************/
X/************************************************************/
X
X
Xstatic void SliderGetGC(w)
XSliderWidget w;
X{
X    XGCValues values;
X
X    values.foreground = w->slider.foreground;
X    values.background = w->core.background_pixel;
X    values.font = w->slider.font->fid;
X
X    w->slider.normal_gc = XtGetGC((Widget) w, (unsigned) GCForeground |
X      GCBackground | GCFont, &values);
X
X    values.foreground = values.background;
X
X    w->slider.clear_gc = XtGetGC((Widget) w, (unsigned) GCForeground |
X      GCBackground | GCFont, &values);
X}
X
X
Xstatic void SliderSetSize(w)
XSliderWidget w;
X{
X    XtWidgetGeometry my_request;
X    XFontStruct *fs = w->slider.font;
X    Cardinal height = fs->max_bounds.ascent + fs->max_bounds.descent;
X    Cardinal width = fs->max_bounds.width;
X
X    w->slider.baseline = fs->max_bounds.ascent + 1;
X    w->slider.char_width = width;
X    w->slider.char_height = height;
X    w->slider.arrow_width = width * 2;
X    w->slider.knob_width = width * 2;
X    w->slider.center_to_left_edge = width;
X
X    w->slider.bar_width = w->slider.max_value - w->slider.min_value +
X      w->slider.char_width + 2 * w->slider.arrow_width + w->slider.knob_width;
X
X    w->slider.value_width = (w->slider.show_value == False ? 0 :
X      w->slider.value_len * width);
X
X    my_request.request_mode = CWWidth | CWHeight | CWBorderWidth;
X    my_request.width = w->slider.bar_width + w->slider.value_width;
X    my_request.height = w->slider.char_height + 2;
X    my_request.border_width = 0;
X
X    XtMakeGeometryRequest((Widget) w, &my_request, NULL);
X
X    w->slider.min_x = w->slider.char_width + w->slider.arrow_width;
X    w->slider.max_x = w->slider.bar_width - w->slider.arrow_width -
X      w->slider.knob_width;
X}
X
X
X/*ARGSUSED*/
Xstatic void SliderInitialize(request, new)
XWidget request;			/* unused */
XWidget new;
X{
X    SliderWidget w = (SliderWidget) new;
X    int min_len, max_len;
X
X    if (w->slider.dialogbox == NULL)
X    {
X	eprintf("XtNdialogbox not set\n");
X	abort();
X    }
X
X    if (w->slider.show_value == True)
X    {
X	w->slider.show_sign = w->slider.min_value < 0;
X	(void) sprintf(w->slider.value_in_ascii, "%+d", w->slider.min_value);
X	min_len = strlen(w->slider.value_in_ascii);
X
X	(void) sprintf(w->slider.value_in_ascii, "%+d", w->slider.max_value);
X	max_len = strlen(w->slider.value_in_ascii);
X
X	/* compute total length of string (e.g. " [-10]") */
X	w->slider.value_len = MAX(min_len, max_len) +
X	  (w->slider.show_sign ? 3 : 2);
X    }
X
X    SliderGetGC(w);
X    SliderSetSize(w);
X
X    w->slider.active = False;
X    w->slider.scrolling = False;
X    w->slider.knob_x = w->slider.min_x + w->slider.position -
X      w->slider.min_value;
X}
X
X
Xstatic void SliderRealize(widget, valueMask, attrs)
XWidget widget;
XXtValueMask *valueMask;
XXSetWindowAttributes *attrs;
X{
X    SliderWidget w = (SliderWidget) widget;
X    Display *dpy = XtDisplay(w);
X    Window window;
X    Position x;
X
X    XtCreateWindow(widget, InputOutput, (Visual *) CopyFromParent,
X      *valueMask, attrs);
X
X    window = XtWindow(w);
X
X    w->slider.pixmap = XCreatePixmap(dpy, window, w->core.width, w->core.height,
X      w->core.depth);
X
X    if (!w->slider.pixmap)
X    {
X	eprintf("Insufficient space for pixmap\n");
X	abort();
X    }
X
X    /* clear the pixmap */
X    XFillRectangle(dpy, w->slider.pixmap, w->slider.clear_gc, 0, 0,
X      w->core.width, w->core.height);
X
X    x = w->slider.char_width;
X    XDrawImageString(dpy, w->slider.pixmap, w->slider.normal_gc, x,
X      w->slider.baseline, LEFT_ARROW_STRING, 2);
X
X    for (x = w->slider.min_x; x < w->slider.bar_width - w->slider.arrow_width;
X      x += w->slider.knob_width)
X	XDrawImageString(dpy, w->slider.pixmap, w->slider.normal_gc, x,
X	  w->slider.baseline, SLOT_STRING, 2);
X
X    x = w->slider.bar_width - w->slider.arrow_width;
X    XDrawImageString(dpy, w->slider.pixmap, w->slider.normal_gc, x,
X      w->slider.baseline, RIGHT_ARROW_STRING, 2);
X
X    x = w->slider.knob_x;
X    XDrawImageString(dpy, w->slider.pixmap, w->slider.normal_gc, x,
X      w->slider.baseline, KNOB_STRING, 2);
X
X    XDrawLine(dpy, w->slider.pixmap, w->slider.normal_gc, w->slider.char_width,
X      0, w->core.width - w->slider.value_width - 1, 0);
X
X    XDrawLine(dpy, w->slider.pixmap, w->slider.normal_gc, w->slider.char_width,
X      w->core.height - 1, w->core.width - w->slider.value_width - 1,
X      w->core.height - 1);
X}
X
X
X
X/*ARGSUSED*/
Xstatic void SliderRedisplay(widget, event, region)
XWidget widget;
XXEvent *event;
XRegion region;			/* unused */
X{
X    SliderWidget w = (SliderWidget) widget;
X    Window window = XtWindow(w);
X    Display *dpy = XtDisplay(w);
X    XExposeEvent *ev = (XExposeEvent *) event;
X
X    if (XtIsRealized(widget) == False)
X	return;
X
X    if (ev == NULL)
X	XCopyArea(dpy, w->slider.pixmap, window, w->slider.normal_gc,
X	  0, 0, w->core.width, w->core.height, 0, 0);
X    else
X	XCopyArea(dpy, w->slider.pixmap, window, w->slider.normal_gc,
X	  ev->x, ev->y, (unsigned) ev->width, (unsigned) ev->height,
X	  ev->x, ev->y);
X
X    SliderDrawArrow(widget);
X
X    if (w->slider.show_value)
X    {
X	if (w->slider.show_sign)
X	    (void) sprintf(w->slider.value_in_ascii, " [%+d]",
X	      w->slider.position);
X	else
X	    (void) sprintf(w->slider.value_in_ascii, " [%d]",
X	      w->slider.position);
X
X	XDrawImageString(dpy, window, w->slider.normal_gc,
X	  (int) (w->core.width - w->slider.value_width), w->slider.baseline,
X	  w->slider.value_in_ascii, strlen(w->slider.value_in_ascii));
X    }
X}
X
X
Xstatic void SliderDestroy(widget)
XWidget widget;
X{
X    SliderWidget w = (SliderWidget) widget;
X
X    XtReleaseGC(widget, w->slider.normal_gc);
X    XtReleaseGC(widget, w->slider.clear_gc);
X}
X
X
Xstatic void SliderDrawArrow(widget)
XWidget widget;
X{
X    SliderWidget w = (SliderWidget) widget;
X    Display *dpy = XtDisplay(w);
X    Window window = XtWindow(w);
X    char active_string[1];
X
X    /* must convert the arrow/blank char into string for printing */
X    active_string[0] = w->slider.active ? ARROW : BLANK;
X
X    XDrawImageString(dpy, window, w->slider.normal_gc, 0,
X      w->slider.baseline, active_string, 1);
X}
X
X
Xstatic void SliderMoveKnob(widget, x)
XWidget widget;
XPosition x;
X{
X    SliderWidget w = (SliderWidget) widget;
X    Display *dpy = XtDisplay(w);
X
X    x -= w->slider.center_to_left_edge;
X
X    if (x < w->slider.min_x)
X	x = w->slider.min_x;
X    else if (x > w->slider.max_x)
X	x = w->slider.max_x;
X
X    if (x == w->slider.knob_x)
X	return;
X
X    w->slider.position = x - w->slider.min_x + w->slider.min_value;
X
X    /* Erase the old knob */
X    XDrawImageString(dpy, w->slider.pixmap, w->slider.normal_gc,
X      w->slider.knob_x, w->slider.baseline, SLOT_STRING, 2);
X
X    w->slider.knob_x = x;
X
X    /* Draw new knob */
X    XDrawImageString(dpy, w->slider.pixmap, w->slider.normal_gc,
X      w->slider.knob_x, w->slider.baseline, KNOB_STRING, 2);
X
X    SliderRedisplay(widget, (XEvent *) NULL, (Region) NULL);
X    XtCallCallbacks(widget, XtNcallback, (XtPointer) (w->slider.position));
X}
X
X
X/***********************************************************/
X/******************** Action Procedures ********************/
X/***********************************************************/
X
X
X/*ARGSUSED*/
Xstatic void SliderFocusIn(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;
XCardinal *num_params;		/* unused */
X{
X    SliderWidget w = (SliderWidget) widget;
X
X    if (w->slider.active == False)
X    {
X	w->slider.active = True;
X	SliderDrawArrow(widget);
X    }
X}
X
X
X/*ARGSUSED*/
Xstatic void SliderFocusOut(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;
XCardinal *num_params;		/* unused */
X{
X    SliderWidget w = (SliderWidget) widget;
X
X    if (w->slider.active == True)
X    {
X	w->slider.active = False;
X	SliderDrawArrow(widget);
X    }
X}
X
X
X/*ARGSUSED*/
Xstatic void SliderMark(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    SliderWidget w = (SliderWidget) widget;
X    XButtonEvent *ev = (XButtonEvent *) & event->xbutton;
X
X    w->slider.active = True;
X    DialogSetNewFocus(w->slider.dialogbox, widget);
X
X    SliderDrawArrow(widget);
X
X    if (IN_SCROLLBAR(w, ev->x, ev->y))
X    {
X	w->slider.scrolling = True;
X	SliderMoveKnob(widget, ev->x);
X    }
X    else if (IN_LEFT_ARROW(w, ev->x, ev->y))
X	SliderMoveKnob(widget, w->slider.knob_x +
X	  w->slider.center_to_left_edge - 1);
X    else if (IN_RIGHT_ARROW(w, ev->x, ev->y))
X	SliderMoveKnob(widget, w->slider.knob_x +
X	  w->slider.center_to_left_edge + 1);
X}
X
X
X/* ARGSUSED */
Xstatic void SliderGoto(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;
XCardinal *num_params;		/* unused */
X{
X    SliderWidget w = (SliderWidget) widget;
X
X    switch (params[0][0])
X    {
X    case 'P':
X	DialogSetPrevFocus(w->slider.dialogbox);
X	break;
X
X    case 'N':
X	DialogSetNextFocus(w->slider.dialogbox);
X	break;
X    }
X
X    w->slider.active = False;
X
X    SliderDrawArrow(widget);
X}
X
X
X/* ARGSUSED */
Xstatic void SliderSlide(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;
XCardinal *num_params;		/* unused */
X{
X    SliderWidget w = (SliderWidget) widget;
X
X    switch (params[0][0])
X    {
X    case 'L':
X	SliderMoveKnob(widget, w->slider.knob_x +
X	  w->slider.center_to_left_edge - 1);
X	break;
X
X    case 'R':
X	SliderMoveKnob(widget, w->slider.knob_x +
X	  w->slider.center_to_left_edge + 1);
X	break;
X    }
X}
X
X
X/*ARGSUSED*/
Xstatic void SliderBtnUp(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    SliderWidget w = (SliderWidget) widget;
X    XButtonEvent *ev = (XButtonEvent *) & event->xbutton;
X
X    if (w->slider.scrolling == False)
X	return;
X
X    w->slider.scrolling = False;
X    SliderMoveKnob(widget, ev->x);
X}
X
X
X/*ARGSUSED*/
Xstatic void SliderLeave(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    SliderWidget w = (SliderWidget) widget;
X    XCrossingEvent *ev = (XCrossingEvent *) & event->xcrossing;
X
X    if (w->slider.scrolling == False)
X	return;
X
X    w->slider.scrolling = False;
X    SliderMoveKnob(widget, ev->x);
X}
X
X
X/*ARGSUSED*/
Xstatic void SliderMotion(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    SliderWidget w = (SliderWidget) widget;
X    Display *dpy = XtDisplay(w);
X    Window window = XtWindow(w);
X    XMotionEvent *ev = (XMotionEvent *) & event->xmotion;
X
X    /* Always skip ahead to the latest ButtonMotionEvent in the queue */
X    /* SUPPRESS 530 */
X    while (XCheckWindowEvent(dpy, window, ButtonMotionMask, ev));
X
X    if (w->slider.scrolling == False)
X	return;
X
X    SliderMoveKnob(widget, ev->x);
X}
X
X
X/***********************************************************/
X/******************** Public Procedures ********************/
X/***********************************************************/
X
Xvoid SliderChangePosition(widget, value)
XWidget widget;
Xint value;
X{
X    SliderWidget w = (SliderWidget) widget;
X    Display *dpy = XtDisplay(w);
X    int x;
X
X    if (value > w->slider.max_value)
X	value = w->slider.max_value;
X
X    if (value < w->slider.min_value)
X	value = w->slider.min_value;
X
X    w->slider.position = value;
X
X    x = w->slider.position + w->slider.min_x - w->slider.min_value;
X
X    if (x == w->slider.knob_x)
X	return;
X
X    if (XtIsRealized(widget) == False)
X    {
X	w->slider.knob_x = x;
X	return;
X    }
X
X    /* Erase the old knob */
X    XDrawImageString(dpy, w->slider.pixmap, w->slider.normal_gc,
X      w->slider.knob_x, w->slider.baseline, SLOT_STRING, 2);
X
X    w->slider.knob_x = x;
X
X    /* Draw new knob */
X    XDrawImageString(dpy, w->slider.pixmap, w->slider.normal_gc,
X      w->slider.knob_x, w->slider.baseline, KNOB_STRING, 2);
X
X    SliderRedisplay(widget, (XEvent *) NULL, (Region) NULL);
X}
END_OF_FILE
if test 16605 -ne `wc -c <'widgets/Slider.c'`; then
    echo shar: \"'widgets/Slider.c'\" unpacked with wrong size!
fi
# end of 'widgets/Slider.c'
fi
if test -f 'widgets/Text.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'widgets/Text.c'\"
else
echo shar: Extracting \"'widgets/Text.c'\" \(16216 characters\)
sed "s/^X//" >'widgets/Text.c' <<'END_OF_FILE'
X/*
X * Copyright (c) Ken W. Marks 1989, 1990.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <X11/Intrinsic.h>
X#include <X11/StringDefs.h>
X#include <Chaos.h>
X#include <LocalDefs.h>
X#include <TextP.h>
X#include <DlgShell.h>
X
X/* Default number of characters wide for widget */
X#define DEFAULT_WIDTH		20
X
X#define CARET_CURSOR		"\001"
X#define BAR_CURSOR		"\002"
X
X#define ARROW			'\037'
X#define BLANK			'\036'
X
Xstatic void TextInitialize();
Xstatic void TextResize();
Xstatic void TextRedisplay();
Xstatic void TextDestroy();
Xstatic void TextMark();
Xstatic void TextGoto();
Xstatic void TextFocusIn();
Xstatic void TextFocusOut();
X
Xstatic void TextDeleteNextChar();
Xstatic void TextDeletePreviousChar();
Xstatic void TextDeleteNextAll();
Xstatic void TextDeletePreviousAll();
Xstatic void TextMoveLeft();
Xstatic void TextMoveRight();
Xstatic void TextMoveStart();
Xstatic void TextMoveEnd();
Xstatic void TextInsertChar();
X
X#define offset(field) XtOffset(TextWidget, text.field)
Xstatic XtResource text_resources[] = {
X    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
X    offset(foreground), XtRString, "XtDefaultForeground"},
X    {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
X    offset(font), XtRString, "chaos-bold"},
X    {XtNbuffer, XtCBuffer, XtRString, sizeof(String),
X    offset(buffer), XtRString, NULL},
X    {XtNbufferLen, XtCLength, XtRInt, sizeof(int),
X    offset(buffer_len), XtRImmediate, (caddr_t) 0},
X    {XtNcharsWide, XtCLength, XtRInt, sizeof(int),
X    offset(width_in_chars), XtRImmediate, (caddr_t) DEFAULT_WIDTH},
X    {XtNinitialText, XtCText, XtRString, sizeof(String),
X    offset(initial_text), XtRString, NULL},
X    {XtNdialogbox, XtCWidget, XtRWidget, sizeof(Widget),
X    offset(dialogbox), XtRWidget, (caddr_t) NULL},
X};
X
Xstatic XtActionsRec text_actions[] =
X{
X    {"mark", TextMark},
X    {"goto", TextGoto},
X    {"focus_in", TextFocusIn},
X    {"focus_out", TextFocusOut},
X    {"delete-next-character", TextDeleteNextChar},
X    {"delete-previous-character", TextDeletePreviousChar},
X    {"delete-next-all", TextDeleteNextAll},
X    {"delete-previous-all", TextDeletePreviousAll},
X    {"move-left", TextMoveLeft},
X    {"move-right", TextMoveRight},
X    {"move-start", TextMoveStart},
X    {"move-end", TextMoveEnd},
X    {"insert-char", TextInsertChar},
X};
X
X#define superclass		(&simpleClassRec)
X
Xstatic char text_translations[] =
X"<BtnDown>:		mark()\n\
X Shift<Key>Tab:		goto(PREV)\n\
X <Key>Tab:		goto(NEXT)\n\
X <FocusIn>:		focus_in()\n\
X <FocusOut>:		focus_out()\n\
X Ctrl<Key>D:		delete-next-character()\n\
X <Key>BackSpace:	delete-previous-character()\n\
X <Key>Delete:		delete-previous-character()\n\
X Ctrl<Key>K:		delete-next-all()\n\
X Ctrl<Key>U:		delete-previous-all()\n\
X <Key>Left:		move-left()\n\
X Ctrl<Key>B:		move-left()\n\
X <Key>Right:		move-right()\n\
X Ctrl<Key>F:		move-right()\n\
X Shift<Key>Left:	move-start()\n\
X Ctrl<Key>A:		move-start()\n\
X Shift<Key>Right:	move-end()\n\
X Ctrl<Key>E:		move-end()\n\
X <Key>:			insert-char()\n\
X";
X
XTextClassRec textClassRec = {
X    {
X	/* core fields 		 */
X	 /* superclass		 */ (WidgetClass) superclass,
X	 /* class_name		 */ "Text",
X	 /* widget_size		 */ sizeof(TextRec),
X	 /* class_initialize	 */ NULL,
X	 /* class_part_initialize */ NULL,
X	 /* class_inited	 */ FALSE,
X	 /* initialize		 */ TextInitialize,
X	 /* initialize_hook	 */ NULL,
X	 /* realize		 */ XtInheritRealize,
X	 /* actions		 */ text_actions,
X	 /* num_actions		 */ XtNumber(text_actions),
X	 /* resources		 */ text_resources,
X	 /* resource_count	 */ XtNumber(text_resources),
X	 /* xrm_class		 */ NULLQUARK,
X	 /* compress_motion	 */ TRUE,
X	 /* compress_exposure	 */ TRUE,
X	 /* compress_enterleave	 */ TRUE,
X	 /* visible_interest	 */ FALSE,
X	 /* destroy		 */ TextDestroy,
X	 /* resize		 */ TextResize,
X	 /* expose		 */ TextRedisplay,
X	 /* set_values		 */ NULL,
X	 /* set_values_hook	 */ NULL,
X	 /* set_values_almost	 */ XtInheritSetValuesAlmost,
X	 /* get_values_hook	 */ NULL,
X	 /* accept_focus	 */ NULL,
X	 /* version		 */ XtVersion,
X	 /* callback_private	 */ NULL,
X	 /* tm_table		 */ text_translations,
X	 /* query_geometry       */ NULL,
X	 /* display_accelerator	 */ XtInheritDisplayAccelerator,
X	 /* extension		 */ NULL
X    },
X    {
X	/* Simple class fields initialization */
X	 /* change_sensitive	 */ XtInheritChangeSensitive
X    }
X};
X
XWidgetClass textWidgetClass = (WidgetClass) & textClassRec;
X
X
X/************************************************************/
X/******************** Private Procedures ********************/
X/************************************************************/
X
X
Xstatic void TextGetGC(w)
XTextWidget w;
X{
X    XGCValues values;
X
X    values.foreground = w->text.foreground;
X    values.background = w->core.background_pixel;
X    values.font = w->text.font->fid;
X
X    w->text.normal_gc = XtGetGC((Widget) w, (unsigned) GCForeground |
X      GCBackground | GCFont, &values);
X}
X
X
Xstatic void TextSetSize(w)
XTextWidget w;
X{
X    XtWidgetGeometry my_request;
X    XFontStruct *fs = w->text.font;
X    int width;
X
X    width = fs->max_bounds.width;
X    w->text.baseline = fs->max_bounds.ascent;
X    w->text.char_width = width;
X    w->text.text_offset = width / 2;
X
X    /* Width is based on (width_in_chars + 2) characters to account for the
X     * arrow character and a half character's width worth of spacing at either
X     * end. */
X
X    my_request.request_mode = CWWidth | CWHeight | CWBorderWidth;
X    my_request.width = (w->text.width_in_chars + 2) * w->text.char_width;
X    my_request.height = fs->max_bounds.ascent + fs->max_bounds.descent;
X    my_request.border_width = 1;
X
X    XtMakeGeometryRequest((Widget) w, &my_request, NULL);
X}
X
X
X/* ARGSUSED */
Xstatic void TextInitialize(request, new)
XWidget request;
XWidget new;
X{
X    TextWidget w = (TextWidget) new;
X
X    if (w->text.dialogbox == NULL)
X    {
X	eprintf("XtNdialogbox not set\n");
X	abort();
X    }
X
X    if (w->text.buffer == NULL)
X    {
X	eprintf("NULL buffer specified\n");
X	abort();
X    }
X
X    if (w->text.buffer_len == 0)
X    {
X	eprintf("Zero buffer length specified\n");
X	abort();
X    }
X
X    w->text.displayed_text = malloc((unsigned) (w->text.width_in_chars + 3));
X
X    /* The string displayed_text always has a space in the last character */
X    w->text.displayed_text[w->text.width_in_chars + 2] = BLANK;
X
X    w->text.text_len = STRLEN(w->text.initial_text);
X    w->text.text_len = MIN(w->text.text_len, w->text.buffer_len - 1);
X
X    if (w->text.text_len != 0)
X    {
X	(void) memcpy(w->text.buffer, w->text.initial_text,
X	  w->text.text_len);
X	w->text.buffer[w->text.text_len] = 0;
X    }
X
X    w->text.cursor_position = w->text.text_len;
X    w->text.active = False;
X    w->text.first_char = MAX(0, w->text.text_len - w->text.width_in_chars);
X
X    TextGetGC(w);
X    (*XtClass(new)->core_class.resize) ((Widget) w);
X}
X
X
X/* ARGSUSED */
Xstatic void TextRedisplay(widget, event, region)
XWidget widget;
XXEvent *event;
XRegion region;
X{
X    TextWidget w = (TextWidget) widget;
X    int length;
X
X    if (XtIsRealized(widget) == False)
X	return;
X
X    length = MIN(w->text.text_len, w->text.width_in_chars);
X
X    if (w->text.active)
X	w->text.displayed_text[0] = ARROW;
X    else
X	w->text.displayed_text[0] = BLANK;
X
X    (void) memcpy(&(w->text.displayed_text[1]),
X      &(w->text.buffer[w->text.first_char]), length);
X
X    if (length < w->text.width_in_chars)
X	(void) memset(&(w->text.displayed_text[length + 1]), BLANK,
X	  w->text.width_in_chars - length);
X
X    /* Draw text (with a trailing space to pick up EOL cursor droppings) */
X    XDrawImageString(XtDisplay(w), XtWindow(w), w->text.normal_gc,
X      w->text.text_offset, w->text.baseline, w->text.displayed_text,
X      w->text.width_in_chars + 2);
X
X    /* Draw cursor */
X    XDrawString(XtDisplay(w), XtWindow(w), w->text.normal_gc,
X      (int) (w->text.char_width * (w->text.cursor_position -
X	  w->text.first_char + 1)), w->text.baseline, BAR_CURSOR, 1);
X}
X
X
Xstatic void TextResize(widget)
XWidget widget;
X{
X    TextSetSize((TextWidget) widget);
X}
X
X
Xstatic void TextDestroy(widget)
XWidget widget;
X{
X    TextWidget w = (TextWidget) widget;
X
X    XtReleaseGC(widget, w->text.normal_gc);
X}
X
X
X/***********************************************************/
X/******************** Action Procedures ********************/
X/***********************************************************/
X
X
X/* ARGSUSED */
Xstatic void TextMark(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X    XButtonEvent *ev = (XButtonEvent *) & event->xbutton;
X
X    int position;
X
X    w->text.active = True;
X
X    position = (ev->x) / w->text.char_width - 1;
X    position = MAX(position, 0);
X    position = MIN(position, w->text.text_len);
X
X    w->text.cursor_position = position + w->text.first_char;
X
X    TextRedisplay(widget, (XEvent *) NULL, (Region) NULL);
X    DialogSetNewFocus(w->text.dialogbox, widget);
X}
X
X
X/* ARGSUSED */
Xstatic void TextGoto(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X
X    switch (params[0][0])
X    {
X    case 'P':
X	DialogSetPrevFocus(w->text.dialogbox);
X	break;
X
X    case 'N':
X	DialogSetNextFocus(w->text.dialogbox);
X	break;
X    }
X
X    w->text.active = False;
X
X    TextRedisplay(widget, (XEvent *) NULL, (Region) NULL);
X}
X
X
X/*ARGSUSED*/
Xstatic void TextFocusIn(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X
X    if (w->text.active == False)
X    {
X	w->text.active = True;
X	TextRedisplay(widget, (XEvent *) NULL, (Region) NULL);
X    }
X}
X
X
X/*ARGSUSED*/
Xstatic void TextFocusOut(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X
X    if (w->text.active == True)
X    {
X	w->text.active = False;
X	TextRedisplay(widget, (XEvent *) NULL, (Region) NULL);
X    }
X}
X
X
X/* ARGSUSED */
Xstatic void TextDeleteNextChar(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X
X    if (w->text.cursor_position >= w->text.text_len)
X	return;
X
X    (void) memcpy(&(w->text.buffer[w->text.cursor_position]),
X      &(w->text.buffer[w->text.cursor_position + 1]),
X      w->text.text_len - w->text.cursor_position);
X
X    --w->text.text_len;
X
X    w->text.first_char = MIN(w->text.first_char, MAX(w->text.text_len -
X	w->text.width_in_chars, 0));
X
X    (*XtClass(widget)->core_class.expose) (widget, NULL, NULL);
X}
X
X
X/* ARGSUSED */
Xstatic void TextDeletePreviousChar(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X
X    if (w->text.cursor_position == 0)
X	return;
X
X    (void) memcpy(&(w->text.buffer[w->text.cursor_position - 1]),
X      &(w->text.buffer[w->text.cursor_position]),
X      w->text.text_len - w->text.cursor_position + 1);
X
X    --w->text.text_len;
X    --w->text.cursor_position;
X
X    w->text.first_char = MIN(w->text.first_char, MAX(w->text.text_len -
X	w->text.width_in_chars, 0));
X
X    (*XtClass(widget)->core_class.expose) (widget, NULL, NULL);
X}
X
X
X/* ARGSUSED */
Xstatic void TextDeleteNextAll(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X
X    w->text.text_len = w->text.cursor_position;
X    w->text.buffer[w->text.text_len] = 0;
X    w->text.first_char = MAX(0, w->text.text_len - w->text.width_in_chars);
X
X    (*XtClass(widget)->core_class.expose) (widget, NULL, NULL);
X}
X
X
X/* ARGSUSED */
Xstatic void TextDeletePreviousAll(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X
X    if (w->text.cursor_position == 0)
X	return;
X
X    (void) memcpy(w->text.buffer, &(w->text.buffer[w->text.cursor_position]),
X      w->text.text_len - w->text.cursor_position + 1);
X
X    w->text.text_len -= w->text.cursor_position;
X    w->text.cursor_position = 0;
X    w->text.first_char = 0;
X
X    (*XtClass(widget)->core_class.expose) (widget, NULL, NULL);
X}
X
X
X/* ARGSUSED */
Xstatic void TextMoveLeft(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X
X    if (w->text.cursor_position == 0)
X	return;
X
X    --w->text.cursor_position;
X
X    w->text.first_char = MIN(w->text.first_char, w->text.cursor_position);
X
X    (*XtClass(widget)->core_class.expose) (widget, NULL, NULL);
X}
X
X
X/* ARGSUSED */
Xstatic void TextMoveRight(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X
X    if (w->text.cursor_position >= w->text.text_len)
X	return;
X
X    ++w->text.cursor_position;
X
X    w->text.first_char = MAX(w->text.first_char, w->text.cursor_position -
X      w->text.width_in_chars);
X
X    (*XtClass(widget)->core_class.expose) (widget, NULL, NULL);
X}
X
X
X/* ARGSUSED */
Xstatic void TextMoveStart(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X
X    if (w->text.cursor_position == 0)
X	return;
X
X    w->text.cursor_position = 0;
X    w->text.first_char = 0;
X
X    (*XtClass(widget)->core_class.expose) (widget, NULL, NULL);
X}
X
X
X/* ARGSUSED */
Xstatic void TextMoveEnd(widget, event, params, num_params)
XWidget widget;
XXEvent *event;			/* unused */
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    TextWidget w = (TextWidget) widget;
X
X    if (w->text.cursor_position >= w->text.text_len)
X	return;
X
X    w->text.cursor_position = w->text.text_len;
X
X    w->text.first_char = MAX(0, w->text.text_len - w->text.width_in_chars);
X
X    (*XtClass(widget)->core_class.expose) (widget, NULL, NULL);
X}
X
X
X/* ARGSUSED */
Xstatic void TextInsertChar(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params;			/* unused */
XCardinal *num_params;		/* unused */
X{
X    char buffer[64];
X    TextWidget w = (TextWidget) widget;
X    KeySym keysym;
X    int length;
X
X    length = XLookupString(&(event->xkey), buffer, 64, &keysym, NULL);
X    if (length == 0 || !isprint(buffer[0]))
X	return;
X
X    if (w->text.text_len + length < w->text.buffer_len)
X    {
X	{
X	    /* move any following text to the right. we do this manually since
X	     * memcpy() is too stupid to deal with overlapping regions. */
X
X	    int ii = w->text.text_len - w->text.cursor_position + 1;
X	    char *from = &(w->text.buffer[w->text.text_len]);
X	    char *to = &(w->text.buffer[w->text.text_len + length]);
X
X	    while (ii-- > 0)
X		*(to--) = *(from--);
X	}
X
X	if (length == 1)
X	    w->text.buffer[w->text.cursor_position] = buffer[0];
X	else
X	    (void) memcpy(&(w->text.buffer[w->text.cursor_position]), buffer,
X	      length);
X
X	w->text.text_len += length;
X	w->text.cursor_position += length;
X    }
X    else
X	XBell(XtDisplay(w), 0);
X
X    w->text.first_char = MAX(w->text.first_char, w->text.cursor_position -
X      w->text.width_in_chars);
X
X    (*XtClass(widget)->core_class.expose) (widget, NULL, NULL);
X}
X
X
X/***********************************************************/
X/******************** Public Procedures ********************/
X/***********************************************************/
X
Xvoid TextChangeText(widget, text)
XWidget widget;
XString text;
X{
X    TextWidget w = (TextWidget) widget;
X
X    if (text == NULL)
X	w->text.buffer[0] = 0;
X    else
X	(void) strcpy(w->text.buffer, text);
X
X    w->text.text_len = STRLEN(w->text.buffer);
X    w->text.cursor_position = w->text.text_len;
X    w->text.first_char = MAX(0, w->text.text_len - w->text.width_in_chars);
X
X    (*XtClass(widget)->core_class.expose) (widget, NULL, NULL);
X}
END_OF_FILE
if test 16216 -ne `wc -c <'widgets/Text.c'`; then
    echo shar: \"'widgets/Text.c'\" unpacked with wrong size!
fi
# end of 'widgets/Text.c'
fi
echo shar: End of archive 5 \(of 10\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 10 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

dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.