
/*
 * Filename: 	widgets.c
 *
 * This file is part of the Muse authoring system,
 * developed at MIT Project Athena.
 *
 * Author(s):	Matthew E. Hodges,  Digital Equipment Corporation
 *              Russell M. Sasnett, GTE Laboratories Incorporated
 *              V. Judson Harward,  MIT Project Athena
 * 
 * Copyright 1989, 1990 by the Massachusetts Institute of Technology;
 * see the file COPYRIGHTS for a complete notice.
 *
 * CHANGE LOG:
 * ===========
 *
 * $Log:	widgets.c,v $
 * Revision 2.1  91/01/02  17:32:43  jud
 * Muse 2 initial version for Athena Release 7.2
 * 
 *
 */

#ifndef lint
static char *rcsid_widgets_c = 
"MuseID: widgets.c $Revision: 2.1 $ $Date: 91/01/02 17:32:43 $ $Author: jud $";
#endif /* lint */

#define WIDGETS_C

/* ------------------------------------------------------------------- */

#include <stdio.h>

#include "xdefs.h"
#include "prsdefs.h"
#include "structs.h"
#include "widgets.h"
#include "functions.h"
#include "y.tab.h"
#include "internal.h"

extern int ev_Debug;

/* defaults */

TKtext          TKtextDefaults = 
{
				  0,
				  (Window) NULL, (Window) NULL,
				  0, 0, 100, 20, 200, 4,
				  0, 1, 0,
				  (Pixmap) 0, (Pixmap) 0, (Pixmap) 0,
				  "",
				  "RootWindow",
				  "*-helvetica-bold-r-normal--12-*",
				  "", "", "",
				  scrollVertical,
				  0, 0, 2,
				  NULL,
				  XttextRead
};

TKscrollbar     ScrollDefaults = 
{
				  0,
				  (Window) NULL, (Window) NULL,
				  "horizontal",
				  0, 0, 20, 10, 1,
				  0, 1, 0,
				  (Pixmap) 0,
				  (Pixmap) 0,
				  (Pixmap) 0,
				  "",
				  "RootWindow",
				  (
				   void (*) ()) NULL,
				  (void (*) ()) NULL,
				  "",
				  NULL,
				  INT_PARAM,
				  0.0, 0.0,
				  NULL, NULL
};

Button          ButtonDefaults = 
{
				  0,
				  (Window) NULL, (Window) NULL,
				  0, 0, 10, 10, 1,
				  0, 1, 0,
				  (Pixmap) 0, (Pixmap) 0, (Pixmap) 0,
				  "",
				  "RootWindow",
				  "",
				  "*-helvetica-bold-r-normal--12-*",
				  "quit",
				  NULL,
				  (void (*) ()) NULL,
				  "",
				  NULL,
				  INT_PARAM,
				  0,
				  NULL, 0, 1,
#ifndef X11R3
				  /*
				   * shape extension only in R4 toolkit
				   */
				  XawShapeRectangle,
				  25
#endif
};

ScribeViewer    ScribeViewerDefaults =
{
  0,
  (Window) NULL, (Window) NULL,
  0, 0, 10, 10, 1,
  0, 1, 0,
  (Pixmap) 0, (Pixmap) 0, (Pixmap) 0,
  "", "RootWindow", "",
  "*nofile*", 0, 0, 1,
  0, 0,
};

Button         *
button_create()
{
    Button         *b;

    b = (Button *) xcalloc(1, sizeof(Button));
    bcopy(&ButtonDefaults, b, sizeof(Button));
    b->foreground_pixmap = b->background_pixmap = b->border_pixmap
	= (Pixmap) 0;
    return (b);
}

TKscrollbar    *
scrollbar_create()
{
    TKscrollbar    *s;

    s = (TKscrollbar *) xcalloc(1, sizeof(TKscrollbar));
    bcopy(&ScrollDefaults, s, sizeof(TKscrollbar));
    s->foreground_pixmap = s->background_pixmap = s->border_pixmap
	= (Pixmap) 0;
    s->top = s->shown = 0.0;
    return (s);
}


TKtext         *
text_create(string_or_file_ptr)
    int            *string_or_file_ptr;
{
    TKtext         *t;

    t = (TKtext *) xcalloc(1, sizeof(TKtext));
    bcopy(&TKtextDefaults, t, sizeof(TKtext));
    *string_or_file_ptr = 0;
    t->foreground_pixmap = t->border_pixmap = t->background_pixmap =
	(Pixmap) 0;
    return (t);
}

ScribeViewer   *
scribe_create()
{
    ScribeViewer   *svp;

    svp = (ScribeViewer *) xcalloc(1, sizeof(ScribeViewer));
    bcopy(&ScribeViewerDefaults, svp, sizeof(ScribeViewer));
    svp->foreground_pixmap = svp->border_pixmap =
	svp->background_pixmap = (Pixmap) 0;
    return svp;
}

/* 
 * following routine takes a scrl bar and adds the data 
 * from the "represents" parameter; used by parser
 */

scrl_bar_add_reps(ele, map, scroll_bar, pkg_name, dim_name, fcode, extent)
    Element        *ele;
    Map            *map;
    TKscrollbar    *scroll_bar;
    char           *pkg_name;	/* package name */
    char           *dim_name;	/* dimension_name */
    int             fcode;	/* feature code */
    int             extent;	/* how much range to represent */

{
    DimRep         *dr;
    Packpos        *p;


    dr = (DimRep *) xcalloc(1, sizeof(DimRep));
    dr->update_fn = (int (*) ()) update_scrollbar;
    dr->e = ele;
    dr->m = map;
    dr->packname = pkg_name;
    dr->dimname = dim_name;
    dr->extent = extent;
    dr->feature = fcode;

    dr->tmp = ele->p->reps;
    ele->p->reps = dr;

    /* 
     * Fill in the function and value on the scroll bar at the same time.
     */
    p = (Packpos *) xcalloc(1, sizeof(Packpos));
    p->pname = alloc_string(dr->packname);
    p->dimname = alloc_string(dr->dimname);
    Debug((stderr, 
	   "%s: representing %s->%s\n", funcname, p->pname, p->dimname));
    p->e = ele;
    scroll_bar->param_type = PACKPOS_PARAM;
    scroll_bar->ptrparam = (char *) p;
    scroll_bar->thumbproc = scroll_control_package;
    scroll_bar->scrollupdownproc = scroll;
}

/* 
 * following adds function to scrollbar according to Param_type 
 */

scrl_bar_add_proc(scrl_bar, function, element, param_type)
     TKscrollbar    *scrl_bar;
     void            (*function) ();
     Element        *element;
     int             param_type;

{
    Packpos        *p;

    scrl_bar->scrollupdownproc = function;
    if ((scrl_bar->param_type = param_type) == PACKPOS_PARAM)
    {
	p = (Packpos *) xcalloc(1, sizeof(Packpos));
	p->e = element;
	scrl_bar->ptrparam = (char *) p;
    }
}

/* 
 * following makes struct to store widget callback function parameters 
 */

Packpos        *
scrl_bar_packpos_create(name, widget, element)
    char           *name;
    TKscrollbar    *widget;
    Element        *element;
{
    Packpos        *p;

    p = (Packpos *) xcalloc(1, sizeof(Packpos));
    p->pname = xsave_string(name);
    p->e = element;
    widget->ptrparam = (char *) p;
    return (p);
}

Packpos        *
packpos_create(name, element)
    char           *name;
    Element        *element;
{
    Packpos        *p;

    p = (Packpos *) xcalloc(1, sizeof(Packpos));
    p->pname = xsave_string(name);
    p->e = element;
    return (p);
}

text_add_string(flag_ptr, text_ptr, string_ptr)
    int            *flag_ptr;
    char           *text_ptr;
    char           *string_ptr;
{
extern int lineno;

    if (*flag_ptr)
    {
      if(ev_Debug)
	printf("found both string and file, line %d\n",
	       lineno);
    }
    else
    {
	++*flag_ptr;
	text_ptr = string_ptr;
    }
}

/* 
 * if you use the following from EventScript directly,
 * you MUST NOT declare it as returning "Cstr",
 * because you'll run over the size limit for
 * ES strings (256 at the moment); instead, declare
 * it as returning "Cint" and use it as a pointer;
 * you won't be able to print it out or anything else
 * from eventscript, but you can pass it to functions
 * expecting a "char *" 
 */

char           *
u_CreateStringFromPipe(cmd)
    char           *cmd;
{
    FILE           *fp;
    char           *str;
    char           *malloc();
    char           *realloc();
    char           *buf;
    long            bufsize = 1024;
    long            len = 0;
    long            newlen = 0;
    char            line[512];

    if (!cmd)
    {
	printf("CreateStringFromPipe(): given NULL string\n");
	return NULL;
    }

    fp = popen(cmd, "r");
    if (!fp)
    {
	printf("CreateStringFromPipe(): popen() failed\n");
	return NULL;
    }

    buf = malloc(bufsize);
    if (!buf)
    {
	printf("CreateStringFromPipe(): malloc failed\n");
	exit(1);
    }

    str = buf;

    while (!feof(fp))
    {
	char           *s;

	s = fgets(line, 255, fp);
	if (s == NULL)		/* end of file */
	    break;

	newlen = STRLEN(line);

	if (len + newlen + 1 >= bufsize)
	{
	    bufsize = bufsize + (bufsize >> 1);	/* 1.5 */
	    buf = realloc(buf, bufsize);
	    if (!buf)
	    {
		printf("realloc() failed reading pipe\n");
		exit(1);
	    }

	    /*
	     * following is VERY important in case the block got moved 
	     */
	    str = buf + len;
	}

	STRCPY(str, line);

	str += newlen;		/* want to point at the new null */
	len += newlen;		/* don't count the new NULL */
    }	

    pclose(fp);

    if (len > 0)
	return buf;
    else
    {
	free(buf);
	return NULL;
    }
}

/*
 * following is an EventScript interface to above; stuffs
 * pipe output into a string-based text widget; since
 * the toolkit won't allow you to reset the string buffer,
 * must kill the current widget in the element and then
 * call activate_element() to cause a new one to be
 * created from the values in the Muse wrapper structure
 * (TkText *) 
 */

int
FillTextWithString(e, str)
    Element        *e;
    char           *str;
{
    Widget          w;
    Arg             args[2];
    TKtext         *t;
    Map            *m;
    int             n;

    if (!e || !(e->type == TEXT) || !e->widgetptr)
    {
	fprintf(stderr, "FillTextWithString(): bad text element ptr\n");
	fprintf(stderr, "\telement 0x%lx type: %d widgetptr: 0x%lx\n",
		e, (e ? e->type : 0), (e ? e->widgetptr : 0));
	return -1;
    }

    if (!str)
    {
	fprintf(stderr, "FillTextWithString(): given NULL string\n");
	return -1;
    }

    w = e->widgetptr;

    if (!XtIsSubclass(w, asciiStringWidgetClass))
    {
	fprintf(stderr, 
		"FillTextWithString(): text widget is not of String class\n");
	return -1;
    }

    m = e->map;
    t = (TKtext *) m->simple.widget;

#ifdef X11R3

    /* 
     * now destroy old widget; have to in R3 cause you can't set resource
     */
    XtDestroyWidget(w);

    /* 
     * now null these out so activate() will create a new widget 
     */
    e->widgetptr = NULL;
    e->w = 0;
    for (; m; m = m->simple.next)
	m->simple.w = 0;

    /*
     * HACK ALERT:
     * need to store original value of text widget;
     * the easy thing (?) is to use event_bindings because it takes
     * so long to recompile if I change a header file 
     */

    if (!STRLEN(t->event_bindings))	/* save original string there */
    {
	t->event_bindings = xsave_string(t->string);
    }

    free(t->string);
    t->string = str;

    /* 
     * let make_tk_text() give it a length 
     */
    t->length = 0;

    activate_element(e);
    refresh(e);

#else

    n = 0;
    XtSetArg(args[n], XtNstring, str);
    n++;

    XtSetValues(w, args, n);
    
#endif /* X11R3 */

    return 0;
}

int
SetMuseTextResource(w, t, name, value)
    Widget          w;
    TKtext         *t;
    char           *name;
    char           *value;
{
    static Arg      wargs[2];
    int             num;
    XrmValue        from,
                    to;
    int             valid = 0;
    char           *cp;

    if (!w || !t || !name || !value)
	return -1;

    switch (name[0])
    {

    case 'x':
	if (!strcmp(name, "x"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    t->x = num;
	    valid = 1;
	}
	break;

    case 'y':
	if (!strcmp(name, "y"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    t->y = num;
	    valid = 1;
	}
	break;

    case 'w':
	if (!strcmp(name, "width"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    t->width = num;
	    valid = 1;
	}
	break;

    case 'h':
	if (!strcmp(name, "height"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    t->height = num;
	    valid = 1;
	}
	break;

    case 'b':
	num = atoi(value);
	if (!strcmp(name, "background"))
	{
	    XtSetArg(wargs[0], name, num);	/* Muse color */
	    t->background = num;
	    valid = 1;
	}
	else
	if (!strcmp(name, "borderColor"))
	{
	    XtSetArg(wargs[0], name, num);	/* Muse color */
	    t->border = num;
	    valid = 1;
	}
	else
	if (!strcmp(name, "borderWidth"))
	{
	    XtSetArg(wargs[0], name, num);
	    t->borderwidth = num;
	    valid = 1;
	}
	break;

	/* END OF GENERIC */

    case 'f':
	if (!strcmp(name, "font"))
	{
	    from.size = strlen(value);
	    from.addr = value;

	    XtConvert(w, XtRString, &from, XtRFontStruct, &to);
	    if (!to.addr)
	    {
		fprintf(stderr, 
			"SetMuseTextResource(): can't convert font <%s>\n",
			value);
		return -1;
	    }
	    cp = *(char **) to.addr;
	    XtSetArg(wargs[0], name, cp);
	    t->font = (XFontStruct *) cp;
	    if (STRLEN(t->fontname))
		free(t->fontname);
	    t->fontname = (char *) xsave_string(value);
	    valid = 1;
	}
	else
	if (!strcmp(name, "foreground"))
	{
	    num = atoi(value);
	    if (num >= 35 && num <= 191)
	    {
		XtSetArg(wargs[0], name, num);
		t->foreground = num;
		valid = 1;
	    }
	    else
	    {
		fprintf(stderr, 
			"SetMuseTextResource(): bad color string <%s>\n",
			value);
		return -1;
	    }
	}

#ifndef X11R3
	else if(!strcmp(name,"file"))
	  {
	    XtSetArg(wargs[0], XtNstring, value);
	    valid = 1;
	  }
#endif
	break;

#ifndef X11R3
      case 's':
	if (!strcmp(name,"string"))
	  {
	    XtSetArg(wargs[0], XtNstring, value);
	    valid = 1;
	  }
	break;
#endif

    default:
	break;
    }

    if (!valid)
    {
	fprintf(stderr, "SetMuseTextResource(): bad resource name <%s>\n",
		name);
	return -1;
    }

    XtSetValues(w, wargs, 1);
    return 0;
}

int
SetMuseButtonResource(w, b, name, value)
    Widget          w;
    Button         *b;
    char           *name;
    char           *value;
{
    static Arg      wargs[2];
    int             num;
    XrmValue        from,
                    to;
    int             valid = 0;
    char           *cp;

    if (!w || !b || !name || !value)
	return -1;

    switch (name[0])
    {

    case 'x':
	if (!strcmp(name, "x"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    b->x = num;
	    valid = 1;
	}
	break;

    case 'y':
	if (!strcmp(name, "y"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    b->y = num;
	    valid = 1;
	}
	break;

    case 'w':
	if (!strcmp(name, "width"))
	{
	    /* 
	     * if user gave explicit width, don't allow self-resize 
	     */
	    b->resize = 0;
	    XtSetArg(wargs[0], XtNresize, 0);
	    XtSetValues(w, wargs, 1);

	    num = atoi(value);
	    b->width = num;
	    XtSetArg(wargs[0], name, num);
	    valid = 1;
	}
	break;

    case 'h':
	if (!strcmp(name, "height"))
	{
	    /* 
	     * if give explicit height, don't allow self-resize 
	     */
	    b->resize = 0;
	    XtSetArg(wargs[0], XtNresize, 0);
	    XtSetValues(w, wargs, 1);

	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    b->height = num;
	    valid = 1;
	}
	break;

    case 'b':
	num = atoi(value);
	if (!strcmp(name, "background"))
	{
	    XtSetArg(wargs[0], name, num);	/* Muse color */
	    b->background = num;
	    valid = 1;
	}
	else
	if (!strcmp(name, "borderColor"))
	{
	    XtSetArg(wargs[0], name, num);	/* Muse color */
	    b->border = num;
	    valid = 1;
	}
	else
	if (!strcmp(name, "borderWidth"))
	{
	    XtSetArg(wargs[0], name, num);
	    b->borderwidth = num;
	    valid = 1;
	}
	break;

	/* END OF GENERIC */

    case 'f':
	if (!strcmp(name, "font"))
	{
	    from.size = strlen(value);
	    from.addr = value;

	    XtConvert(w, XtRString, &from, XtRFontStruct, &to);
	    if (!to.addr)
	    {
		fprintf(stderr, 
			"SetMuseButtonResource(): can't convert font <%s>\n",
			value);
		return -1;
	    }
	    cp = *(char **) to.addr;
	    XtSetArg(wargs[0], name, cp);
	    b->font = (XFontStruct *) cp;
	    if (STRLEN(b->fontname))
		free(b->fontname);
	    b->fontname = (char *) xsave_string(value);
	    valid = 1;
	}
	else
	if (!strcmp(name, "foreground"))
	{
	    num = atoi(value);
	    if (num >= 35 && num <= 191)
	    {
		XtSetArg(wargs[0], name, num);
		b->foreground = num;
		valid = 1;
	    }
	    else
	    {
		fprintf(stderr, 
			"SetMuseButtonResource(): bad color string <%s>\n",
			value);
		return -1;
	    }
	}
	break;

    case 'l':
	if (!strcmp(name, "label"))
	{
	    XtSetArg(wargs[0], name, value);
	    if (STRLEN(b->label))
		free(b->label);
	    b->label = xsave_string(value);
	    valid = 1;
	}
	break;

    case 'j':
	if (!strcmp(name, "justify"))
	{
	    if (!strcmp(value, "left"))
		num = (int) XtJustifyLeft;
	    else
	    if (!strcmp(value, "center"))
		num = (int) XtJustifyCenter;
	    else
	    if (!strcmp(value, "right"))
		num = (int) XtJustifyRight;
	    else
		num = (int) XtJustifyCenter;
	    XtSetArg(wargs[0], name, num);
	    b->justify = num;
	    valid = 1;
	}
	break;

    default:
	break;
    }

    if (!valid)
    {
	fprintf(stderr, "SetMuseButtonResource(): bad resource name <%s>\n",
		name);
	return -1;
    }

    XtSetValues(w, wargs, 1);
    return 0;
}

int
SetMuseScrollbarResource(w, s, name, value)
    Widget          w;
    TKscrollbar    *s;
    char           *name;
    char           *value;
{
    static Arg      wargs[2];
    int             num;
    XrmValue        from,
                    to;
    int             valid = 0;

    if (!w || !s || !name || !value)
	return -1;

    switch (name[0])
    {

    case 'x':
	if (!strcmp(name, "x"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    s->x = num;
	    valid = 1;
	}
	break;

    case 'y':
	if (!strcmp(name, "y"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    s->y = num;
	    valid = 1;
	}
	break;

    case 'w':
	if (!strcmp(name, "width"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    s->width = num;
	    valid = 1;
	}
	break;

    case 'h':
	if (!strcmp(name, "height"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    s->height = num;
	    valid = 1;
	}
	break;

    case 'b':
	num = atoi(value);
	if (!strcmp(name, "background"))
	{
	    XtSetArg(wargs[0], name, num);	/* Muse color */
	    s->background = num;
	    valid = 1;
	}
	else
	if (!strcmp(name, "borderColor"))
	{
	    XtSetArg(wargs[0], name, num);	/* Muse color */
	    s->border = num;
	    valid = 1;
	}
	else
	if (!strcmp(name, "borderWidth"))
	{
	    XtSetArg(wargs[0], name, num);
	    s->borderwidth = num;
	    valid = 1;
	}
	break;

	/* END OF GENERIC */

    case 'f':
	if (!strcmp(name, "foreground"))
	{
	    num = atoi(value);
	    if (num >= 35 && num <= 191)
	    {
		XtSetArg(wargs[0], name, num);
		valid = 1;
		s->foreground = num;
	    }
	    else
	    {
		fprintf(stderr, 
			"SetMuseScrollbarResource(): bad color string <%s>\n",
			value);
		return -1;
	    }
	}
	break;

    default:
	break;
    }

    if (!valid)
    {
	fprintf(stderr, 
		"SetMuseScrollbarResource(): bad resource name <%s>\n",
		name);
	return -1;
    }

    XtSetValues(w, wargs, 1);
    return 0;
}

int
SetMuseScreenResource(w, scr, name, value)
    Widget          w;
    u_Screen       *scr;
    char           *name;
    char           *value;
{
    static Arg      wargs[2];
    int             num;
    XrmValue        from,
                    to;
    int             valid = 0;

    if (!w || !scr || !name || !value)
	return -1;

    switch (name[0])
    {

    case 'x':
	if (!strcmp(name, "x"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    scr->x = num;
	    valid = 1;
	}
	break;

    case 'y':
	if (!strcmp(name, "y"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    scr->y = num;
	    valid = 1;
	}
	break;

    case 'w':
	if (!strcmp(name, "width"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    scr->width = num;
	    valid = 1;
	}
	break;

    case 'h':
	if (!strcmp(name, "height"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    scr->height = num;
	    valid = 1;
	}
	break;

    case 'b':
	num = atoi(value);
	if (!strcmp(name, "background"))
	{
	    XtSetArg(wargs[0], name, num);	/* Muse color */
	    scr->background = num;
	    valid = 1;
	}
	else
	if (!strcmp(name, "borderColor"))
	{
	    XtSetArg(wargs[0], name, num);	/* Muse color */
	    scr->border = num;
	    valid = 1;
	}
	else
	if (!strcmp(name, "borderWidth"))
	{
	    XtSetArg(wargs[0], name, num);
	    scr->borderwidth = num;
	    valid = 1;
	}
	break;

    default:
	break;
    }

    if (!valid)
    {
	fprintf(stderr, "SetMuseScreenResource(): bad resource name <%s>\n",
		name);
	return -1;
    }

    XtSetValues(w, wargs, 1);
    return 0;
}

int
SetMuseScribeResource(w, scribe, name, value)
    Widget          w;
    ScribeViewer   *scribe;
    char           *name;
    char           *value;
{
    static Arg      wargs[2];
    int             num;
    XrmValue        from,
                    to;
    int             valid = 0;

    if (!w || !scribe || !name || !value)
	return -1;

    switch (name[0])
    {

    case 'x':
	if (!strcmp(name, "x"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    scribe->x = num;
	    valid = 1;
	}
	break;

    case 'y':
	if (!strcmp(name, "y"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    scribe->y = num;
	    valid = 1;
	}
	break;

    case 'w':
	if (!strcmp(name, "width"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    scribe->width = num;
	    valid = 1;
	}
	break;

    case 'h':
	if (!strcmp(name, "height"))
	{
	    num = atoi(value);
	    XtSetArg(wargs[0], name, num);
	    scribe->height = num;
	    valid = 1;
	}
	break;

    case 'b':
	num = atoi(value);
	if (!strcmp(name, "background"))
	{
	    XtSetArg(wargs[0], name, num);	/* Muse color */
	    scribe->background = num;
	    valid = 1;
	}
	else
	if (!strcmp(name, "borderColor"))
	{
	    XtSetArg(wargs[0], name, num);	/* Muse color */
	    scribe->border = num;
	    valid = 1;
	}
	else
	if (!strcmp(name, "borderWidth"))
	{
	    XtSetArg(wargs[0], name, num);
	    scribe->borderwidth = num;
	    valid = 1;
	}
	break;

	/* END OF GENERIC */

    case 'f':
	if (!strcmp(name, "foreground"))
	{
	    num = atoi(value);
	    if (num >= 35 && num <= 191)
	    {
		XtSetArg(wargs[0], name, num);
		scribe->foreground = num;
		valid = 1;
	    }
	    else
	    {
		fprintf(stderr, 
			"SetMuseScribeResource(): bad color string <%s>\n",
			value);
		return -1;
	    }
	}
	break;

    default:
	break;
    }

    if (!valid)
    {
	fprintf(stderr, 
		"SetMuseScribeResource(): bad resource name <%s>\n",
		name);
	return -1;
    }

    XtSetValues(w, wargs, 1);
    return 0;
}
