#include <Xm/Text.h>

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 ;
			}
		}
	}
}
