From: mayer@hplnpm1.hpl.hp.com (Niels P. Mayer)
Subject: Re: winterp help w/TEXT_, LABEL_ and SELECTION_BOX widgets
Organization: Hewlett-Packard Labs, Software Technology Lab, Palo Alto, CA.
Date: 6 Apr 92 14:25:31


In article <GFE.92Mar26163032@cblpf.ATT.COM> gfe@cblpf.ATT.COM (55440-Gary Ellison(CB0242)000) writes:
> I am experiencing some strange behavior with respect to the attachment
> of a LABEL_WIDGET to a _scrolled_ TEXT_WIDGET. The LABEL_WIDGET's
> top_attachment is a TEXT_WIDGET. All is fine until the _dialog_
> SELECTION_BOX_WIDGET is instantiated. After that the label will always
> attach to the top of the form even if I restart the application.
> I have to exit winterp to get things rectified. 
> 
> Through experimentation I can safely say this does not occur if the
> TEXT_WIDGET is not :scrolled or if I use a LABEL_GADGET or if the
> SELECTION_BOX is never instantiated or if it is not a :dialog widget.
> 
> Versions:
>     SunOS 4.1.1 (sparc)
>     Winterp 1.13
>     Motif 1.1.3
>     X11R4 fully patched

The problem is in the last place you'd expect it -- you are calling
XtRealize() in the wrong place:

   (defun make-form-shell (s_geom)
     (let*
	 ((toplevel_w
	   (send TOP_LEVEL_SHELL_WIDGET_CLASS :new "Muzak"
		 :XMN_GEOMETRY s_geom
		 :XMN_TITLE    "Bring The Noise"
		 ))
	  (form_w
	   (send XM_FORM_WIDGET_CLASS :new :managed
		 "form" toplevel_w
		 )))
>>>    (send toplevel_w :realize)

       form_w))

What is happening is that you are calling :REALIZE almost immediately after
you create the top-level widget. That in itself is not really a problem
(though it is against Xt style). The problem is that the realization isn't
really complete until the top-level widget's window is created. To do that,
you need to actually get back to the event loop for long enough to process
all the events generated by message :REALIZE. I believe this would be the
case for a traditional C/Motif program, as well as for WINTERP (which is
essentially just a traditional C/Motif program with an added
mini-interpreter layer).

You might think that evaluating the statement '(make-form-shell...)' at the
top-level evaluator of WINTERP is exactly the same as evaluating it from
within a sequence of statements.  In fact, what is happening is that any
interactive code evaluations occurring at the top level are actually
occurring as a 'callback' out of the main Xt event loop, such that upon
return from the 'callback', the events associated with the :REALIZE message
get processed.

In your code, 
   (let (FormW)
     (openup-form)
     (setq FormW (make-form-shell "=300x100+850+200"))
     (popup-sel-box FormW)
     )
the events get processed only after the '(let ...)" statement is evaluated.
Since 'make-form-shell' calls :REALIZE on the toplevel widget, 'FormW' is
only partially realized by the time it is passed in as the parent of the
dialog widget. The problem seems to be that the dialog widget wants it's 
parent widget to be realized.

My gut feeling is that your partially-realized widget parent is causing
trash data to be passed in to a widget creation, or perhaps some memory is
getting corrupted in Xt/Xm. It might even be something simple, like the
actual as-yet uncreated window being referenced by the popup/dialog widget.

As I said this is a gut feeling on my part. I haven't confirmed the above
hypothesis by running the code through a C debugger, nor have I looked at
the source to verify that my claim is correct. I simply don't have the time
to do that kind of free Motif consulting...

However, my version of your code works correctly. Below is a slight rewrite
of your code. Basically, I got rid of 'make-form-shell' entirely because
you need to do :REALIZE outside the temporal scope of that function. Also,
the commented out portions ";;;NPM" indicate some things (such as
attachments) that weren't in your code, and should perhaps be added:

(defun openup-form ()
  (let (toplevel_w uFormW lyricLabelW lyricFieldW whyHereLabelW)
    (setq toplevel_w
	  (send TOP_LEVEL_SHELL_WIDGET_CLASS :new "Muzak"
		:XMN_GEOMETRY "=640x480+490+204"
		:XMN_TITLE    "Bring The Noise"
		))
    (setq uFormW
	  (send XM_FORM_WIDGET_CLASS :new :managed
		"form" toplevel_w
		))
    (setq lyricLabelW
	  (send XM_LABEL_WIDGET_CLASS :new :managed 
		"lyricLabelW" uFormW
		:XMN_LABEL_STRING     "Trouble Funk Lyrics"
		:XMN_LEFT_ATTACHMENT  :attach_form
;;;NPM		:XMN_RIGHT_ATTACHMENT :attach_form
		:XMN_TOP_ATTACHMENT   :attach_form
		))
    (setq lyricFieldW
	  (send XM_TEXT_WIDGET_CLASS :new :managed :scrolled
		"lyricFieldW" uFormW
		:XMN_EDIT_MODE         :MULTI_LINE_EDIT
		:XMN_ROWS              2
		:XMN_LEFT_ATTACHMENT   :attach_form
		:XMN_RIGHT_ATTACHMENT  :attach_form
		:XMN_TOP_ATTACHMENT    :attach_widget
		:XMN_TOP_WIDGET        lyricLabelW
		))
    (setq whyHereLabelW
	  (send XM_LABEL_WIDGET_CLASS :new :managed
		"whyHereLabelW" uFormW
		:XMN_LABEL_STRING     "On Top Of Lyric Stuff"
		:XMN_TOP_ATTACHMENT   :attach_widget
		:XMN_TOP_WIDGET       lyricFieldW
		:XMN_LEFT_ATTACHMENT  :attach_form
;;;NPM		:XMN_RIGHT_ATTACHMENT :attach_form
;;;NPM		:XMN_BOTTOM_ATTACHMENT :attach_form
		))
    (send toplevel_w :realize)		;NPM sez do XtRealize() at 'end' of 'procedure'
    ))

(defun popup-sel-box (w)
  (let (genreSel_ListW)
    (setq genreSel_ListW
	  (send XM_SELECTION_BOX_WIDGET_CLASS :new :managed :dialog
		"selection" w
		:XMN_SELECTION_LABEL_STRING "Select Genre"
		:XMN_MUST_MATCH		  t
		:XMN_LIST_ITEMS             #("Blues" "Funk" "Garage Funk" 
					      "Hardcore" "Rap")
		:XMN_LIST_ITEM_COUNT        5
		:XMN_LIST_VISIBLE_ITEM_COUNT 5
		))
    (send genreSel_ListW :set_callback :XMN_OK_CALLBACK '()
	  '(
	    (openup-form)
	    ))
    ))

(let (toplevel_w)
  (openup-form)
  (setq toplevel_w
	(send TOP_LEVEL_SHELL_WIDGET_CLASS :new "Muzak"
	      :XMN_GEOMETRY "=300x100+850+200"
	      :XMN_TITLE    "Bring The Noise"
	      ))
  (send toplevel_w :realize)

  (if (and (= *XLISP_VERSION* 2) (= *XLISP_REVISION* 11))
      (progn
	;; for winterp 1.14, we can replace code below with the following:
	;; :FORCED_EXPOSE_UPDATE -- returns only after toplevel_w exposed
	(send toplevel_w :FORCED_EXPOSE_UPDATE)	
	;; now that toplevel_w is exposed/fully-realized, we can pass it
	;; on as parent of popup widget.
	(popup-sel-box toplevel_w)
	)
    (progn
      ;; for winterp 1.13, we schedule the popup-sel-box
      ;; events to get processed only after the ':realize' events by
      ;; adding a 0-length timeout.
      ;; (this is because winterp 1.13 doesn't have :FORCED_EXPOSED_UPDATE)
      (xt_add_timeout 0
		      '(
			(popup-sel-box toplevel_w)
			))
      ))
  )

		--------------------

If my hypothesis is correct, then the behavior caused by your could be
assumed to be a Motif bug. On the other hand, calling XtRealize() at the
wrong place could be considered a programming error. It would certainly be
better if Motif/Xt didn't trash memory -- a warning would be better. For
example, if you call XtMap() or XtUnmap() on an unrealized widget, you
get an Xlib error (bad window), rather than unreported corruption.

		--------------------

Note at how I arrived at this "solution":

;; interactively evaling this form exhibits bug:
(let (FormW)
  (openup-form)
  (setq FormW (make-form-shell "=300x100+850+200"))
  (popup-sel-box FormW)
  )

;; problem doesn't occur in interactively evaling the form below:
;; (NOTE: *toplevel_widget* is an unmapped widget created as the default 
;; application shell widget for WINTERP. Multiple applications and
;; application shells can be created by WINTERP, however, motif
;; requires at least one widget to be created initially in order 
;; to have application resources, and also for doing resource conversions.
(popup-sel-box *toplevel_widget*)

;; problem doesn't occur if interactively evaling this:
(openup-form)

;; interactively evaling this doesn't exhibit problem either. However,
;; since toplevel_w isn't realized when passed in to 'popup-sel-box' you
;; have to manually place the dialog -- positioning of dialog is based
;; on the location of the toplevel_w, and an unrealized widget has no location.
(let
    ((toplevel_w
      (send TOP_LEVEL_SHELL_WIDGET_CLASS :new "Muzak"
	    :XMN_GEOMETRY "=300x100+850+200"
	    :XMN_TITLE    "Bring The Noise"
	    ))
     )
  (openup-form)
  (popup-sel-box toplevel_w)
  (send toplevel_w :realize)		;note realize occurs after popup-sel-box
  )


;; interactively evaling this doesn't exhibit problem either:
(let ()
  (openup-form)
  (popup-sel-box *toplevel_widget*)

--
-------------------------------------------------------------------------------
	    Niels Mayer -- hplabs!mayer -- mayer@hplabs.hp.com
		  Human-Computer Interaction Department
		       Hewlett-Packard Laboratories
			      Palo Alto, CA.
				   *
--
-------------------------------------------------------------------------------
	    Niels Mayer -- hplabs!mayer -- mayer@hplabs.hp.com
		  Human-Computer Interaction Department
		       Hewlett-Packard Laboratories
			      Palo Alto, CA.
				   *