#include static int GetTextMaximum(Widget w) { int maxLength = 0 ; XtVaGetValues(w, XmNmaxLength, &maxLength, NULL) ; return maxLength ; } void NextFieldAfterMaxCharactersCallback(Widget w, XtPointer client_data, XtPointer xt_call_data) { XmTextVerifyCallbackStruct *call_data = (XmTextVerifyCallbackStruct *) xt_call_data ; if (call_data != (XmTextVerifyCallbackStruct *) 0) { if (call_data->text->length == 0) { /* Deletion - allow this */ } else { /* ** A simple check of current_length + call_data->text->length >= XmNmaxLength ** is wrong, because if the user is typing over selected text, the overall length ** can in fact decrease as the new text replaces the old selection. */ int maximum = GetTextMaximum(w) ; /* This returns the length of text before insertion */ XmTextPosition current_length = XmTextGetLastPosition(w) ; /* The length of data to insert */ int insertion_length = call_data->text->length ; /* A selection change will have end > start */ long change_length = call_data->endPos - call_data->startPos ; /* The final new length of the text after insertion */ long new_length = (current_length + insertion_length - change_length) ; if (new_length == maximum) { XmProcessTraversal(w, XmTRAVERSE_NEXT_TAB_GROUP) ; } else if (new_length > maximum) { /* This should not happen from the keyboard by definition of XmNmaxLength */ /* But it can happen because of a rogue programmatic XmTextSetString, */ /* or XtVaSetValues(w, XmNvalue, ...) which do not respect any setting */ /* of the XmNmaxLength resource. */ call_data->doit = False ; } } } }