This note documents why XEmacs external widget is important, and
provides a fix to some annoying behavior on Solaris 7 when using
external widget under XEmacs 21.1.14 on Solaris 7. This writeup and
the patch are both courtesy of Kenny Chien
(Kenny.Chien(a)morganstanley.com).
Morgan Stanley's in-house C++ widget toolkit is based solely on the
X11 libraries, with no dependency on Xt or Motif. This toolkit
implements a Motif look and feel.
The use of XEmacs's external widget feature was driven by a real
business need in a trading application. In this application, users
structure business logic using a high level business specific
programming language.
Instead of expending resources in implementing a full blown editor
widget, we decided to give XEmacs external widget a try. It has been
incorporated into our toolkit and used in production since 1997.
The editor widget is also supported via Java on Solaris and NT. At
least 3 production applications, two in C++ and one in Java, utilize
this editor widget. The response from the user community has been
excellent because there are simply no better editor widgets out there.
Now, for the technical content. The function extw_wait_for_response()
in extw-Xt.c behaves inconsistently between Solaris 2.5.1 and Solaris
7. More specifically, the underlying _XtWaitForSomething() function
invoked by extw_wait_for_response() behaves differently when a timeout
occurs. In Solaris 7, it doesn't seem to return -1 when it times out,
it returns 1 instead. extw_wait_for_response() therefore loops
indefinitely causing xemacs to hang.
The fix to this problem is to not use _XtWaitForSomething(). The
biggest reason is of course it is an undocumented internal Xt
function, there is technically no guarantee of the existence and
the behavior of this function in future releases.
This patch rewrites extw_wait_for_response() to use only public Xt
functions and at the same time preserve the semantics of this
function. It will now behave consistently and timeout properly.
Here is the patch, against XEmacs 21.1.14. extw_wait_for_response()
seems to have been rewritten in XEmacs 21.4, but it still uses the
undocumented _XtWaitForSomething function. This method is probably
more portable...
--- extw-Xt.c.save Fri May 25 17:28:57 2001
+++ extw-Xt.c Fri May 25 17:28:17 2001
@@ -35,47 +35,10 @@
#endif
#include <X11/Intrinsic.h>
-#include <X11/IntrinsicP.h>
#include <stdlib.h>
#include <stdio.h>
#include "extw-Xt.h"
-/* Yeah, that's portable!
-
- Why the hell didn't the Xt people just export this function
- for real? */
-
-#if (XT_REVISION > 5)
-int _XtWaitForSomething(
- XtAppContext app,
- _XtBoolean ignoreEvents,
- _XtBoolean ignoreTimers,
- _XtBoolean ignoreInputs,
- _XtBoolean ignoreSignals,
- _XtBoolean block,
-#ifdef XTHREADS
- _XtBoolean drop_lock,
-#endif
- unsigned long *howlong);
-
-# ifndef XTHREADS
-# define _XtwaitForSomething(timers,inputs,events,block,howlong,appCtx) \
- _XtWaitForSomething(appCtx,events,timers,inputs,0,block,howlong)
-# else
-# define _XtwaitForSomething(timers,inputs,events,block,howlong,appCtx) \
- _XtWaitForSomething(appCtx,events,timers,inputs,0,block,1,howlong)
-# endif
-#else
-int _XtwaitForSomething(
- Boolean ignoreTimers,
- Boolean ignoreInputs,
- Boolean ignoreEvents,
- Boolean block,
- unsigned long *howlong,
- XtAppContext app
- );
-#endif
-
#ifdef DEBUG_WIDGET
static int geom_masks[] = {
@@ -195,35 +158,24 @@
/* check if an event is of the sort we're looking for */
-static FILE *file;
static Bool
isMine(XEvent *event, QueryStruct *q)
{
Widget w = q->w;
- fprintf(file,"Event Type is %d\n",event->type);
- if (event->type == ClientMessage)
- {
- fprintf(file,"***** It's a ClientMessage.*****\n");
- }
-
+
if ( (event->xany.display != XtDisplay(w)) || (event->xany.window != XtWindow(w))
)
{
- if ( (event->xany.display != XtDisplay(w)))
- {
- fprintf(file,"Wrong Display\n");
- }
- else
- {
- fprintf(file,"Wrong Window ID\n");
- }
return FALSE;
- }
- if (event->xany.serial >= q->request_num) {
+ }
+ if (event->xany.serial >= q->request_num)
+ {
if (event->type == ClientMessage &&
event->xclient.message_type == a_EXTW_NOTIFY &&
event->xclient.data.l[0] == 1 - extw_which_side &&
event->xclient.data.l[1] == q->type)
- return TRUE;
+ {
+ return TRUE;
+ }
}
return FALSE;
}
@@ -235,8 +187,10 @@
}
/* wait for a ClientMessage of the specified type from the other widget, or
- time-out. isMine() determines whether an event matches. Culled from
- Shell.c. */
+ time-out. isMine() determines whether an event matches.
+ Took out the call to _XtWaitForSomething and replaced it with public
+ Xt api's.
+*/
Bool
extw_wait_for_response(Widget w, XEvent *event, unsigned long request_num,
@@ -247,7 +201,6 @@
QueryStruct q;
Bool expired;
XtIntervalId id;
- file=fopen("/tmp/debug","a");
q.w = w;
q.request_num = request_num;
@@ -257,46 +210,26 @@
id=XtAppAddTimeOut(app,timeout,responseTimeOut,&expired);
while (!expired)
{
-/* fprintf(file,"Looking for Pending event.\n"); */
inputMask=XtAppPending(app);
if (inputMask & XtIMXEvent)
{
- fprintf(file,"Got an X Event.\n");
- fflush(file);
XtAppNextEvent(app,event);
- if (event->type==Expose)
- {
- fprintf(file,"Dispatching Expose.\n");
-/* XtDispatchEvent(event); */
- }
- else if (isMine(event,&q))
+ if (isMine(event,&q))
{
- fprintf(file,"===========> Got the Client Message Event\n");
- fflush(file);
if (!expired) XtRemoveTimeOut(id);
return True;
}
else
{
/* Do Nothing and go back to waiting */
- fprintf(file,"Don't want this X Event.\n");
- fflush(file);
}
}
if (inputMask & XtIMTimer)
{
/* Process the expired timer */
- fprintf(file,"Got a timer event.\n");
XtAppProcessEvent(app,XtIMTimer);
}
- if (inputMask & XtIMAlternateInput)
- {
-/* fprintf(file,"Got some Alternate Input Event.\n"); */
- }
}
/* Must have expired */
- fprintf(file,"Timer Expired.\n");
- fflush(file);
- fclose(file);
return False;
}
--
Isaac Hollander Morgan Stanley Dean Witter
isaac.hollander(a)morganstanley.com 1585 Broadway, 2nd floor
(212) 761 3417 New York, NY