From:	MERC::"uunet!CRVAX.SRI.COM!RELAY-INFO-VAX"  9-MAR-1993 22:25:07.92
To:	Info-VAX@KL.SRI.COM
CC:	
Subj:	Re: problem with callback? (VAX/VMS+MOTIF+FORTRAN)


In article <C3F519.9tM@ireq.hydro.qc.ca>, ratel@ireq.hydro.qc.ca 
(Gilles Ratel 8720) writes about a problem getting a DECwindows Motif program
written in Fortran to work.  I contacted Gilles offline and helped him out;
for others' benefit, I'll detail what I found.

The first problem was the result of common and understandable confusion as
to how to translate C-style argument passing mechanisms to Fortran; there were
levels of address indirection included which were not necessary.  There is
a manual in the DECwindows Motif document set which discusses "non-C bindings",
but some simple rules are generally all that's needed:

	1.  If the C argument type isn't documented with an * next to the
	    type or argument name, and it isn't a string or a routine, then
	    it's probably passed by immediate value using %VAL.

	2.  If it's a string, it wants a null-terminated string passed by
	    reference.  For filling in "arg lists" with predeclared strings
	    of the XmNwhatever form, use %LOC(name); the strings are already
	    null-terminated in DECW$MOTIF.FOR.  If you're passing a string
	    as an argument to a routine, use %REF.

	3.  If it's a routine you're passing, just declare the routine
	    EXTERNAL and pass it directly; no %LOC.

The second problem was a generic Motif misunderstanding.  Gilles was asking
for the callback routine to be called when a SingleSelection occurred, but
the default selection type for a list widget is not SingleSelection (I think
it's ExtendedSelection, but I'm not sure).  Specifying single selection as
the selection policy when the widget was created fixed that problem.

I disagree with Brian McMillan's remarks on how difficult it is to do
Motif programming in Fortran.  It may be a bit confusing because of the
C bias of the Motif documentation and most of the examples, but it's fairly
straightforward to figure out how to use Fortran instead.  There are two
Fortran Motif examples provided on the DECwindows Motif toolkit which can
be very helpful. 

I've attached my corrected version of Gilles' program with some annotation.

	PROGRAM LISTTEST                                        
 
	IMPLICIT	NONE
	INCLUDE		'SYS$LIBRARY:DECW$MOTIF.FOR'
 
	INTEGER		I,J,N
 
	INTEGER*4	FETCH_FROM_ADDRESS
	EXTERNAL        FETCH_FROM_ADDRESS
	EXTERNAL	applicationShellWidgetClass
 
	EXTERNAL	LSELECT    ! routine for Callback
 
C...Widgets
	INTEGER*4	APP_CONTEXT
	INTEGER*4	DISPLAY
	INTEGER*4	TOPLEVEL
	INTEGER*4	LIST
 
	CHARACTER*35	TXT(5)      ! item list
	INTEGER*4	STXT(5)     ! XmString for TXT
	INTEGER		LT(5)       ! lenght for TXT(*)
 
	RECORD /ARG/ AL(0:7), ARG_LIST(0:0), ARGLIST_NULL(0:0)
 
C...X Routine Initialize, create 'application context' and 'Display'
	ARGLIST_NULL(0).NAME  = 0
	ARGLIST_NULL(0).VALUE = 0
 
	CALL XtToolkitInitialize()
	APP_CONTEXT = XtCreateApplicationContext()
 
	DISPLAY = XtOpenDisplay(
	1 %VAL(APP_CONTEXT),                  ! application context
	1 %VAL(0),                        ! display string
	1 %REF('TEST'//CHAR(0)),          ! application name
	1 %REF('XXXX'//CHAR(0)),       ! application class
	1 %VAL(0),                        ! options
	1 %VAL(0),                        ! num_options
	1 ARGLIST_NULL,                   ! argc
	1 %VAL(0))                        ! argv
	IF (DISPLAY .EQ. NULL) THEN
	  WRITE(*,*) 'Can''t open display'
	  STOP
	ENDIF
 
 
C...Design for manage 'Display'
	I = 0
	ARG_LIST(I).NAME = %LOC(XmNallowShellResize)  ! 
	ARG_LIST(I).VALUE = TRUE
        I=I+1
	ARG_LIST(I).NAME = %LOC(XmNy)
	ARG_LIST(I).VALUE = 200
	I=I+1
	ARG_LIST(I).NAME = %LOC(XmNx)
	ARG_LIST(I).VALUE = 100
 
	toplevel = XtAppCreateShell(
	1 %VAL(0),     ! appplication name
	1 %VAL(0),     ! application class
	1 %VAL(FETCH_FROM_ADDRESS(applicationShellWidgetClass)),
	1 %VAL(DISPLAY),
	1 ARG_LIST,  ! Structures and arrays always passed by reference
	1 %VAL(I+1) )
 
C...Create List Widget
C   note: actually, I not use XmListAddItem (i.e. I proceed step by step)
 
C...ITEM LIST
	TXT(1) = 'Hello World'    
	LT(1) = 11
	TXT(2) = 'my first motif' 
	LT(2) = 14
	TXT(3) = 'program'        
	LT(3) = 7
	N = 3
 
	DO J=1,N
	  STXT(J) = XmStringCreateLtoR (
	1 %REF(TXT(J)(1:LT(J))//CHAR(0)),  
	1  %REF(XmString_Default_Charset))  
	ENDDO
 
	I = J
	al(I).name = %LOC(XmNvisibleItemCount)  ! Address of string
	al(I).value = N
        I=I+1
	al(I).name = %LOC(XmNitems)
	al(I).value = %LOC(STXT)
        I=I+1
	al(I).name = %LOC(XmNitemCount)
	al(I).value = N
	I=I+1
	al(I).name = %LOC(XmNSelectionPolicy)  ! Added
	al(I).value = XmSingle_Select
	I = I + 1
 
	list = XmCreateList(
	1 %VAL(TOPLEVEL),            
	1 %REF('XXX'//char(0)),      
	1 al,                        
	1 %VAL(I+1))                 
 
C...Associate Callback for widget List
	CALL XtAddCallback( %VAL(list), 
	1 %REF(XmNsingleSelectionCallback), ! String passed by reference
	1 LSELECT,  ! Routine passed by reference 
	1 %VAL(0) )
 
	CALL XtManageChild(%VAL(list))      
	CALL XtRealizeWidget(%VAL(toplevel)) 
	CALL XtAppMainloop(%VAL(app_context))    
 
	STOP
	END
C============================================================================
	SUBROUTINE LSELECT (list,TAG,CBS)
 
C	Callback routine called whenever any pushbutton is pressed.
C	
 
	IMPLICIT NONE
!	INCLUDE 'SYS$LIBRARY:DECW$MOTIF/NOLIST'
 
	INTEGER*4 LIST		! Widget
	INTEGER*4 TAG		! Index into WIDGET_ARRAY
	INTEGER*4 CBS           ! not used   (callback structure)
 
	INTEGER*4	nselect
	INTEGER*4	iselect(25)
 
 
	WRITE(*,*)'SUCCESS'
 
	RETURN
	END	
C============================================================================
	INTEGER*4 FUNCTION FETCH_FROM_ADDRESS (LOCATION)
 
C	Function used to fetch the contents of a variable at a given
C	address.  This is used to reference external variables
C
	IMPLICIT NONE
	INTEGER*4 LOCATION
	FETCH_FROM_ADDRESS = LOCATION
	RETURN
	END

--

Steve Lionel                    lionel@quark.enet.dec.com
SDT Languages Group
Digital Equipment Corporation
110 Spit Brook Road
Nashua, NH 03062

