Path: utzoo!attcan!uunet!lll-winken!lll-tis!ames!mailrus!purdue!decwrl!hplabs!hp-pcd!hpcvlx!fred
From: fred@hpcvlx.HP.COM (Fred Taft)
Newsgroups: comp.windows.x
Subject: Re: HP's Xtk Fixes (as Context Diffs)
Message-ID: <1610053@hpcvlx.HP.COM>
Date: 19 Aug 88 19:53:22 GMT
References: <1610043@hpcvlx.HP.COM>
Organization: Hewlett-Packard Co., Corvallis, OR, USA
Lines: 177


### bug number:   402
### area:         Xt
### severity:     medium
### comments:     


VERSION:
	Xtk release 2

SYNOPSIS:
	XtGetValues() returns bogus information on 68000 architecture
        machines, if the application queries a short or char value, and
        it also specifies within the arglist  a pointer to a short or char 
        variable, into which the result is to be placed.

DESCRIPTION:
   Several months ago, I reported a discrepancy in how XtGetValues() worked,
   versus how it was documented.  I received a message that the problem was
   being fixed, yet I notice that it is still present in the R2 toolkit,
   to a degree anyways.  According to the documentation, when you issue a 
   GetValue request, you pass in an arglist composed of an argument 
   name/address pair; the address indicates where the return value should be 
   placed.  If I don't supply a pointer (i.e. I pass in a NULL address),
   when I query a Boolean value, the value is always returned in the arglist;
   I noticed that CopyToArg() specifically tested for this case; I can live
   with this, since it allows old clients to continue to run.  However, if
   I do pass in an address, then the returned boolean value was always 0
   (FALSE).  

   After further investigation, I believe the problem lies in the following
   line of code which had been added to CopyToArg() to fix the original
   problem:

        if (*dst != NULL)
           dst = *(XtArgVal **)dst;

   The above statement treats everything as a pointer to a long variable;
   XtArgVal is typedef'ed to a long.  In the days where the values were
   always returned in the arglist, treating the destination as a long was 
   fine since the value field really was a long.  However, since the
   value now pointed to by dst can be a char, a short, a long, etc, this
   assumption is no longer valid.  For instance, assume the following:

     dst ----> arglist value entry ----> a boolean variable

        ("---->" denotes 'pointing to')

   When the buggy statement shown above is executed, the picture now
   looks like the following:

     dst ----> a boolean variable

   Since the argument being queried is a char, the following is used to
   copy the value into the specified destinatioin:

     *dst = (XtArgVal) *((char *) src);

   Since the value pointed to by dst is assumed to be a long, the following
   four bytes are copied into the location we specified:

      0x00, 0x00, 0x00, 0x01

   Unfortunately, at least for those of us using 68000 architecture, the
   first 0x00 is copied into our destination, instead of the 0x01.



REPEAT-BY:
   Boolean flag;
   Arg     arg[1];

   XtSetArg (arg[0], XtNsensitive, &flag);
   XtGetValues (w, arg, XtNumber(arg));

FIX:

*** Resources.c	Fri Aug 19 12:28:34 1988
--- Resources.new.	Fri Aug 19 12:28:20 1988
***************
*** 62,67
      XtArgVal src, *dst;
      register unsigned int size;
  {
      /* ||| Old semantics are yucky, but keep as long as NULL value */
      if (*dst != NULL) 
  	dst = *(XtArgVal **)dst;

--- 62,69 -----
      XtArgVal src, *dst;
      register unsigned int size;
  {
+     Boolean addrGiven = False;
+ 
      /* ||| Old semantics are yucky, but keep as long as NULL value */
      if (*dst != NULL) 
      {
***************
*** 64,69
  {
      /* ||| Old semantics are yucky, but keep as long as NULL value */
      if (*dst != NULL) 
  	dst = *(XtArgVal **)dst;
  
      if (size == sizeof(XtArgVal))

--- 66,72 -----
  
      /* ||| Old semantics are yucky, but keep as long as NULL value */
      if (*dst != NULL) 
+     {
  	dst = *(XtArgVal **)dst;
          addrGiven = True;
      }
***************
*** 65,70
      /* ||| Old semantics are yucky, but keep as long as NULL value */
      if (*dst != NULL) 
  	dst = *(XtArgVal **)dst;
  
      if (size == sizeof(XtArgVal))
  	*dst = *(XtArgVal *)src;

--- 68,75 -----
      if (*dst != NULL) 
      {
  	dst = *(XtArgVal **)dst;
+         addrGiven = True;
+     }
  
      if (size == sizeof(XtArgVal))
  	*dst = *(XtArgVal *)src;
***************
*** 69,75
      if (size == sizeof(XtArgVal))
  	*dst = *(XtArgVal *)src;
      else if (size == sizeof(short)) 
! 	*dst = (XtArgVal) *((short *) src);
      else if (size == sizeof(char))
          *dst = (XtArgVal) *((char *) src);
      else if (size < sizeof(XtArgVal))

--- 74,85 -----
      if (size == sizeof(XtArgVal))
  	*dst = *(XtArgVal *)src;
      else if (size == sizeof(short)) 
!     {
!         if (addrGiven)
! 	   *((short *)dst) = (short)*((short *) src);
!         else
! 	   *dst = (XtArgVal) *((short *) src);
!     }
      else if (size == sizeof(char))
      {
          if (addrGiven)
***************
*** 71,77
      else if (size == sizeof(short)) 
  	*dst = (XtArgVal) *((short *) src);
      else if (size == sizeof(char))
!         *dst = (XtArgVal) *((char *) src);
      else if (size < sizeof(XtArgVal))
  	bcopy((char *) src, (char *) dst, (int) size);
      else

--- 81,92 -----
  	   *dst = (XtArgVal) *((short *) src);
      }
      else if (size == sizeof(char))
!     {
!         if (addrGiven)
!            *((char *)dst) = (char)*((char *) src);
!         else
!            *dst = (XtArgVal) *((char *) src);
!     }
      else if (size < sizeof(XtArgVal))
  	bcopy((char *) src, (char *) dst, (int) size);
      else