/* 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. */
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; }