[comp.sources.x] v03i014: file browsing widget, Part01/01

mikew@wyse.wyse.com (Mike Wexler) (02/18/89)

Submitted-by: shipley@web.berkeley.edu
Posting-number: Volume 3, Issue 14
Archive-name: browserw/part01

#! /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 1 (of 1)."
# Contents:  README AUTHOR Browser.c Browser.h BrowserP.h
#   ListWidget.patch Makefile browser.3x main.c patchlevel.h
# Wrapped by mikew@wyse on Fri Feb 17 09:15:16 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(391 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThis Directory contains the source for a Directory Browser Widget and a
Xtest program.  For this program to work the Athena List widget must
Xwork also I and included a patch that will stop the Athena List widget
Xfrom dumping core (this patch dose not fix the problem cause, just the
Xsymptom).  Please mail any bug (and/or fixes) to:
X	
X	shipley@widow.Berkeley.Edu
X		-or-
X	ucbvax!widow!shipley
END_OF_FILE
if test 391 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'AUTHOR' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'AUTHOR'\"
else
echo shar: Extracting \"'AUTHOR'\" \(713 characters\)
sed "s/^X//" >'AUTHOR' <<'END_OF_FILE'
X(Message inbox:687)
XReturn-Path: shipley%WEB.Berkeley.EDU@lilac.berkeley.edu
XReceived:  by wyse.wyse.com (5.58/Wyse master/5-13-88)
X	id AA07715; Sat, 31 Dec 88 03:05:26 PST
XFrom: shipley%WEB.Berkeley.EDU@lilac.berkeley.edu
XReceived: from lilac.Berkeley.EDU by uunet.UU.NET (5.59/1.14) 
X	id AA02624; Sat, 31 Dec 88 01:00:15 EST
XReceived: from web-2e.berkeley.edu
X	by lilac.berkeley.edu (5.54 (CFC 4.22.3)/1.16.18B)
X	id AA13855; Fri, 30 Dec 88 21:58:39 PST
XReceived: by web-2e.berkeley.edu (3.2/SMI-3.0DEV3.9MXl)
X	id AA02582; Fri, 30 Dec 88 22:01:50 PST
XDate: Fri, 30 Dec 88 22:01:50 PST
XMessage-Id: <8812310601.AA02582@web-2e.berkeley.edu>
XTo: mikew@wyse.wyse.com
XSubject: BrowserWidget
X
X
Xmkdir Browser
Xcd Browser
END_OF_FILE
if test 713 -ne `wc -c <'AUTHOR'`; then
    echo shar: \"'AUTHOR'\" unpacked with wrong size!
fi
# end of 'AUTHOR'
fi
if test -f 'Browser.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Browser.c'\"
else
echo shar: Extracting \"'Browser.c'\" \(31119 characters\)
sed "s/^X//" >'Browser.c' <<'END_OF_FILE'
X#if ( !defined(lint) && !defined(Pete_copyright))
X#define Pete_copyright 1
Xstatic char pete_copyright[] = "\
X Copyright 1986 by Peter Shipley All rights reserved\n\
X\n\
X Copy permission is hereby granted provided that this notice is\n\
X retained on all partial or complete copies.\n\
X\n\
X please mail questions and fixes to shipley@widow,berkeley.edu\n";
X#endif
X
X
X#include <stdio.h>
X#include <errno.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/file.h>
X#include <sys/param.h>
X#include <sys/dir.h>
X#include <signal.h>
X
X#include <X11/Xlib.h>
X#include <X11/IntrinsicP.h>
X/*
X#include <X11/Shell.h>
X#include <X11/Form.h>
X*/
X#include <X11/cursorfont.h>
X/* #include <X11/Xlibint.h> */
X#include <X11/AsciiText.h>
X#include <X11/StringDefs.h>
X#include <X11/Xos.h>
X#include <X11/Xutil.h>
X#include <X11/Command.h>
X#include <X11/List.h>
X#include <X11/Viewport.h>
X#include <X11/Xmu.h>
X
X
X#include "BrowserP.h"
X
X/* Private Definitions */
X
Xstatic int def_spacing = 10;
X
X
X    /* {name, class, type, size, offset, default_type, default_addr}, */
Xstatic XtResource resources[] = {
X    {XtNvalue, XtCValue, XtRString, sizeof(String),
X	XtOffset(BrowserWidget, browser.path), XtRString, NULL},
X    {XtNdefaultDistance, XtCThickness, XtRInt, sizeof(int),
X	XtOffset(BrowserWidget, browser.spacing), XtRInt,(caddr_t)&def_spacing},
X    {XtNcancelCallback, XtCCallback, XtRCallback, sizeof(caddr_t),
X	XtOffset(BrowserWidget, browser.sel_callback), XtRCallback, NULL},
X    {XtNopenCallback, XtCCallback, XtRCallback, sizeof(caddr_t),
X	XtOffset(BrowserWidget, browser.can_callback), XtRCallback, NULL},
X    {XtNfunction, XtCFunction, XtRFunction, sizeof (XtWorkProc),
X	XtOffset(BrowserWidget, browser.testProc), XtRFunction, NULL},
X    {XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
X	XtOffset(BrowserWidget, browser.reverse_video), XtRString, "FALSE"}
X};
X
Xstatic Boolean SetValues(), ConstraintSetValues();
Xstatic XtGeometryResult GeometryManager();
Xstatic list_type *createFileList();
X
Xextern int alphasort();
X
X
Xstatic void CreateLabelWidget(),	/* random Widget creation func. */
X	    CreateFileListWidget(),
X	    CreateErrorWidget(),
X	    CreateCommandButtons(),
X
X	    CreateCursors(),
X
X	    followdir(),
X	    Bdestroy(),			/* callback to deallocate shit */
X					/* toolkit failures */
X
X	    UpDateLabel(),		/* Update the path label */
X	    LocalNotify(),		/* generic callback */
X#ifdef DEBUG
X	    showList(),			/* DEBUG func. (prints current list) */
X#endif DEBUG
X
X	    prev_callback(),
X	    next_callback(),
X	    path_completion(),
X	    kill_callback(),
X
X	    dummy(),			/* a do nothing func. */
X
X	    _openCall(),		/* callback for open button */
X	    _cancelCall(),		/* callback for cancel button */
X
X	    ChangeManaged(),
X	    Initialize(),
X	    Resize(),
X	    Realize(),
X	    RefigureLocations(),
X	    ConstraintInitialize(),
X
X	    showError(),
X	    clearError(),
X
X	    SetWorkState(),
X
X	    deleteList();		/* de-allocate current list */
X
X#ifdef DEBUG
X#define printList(X) (void) fprintf(stderr, \
X    "list->count = %d\tmin = '%s'\tmax = '%s'\n", \
X    X->count, X->namelist[0],  X->namelist[X->count -1]);
X#endif DEBUG
X
X
X
X
XBrowserClassRec browserClassRec = {
X  { /* core_class fields */
X    /* superclass         */    (WidgetClass) &compositeClassRec,
X    /* class_name         */    "Browser",
X    /* widget_size        */    sizeof(BrowserRec),
X    /* class_initialize   */    NULL,
X    /* class_part_init    */    NULL,
X    /* class_inited       */    FALSE,
X    /* initialize         */    Initialize,
X    /* initialize_hook    */    NULL,
X    /* realize            */    Realize,
X    /* actions            */    NULL,
X    /* num_actions        */    0,
X    /* resources          */    resources,
X    /* num_resources      */    XtNumber(resources),
X    /* xrm_class          */    NULLQUARK,
X    /* compress_motion    */    TRUE,
X    /* compress_exposure  */    TRUE,
X    /* compress_enterleave*/    TRUE,
X    /* visible_interest   */    FALSE,
X    /* destroy            */    Bdestroy,
X    /* resize             */    Resize,
X    /* expose             */    XtInheritExpose,
X    /* set_values         */    SetValues,
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           */    NULL,
X    /* query_geometry     */	XtInheritQueryGeometry,	/* %%% fix this! */
X    /* display_accelerator*/	XtInheritDisplayAccelerator,
X    /* extension          */	NULL
X  },
X  { /* composite_class fields */
X    /* geometry_manager   */   GeometryManager,
X    /* change_managed     */   NULL, /* ChangeManaged, */
X    /* insert_child       */   XtInheritInsertChild,
X    /* delete_child       */   XtInheritDeleteChild,
X    /* extension          */   NULL
X  },
X  { /* browser_class fields */
X    /* empty              */   0
X  }
X};
X
XWidgetClass browserWidgetClass = (WidgetClass)&browserClassRec;
X
X/****************************************************************
X *
X * Private Procedures
X *
X ****************************************************************/
X
Xstatic void CreateCursors(br)
XBrowserWidget br;
X{
X
Xstatic XColor b = { 0,    0,     0,     0  };  /* black */
Xstatic XColor f = { 0, 65535, 65535, 65535 };  /* white */
X
X#ifdef nodef
XXColor f, b;
X
X    if (XtDisplay(br)->cursor_font == None) {
X	XtDisplay(br)->cursor_font = XLoadFont (XtDisplay(br), CURSORFONT);
X	if (XtDisplay(br)->cursor_font) {
X	    XtWarning("failed to open cursor_font");
X	    return;
X	}
X    }
X
X    if(br->browser.reverse_video) {
X	f = foreground;
X	b = background;
X    } else {
X	b = foreground;
X	f = background;
X    }
X
X    br->browser.ArrowCursor = XCreateGlyphCursor(XtDisplay(br),
X		XtDisplay(br)->cursor_font, XtDisplay(br)->cursor_font,
X		XC_left_ptr, XC_left_ptr +1, &f, &b);
X
X    br->browser.CrossCursor = XCreateGlyphCursor(XtDisplay(br),
X		XtDisplay(br)->cursor_font, XtDisplay(br)->cursor_font,
X		XC_cross, XC_cross +1, &f, &b);
X
X    br->browser.ClockCursor = XCreateGlyphCursor(XtDisplay(br),
X		XtDisplay(br)->cursor_font, XtDisplay(br)->cursor_font,
X		XC_watch, XC_watch +1, &f, &b);
X#endif nodef
X
X    /* get the standard Cursors */
X    br->browser.ArrowCursor = XCreateFontCursor(XtDisplay(br), XC_left_ptr);
X    br->browser.CrossCursor = XCreateFontCursor(XtDisplay(br), XC_cross);
X    br->browser.ClockCursor = XCreateFontCursor(XtDisplay(br), XC_watch);
X
X    /* recolor cursor is we are displayed in reverse video. */
X    if(br->browser.reverse_video) {
X	XRecolorCursor(XtDisplay(br), br->browser.CrossCursor, &f, &b);
X	XRecolorCursor(XtDisplay(br), br->browser.ClockCursor, &f, &b);
X    }
X
X    return;
X}
X
X/* ARGSUSED */
Xstatic void Initialize(request, new)
X    Widget request, new;
X{
X    BrowserWidget br = (BrowserWidget)new;
X
X
X    if(br->core.width == 0) br->core.width = 400;
X    if(br->core.height == 0) br->core.height = 350;
X
X    /* allocate room for path data */
X    br->browser.labelpath = XtMalloc(MAXPATHLEN);
X    br->browser.basepath = XtMalloc(MAXPATHLEN);
X
X    /* labelpath NEEDS to be  NULL */
X    bzero(br->browser.labelpath, MAXPATHLEN);
X
X    /* copy the base into an interal string */
X    (void) strcpy(br->browser.basepath, br->browser.path);
X
X    CreateCursors(br);
X
X    /* get the dirt on the basepath */
X    br->browser.list = (list_type *) createFileList(br, br->browser.path);
X
X#ifdef DEBUG
X    showList(br->browser.list);
X#endif DEBUG
X
X    /* Guess what these do ... */
X    CreateLabelWidget(br);
X
X    CreateErrorWidget(br);
X
X    CreateFileListWidget(br);
X
X    CreateCommandButtons(br);
X
X    /* set the Keyboard Focus */
X    XtSetKeyboardFocus(br, br->browser.b_label);
X
X    /* display the current path */
X    UpDateLabel(br, TRUE);
X
X    return;
X}
X
X
Xstatic void CreateLabelWidget(br)
XBrowserWidget br;
X{
XXtTranslations  text_tran;
X
X    static String newtextTranslations =
X       "Ctrl<Key>W:		prev_callback()\n\
X	Ctrl<Key>M:		next_callback()\n\
X	Ctrl<Key>J:		next_callback()\n\
X	<Key>0xFF0D:		next_callback()\n\
X	<Key>0xFF0A:		next_callback()\n\
X	Meta<Key>I:		dummy()\n\
X	Ctrl<Key>C:		kill_callback()\n\
X	<Key>0xFF1B:    	path_completion()\n\
X	Ctrl<Key>[:		path_completion()\n";
X
X    static XtActionsRec newtext_actions[] = {
X	{"prev_callback",	prev_callback},
X	{"next_callback",	next_callback},
X	{"path_completion",	path_completion},
X	{"kill_callback",	kill_callback},
X	{"dummy",		dummy}
X    };
X
X    static Arg label_arg[] = {
X	{XtNstring,		(XtArgVal) NULL},
X	{XtNcursor,		(XtArgVal) NULL},
X	{XtNlength,		(XtArgVal) MAXPATHLEN},
X	{XtNtextOptions,	(XtArgVal) editable},
X	{XtNeditType,		(XtArgVal) XttextEdit},
X	{XtNjustify,		(XtArgVal) XtJustifyLeft},
X	{XtNborderWidth,	(XtArgVal) 0},
X	{XtNresize,		(XtArgVal) FALSE}
X    };
X
X    label_arg[0].value = (XtArgVal) br->browser.labelpath;
X    label_arg[1].value = (XtArgVal) br->browser.CrossCursor;
X
X    br->browser.b_label = XtCreateManagedWidget("Browser_label",
X		asciiStringWidgetClass, br, label_arg, XtNumber(label_arg));
X
X    /* install the new actions record */
X    XtAddActions(newtext_actions, XtNumber(newtext_actions));
X
X    /* creat a Translation Table */
X    text_tran = XtParseTranslationTable(newtextTranslations);
X
X    /* install the new Translation Table */
X    XtOverrideTranslations(br->browser.b_label, text_tran);
X
X    return;
X}
X
X
Xstatic void CreateFileListWidget(br)
XBrowserWidget br;
X{
XXtTranslations list_trans;
X
X    static Arg view_args[] = {
X	{XtNallowVert,          (XtArgVal) TRUE},
X	{XtNforceBars,          (XtArgVal) TRUE},
X	{XtNresize,             (XtArgVal) FALSE},
X	{XtNuseRight,           (XtArgVal) TRUE}
X    };
X
X    static String newTranslations =
X	"<Btn1Down>:    Set()\n\
X	<Btn1Down>(2+): Notify()\n";
X
X    static XtCallbackRec list_call[] = {
X	{(XtCallbackProc) _openCall,	(caddr_t) NULL},
X	{(XtCallbackProc) NULL,		(caddr_t) NULL}
X    };
X
X    static Arg list_args[] = {
X	{XtNlist,		(XtArgVal) NULL},
X	{XtNnumberStrings,	(XtArgVal) NULL},
X	{XtNcallback,		(XtArgVal) list_call},
X	{XtNverticalList,	(XtArgVal) TRUE},
X	{XtNforceColumns,	(XtArgVal) 1},
X	{XtNdefaultColumns,	(XtArgVal) 1},
X	{XtNcolumnSpacing,	(XtArgVal) 1000}
X    };
X
X
X    list_call[0].closure = (caddr_t) br;
X
X    list_args[0].value = (XtArgVal) br->browser.list->list;
X    list_args[1].value = (XtArgVal) br->browser.list->count;
X
X    /* create a viewport widget so the list widget will have scrollbars */
X    br->browser.b_view = XtCreateManagedWidget( "view", viewportWidgetClass,
X			br, view_args, XtNumber(view_args));
X
X    /* Create the list widget at a child of the viewport widget */
X    br->browser.b_list = XtCreateManagedWidget( "list", listWidgetClass,
X			br->browser.b_view, list_args, XtNumber(list_args));
X
X    /* Parse the replacement TranslationTable and install it */
X    list_trans = XtParseTranslationTable(newTranslations);
X    XtOverrideTranslations(br->browser.b_list, list_trans);
X
X    return;
X}
X
Xstatic void CreateErrorWidget(br)
XBrowserWidget br;
X{
X    static Arg error_list[] = {
X	{XtNjustify,		(XtArgVal) XtJustifyLeft},
X	{XtNborderWidth,	(XtArgVal) 0},
X	{XtNresize,             (XtArgVal) FALSE},
X	{XtNlabel,		(XtArgVal) ">"}
X    };
X
X    br->browser.b_error = XtCreateManagedWidget("error", labelWidgetClass,
X			br, error_list, XtNumber(error_list));
X    return;
X}
X
X
Xstatic void CreateCommandButtons(br)
XBrowserWidget br;
X{
X    static XtCallbackRec cancel_call[] = {
X	{(XtCallbackProc) _cancelCall,	(caddr_t) NULL},
X	{(XtCallbackProc) NULL,		(caddr_t) NULL}
X    };
X
X    static XtCallbackRec open_call[] = {
X	{(XtCallbackProc) _openCall,	(caddr_t) NULL},
X	{(XtCallbackProc) NULL,		(caddr_t) NULL}
X    };
X
X    static Arg comm_args[] = {
X	{XtNcursor,		(XtArgVal) NULL},
X	{XtNlabel,		(XtArgVal) "Open"},
X	{XtNcallback,		(XtArgVal) open_call},
X	{XtNresize,             (XtArgVal) FALSE},
X	{XtNresizable,		(XtArgVal) FALSE},
X	{XtNwidth,		(XtArgVal) 70}
X    };
X
X    comm_args[0].value = (XtArgVal) br->browser.ArrowCursor;
X
X    /* compleate the callback data arrays */
X    open_call[0].closure = cancel_call[0].closure = (caddr_t) br;
X
X    /* create the open button */
X    br->browser.b_open = XtCreateManagedWidget( "open", commandWidgetClass,
X			br, comm_args, XtNumber(comm_args) );
X
X    /* reuses the arg array for the Cancel button */
X    comm_args[1].value = (XtArgVal) "Cancel";
X    comm_args[2].value = (XtArgVal) cancel_call;
X
X    /* and now the Cancel command button */
X    br->browser.b_cancel = XtCreateManagedWidget( "Cancel", commandWidgetClass,
X			br, comm_args, XtNumber(comm_args));
X
X    return;
X}
X
X
Xstatic void RefigureLocations(wi)
X    BrowserWidget wi;
X{
X    BrowserWidget br = (BrowserWidget)wi;
X
X    Position x, y, y1;
X
X#ifdef DEBUG
X    (void) fputs("RefigureLocations called\n", stderr);
X#endif DEBUG
X
X    /* first we do the label bar */
X    XtConfigureWidget(br->browser.b_label,
X		br->browser.spacing, br->browser.spacing,	/* x & y*/
X		br->core.width -(br->browser.spacing *2) 	/* width */
X		-(br->browser.b_label->core.border_width *2),
X		br->browser.b_label->core.height,		/* height */
X		br->browser.b_label->core.border_width);	/* border */
X
X    /* here we calc the Y Position for the selection list & buttons  */
X    y1 = br->browser.b_label->core.height
X	    +(br->browser.spacing *2)
X	    +(br->browser.b_label->core.border_width *2);
X
X
X    /* calc the X Position for the buttons */
X    x = br->core.width -br->browser.spacing -br->browser.b_cancel->core.width;
X
X    /* Position the first button */
X    XtMoveWidget(br->browser.b_open, x, y1);
X
X    XtMoveWidget(br->browser.b_cancel, x, 
X	    y1 +br->browser.spacing
X	    +br->browser.b_open->core.height
X	    +(br->browser.b_open->core.border_width *2));
X
X
X    /* here we calc the Y Position error area */
X    y = br->core.height -br->browser.spacing -br->browser.b_error->core.height
X		-(br->browser.b_error->core.border_width *2);
X
X    XtConfigureWidget(br->browser.b_error,
X	    br->browser.spacing, y,				/* x & y */
X	    br->core.width -(br->browser.spacing *2)		/* width */
X	    -(br->browser.b_error->core.border_width *2),
X	    br->browser.b_error->core.height,			/* height */
X	    br->browser.b_error->core.border_width);		/* border */
X
X
X
X    XtConfigureWidget(br->browser.b_view,
X	    br->browser.spacing, y1,				/* x & y */
X	    x -(br->browser.b_view->core.border_width *2)	/* width */
X	    -(br->browser.spacing *2),
X	    y -(br->browser.b_view->core.border_width *2)	/* height */
X	    -y1 -br->browser.spacing,
X	    br->browser.b_view->core.border_width);		/* border */
X
X    /* done */
X    return;
X}
X
X
Xstatic void Realize(wi, value_mask, attributes)
XWidget               wi;
XMask                 *value_mask;
XXSetWindowAttributes *attributes;
X{
X
X#ifdef DEBUG
X    (void) fputs("Realize called\n", stderr);
X#endif DEBUG
X
X    XtCreateWindow(wi, (unsigned int) InputOutput,
X	(Visual *) CopyFromParent, *value_mask, attributes);
X
X    RefigureLocations((BrowserWidget) wi);
X
X    XDefineCursor(XtDisplay(wi), XtWindow(wi),
X			((BrowserWidget) wi)->browser.CrossCursor);
X
X    return;
X}
X
X
Xstatic void Resize(w)
X    Widget w;
X{
X
X#ifdef DEBUG
X    (void) fputs("Resize called\n", stderr);
X#endif DEBUG
X
X    RefigureLocations((BrowserWidget) w);
X
X    return;
X}
X
X
X/* ARGSUSED */
Xstatic XtGeometryResult GeometryManager(w, request, reply)
X    Widget w;
X    XtWidgetGeometry *request;
X    XtWidgetGeometry *reply;	/* RETURN */
X{
X#ifdef DEBUG
X    (void) fprintf(stderr, "GeometryManager called: %s\n", w->core.name);
X#endif DEBUG
X
X    return XtGeometryNo;
X}
X
X
X
X/* ARGSUSED */
Xstatic Boolean SetValues(current, request, new)
X    Widget current, request, new;
X{
X    BrowserWidget br = (BrowserWidget)new;
X    BrowserWidget old = (BrowserWidget)current;
X
X#ifdef DEBUG
X    (void) fputs("SetValues called\n", stderr);
X#endif DEBUG
X
X    if(br->browser.path != old->browser.path
X	|| br->browser.path != NULL
X	    && (old->browser.path != NULL
X	    && strcmp(br->browser.path, old->browser.path)))
X    {
X	/* delete the old list */
X	deleteList(old->browser.list);
X
X	/* copy the new path into a safe area */
X	(void) strcpy(br->browser.basepath, br->browser.path);
X
X	/* create list of file to select from */
X	br->browser.list = createFileList(br, br->browser.path);
X
X	/* Update the displayed list */
X	XtListChange(br->browser.b_list, br->browser.list->list,
X		    br->browser.list->count, 0, TRUE);
X
X	/* update the displayed label */
X	UpDateLabel(br, TRUE);
X
X    }
X
X    return( FALSE );
X}
X
X/* this is the util. for creating file listings */
Xstatic list_type *createFileList(br, selection)
XBrowserWidget br;
Xchar *selection;
X{
Xregister Cardinal    i;
Xstruct stat stat_buf;
Xlist_type *ret_list;
Xextern errno;
X
X    errno = 0;
X
X    /* open requested directory */
X    if (selection == (char *) NULL)
X	selection = ".";
X
X    /* malloc the return list */
X    ret_list = (list_type *) XtMalloc(sizeof (list_type));
X
X
X    /* report fuckups */
X    if (ret_list == NULL) {
X	return (list_type *) NULL;
X    }
X
X    ret_list->count =
X		scandir(selection, &ret_list->namelist, br->browser.testProc,
X		alphasort);
X
X    /* test the scaning */
X    if(ret_list->count == -1) {
X#ifdef DEBUG
X	XtWarning("Fucked up in opening dir");
X#endif DEBUG
X	XtFree((char *) ret_list);
X	return (list_type *) NULL;
X    }
X
X    ret_list->list = (char **)XtCalloc(ret_list->count +1, sizeof(char *));
X    ret_list->mode = (int *)  XtCalloc(ret_list->count, sizeof(int));
X
X    for(i=0; i < ret_list->count; i++) {
X	int len;
X	char tbuf[MAXNAMLEN +2];
X
X	/* get the length of the file name for later use [and reuse] */
X	len = strlen(ret_list->namelist[i]->d_name) + 2;
X
X	/* copy file name into a new buffer */
X	ret_list->list[i] =
X		strcpy( XtMalloc(len), ret_list->namelist[i]->d_name);
X
X	/* copy the current directory into a tempory space */
X	(void) strcpy(tbuf, selection);
X
X	/* add a "/" to the current directory path if it's not there already */
X	if (tbuf[strlen(tbuf) -1] != '/')
X	    (void) strcat(tbuf, "/");
X
X	/* tack on the current file name */
X	(void) strcat(tbuf, ret_list->list[i]);
X
X	/* get the status of our 'file', if we fail ignore the file */
X	if ( stat(tbuf, &stat_buf) != 0 ) {
X#ifdef DEBUG
X	    (void) perror(ret_list->namelist[i]->d_name);
X	    XtWarning("Fucked up in stating file");
X#endif DEBUG
X	    showError(br, ret_list->list[i]);
X	    continue;
X	}
X
X	ret_list->mode[i] = stat_buf.st_mode;
X
X	/* add the '/' to the end of the name to indicate directrices, etc..*/
X	switch (ret_list->mode[i] & S_IFMT) {
X	    case S_IFDIR:
X		(void) strcat(ret_list->list[i], "/");
X		break;
X	    case S_IFSOCK:
X		(void) strcat(ret_list->list[i], "=");
X		break;
X	    default:
X		if ( (stat_buf.st_mode & ~S_IFMT) & 0111)
X		    (void) strcat(ret_list->list[i], "*");
X		break;
X	}
X    }
X
X    /* null out the next slot [it should be null from calloc but..] */
X    ret_list->list[i +1] = (char *) NULL;
X
X#ifdef DEBUG
X    printList(ret_list);
X#endif DEBUG
X
X    /* return with our work */
X    return ret_list;
X}
X
X
X/* A clean up utility */
Xstatic void deleteList(dead_list)
Xlist_type *dead_list;
X{
Xregister int i;
X
X    /* Test to see it we have a list */
X    if(dead_list == (list_type *) NULL)
X	return;
X
X    /* free the strings */
X    for(i=0; i < dead_list->count; i++) {
X	XtFree( (char *) dead_list->list[i]);
X    }
X
X    XtFree((char *) dead_list->namelist);
X    XtFree((char *) dead_list->list);
X    XtFree((char *) dead_list);
X
X    return;
X}
X
X
X
X/*ARGUSED*/
Xstatic void _cancelCall(wi, client_data, call_data)
XWidget wi;
Xcaddr_t client_data;
Xcaddr_t call_data;
X{
XBrowserWidget br = (BrowserWidget)client_data;
X
X    /* Change the Cursors to a clock so the they think we're fuckup */
X    SetWorkState(br, TRUE);
X
X    /* Clear the error line*/
X    clearError(br);
X
X    XtCallCallbacks((Widget) br, XtNcancelCallback, (char *) NULL);
X
X    /* Tell the user we are done */
X    SetWorkState(br, FALSE);
X
X    return;
X}
X
X
X/*ARGUSED*/
Xstatic void _openCall(wi, client_data, call_data)
XWidget wi;
Xcaddr_t client_data;
Xcaddr_t call_data;
X{
Xint i;
XXtListReturnStruct *ret_value;
XBrowserWidget br = (BrowserWidget)client_data;
X
X    /* Clear the error line*/
X    clearError(br);
X
X    /* get the current selected list */
X    ret_value = XtListShowCurrent(br->browser.b_list);
X    i = ret_value->index;
X
X    /* free as soon as we don't need */
X    XtFree((char *)ret_value);
X
X
X    /* test to see it there is a current seletion */
X    if( i != XT_LIST_NONE ) {
X
X	/* Change the Cursors to a clock so the they think we're fuckup */
X	SetWorkState(br, TRUE);
X
X	/* test if we are looking at a directory or not */
X	if ( br->browser.list->mode[i] & (S_IFMT & S_IFDIR) )
X	    followdir(br, br->browser.list->namelist[i]->d_name);
X	else
X	    XtCallCallbacks((Widget) br, XtNopenCallback,
X			    br->browser.list->namelist[i]->d_name);
X
X	/* Tell the user we are done */
X	SetWorkState(br, FALSE);
X
X    }
X
X    return;
X}
X
X
X
X
Xstatic void followdir(br, new_path)
XBrowserWidget br;
XString new_path;
X{
Xregister u_int i;
Xchar	*c;
Xchar	t_path[MAXPATHLEN];
Xlist_type *t_list;
X
X    /* reset the error index */
X    clearError(br);
X
X#ifdef DEBUG
X    (void) fputs("followdir\n", stderr);
X#endif DEBUG
X
X    /* just in case save the old path and lists */
X    (void) strcpy(t_path, br->browser.basepath);
X    t_list = br->browser.list;
X
X    /* see it we are just backing up one dir, there has to be a better way.. */
X    if( strncmp(new_path, "..", 2) == 0 ) {
X
X	/* get the last occurance of the char '/' in the string  */
X	c = rindex(br->browser.basepath, '/');
X
X	/* report if it is not possible to back out */
X	if(c == (char *)NULL) {
X	    showError(br, "Burp!: could not track '/'");
X	    return;
X	}
X
X	/* check if we index'ed  to root's "/" */
X	if ( c == br->browser.basepath ) {
X	    (void) strcpy(br->browser.basepath, "/");
X	} else {
X	    /* Null out the rest of the string */
X	    while( *c != '\0') *c++ = '\0';
X	}
X
X    } else {
X
X	i = strlen(br->browser.basepath) -1;
X
X	if (br->browser.basepath[i] != '/')
X	    (void) strcat(br->browser.basepath, "/");
X
X	(void) strcat(br->browser.basepath, new_path);
X
X	i = strlen(br->browser.basepath) -1;
X
X	if (br->browser.basepath[i] == '/')
X	    br->browser.basepath[i] = (char) NULL;
X    }
X
X    /* create a new list of files useing the new base path */
X    br->browser.list = createFileList(br, br->browser.basepath);
X
X    /* Test the new list, if error report it and restore old values */
X    if (br->browser.list == (list_type *) NULL) {
X	showError(br, br->browser.basepath);
X	(void) strcpy(br->browser.basepath, t_path);
X	br->browser.list = t_list;
X	return;
X    }
X
X    /* free the storage used by the current list */
X    deleteList(t_list);
X
X#ifdef DEBUG
X    showList(br->browser.list);
X    (void) fprintf(stderr, "basepath = `%s`\n", br->browser.basepath);
X#endif DEBUG
X
X    /* Update the path label with the new path */
X    UpDateLabel(br, TRUE);
X
X    /* Update the listing with the new list */
X    XtListChange(br->browser.b_list, br->browser.list->list, br->browser.list->count, 0, TRUE);
X
X    return;
X}
X
X#ifdef DEBUG
Xstatic void showList(ll)
Xlist_type *ll;
X{
Xregister int i;
X
X    for (i=0; i < ll->count; i++)
X	(void) fprintf(stderr,
X	"%d:\tlist->list[i] = `%s`\tnamelist[i]->d_name= `%s`\tmode = %lo\n",
X	    i, ll->list[i], ll->namelist[i]->d_name, ll->mode[i]);
X
X    printList(ll);
X
X    return;
X}
X#endif DEBUG
X
Xstatic void UpDateLabel(br, copy)
XBrowserWidget br;
XBoolean copy;
X{
XXtTextPosition len;
X
X    /* Unset whatever maybe highlighted */
X    XtTextUnsetSelection(br->browser.b_label);
X
X    /* copy the real path in the shown path */
X    if(copy)
X	(void) strcpy(br->browser.labelpath, br->browser.basepath);
X
X    /* get the length of the current path */
X    len = (XtTextPosition) strlen(br->browser.labelpath);
X
X    /* set the last position in the buffer */
X    XtTextSetLastPos(br->browser.b_label, len);
X
X    /* move the Cursor to the last position in the buffer */
X    XtTextSetInsertionPoint(br->browser.b_label, len);
X
X    return;
X}
X
X/* this is the callback for our widget when it it is destroyed */
Xstatic void Bdestroy(wi)
XWidget wi;
X{
X    BrowserWidget br = (BrowserWidget)wi;
X
X#ifdef DEBUG
X    (void) fputs("Bdestroy called\n", stderr);
X#endif DEBUG
X
X    deleteList(br->browser.list);
X
X    XtFree(br->browser.basepath);
X    XtFree(br->browser.labelpath);
X
X    XFreeCursor(br->browser.ArrowCursor);
X    XFreeCursor(br->browser.CrossCursor);
X    XFreeCursor(br->browser.ClockCursor);
X
X    return;
X}
X
Xstatic void
Xprev_callback(wi)
XWidget wi;
X{
Xchar *c;
XBrowserWidget br = (BrowserWidget)XtParent(wi);
X
X    /* clear the error window */
X    clearError(br);
X
X    /* get the last occurance of the char '/' in the string  */
X    c = rindex(br->browser.labelpath, '/');
X
X    /* report if it is not possible to back out */
X    if(c == (char *)NULL) {
X	showError(br, "Burp!: could not track '/'");
X	XBell(XtDisplay(br), 0);
X	return;
X    }
X
X    /* check if we index'ed  to root's "/" */
X    if ( c == br->browser.labelpath ) {
X	(void) strcpy(br->browser.labelpath, "/");
X    } else {
X	/* Null out the rest of the string */
X	while( *c != '\0') *c++ = '\0';
X    }
X
X    /* have the label reflect the change */
X    UpDateLabel(br, FALSE);
X
X    return;
X}
X
Xstatic void next_callback(wi)
XWidget wi;
X{
Xstruct stat stat_buf;
XBrowserWidget br = (BrowserWidget)XtParent(wi);
X
X#ifdef DEBUG
X    (void) fputs("next_callback called\n", stderr);
X#endif DEBUG
X
X	/* turn off input and set the cursors to a clock */
X	SetWorkState(br, TRUE);
X
X	/* clear the error window */
X	clearError(br);
X
X	/* get the status of our 'file', if we fail ignore the file */
X	if ( stat(br->browser.labelpath, &stat_buf) != 0 ) {
X		showError(br, br->browser.labelpath);
X	}
X
X	if (stat_buf.st_mode & (S_IFMT & S_IFDIR) ) {
X	    list_type *t_list = br->browser.list;
X
X	    br->browser.list = createFileList(br, br->browser.labelpath);
X
X	    /* Test the new list */
X	    if (br->browser.list == (list_type *) NULL) {
X
X		/* (void) strcpy(br->browser.basepath, t_path); */
X		br->browser.list = t_list;
X		showError(br, br->browser.labelpath);
X		SetWorkState(br, FALSE);
X		return;
X	    }
X
X	    /* Update the listing with the new list */
X	    XtListChange(br->browser.b_list, br->browser.list->list,
X				    br->browser.list->count, 0, TRUE);
X
X	    (void) strcpy(br->browser.basepath, br->browser.labelpath);
X
X	    /* this should not be needed */
X	    UpDateLabel(br, FALSE);
X
X	} else
X	    XtCallCallbacks(br, XtNopenCallback, br->browser.labelpath);
X
X    SetWorkState(br, FALSE);
X
X    return;
X}
X
Xstatic void path_completion(wi)
XWidget wi;
X{
Xchar *c;
Xint     len;
Xint    dir_count;
Xu_int   i;
Xu_int   hit=0;
Xchar    selection[MAXPATHLEN];
Xchar	name[MAXNAMLEN];
Xstruct direct **dir_list;
XBoolean free;
XBrowserWidget br = (BrowserWidget)XtParent(wi);
X
X
X#ifdef DEBUG
X    (void) fputs("path_completion called\n", stderr);
X#endif DEBUG
X
X    clearError(br);
X
X    /* get the last occurance of the char '/' in the string  */
X    c = rindex(br->browser.labelpath, '/');
X
X    /* report if it is not possible to back out */
X    if(c == (char *)NULL) {
X	c = br->browser.labelpath;
X	/*
X	showError(br, "Burp!: could not track '/'");
X	return;
X	*/
X    }
X
X    /* move forward to skip the '/' */
X    *c++;
X
X    len = strlen(c);
X
X    /* we will have trouble it these strings are not nulled */
X    bzero(name, MAXNAMLEN);
X    bzero(selection, MAXPATHLEN);
X
X    (void) strncpy(selection, br->browser.labelpath,
X		((int)c -(int)br->browser.labelpath));
X
X    if (strcmp(selection, br->browser.basepath) == 0) {
X	dir_count = br->browser.list->count;
X	dir_list = br->browser.list->namelist;
X	free = FALSE;
X    } else {
X	dir_count = scandir(selection, &dir_list, br->browser.testProc,
X		alphasort);
X
X	if ( dir_count == -1) {
X	    showError(br, selection);
X	    return;
X	}
X
X	free = TRUE;
X    }
X
X    /* Enter Loop only if there is something to do */
X    if (len > 0) {
X	for(i=0; i < dir_count; i++)
X	    if ( strncmp(c, dir_list[i]->d_name, len) == 0) {
X		/* if this is the first match copy if in full */
X		hit++;
X		if(hit == 1)
X		    (void) strcpy(name, dir_list[i]->d_name);
X		else {
X		    register int j=0;
X
X		    for(; dir_list[i]->d_name[j] == name[j]; j++);
X
X		    name[j] = '\0';
X
X		    if(j == len)
X			break;
X		}
X	    }
X
X
X	/* Ugly Ugly Ugly */
X	if(hit == 0) {
X
X	    XBell(XtDisplay(br), 0);
X	    showError(br, "No matches found");
X
X	} else {
X
X	    /* if we matched more then once ring bell */
X	    if(hit > 1) {
X		char tbuf[MAXPATHLEN];
X
X		(void) strcpy(tbuf, "\"");
X		(void) strcat(tbuf, c);
X		(void) strcat(tbuf, "\": ambiguous");
X
X		XBell(XtDisplay(br), 0);
X		showError(br, tbuf);
X	    }
X
X	    /* if we matched ANYTHING add the result to the current path*/
X	    if(hit) {
X		(void) strcpy(c, name);
X		UpDateLabel(br, FALSE);
X	    }
X	}
X
X
X    }
X
X    if(free)
X	XtFree((char *) dir_list);
X
X    return;
X}
X
Xstatic void dummy()
X{
X#ifdef DEBUG
X    (void) fputs("dummy called\n", stderr);
X#endif DEBUG
X    return;
X}
X
X/* this is call if the user types in a Cont-C */
Xstatic void kill_callback(wi)
XWidget wi;
X{
XBrowserWidget br = (BrowserWidget)XtParent(wi);
X
X    XtCallCallbacks(br, XtNcancelCallback, NULL);
X
X    return;
X}
X
Xstatic void clearError(br)
XBrowserWidget br;
X{
X
X    static Arg update_arg[] = {
X	{XtNlabel,		(XtArgVal) ">"}
X    };
X
X    errno = 0;
X
X#ifdef DEBUG
X    (void) fputs("clearError called\n", stderr);
X#endif DEBUG
X
X    XtSetValues(br->browser.b_error, update_arg, XtNumber(update_arg));
X
X    return;
X}
X
X
X/*
X * This func displays the current error in
X * a error window on the browser window
X */
Xstatic void showError(br, string)
XBrowserWidget br;
Xchar *string;
X{
Xchar    tbuf[MAXPATHLEN +80];
Xextern  char *sys_errlist[];
Xextern  int sys_nerr;
Xextern  int errno;
X
X    static Arg update_arg[] = {
X	{XtNlabel,		(XtArgVal) NULL}
X    };
X
X    if (string != (char *) NULL)
X	(void) strcpy(tbuf, string);
X    else
X	(void) strcpy(tbuf, "Error");
X
X#ifdef DEBUG
X    (void) perror(tbuf);
X#endif DEBUG
X
X    if (errno > 0 && errno < sys_nerr) {
X	(void) strcat(tbuf, ": ");
X	(void) strcat(tbuf, sys_errlist[errno]);
X    }
X
X    update_arg[0].value = (XtArgVal) tbuf;
X
X    XBell(XtDisplay(br), 0);
X
X    if(XtIsRealized(br))
X	XtSetValues(br->browser.b_error, update_arg, XtNumber(update_arg));
X
X    return;
X}
X
Xstatic void SetWorkState(br, state)
XBrowserWidget br;
XBoolean state;
X{
X
X    if (state) {
X	XDefineCursor(XtDisplay(br), XtWindow(br), br->browser.ClockCursor);
X	XDefineCursor(XtDisplay(br), XtWindow(br->browser.b_list),
X			    br->browser.ClockCursor);
X	XDefineCursor(XtDisplay(br), XtWindow(br->browser.b_label),
X			    br->browser.ClockCursor);
X
X
X	XtSetSensitive(br->browser.b_open, FALSE);
X	XtSetSensitive(br->browser.b_label, FALSE);
X	XtSetSensitive(br->browser.b_cancel, FALSE);
X
X    } else {
X
X	XDefineCursor(XtDisplay(br), XtWindow(br), br->browser.CrossCursor);
X	XDefineCursor(XtDisplay(br), XtWindow(br->browser.b_list),
X			    br->browser.ArrowCursor);
X	XDefineCursor(XtDisplay(br), XtWindow(br->browser.b_label),
X			    br->browser.CrossCursor);
X
X	XtSetSensitive(br->browser.b_open, TRUE);
X	XtSetSensitive(br->browser.b_label, TRUE);
X	XtSetSensitive(br->browser.b_cancel, TRUE);
X    }
X
X    return;
X}
X
X/**********************************************************************
X *
X * Public routines
X *
X **********************************************************************/
X
X/* none */
X
X
X/* END OF TEXT */
END_OF_FILE
if test 31119 -ne `wc -c <'Browser.c'`; then
    echo shar: \"'Browser.c'\" unpacked with wrong size!
fi
# end of 'Browser.c'
fi
if test -f 'Browser.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Browser.h'\"
else
echo shar: Extracting \"'Browser.h'\" \(2121 characters\)
sed "s/^X//" >'Browser.h' <<'END_OF_FILE'
X#if ( !defined(lint) && !defined(Pete_copyright))
X#define Pete_copyright 1
Xstatic char pete_copyright[] = "\
X Copyright 1986 by Peter Shipley All rights reserved\n\
X\n\
X Copy permission is hereby granted provided that this notice is\n\
X retained on all partial or complete copies.\n\
X\n\
X please mail questions and fixes to shipley@widow,berkeley.edu\n";
X#endif
X
X#ifndef _Browser_h
X#define _Browser_h
X
X#include <X11/Constraint.h>
X
X/***********************************************************************
X *
X * Browser Widget
X *
X ***********************************************************************/
X
X/* Parameters:
X
X Name		     Class		RepType		Default Value
X ----		     -----		-------		-------------
X background	     Background		Pixel		XtDefaultBackground
X border		     BorderColor	Pixel		XtDefaultForeground
X borderWidth	     BorderWidth	Dimension	1
X defaultDistance     Thickness		int		4
X destroyCallback     Callback		Pointer		NULL
X height		     Height		Dimension	computed at realize
X mappedWhenManaged   MappedWhenManaged	Boolean		True
X sensitive	     Sensitive		Boolean		True
X width		     Width		Dimension	computed at realize
X x		     Position		Position	0
X y		     Position		Position	0
X
X*/
X
X/* Constraint parameters:
X
X Name		     Class		RepType		Default Value
X ----		     -----		-------		-------------
X bottom		     Edge		XtEdgeType	XtRubber
X fromHoriz	     Widget		Widget		(left edge of browser)
X fromVert	     Widget		Widget		(top of browser)
X horizDistance	     Thickness		int		defaultDistance
X left		     Edge		XtEdgeType	XtRubber
X resizable	     Boolean		Boolean		False
X right		     Edge		XtEdgeType	XtRubber
X top		     Edge		XtEdgeType	XtRubber
X vertDistance	     Thickness		int		defaultDistance
X
X*/
X
X
X
X#define XtNopenCallback		"openCallback"
X#define XtNcancelCallback	"cancelCallback"
X
X#define XtNdefaultDistance	"defaultDistance"
X#define XtNresizable		"resizable"
X
X#define XtCEdge			"Edge"
X#define XtCWidget		"Widget"
X
X#define XtRWidget		"Widget"
X
Xtypedef struct _BrowserClassRec	*BrowserWidgetClass;
Xtypedef struct _BrowserRec	*BrowserWidget;
X
Xextern WidgetClass browserWidgetClass;
X 
X#endif _Browser_h
X
END_OF_FILE
if test 2121 -ne `wc -c <'Browser.h'`; then
    echo shar: \"'Browser.h'\" unpacked with wrong size!
fi
# end of 'Browser.h'
fi
if test -f 'BrowserP.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'BrowserP.h'\"
else
echo shar: Extracting \"'BrowserP.h'\" \(2195 characters\)
sed "s/^X//" >'BrowserP.h' <<'END_OF_FILE'
X#if ( !defined(lint) && !defined(Pete_copyright))
X#define Pete_copyright 1
Xstatic char pete_copyright[] = "\
X Copyright 1986 by Peter Shipley All rights reserved\n\
X\n\
X Copy permission is hereby granted provided that this notice is\n\
X retained on all partial or complete copies.\n\
X\n\
X please mail questions and fixes to shipley@widow,berkeley.edu\n";
X#endif
X/* Browser widget private definitions */
X
X#ifndef _BrowserP_h
X#define _BrowserP_h
X
X#include "Browser.h"
X#include <X11/CompositeP.h>
X
Xtypedef struct {int empty;} BrowserClassPart;
X
Xtypedef struct _BrowserClassRec {
X    CoreClassPart	core_class;
X    CompositeClassPart	composite_class;
X    BrowserClassPart	browser_class;
X} BrowserClassRec;
X
Xextern BrowserClassRec browserClassRec;
X
X
Xtypedef struct _list_type {
X    char   **list;              /* a list of strings for listWidget*/
X    struct direct **namelist;
X    int    count;
X    int    *mode;
X} list_type;
X
X
Xtypedef struct _BrowserPart {
X    String    basepath;			/* Current scaned path */
X    String    labelpath;		/* Current displayed scaned path */
X    String    path;			/* starting path */
X
X    Widget    b_view;			/* Viewport widget for scrollbar*/
X    Widget    b_list;			/* listWidget, child of Viewport */
X    Widget    b_open;			/* "Open" command widget */
X    Widget    b_cancel;			/* "Cancel" command widget */
X    Widget    b_label;			/* path label */
X    Widget    b_error;			/* error output */
X
X    int       spacing;
X
X    XtWorkProc  testProc;		/* pointer to fun that returns Boolean
X					   takes a String for a arg and test
X					   if it should be included in
X					   selection list */
X    Boolean   reverse_video;
X
X    Cursor    ArrowCursor;		/* Cursor for list & command widget */
X    Cursor    CrossCursor;		/* Cursor for formWidget */
X    Cursor    ClockCursor;		/* Wait Cursor list & command widget */
X
X    XtCallbackList sel_callback;	/* callback func. for Cancel widget */
X    XtCallbackList can_callback;	/* callback func. for Open widget */
X
X    list_type *list;			/* struct containing list data */
X
X} BrowserPart;
X
Xtypedef struct _BrowserRec {
X    CorePart		core;
X    CompositePart	composite;
X    BrowserPart		browser;
X} BrowserRec;
X
X#endif _BrowserP_h
END_OF_FILE
if test 2195 -ne `wc -c <'BrowserP.h'`; then
    echo shar: \"'BrowserP.h'\" unpacked with wrong size!
fi
# end of 'BrowserP.h'
fi
if test -f 'ListWidget.patch' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ListWidget.patch'\"
else
echo shar: Extracting \"'ListWidget.patch'\" \(170 characters\)
sed "s/^X//" >'ListWidget.patch' <<'END_OF_FILE'
X447,453d446
X<     if ( item >= lw->list.nitems ) {
X< #ifdef DEBUG
X< 	XtWarning("ListWidget: HighlightBackground:  item > nitems\n");
X< #endif DEBUG
X< 	return;
X<     }
X< 
END_OF_FILE
if test 170 -ne `wc -c <'ListWidget.patch'`; then
    echo shar: \"'ListWidget.patch'\" unpacked with wrong size!
fi
# end of 'ListWidget.patch'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(1189 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XDEST	      = /global/bin
X
XEXTHDRS	      = /usr/include/signal.h \
X		/usr/include/stdio.h
X
XHDRS	      = Browser.h \
X		BrowserP.h
X
XLDFLAGS	      =  -L/global/lib
X
XCFLAGS	      = -g -I/global/include
X#-DDEBUG
X
XLIBS	      = -lXaw -lXmu -lXt -lX11 
X
XLINKER	      = /bin/cc
X
XCC	      = /bin/cc
X
XMAKEFILE      = Makefile
X
XOBJS	      = Browser.o \
X		main.o
X
XPRINT	      = enscript
X
XPROGRAM	      = test
X
XSRCS	      = Browser.c \
X		main.c
X
Xall:		$(PROGRAM)
X
X$(PROGRAM):     $(OBJS)
X		@echo "Loading $(PROGRAM) ... "
X		$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
X		@echo "done"
X
Xclean:;		/bin/rm -f $(OBJS) *~ \#* core
X
Xdepend:;	@mkmf -d -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST) 
X
Xindex:;		ctags -wx $(HDRS) $(SRCS)  ;
X
Xinstall:	$(PROGRAM)
X		@echo Installing $(PROGRAM) in $(DEST)
X		@install -s $(PROGRAM) $(DEST)
X
Xprint:;		@$(PRINT) $(HDRS) $(SRCS)
X
Xprogram:        $(PROGRAM)
X
Xlint:;		lint $(SRCS) -I/usr/X11 -I.
X
Xtags:           $(HDRS) $(SRCS)
X		ctags -tw $(HDRS) $(SRCS) 
X
Xupdate:		$(DEST)/$(PROGRAM)
X
X$(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS)
X		@make -f $(MAKEFILE) DEST=$(DEST) install
X
Xnew:		clean $(PROGRAM)
X
X###
X
XBrowser.o: BrowserP.h Browser.h
Xmain.o: Browser.h
END_OF_FILE
if test 1189 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'browser.3x' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'browser.3x'\"
else
echo shar: Extracting \"'browser.3x'\" \(3828 characters\)
sed "s/^X//" >'browser.3x' <<'END_OF_FILE'
X(Message inbox:717)
XReturn-Path: shipley%WEB.Berkeley.EDU@lilac.berkeley.edu
XReceived:  by wyse.wyse.com (5.58/Wyse master/5-13-88)
X	id AA02643; Wed, 4 Jan 89 22:53:38 PST
XFrom: shipley%WEB.Berkeley.EDU@lilac.berkeley.edu
XReceived: from lilac.Berkeley.EDU by uunet.UU.NET (5.59/1.14) 
X	id AA25181; Thu, 5 Jan 89 01:42:01 EST
XReceived: from e260-4f.berkeley.edu
X	by lilac.berkeley.edu (5.54 (CFC 4.22.3)/1.16.19)
X	id AA06780; Wed, 4 Jan 89 22:40:27 PST
XReceived: by e260-4f.berkeley.edu (3.2/SMI-3.0DEV3.9MXl)
X	id AA02312; Wed, 4 Jan 89 22:43:36 PST
XMessage-Id: <8901050643.AA02312@e260-4f.berkeley.edu>
XTo: ames!mailrus!umix!wyse.com!mcf.uucp!mikew@cad.Berkeley.EDU
XCc: shipley%widow.Berkeley.EDU@lilac.berkeley.edu, mikew@wyse.wyse.com
XSubject: Re: browser widget 
XIn-Reply-To: Your message of Wed, 04 Jan 89 10:58:55 PST.
X             <8901041858.AA00866@wyse.wyse.com> 
XDate: Wed, 04 Jan 89 22:43:32 PST
X
X
X> Could you send me a man page for the browser widget?
X> Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
X> Moderator of comp.sources.x
X
X.TH BrowserWidget 3X
X.SH NAME
XBrowserWidget - Dialog widet for selecting files
X.SH DESCRIPTION
XThe BrowserWidget is a Utility widget which prompts
Xthe user ror file sectection.
X.SH RESOURCES
X.TS
Xl l l l.
X_
X\fBName	Type	Default	Description\fR
X=
XXtNvalue	XtRString	NULL	T{
Xfull path to directory to start Browsing
XT}
XXtNdefaultDistance	XtRInt	10	T{
Xdistance between subwidgets inside BrowserWidget
XT}
XXtNopenCallback	XtCallbackList	NULL	Callbacks for open button
XXtNcancelCallback	XtCallbackList	NULL	Callbacks for cansel button
XXtNdestroyCallback	XtCallbackList	NULL	Callbacks for XtDestroyWidget
XXtNmappedWhenManaged	Boolean	True	Whether XtMapWidget is automatic
XXtNfunction	Boolean (*func)()	NULL	see below
XXtNreverseVideo	Boolean	FALSE	display widget in reverse video
X_
X.TE
X.IP XtNvalue
XThe resource \*QXtNvalue\*U defines the base directory which the BrowserWidget
Xuse to start querying user from.
XThis resource has no default value thus it \fBmust be given\fR.
X.\"
X.IP XtNdefaultDistance
XThe resource \*QXtNdefaultDistance\*U defines the distance
Xbetween the child widgets of the BrowserWidget.
X.\"
X.IP XtNopenCallback
XThis callback is called when the user selects a file.
X.\"
X.IP XtNcancelCallback
XThis callback is called when the user selects the cancel button.
X.\"
X.IP XtNfunction
XThis resource is a pointer to a function whose argument is
Xa pointer to a directory entry for each file in the directory
Xcurrently being scaned; the function should return TRUE if the
Xdirectory entry is to be included.
XIf this pointer is null, then all the directory entries will be included.
X.\"
X.IP "Other resources"
XThe resource for the open button is \*Qopen\*U; the resource for the cancel
Xbutton is \*Qcancel\*U. These can be used to change the default labels.
X.\"
X.SH USE
XThe BrowserWidget takes command via mouse actions or keyboard entery.
XSelection using the mouse is done by ether double clicking on the
Xdesired file of directory, or by clicking once on the desired entry
Xand selecting the open button.
XSelection using the keyboard is very much like using file completion
Xin the C-shell.
XGenerally you type a partial filename followed by an ESC character
Xand the BrowserWidget fills in the remaining unambiguous characters
Xof partial filename
XIf the user enters a Control-C the cancel callback will be called.
XSelection is done by entering a line feed for or carrage return.
X.LP
XIf the selected directory entry is a directory the directory will
Xbe followed and the menu will be redisplayed else the selected file
Xwill be returned as a part of the open callback.
X.\"
X.SH SEE ALSO
Xscandir(3)
X.\"
X.SH BUGS
XViewport sometime gets confused about the size of the ListWidget (menu)
Xand the user will be unable to use scrollbar.
XListWidget will dump core if the user mouses to quickly.
END_OF_FILE
if test 3828 -ne `wc -c <'browser.3x'`; then
    echo shar: \"'browser.3x'\" unpacked with wrong size!
fi
# end of 'browser.3x'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(2200 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/dir.h>
X#include <sys/param.h>
X#include <X11/Intrinsic.h>
X#include <X11/Cardinals.h>
X#include <X11/List.h>
X#include <X11/StringDefs.h>
X#include "Browser.h"
X
X
XArg      args[20];
XWidget toplevel;
X
Xstatic XrmOptionDescRec options[] = {
X{"-label",	"*label",	XrmoptionSepArg,	NULL}
X};
X
X
Xvoid Syntax(call)
X    char *call;
X{
X    (void) fprintf( stderr, "Usage: %s\n", call );
X
X    return;
X}
X
X
Xstatic void ss(wi, client_data, call_data)
XWidget wi;
Xcaddr_t client_data;
Xcaddr_t call_data;
X{
X    (void) fprintf(stderr, "select %s\n", call_data);
X
X    return;
X}
X
Xstatic void cc(wi, client_data, call_data)
XWidget wi;
Xcaddr_t client_data;
Xcaddr_t call_data;
X{
Xextern Widget toplevel;
X
X    (void) fputs("cancel\n", stderr);
X
X    XtDestroyWidget(toplevel);
X
X    exit(0);
X}
X
Xstatic void dd(wi, client_data, call_data)
XWidget wi;
Xcaddr_t client_data;
Xcaddr_t call_data;
X{
X    (void) fprintf(stderr, "all is dead\n");
X
X    return;
X}
X
Xstatic Boolean tt(d)
Xstruct direct *d;
X{
X    return !(d->d_name[0] == '.' && d->d_name[1]==0);
X}
X
Xvoid main(argc, argv)
Xunsigned int argc;
Xchar **argv;
X{
Xregister Cardinal    n;
XWidget L_widget;
Xextern Widget toplevel;
X
Xstatic XtCallbackRec cancel_call[] = {
X    { cc, 		(caddr_t) NULL}, 
X    {(XtCallbackProc) NULL,    (caddr_t) NULL}
X};
X
Xstatic XtCallbackRec destroy_call[] = {
X    { dd, 		(caddr_t) NULL}, 
X    {(XtCallbackProc) NULL,    (caddr_t) NULL}
X};
X
Xstatic XtCallbackRec list_call[] = {
X    { ss, 		(caddr_t) NULL}, 
X    {(XtCallbackProc) NULL,    (caddr_t) NULL}
X};
X
X    toplevel = XtInitialize( NULL, "XLabel",
X			     options, XtNumber(options),
X			     &argc, argv );
X
X    n = ZERO;
X    XtSetArg(args[n], XtNvalue,		"/usr"); n++;
X    XtSetArg(args[n], XtNopenCallback,	list_call); n++;
X    XtSetArg(args[n], XtNcancelCallback,cancel_call); n++;
X    XtSetArg(args[n], XtNheight,	350); n++;
X    XtSetArg(args[n], XtNwidth,		400); n++;
X    XtSetArg(args[n], XtNfunction,	tt); n++;
X    XtSetArg(args[n], XtNdestroyCallback,	destroy_call); n++; 
X
X    L_widget = XtCreateManagedWidget( "browser", browserWidgetClass,
X		toplevel, args, n );
X
X    
X    XtRealizeWidget(toplevel);
X    XtMainLoop();
X}
END_OF_FILE
if test 2200 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(22 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X#define PATCHLEVEL 0
X
END_OF_FILE
if test 22 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    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
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
Moderator of comp.sources.x