Tk-TableMatrix

 view release on metacpan or  search on metacpan

pTk/mTk/Tktable800/tkTable.c  view on Meta::CPAN


/*
 *----------------------------------------------------------------------
 *
 * TableRestrictProc --
 *	A Tk_RestrictProc used by TableValidateChange to eliminate any
 *	extra key input events in the event queue that
 *	have a serial number no less than a given value.
 *
 * Results:
 *	Returns either TK_DISCARD_EVENT or TK_DEFER_EVENT.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static Tk_RestrictAction
TableRestrictProc(serial, eventPtr)
     ClientData serial;
     XEvent *eventPtr;
{
    if ((eventPtr->type == KeyRelease || eventPtr->type == KeyPress) &&
	((eventPtr->xany.serial-(unsigned int)serial) > 0)) {
	return TK_DEFER_EVENT;
    } else {
	return TK_PROCESS_EVENT;
    }
}

/*
 *--------------------------------------------------------------
 *
 * TableValidateChange --
 *	This procedure is invoked when any character is added or
 *	removed from the table widget, or a set has triggered validation.
 *
 * Results:
 *	TCL_OK    if the validatecommand accepts the new string,
 *	TCL_BREAK if the validatecommand rejects the new string,
 *      TCL_ERROR if any problems occured with validatecommand.
 *
 * Side effects:
 *      The insertion/deletion may be aborted, and the
 *      validatecommand might turn itself off (if an error
 *      or loop condition arises).
 *
 *--------------------------------------------------------------
 */
int
TableValidateChange(tablePtr, r, c, old, new, index)
     register Table *tablePtr;	/* Table that needs validation. */
     int r, c;			/* row,col index of cell in user coords */
     char *old;			/* current value of cell */
     char *new;			/* potential new value of cell */
     int index;			/* index of insert/delete, -1 otherwise */
{
    register Tcl_Interp *interp = tablePtr->interp;
    int code, booln; /* perltk: Bool to booln to avoid problems with DEFINES*/ 
    Tk_RestrictProc *rstrct;
    ClientData cdata;
  
    if (tablePtr->valCmd == NULL || tablePtr->validate == 0) {
	return TCL_OK;
    }

    /* Magic code to make this bit of code UI synchronous in the face of
     * possible new key events */
    XSync(tablePtr->display, False);
    rstrct = Tk_RestrictEvents(TableRestrictProc, (ClientData)
				 NextRequest(tablePtr->display), &cdata);

    /*
     * If we're already validating, then we're hitting a loop condition
     * Return and set validate to 0 to disallow further validations
     * and prevent current validation from finishing
     */
    if (tablePtr->flags & VALIDATING) {
	tablePtr->validate = 0;
	return TCL_OK;
    }
    tablePtr->flags |= VALIDATING;

    code = LangDoCallback(tablePtr->interp, tablePtr->valCmd, 1, 5, "%d %d %s %s %d",
    	r, c, old, new, index);


    if (code != TCL_OK && code != TCL_RETURN) {
	Tcl_AddErrorInfo(interp,
			 "\n\t(in validation command executed by table)");
	Tcl_BackgroundError(interp);
	code = TCL_ERROR;
    } else if (Tcl_GetBooleanFromObj(interp, Tcl_GetObjResult(interp),
				     &booln) != TCL_OK) {
	Tcl_AddErrorInfo(interp,
			 "\n\tboolean not returned by validation command");
	Tcl_BackgroundError(interp);
	code = TCL_ERROR;
    } else {
	code = (booln) ? TCL_OK : TCL_BREAK;
    }
    Tcl_SetStringObj(Tcl_GetObjResult(interp), (char *) NULL, 0);

    /*
     * If ->validate has become VALIDATE_NONE during the validation,
     * it means that a loop condition almost occured.  Do not allow
     * this validation result to finish.
     */
    if (tablePtr->validate == 0) {
	code = TCL_ERROR;
    }

    /* If validate will return ERROR, then disallow further validations */
    if (code == TCL_ERROR) {
	tablePtr->validate = 0;
    }

    Tk_RestrictEvents(rstrct, cdata, &cdata);
    tablePtr->flags &= ~VALIDATING;

    return code;
}

/*
 *--------------------------------------------------------------
 *
 * ExpandPercents --
 *	Given a command and an event, produce a new command
 *	by replacing % constructs in the original command
 *	with information from the X event.
 *
 * Results:
 *	The new expanded command is appended to the dynamic string
 *	given by dsPtr.
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */
void
ExpandPercents(tablePtr, before, r, c, old, new, index, dsPtr, cmdType)
     Table *tablePtr;		/* Table that needs validation. */
     char *before;		/* Command containing percent
				 * expressions to be replaced. */
     int r, c;			/* row,col index of cell */
     char *old;                 /* current value of cell */
     char *new;                 /* potential new value of cell */
     int index;                 /* index of insert/delete */
     Tcl_DString *dsPtr;        /* Dynamic string in which to append
				 * new command. */
     int cmdType;		/* type of command to make %-subs for */
{
    int length, spaceNeeded, cvtFlags;
#ifdef TCL_UTF_MAX
    Tcl_UniChar ch;
#else
    char ch;
#endif
    char *string, buf[INDEX_BUFSIZE];

    /* This returns the static value of the string as set in the array */
    if (old == NULL && cmdType == CMD_VALIDATE) {
	old = TableGetCellValue(tablePtr, r, c);
    }

    while (1) {
	if (*before == '\0') {
	    break;
	}
	/*
	 * Find everything up to the next % character and append it
	 * to the result string.
	 */

	string = before;
#ifdef TCL_UTF_MAX
	/* No need to convert '%', as it is in ascii range */



( run in 1.758 second using v1.01-cache-2.11-cpan-39bf76dae61 )