[Motiftools-bugs] XmtInputField:SetValues makes incorrect comparisons
Brought to you by:
motiftools
From: <mot...@li...> - 2004-06-23 20:36:51
|
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D XMT BUG REPORT FORM --------------------------- To: mot...@li... Subject: XmtInputField:SetValues makes incorrect comparisons YOUR NAME: Fred L. Kleinschmidt YOUR E-MAIL ADDRESS: fre...@bo... VERSION OF XMT: 4.0.0 HARDWARE AND OPERATING SYSTEM: (HP-UX_11.0, AIX4.3, IRIX6.5, SunOS5.8) X LIBRARIES: X11R6 MOTIF LIBRARY: Motif 2.1.0 LESSTIF LIBRARY: =20 COMPILER NAME AND VERSION: Ansi-C AREA: XmtInputField ONE-LINE SUMMARY: SetValue method compares wrong input records. FULL DESCRIPTION: (Describe the bug or enhancement request below.) There are three problems in how the XmtInputField SetValues method = checks for changes in String resources: 1. The XmtInputField SetValues method defines: #define Changed(field) (rw->input_field.field !=3D = cw->input_field.field) This is incorrect - the Changed macro should compare the new = widget to the current widget, not the requested to the current. It should be: #define Changed(field) (sw->input_field.field !=3D = cw->input_field.field) 2. String resources should be checked for changes using strcmp(). If = the application calls SetValues on a String resource whose value is = identical=20 to the existing value, Changed() will report True when in fact = there was no change, causing unnecessary processing and repaints. 3. When comparing for changes in string resources, the line sw->input_field.xxx =3D XtNewString( sw->input_field.xxx ) should come BEFORE the XtFree of the current value = (cw->input_field.xxx). By freeing the old value first, there is the possibility that the=20 XtNewString call will return the same space that was just freed=20 (This does indeed happen using CYGWIN). When that happens, a = subsequent call to Changed() on the same resource will return False, when in = truth the value did change. This happens for resource "pattern". =20 DUPLICATE BY: w =3D XtVaCreateManagedWidget( "inputfield", = xmtInputFieldWidgetClass, parent, XmtNpattern, "dd", NULL); /* at this point, the input field will accept at most two digits.*/ /* if we subsequently make this call: */ XtVaSetValues( w, XmNpattern, "dddd", NULL); /* then it should now accept four; however, it only accepts two. * This is becauses SetValues failed to call XmTextSetMaxLength = because * of the above errors. * * Also, the SetValues call may cause a crash due to separately = reported bug * where Initialize() fails to copy pattern, but SetValues frees it. */ WORKAROUND: [If you've found a temporary workaround for the bug, please describe = it.] SUGGESTED FIX:=20 /* ARGSUSED */ #if NeedFunctionPrototypes static Boolean SetValues(Widget current, Widget request, Widget set, ArgList arglist, Cardinal *num_args) #else static Boolean SetValues(current, request, set, arglist, num_args) Widget current; Widget request; Widget set; ArgList arglist; Cardinal *num_args; #endif { XmtInputFieldWidget cw =3D (XmtInputFieldWidget) current; XmtInputFieldWidget rw =3D (XmtInputFieldWidget) request; XmtInputFieldWidget sw =3D (XmtInputFieldWidget) set; #define Current(field) (cw->input_field.field) =20 #define Request(field) (rw->input_field.field) #define Set(field) (sw->input_field.field) /* (BOEING flk) Compare sw to cw, not rw to cw */ =20 #define Changed(field) (sw->input_field.field !=3D = cw->input_field.field) /* (BOEING flk) Must copy new one before freeing old one. * Otherwise, if Changed(x) is performed twice on the same field, * it may report false after initially being true, if the new * allocation happens to take the same space as the old one. *=20 /* * handle changes to the buffer or target symbol names */ if (Changed(buffer_symbol_name)) { if (Set(buffer_symbol_name)) { Set(buffer_symbol_name) =3D = XtNewString(Set(buffer_symbol_name)); BindBufferSymbol(sw); } /* XXX do something with the new value in the symbol? */ if (Current(buffer_symbol_name)) { XtFree(Current(buffer_symbol_name)); ReleaseBufferSymbol(cw); } } if (Changed(target_symbol_name)) { if (Set(target_symbol_name)) { Set(target_symbol_name) =3D = XtNewString(Set(target_symbol_name)); BindTargetSymbol(sw); } if (Current(target_symbol_name)) { XtFree(Current(target_symbol_name)); ReleaseTargetSymbol(cw); } } /* * if the value resource changes, copy the new value, set it on the * text widget, and copy it to the buffer, and target, if any. Note * that we do not call the verifyCallback, nor do we handle errors. * Note that changing value updates the buffer, but changing the = buffer * does not change the value. */ if (Changed(input)) { XtFree(Current(input)); if (Set(input)) { Set(input) =3D XtNewString(Set(input)); } SetString(set, Set(input)); (void)SetValueOnSymbols(sw, Set(input), False); } if (Changed(overstrike)) { if (Set(overstrike)) XtAddCallback(set, XmNmodifyVerifyCallback, HandleOverstrike, NULL); else XtRemoveCallback(set, XmNmodifyVerifyCallback, HandleOverstrike, NULL); } /* if pattern changed, free old, copy new, and adjust callbacks */ if (Changed(pattern)) { /* if the new pattern is NULL, remove the callbacks, else copy */ if (Set(pattern) =3D=3D NULL) { XtRemoveCallback(set, XmNmodifyVerifyCallback,HandlePattern, = NULL); } else Set(pattern) =3D XtNewString(Set(pattern)); /* if the old pattern was NULL, add the callbacks, else free */ if (Current(pattern) =3D=3D NULL) { XtAddCallback(set, XmNmodifyVerifyCallback, HandlePattern, = NULL); } else XtFree(Current(pattern)); =09 /* get the new size of the pattern */ if (Set(pattern))=20 Set(pattern_length) =3D strlen(Set(pattern)); else Set(pattern_length) =3D 0; } /* * update max_length from pattern or buffer size */ if (sw->text.max_length !=3D Current(max_length)) Set(max_length) =3D sw->text.max_length; else if (Changed(pattern)) Set(max_length) =3D Set(pattern_length); else if (Changed(buffer_symbol) && Set(buffer_symbol)) Set(max_length) =3D XmtSymbolSize(Set(buffer_symbol)); /* * if max_length or overstrike changed,=20 * update the internal widget */ if (Changed(max_length) || Changed(overstrike)) XmTextSetMaxLength(set, Set(overstrike)?MAXINT:Set(max_length)); =20 /*=20 * if sensitivity changes, set the layoutSensitive resource, in case * we're a child of XmtLayout, and have a caption. */ if ((sw->core.sensitive !=3D cw->core.sensitive) || (sw->core.ancestor_sensitive !=3D cw->core.ancestor_sensitive)) { XtVaSetValues(set, XmtNlayoutSensitive, sw->core.sensitive && sw->core.ancestor_sensitive, NULL); } /* never need to redraw */ return False; #undef Current #undef Request #undef Set =20 #undef Changed =20 } REPEAT BY: [What you did to get the error; include test program or session transcript if at all possible.] Fred L. Kleinschmidt Associate Technical Fellow Technical Architect, Common User Interface Services e-Business Technology Center M/S 2R-94 (206)544-5225 |