MOTIF ANGST PAGE

If you have any ANGSTFUL Motif code, comments, documentation, or resources, please share them with me! Here is some of the stronger stuff I've found. Note: this is only for official Open Software Foundation Motif inspired Angst. If you're experiencing TCL/Tk That Only Looks Like Motif But Doesn't Suck Angst, then you should stop whining and fix the problem yourself, if somebody else hasn't already.

/* Note that the text callbacks are "weird" in that they expect values in the callback structure to be set inside the callback proc to determine what actions need to be taken after the callbackproc returns. In particular, the XmTextVerifyCallbackStruct's 'doit' slot is always set to True, and must be set to False if the callbackproc doesn't want the action to be taken. To do this, Set_Call_Data_For_XmTextVerifyCallbackStruct() is called by Wcb_Meta_Callbackproc() after the callback lisp code is evaluated, and the values bound to these settable variables are set inside call_data....

Another inconsistency with the Text widget is that some callbacks on this widget return XmAnyCallbackStruct's (XmNactivateCallback, XmNfocusCallback, XmNvalueChangedCallback), whereas XmNlosingFocusCallback, XmNmodifyVerifyCallback, and XmNmotionVerifyCallback return XmTextVerifyCallbackStruct. In the code below, we look at the 'reason' slot of the call data, (which is present in both XmAnyCallbackStruct and in XmTextVerifyCallbackStruct) to determine the kind of callback that occured and we only bind the values that are appropriate for that kind of callback. Information about which slots are valid for particular callback was taken from the documentation on the XmText(3X) widget, and verified against the Motif 1.1 source -- this is valid for both XmText and XmTextField widgets... */

static LVAL s_CALLBACK_CUR_INSERT, s_CALLBACK_NEW_INSERT, s_CALLBACK_START_POS, s_CALLBACK_END_POS, s_CALLBACK_TEXT;
static void Lexical_Bindings_For_XmTextVerifyCallbackStruct(bindings_list,
							    lexical_env,
							    call_data,
							    client_data)
     LVAL bindings_list;	/* a list of symbols to which values from XmTextVerifyCallbackStruct are bound */
     LVAL lexical_env;		
     XtPointer call_data;
     LVAL client_data;		/* XLTYPE_CALLBACKOBJ */
{
  extern LVAL true;
  register LVAL s_bindname;
  XmTextVerifyCallbackStruct* cd;

  /* How long can this go on???? */
}

/******************************************************************************
 * As far as I can tell, the only settable field in the Text widget's call_data
 * is the doit field. Of course, the documentation and the source are quite
 * cryptic about this!
 ******************************************************************************/
static void Set_Call_Data_For_XmTextVerifyCallbackStruct(lexical_env, call_data)
     LVAL lexical_env;		
     XtPointer call_data;
{
  register LVAL ep;

  /* Note: Wcb_Meta_Callbackproc() won't call this proc if call_data==NULL */

  switch (((XmAnyCallbackStruct*) call_data)->reason) {
  case XmCR_LOSING_FOCUS:	/* valid XmTextVerifyCallbackStruct fields: reason, event, doit, currInsert, newInsert, startPos, endPos */
  case XmCR_MODIFYING_TEXT_VALUE: /* valid XmTextVerifyCallbackStruct fields: reason, event, doit, currInsert, newInsert, text, startPos, endPos */
  case XmCR_MOVING_INSERT_CURSOR: /* valid XmTextVerifyCallbackStruct fields: reason, event, currInsert, newInsert, doit */
    for (ep = car(lexical_env); /* get current environment stack frame which was created in Wcb_Meta_Callbackproc() by Lexical_Bindings_For_XmTextVerifyCallbackStruct(). */
	 (ep != NIL); ep = cdr(ep)) /* while there are more bindings in current environment */
      if (s_CALLBACK_DOIT == car(car(ep))) { /* check to see if this symbol was bound in the envt */
	((XmTextVerifyCallbackStruct*) call_data)->doit = ((cdr(car(ep)) != NIL) ? TRUE : FALSE); /* set doit field if value is non-NIL */
	return;
      }
    break;
  default:			/* do nothing for most cases... */
    break;
  }
}

/********************************************************************************/
static LVAL Cvt_XmRXmString_to_LVAL(res_val, resource)
     GetValues_Union    res_val;
     Resource_Instance* resource;
{
#ifdef WINTERP_MOTIF_11
#ifdef WINTERP_MOTIF_111	/* MOTIF 1.1.1 version */
  /*
   * Motif 1.1.1 documentation claims that XmStrings retrieved via XtGetValues()
   * are copies of the internal resource value, and that XmStringFree() must be
   * called by the application to free the copyied value. In WINTERP, by passing
   * the XmString pointer to cv_xmstring, we can be assured that the lisp-XmString
   * will get freed upon garbage collection when the node is no longer referenced.
   */
  return (res_val.XtPointer_value ? cv_xmstring((XmString) res_val.XtPointer_value) : NIL);
#else				/* MOTIF 1.1 version */
  /*
   * Motif 1.1's README states:
   * |        Compound String Resources Inconsistently Copied
   * | 
   * |        In this release, XtGetValues for a resource whose value is a
   * |        compound string sometimes does and sometimes does not copy
   * |        the returned string.  Following is a list of some known
   * |        resources whose XmString values are not copied (this list
   * |        may not be exhaustive):
   * | 
   * |             XmBulletinBoard     XmNdialogTitle
   * |             XmFileSelectionBox  XmNdirectory
   * |                                 XmNnoMatchString
   * |             XmRowColumn         XmNlabelString
   * |             XmScale             XmNtitleString
   *
   * Handling the above would require special casing for all XmRString resources,
   * which I don't have time to do. They fixed this stupidity in 1.1.1 (see above),
   * but certainly in a suboptimal fashion -- yet more wasteful copying occurs because
   * all widgets copy their internal XmStrings upon XtGetValues().
   *
   * The upshot of all this is that for Motif 1.1 (but not 1.1.1), there will be a memory
   * leak in XtGetValues() on XmString resources that copy the internal resource value.
   * We must make a copy here because it would be worse to XmStringFree() resources that
   * returned a pointer whose memory was managed by Motif.
   */
  return (res_val.XtPointer_value ? cv_xmstring(XmStringCopy((XmString) res_val.XtPointer_value)) : NIL);
#endif /* WINTERP_MOTIF_111 */
#else				/* MOTIF 1.0 version */
  /*
   * In Motif 1.0, XmStrings() returned via XtGetValues() were temporary pointers
   * that has to be copied via XmStringCopy()...
   */
  return (res_val.XtPointer_value ? cv_xmstring(XmStringCopy((XmString) res_val.XtPointer_value)) : NIL);
#endif /* WINTERP_MOTIF_11 */
}

/* This is so totally ridiculous: there's NO WAY to tell Motif that *any* button can select a menu item. Only one button can have that honor. */

/* If this function looks like it does a lot more work than it needs to, you're right. Blame the Motif scrollbar for not being smart about updating its appearance. */

static void
xm_update_scrollbar (widget_instance *instance, Widget widget,
		     widget_value *val)
{
  if (val->scrollbar_data)
    {
      scrollbar_values *data = val->scrollbar_data;
      Dimension height, width, pane_minimum, pane_maximum;
      Dimension pos_x, pos_y;
      int widget_sliderSize, widget_val;
      int new_sliderSize, new_value;
      double percent;
      double h_water, l_water;

      XtVaGetValues (widget,
		     XmNheight, &height,
		     XmNwidth, &width,
		     XmNx, &pos_x,
		     XmNy, &pos_y,
		     XmNpaneMinimum, &pane_minimum,
		     XmNpaneMaximum, &pane_maximum,
		     XmNsliderSize, &widget_sliderSize,
		     XmNvalue, &widget_val,
		     0);

      /*
       * First size and position the scrollbar widget.
       */
      if (height != data->scrollbar_height || pos_y != data->scrollbar_pos)
	{
	  XtConfigureWidget (widget, pos_x, data->scrollbar_pos,
			     width, data->scrollbar_height, 0);

	  /* Force the manager to recompute the positioning. */
	  XtVaSetValues (widget, XmNrefigureMode, False, 0);
	  XtVaSetValues (widget, XmNrefigureMode, True, 0);
	}

      /* pane_min should always equal pane_max */
      if (pane_minimum != data->scrollbar_height)
	XtVaSetValues (widget,
		       XmNpaneMinimum, data->scrollbar_height,
		       XmNpaneMaximum, data->scrollbar_height, 0);

      /*
       * Now the size the scrollbar's slider.
       */
      percent = (double) data->slider_size /
	(double) (data->maximum - data->minimum);
      new_sliderSize = (int) ((double) (INT_MAX - 1) * percent);

      percent = (double) (data->slider_position - data->minimum) /
	(double) (data->maximum - data->minimum);
      new_value = (int) ((double) (INT_MAX - 1) * percent);

      if (new_sliderSize > (INT_MAX - 1))
	new_sliderSize = INT_MAX - 1;
      if (new_sliderSize < 1)
	new_sliderSize = 1;

      if (new_value > (INT_MAX - new_sliderSize))
	new_value = INT_MAX - new_sliderSize;
      else if (new_value < 1)
	new_value = 1;

      h_water = 1.05;
      l_water = 0.95;
      if (new_sliderSize != widget_sliderSize || new_value != widget_val)
	{
	  int force = ((INT_MAX - widget_sliderSize - widget_val)
		       ? 0
		       : (INT_MAX - new_sliderSize - new_value));

	  if (force
	      || (double)new_sliderSize < (l_water * (double)widget_sliderSize)
	      || (double)new_sliderSize > (h_water * (double)widget_sliderSize)
	      || (double)new_value < (l_water * (double)widget_val)
	      || (double)new_value > (h_water * (double)widget_val))
	    {
	      XmScrollBarSetValues (widget, new_value, new_sliderSize, 1, 1,
				    False);
	    }
	}
    }
}


#if (XmVersion >= 1002)
# define ARMANDACTIVATE_KLUDGE
# define DND_KLUDGE
#endif

#ifdef ARMANDACTIVATE_KLUDGE
 /* We want typing Return at a dialog box to select the default button; but
    we're satisfied with having it select the leftmost button instead.

    In Motif 1.1.5 we could do this by putting this resource in the
    app-defaults file:

	*dialog*button1.accelerators:#override\
	<KeyPress>Return: ArmAndActivate()\n\
	<KeyPress>KP_Enter: ArmAndActivate()\n\
	Ctrl<KeyPress>m: ArmAndActivate()\n

    but that doesn't work with 1.2.1 and I don't understand why. However,
    doing the equivalent C code does work, with the notable disadvantage that
    the user can't override it.  So that's what we do until we figure out
    something better....
  */
static char button_trans[] = "\
<KeyPress>Return: ArmAndActivate()\n\
<KeyPress>KP_Enter: ArmAndActivate()\n\
Ctrl<KeyPress>m: ArmAndActivate()\n";

#endif /* ARMANDACTIVATE_KLUDGE */

#ifdef DND_KLUDGE
 /* This is a kludge to disable drag-and-drop in dialog boxes.  The symptom
    was a segv down in libXm somewhere if you used the middle button on a
    dialog box to begin a drag; when you released the button to make a drop
    things would lose if you were not over the button where you started the 
    drag (canceling the operation).  This was probably due to the fact that
    the dialog boxes were not set up to handle a drag but were trying to do
    so anyway for some reason.

    So we disable drag-and-drop in dialog boxes by turning off the binding for
    Btn2Down which, by default, initiates a drag.  Clearly this is a shitty
    solution as it only works in default configurations, but...
  */
static char disable_dnd_trans[] = "<Btn2Down>: ";
#endif /* DND_KLUDGE */

/* sets the parent window to 0 to fool Motif into not generating a grab */

#ifdef USE_MOTIF
  /* The menu.font_list slot came from the *fontList resource (Motif standard.)
     The menu.font_list_2 slot came from the *font resource, for backward
     compatibility with older versions of this code, and consistency with the
     rest of emacs.  If both font and fontList are specified, we use font.
     If only one is specified, we use that.  If neither are specified, we
     use the "fallback" value.  What a kludge!!!

     Note that this has the bug that a more general wildcard like "*fontList:"
     will override a more specific resoure like "Emacs*menubar.font:".  But
     I can't think of a way around that.
   */
  if (mw->menu.font_list)	  /* if *fontList is specified, use that */
    ;
  else if (mw->menu.font_list_2)  /* else if *font is specified, use that */
    mw->menu.font_list = mw->menu.font_list_2;
  else				  /* otherwise use default */
    mw->menu.font_list = mw->menu.fallback_font_list;
#endif


/*
 *    This is a horrible function which should not be needed.
 *    use it to put the resize method back the way the XlwMenu
 *    class initializer put it. Motif screws with this when
 *    the XlwMenu class gets instantiated.
 */
void
xlw_unmunge_class_resize(Widget w) {
  if (w->core.widget_class->core_class.resize != XlwMenuResize)
    w->core.widget_class->core_class.resize = XlwMenuResize;
}

Date: 19 Jan 90 09:53:11 GMT
From: umich!umeecs!anon@yale-zoo.arpa  (Omar S. Juma)
Subject: Re: To UIL or not to UIL?
To: xpert@expo.lcs.mit.edu

In article <11658.632634712@hplnpm> mayer%hplnpm@HPLABS.HPL.HP.COM (Niels P. Mayer) writes:
[Heavily edited]
>
>                                           ...rumor...           ...UIL...
>                                         ...didn't meet HP's quality...
>            ...poop...
>  ...UIL SUCKS...                        ...silly...
>...buggy...         ...inelegant...
>          ...doesn't make life...                            ...easier...
>...completely nonstandard...
>

I absolutely agree. I've only had 4 years of serious software experience, and UIL is the ***worst*** language/compiler combination I have ever seen. Nothing, not even working with punch cards, has left me with a more bitter taste in my mouth. If UIL were a car, not even the Russians would want to manufacture it. If UIL were a--but, wait a minute, let's be objective for a minute:

I'm really sorry to be saying all of this, but UIL is not a solution. Unfortunately, unless OSF is willing to break with tradition and supply a completely different mechanism for the next release of Motif, we are stuck with UIL for quite a while. Which means we will all waste more time and energy coming up with solutions. Here's some alternatives: I could go on...

anon@eecs.umich.edu

...anon...

Date: 27 Mar 90 13:36:06 GMT
From: alphalpha!nazgul@bloom-beacon.mit.edu (Kee Hinckley)
Subject: Re: UIL or NOT to UIL
To: xpert@expo.lcs.mit.edu

I tried to reply directly to this, but auto-trol.com doesn't seem to be around, so...

In article <792@auto-trol.UUCP> marbru@auto-trol.COM (Martin Brunecky) writes:

For your case I'd need a more generic one, specifying widget ID to to set. Easy to do. I did not think of one, since to accomplish your task we have WsMatrixBox, which does all you need with 2-3 resources, without all that ugly code.

I don't suppose WsMatrixBox is available anywhere?

With the X resource database, there is no problem, since the "hidden" widget always has a name (somehow constructed by the confusion routine). And since there is a name, and a known place in widget hierarchy, you can define any resources you wish.

Ugh. Not your fault, but ugh nonetheless.

Incidentally. OSF did at one point consider using an extended Xresources form as an alternative to UIL, but was convinced (I forget the exact reasons) that it wasn't appropriate (too hacky?).
Wasn't the real reason some OSF member was already using UIL and wanted to make it a "standard" ?

Keep in mind these are my opinions and mine alone, based on my view as part of the team that "created" Motif.

There is no question in my mind that had OSF not chosen UIL, an "OSF Member" would have been upset. The results of that, I don't know - it didn't come to that. My feeling, and what I believe the consensus to have been, was that UIL, while by no means perfect or even correct, was a step in the right direction. I also felt (and I regret not examining the code more throughly in the hour or so I had it) that it could be fixed, and that no better, timely (e.g. Open Dialogue was potentially not timely (in retrospect I know that is wrong, it could have been there, but...)), solution existed. Given that something like it seemed necessary, both as a transfer language for IDTs (something the membership wanted), and as a means for supporting internationalization, it was decided that it should be included but not placed in the AES (Application Environment Specification) - in other words, the specification of UIL is open for change in the future. I, at least, was under the impression that work would begin to correct these problems as soon as Motif was released. In fact, there were several possible approaches bandied about for what the new UIL would look like and who would do the work.

In my opinion OSF dropped the ball here, and frankly I feel somewhat betrayed, since what we worked out was a compromise and I feel it was tossed as soon as the transition team left. I should point out however, that I don't think, given my knowledge of the people who are at OSF, that this was done for political reasons. I suspect it has been more a matter of manpower and priorities. I do think that it's extremely regretable however, since the number of programs using UIL is (as I was afraid) increasing rapidly, and any viable UIL replacement now must support seamless translation to and from UIL files.

-kee