/* $Id: tixGrData.c,v 1.1.1.1 2000/05/17 11:08:42 idiscovery Exp $ */
/*
* tixGrData.c --
*
* This module manipulates the data structure for a Grid widget.
*
* Copyright (c) 1996, Expert Interface Technologies
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#include "tixPort.h"
#include "tixInt.h"
#include "tixGrid.h"
/* need "(unsigned int)" to prevent sign-extension on 64-bit machines, and
* "(unsigned long)" to avoid an egcs warning
*/
#define FIX(X) ((char*)(unsigned long)(unsigned int)(X))
static int FindRowCol _ANSI_ARGS_((TixGridDataSet * dataSet,
int x, int y, TixGridRowCol * rowcol[2],
Tcl_HashEntry * hashPtrs[2]));
static TixGridRowCol * InitRowCol _ANSI_ARGS_((int index));
static int RowColMaxSize _ANSI_ARGS_((WidgetPtr wPtr,
int which, TixGridRowCol *rowCol,
TixGridSize * defSize));
static TixGridRowCol *
InitRowCol(index)
int index;
{
TixGridRowCol * rowCol = (TixGridRowCol *)ckalloc(sizeof(TixGridRowCol));
rowCol->dispIndex = index;
rowCol->size.sizeType = TIX_GR_DEFAULT;
rowCol->size.sizeValue = 0;
rowCol->size.charValue = 0;
rowCol->size.pad0 = 2;
rowCol->size.pad1 = 2;
rowCol->size.pixels = 0;
Tcl_InitHashTable(&rowCol->table, TCL_ONE_WORD_KEYS);
return rowCol;
}
/*----------------------------------------------------------------------
* TixGridDataSetInit --
*
* Create an instance of the TixGridDataSet data structure.
*
*----------------------------------------------------------------------
*/
TixGridDataSet *
TixGridDataSetInit()
{
TixGridDataSet * dataSet =(TixGridDataSet*)ckalloc(sizeof(TixGridDataSet));
Tcl_InitHashTable(&dataSet->index[0], TCL_ONE_WORD_KEYS);
Tcl_InitHashTable(&dataSet->index[1], TCL_ONE_WORD_KEYS);
dataSet->maxIdx[0] = -1;
dataSet->maxIdx[1] = -1;
return dataSet;
}
/*----------------------------------------------------------------------
* TixGridDataSetFree --
*
* Frees an instance of the TixGridDataSet data structure.
*
*----------------------------------------------------------------------
*/
void
TixGridDataSetFree(dataSet)
TixGridDataSet* dataSet;
{
Tcl_HashSearch hashSearch;
Tcl_HashEntry *hashPtr;
TixGridRowCol *rcPtr;
int i;
for (i=0; i<2; i++) {
for (hashPtr = Tcl_FirstHashEntry(&dataSet->index[i], &hashSearch);
hashPtr;
hashPtr = Tcl_NextHashEntry(&hashSearch)) {
rcPtr = (TixGridRowCol *)Tcl_GetHashValue(hashPtr);
if (rcPtr->table.numEntries > 0) {
#if 0
fprintf(stderr, "Grid hash entry leaked: %d : %d\n", i,
rcPtr->dispIndex);
#endif
}
Tcl_DeleteHashTable(&rcPtr->table);
ckfree((char*)rcPtr);
}
}
Tcl_DeleteHashTable(&dataSet->index[0]);
Tcl_DeleteHashTable(&dataSet->index[1]);
ckfree((char*)dataSet);
}
/*----------------------------------------------------------------------
* TixGridDataFindEntry --
*
* Results:
* Return the element if it exists. Otherwise returns NULL.
*
* Side effects:
* None.
*----------------------------------------------------------------------
*/
char *
TixGridDataFindEntry(dataSet, x, y)
TixGridDataSet * dataSet;
int x;
int y;
{
TixGridRowCol *col, *row;
Tcl_HashEntry *hashPtr;
/* (1) Find the row and column */
if (!(hashPtr = Tcl_FindHashEntry(&dataSet->index[0], FIX(x)))) {
return NULL;
}
col = (TixGridRowCol *)Tcl_GetHashValue(hashPtr);
if (!(hashPtr = Tcl_FindHashEntry(&dataSet->index[1], FIX(y)))) {
return NULL;
}
row = (TixGridRowCol *)Tcl_GetHashValue(hashPtr);
/* (2) Find the entry */
if (row->table.numEntries < col->table.numEntries) {
if (!(hashPtr = Tcl_FindHashEntry(&row->table, (char*)col))) {
return NULL;
}
}
else {
if (!(hashPtr = Tcl_FindHashEntry(&col->table, (char*)row))) {
return NULL;
}
}
return (char *)Tcl_GetHashValue(hashPtr);
}
/*----------------------------------------------------------------------
* FindRowCol --
*
* Internal function: finds row and column info an entry.
*
* Results:
* Returns true if BOTH row and column exist. If so, the row and
* column info is returned in the rowcol.
*
* Side effects:
* None.
*----------------------------------------------------------------------
*/
static int
FindRowCol(dataSet, x, y, rowcol, hashPtrs)
TixGridDataSet * dataSet; /* The Grid dataset. */
int x, y; /* Location of the cell. */
TixGridRowCol * rowcol[2]; /* Returns information about the row/col. */
Tcl_HashEntry * hashPtrs[2];/* Returns hash table info about the row/col.*/
{
hashPtrs[0] = Tcl_FindHashEntry(&dataSet->index[0], FIX(x));
if (hashPtrs[0] != NULL) {
rowcol[0] = (TixGridRowCol *)Tcl_GetHashValue(hashPtrs[0]);
} else {
return 0;
}
hashPtrs[1] = Tcl_FindHashEntry(&dataSet->index[1], FIX(y));
if (hashPtrs[1] != NULL) {
rowcol[1] = (TixGridRowCol *)Tcl_GetHashValue(hashPtrs[1]);
} else {
return 0;
}
return 1;
}
/*----------------------------------------------------------------------
* TixGridDataCreateEntry --
*
* Find or create the entry at the specified index.
*
* Results:
* A handle to the entry.
*
* Side effects:
* A new entry is created if it is not already in the dataset.
*----------------------------------------------------------------------
*/
char *
TixGridDataCreateEntry(dataSet, x, y, defaultEntry)
TixGridDataSet * dataSet;
int x;
int y;
char * defaultEntry;
{
TixGridRowCol *rowcol[2];
Tcl_HashEntry *hashPtr;
int isNew, i, dispIndex[2];
dispIndex[0] = x;
dispIndex[1] = y;
for (i=0; i<2; i++) {
hashPtr = Tcl_CreateHashEntry(&dataSet->index[i],
FIX(dispIndex[i]), &isNew);
if (!isNew) {
rowcol[i] = (TixGridRowCol *)Tcl_GetHashValue(hashPtr);
} else {
rowcol[i] = InitRowCol(dispIndex[i]);
Tcl_SetHashValue(hashPtr, (char*)rowcol[i]);
if (dataSet->maxIdx[i] < dispIndex[i]) {
dataSet->maxIdx[i] = dispIndex[i];
}
}
}
hashPtr = Tcl_CreateHashEntry(&rowcol[0]->table,
(char*)rowcol[1], &isNew);
if (!isNew) {
return (char *) Tcl_GetHashValue(hashPtr);
}
else {
TixGrEntry *chPtr = (TixGrEntry *)defaultEntry;
Tcl_SetHashValue(hashPtr, (char*)chPtr);
chPtr->entryPtr[0] = hashPtr;
hashPtr = Tcl_CreateHashEntry(&rowcol[1]->table,
(char*)rowcol[0], &isNew);
Tcl_SetHashValue(hashPtr, (char*)defaultEntry);
chPtr->entryPtr[1] = hashPtr;
return defaultEntry;
}
}
/*----------------------------------------------------------------------
* TixGridDataDeleteEntry --
*
* Deletes the entry at the specified index.
*
* Results:
* True iff the entry existed and was deleted.
*
* Side effects:
* If there is an entry at the index, it is deleted.
*----------------------------------------------------------------------
*/
int
TixGridDataDeleteEntry(dataSet, x, y)
TixGridDataSet * dataSet; /* The Grid dataset. */
int x; /* Column number of the entry. */
int y; /* Row number of the entry. */
{
TixGridRowCol *rowcol[2];
Tcl_HashEntry *hashPtrs[2]; /* Hash entries of the row/col. */
Tcl_HashEntry *cx, *cy; /* Hash entries of the cell in the row/col. */
if (!FindRowCol(dataSet, x, y, rowcol, hashPtrs)) {
/*
* The row and/or the column do not exist.
*/
return 0;
}
cx = Tcl_FindHashEntry(&rowcol[0]->table, (char*)rowcol[1]);
cy = Tcl_FindHashEntry(&rowcol[1]->table, (char*)rowcol[0]);
if (cx == NULL && cy == NULL) {
return 0;
}
else if (cx != NULL && cy != NULL) {
Tcl_DeleteHashEntry(cx);
Tcl_DeleteHashEntry(cy);
}
else {
panic("Inconsistent grid dataset: (%d,%d) : %x %x", x, y, cx, cy);
}
return 1;
/*
* ToDo: trim down the hash table.
*/
}
/* return value: has the size of the grid changed as a result of sorting */
int
TixGridDataUpdateSort(dataSet, axis, start, end, items)
TixGridDataSet * dataSet;
int axis;
int start;
int end;
Tix_GrSortItem *items;
{
TixGridRowCol **ptr;
Tcl_HashEntry *hashPtr;
int numItems = end - start + 1;
int i, k, max = 0;
if (numItems <= 0) {
return 0;
}
ptr = (TixGridRowCol **)ckalloc(numItems * sizeof(TixGridRowCol *));
for (k=0,i=start; i<=end; i++,k++) {
if (!(hashPtr = Tcl_FindHashEntry(&dataSet->index[axis], FIX(i)))) {
/*
* This row/col doesn't exist
*/
ptr[k] = NULL;
} else {
ptr[k] = (TixGridRowCol *)Tcl_GetHashValue(hashPtr);
Tcl_DeleteHashEntry(hashPtr);
}
}
for (k=0,i=start; i<=end; i++,k++) {
int pos, isNew;
pos = items[k].index - start;
if (ptr[pos] != NULL) {
hashPtr = Tcl_CreateHashEntry(&dataSet->index[axis], FIX(i),
&isNew);
Tcl_SetHashValue(hashPtr, (char*)ptr[pos]);
ptr[pos]->dispIndex = i;
max = i;
}
}
ckfree((char*)ptr);
if (end+1 >= dataSet->maxIdx[axis]) {
if (dataSet->maxIdx[axis] != max+1) {
dataSet->maxIdx[axis] = max+1;
return 1; /* size changed */
}
}
return 0; /* size not changed */
}
static int
RowColMaxSize(wPtr, which, rowCol, defSize)
WidgetPtr wPtr;
int which; /* 0=cols, 1=rows */
TixGridRowCol *rowCol;
TixGridSize * defSize;
{
Tcl_HashSearch hashSearch;
Tcl_HashEntry *hashPtr;
TixGrEntry * chPtr;
int maxSize = 1;
if (rowCol->table.numEntries == 0) {
return defSize->pixels;
}
for (hashPtr = Tcl_FirstHashEntry(&rowCol->table, &hashSearch);
hashPtr;
hashPtr = Tcl_NextHashEntry(&hashSearch)) {
chPtr = (TixGrEntry *)Tcl_GetHashValue(hashPtr);
if (maxSize < chPtr->iPtr->base.size[which]) {
maxSize = chPtr->iPtr->base.size[which];
}
}
return maxSize;
}
/*
*----------------------------------------------------------------------
* TixGridDataGetRowColSize --
*
* Returns width of a column or height of a row.
*
* Results:
* The width or height.
*
* Side effects:
* None.
*----------------------------------------------------------------------
*/
int
TixGridDataGetRowColSize(wPtr, dataSet, which, index, defSize, pad0, pad1)
WidgetPtr wPtr; /* Info about Grid widget */
TixGridDataSet * dataSet; /* Dataset of the Grid */
int which; /* 0=cols, 1=rows */
int index; /* Column or row number */
TixGridSize * defSize; /* The default size for the grid cells */
int *pad0; /* Holds return value of horizontal padding. */
int *pad1; /* Holds return value of vertical padding. */
{
TixGridRowCol *rowCol;
Tcl_HashEntry *hashPtr;
int size;
if (!(hashPtr = Tcl_FindHashEntry(&dataSet->index[which], FIX(index)))) {
size = defSize->pixels;
*pad0 = defSize->pad0;
*pad1 = defSize->pad1;
}
else {
rowCol = (TixGridRowCol *)Tcl_GetHashValue(hashPtr);
switch (rowCol->size.sizeType) {
case TIX_GR_AUTO:
size = RowColMaxSize(wPtr, which, rowCol, defSize);
*pad0 = rowCol->size.pad0;
*pad1 = rowCol->size.pad1;
break;
case TIX_GR_DEFINED_PIXEL:
size = rowCol->size.sizeValue;
*pad0 = rowCol->size.pad0;
*pad1 = rowCol->size.pad1;
break;
case TIX_GR_DEFINED_CHAR:
size = (int)(rowCol->size.charValue * wPtr->fontSize[which]);
*pad0 = rowCol->size.pad0;
*pad1 = rowCol->size.pad1;
break;
case TIX_GR_DEFAULT:
default: /* some error ?? */
if (defSize->sizeType == TIX_GR_AUTO) {
size = RowColMaxSize(wPtr, which, rowCol, defSize);
} else {
size = defSize->pixels;
}
*pad0 = defSize->pad0;
*pad1 = defSize->pad1;
}
}
return size;
}
int
TixGridDataGetIndex(interp, wPtr, xStr, yStr, xPtr, yPtr)
Tcl_Interp * interp;
WidgetPtr wPtr;
Tcl_Obj * xStr;
Tcl_Obj * yStr;
int * xPtr;
int * yPtr;
{
Tcl_Obj * str[2];
int * ptr[2];
int i;
str[0] = xStr;
str[1] = yStr;
ptr[0] = xPtr;
ptr[1] = yPtr;
for (i=0; i<2; i++) {
if (str[i] == NULL) { /* ignore this index */
continue;
}
if (strcmp(Tcl_GetString(str[i]), "max") == 0) {
*ptr[i] = wPtr->dataSet->maxIdx[i];
if (*ptr[i] < wPtr->hdrSize[i]) {
*ptr[i] = wPtr->hdrSize[i];
}
}
else if (strcmp(Tcl_GetString(str[i]), "end") == 0) {
*ptr[i] = wPtr->dataSet->maxIdx[i] + 1;
if (*ptr[i] < wPtr->hdrSize[i]) {
*ptr[i] = wPtr->hdrSize[i];
}
} else {
if (Tcl_GetIntFromObj(interp, str[i], ptr[i]) != TCL_OK) {
return TCL_ERROR;
}
}
if (*ptr[i] < 0) {
*ptr[i] = 0;
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
* TixGridDataConfigRowColSize --
*
* Configure width of column or height of rows.
*
* Results:
* Standard Tcl result.
*
* Side effects:
* The column/rows size will be changed in an idle event.
*----------------------------------------------------------------------
*/
int
TixGridDataConfigRowColSize(interp, wPtr, dataSet, which, index, argc, argv,
argcErrorMsg, changed_ret)
Tcl_Interp * interp;
WidgetPtr wPtr;
TixGridDataSet * dataSet;
int which; /* 0=cols, 1=rows */
int index;
int argc;
char ** argv;
char * argcErrorMsg;
int *changed_ret; /* Returns whether size has been changed. */
{
TixGridRowCol *rowCol;
Tcl_HashEntry *hashPtr;
int isNew, code;
hashPtr = Tcl_CreateHashEntry(&dataSet->index[which], FIX(index), &isNew);
if (!isNew) {
rowCol = (TixGridRowCol *)Tcl_GetHashValue(hashPtr);
} else {
rowCol = InitRowCol(index);
Tcl_SetHashValue(hashPtr, (char*)rowCol);
if (dataSet->maxIdx[which] < index) {
dataSet->maxIdx[which] = index;
}
}
code = Tix_GrConfigSize(interp, wPtr, argc, argv, &rowCol->size,
argcErrorMsg, changed_ret);
if (changed_ret) {
*changed_ret |= isNew;
}
return code;
}
/*
*----------------------------------------------------------------------
* TixGridDataGetGridSize --
*
* Returns the number of rows and columns of the grid.
*
* Results:
* None.
*
* Side effects:
* None.
*----------------------------------------------------------------------
*/
/*
* ToDo: maintain numCol and numRow info while adding entries.
*/
void
TixGridDataGetGridSize(dataSet, numCol_ret, numRow_ret)
TixGridDataSet * dataSet;
int *numCol_ret;
int *numRow_ret;
{
int maxSize[2], i;
Tcl_HashEntry *hashPtr;
Tcl_HashSearch hashSearch;
TixGridRowCol * rowCol;
maxSize[0] = 1;
maxSize[1] = 1;
if (dataSet->index[0].numEntries == 0 || dataSet->index[1].numEntries==0) {
goto done;
}
for (i=0; i<2; i++) {
for (hashPtr = Tcl_FirstHashEntry(&dataSet->index[i], &hashSearch);
hashPtr;
hashPtr = Tcl_NextHashEntry(&hashSearch)) {
rowCol = (TixGridRowCol *)Tcl_GetHashValue(hashPtr);
if (maxSize[i] < rowCol->dispIndex+1) {
maxSize[i] = rowCol->dispIndex+1;
}
}
}
done:
if (numCol_ret) {
*numCol_ret = maxSize[0];
}
if (numRow_ret) {
*numRow_ret = maxSize[1];
}
}
/*
* the following four functions return true if done -- no more rows or cells
* are left to traverse
*/
int
TixGrDataFirstRow(dataSet, rowSearchPtr)
TixGridDataSet* dataSet;
Tix_GrDataRowSearch * rowSearchPtr;
{
rowSearchPtr->hashPtr = Tcl_FirstHashEntry(&dataSet->index[0],
&rowSearchPtr->hashSearch);
if (rowSearchPtr->hashPtr != NULL) {
rowSearchPtr->row = (TixGridRowCol *)Tcl_GetHashValue(
rowSearchPtr->hashPtr);
return 0;
} else {
rowSearchPtr->row = NULL;
return 1;
}
}
int
TixGrDataNextRow(rowSearchPtr)
Tix_GrDataRowSearch * rowSearchPtr;
{
rowSearchPtr->hashPtr = Tcl_NextHashEntry(&rowSearchPtr->hashSearch);
if (rowSearchPtr->hashPtr != NULL) {
rowSearchPtr->row = (TixGridRowCol *)Tcl_GetHashValue(
rowSearchPtr->hashPtr);
return 0;
} else {
rowSearchPtr->row = NULL;
return 1;
}
}
int
TixGrDataFirstCell(rowSearchPtr, cellSearchPtr)
Tix_GrDataRowSearch * rowSearchPtr;
Tix_GrDataCellSearch * cellSearchPtr;
{
cellSearchPtr->hashPtr = Tcl_FirstHashEntry(&rowSearchPtr->row->table,
&cellSearchPtr->hashSearch);
if (cellSearchPtr->hashPtr != NULL) {
cellSearchPtr->data = (char *)Tcl_GetHashValue(
cellSearchPtr->hashPtr);
return 0;
} else {
cellSearchPtr->data = NULL;
return 1;
}
}
int
TixGrDataNextCell(cellSearchPtr)
Tix_GrDataCellSearch * cellSearchPtr;
{
cellSearchPtr->hashPtr = Tcl_NextHashEntry(&cellSearchPtr->hashSearch);
if (cellSearchPtr->hashPtr != NULL) {
cellSearchPtr->data = (char *)Tcl_GetHashValue(
cellSearchPtr->hashPtr);
return 0;
} else {
cellSearchPtr->data = NULL;
return 1;
}
}
/*----------------------------------------------------------------------
* TixGridDataDeleteSearchedEntry --
*
* Deletes an entry returned by one of the search functions.
*
* Results:
* None.
*
* Side effects:
* If there is an entry at the index, it is deleted.
*----------------------------------------------------------------------
*/
void
TixGridDataDeleteSearchedEntry(cellSearchPtr)
Tix_GrDataCellSearch * cellSearchPtr;
{
TixGrEntry * chPtr = (TixGrEntry *)cellSearchPtr->data;
Tcl_DeleteHashEntry(chPtr->entryPtr[0]);
Tcl_DeleteHashEntry(chPtr->entryPtr[1]);
}
/*
*----------------------------------------------------------------------
* TixGridDataDeleteRange --
*
* Deletes the rows (columns) at the given range.
*
* Results:
* None.
*
* Side effects:
* The given rows (columns) are deleted.
*----------------------------------------------------------------------
*/
void
TixGridDataDeleteRange(wPtr, dataSet, which, from, to)
WidgetPtr wPtr; /* Info about the grid widget. */
TixGridDataSet * dataSet; /* Dataset of the Grid */
int which; /* 0=cols, 1=rows */
int from; /* Starting column/row. */
int to; /* Ending column/row (inclusive). */
{
int tmp, i, other, deleted = 0;
if (from < 0 ) {
from = 0;
}
if (to < 0 ) {
to = 0;
}
if (from > to) {
tmp = to;
to = from;
from = tmp;
}
if (which == 0) {
other = 1;
} else {
other = 0;
}
for (i=from; i<=to; i++) {
Tcl_HashEntry *hashPtr, *hp, *toDel;
TixGridRowCol *rcPtr, *rcp;
Tcl_HashSearch hashSearch;
hashPtr = Tcl_FindHashEntry(&dataSet->index[which], FIX(i));
if (hashPtr != NULL) {
rcPtr = (TixGridRowCol *)Tcl_GetHashValue(hashPtr);
for (hp = Tcl_FirstHashEntry(&dataSet->index[other], &hashSearch);
hp;
hp = Tcl_NextHashEntry(&hashSearch)) {
rcp = (TixGridRowCol *)Tcl_GetHashValue(hp);
toDel = Tcl_FindHashEntry(&rcp->table, (char*)rcPtr);
if (toDel != NULL) {
TixGrEntry * chPtr;
chPtr = (TixGrEntry *)Tcl_GetHashValue(toDel);
if (chPtr) {
deleted = 1;
Tix_GrFreeElem(chPtr);
}
Tcl_DeleteHashEntry(toDel);
}
}
Tcl_DeleteHashEntry(hashPtr);
Tcl_DeleteHashTable(&rcPtr->table);
ckfree((char*)rcPtr);
}
}
if (deleted) {
Tix_GrDoWhenIdle(wPtr, TIX_GR_RESIZE);
}
}
/*
*----------------------------------------------------------------------
* TixGridDataMoveRange --
*
* Moves a range of row (columns) by a given offset. E.g. move 2-4 by 2
* changes the rows 2,3,4 to 4,5,6.
*
* Results:
* None.
*
* Side effects:
* Rows (columns) at locations where the given rows will be moved
* to are deleted.
*----------------------------------------------------------------------
*/
void
TixGridDataMoveRange(wPtr, dataSet, which, from, to, by)
WidgetPtr wPtr; /* Info about the grid widget. */
TixGridDataSet * dataSet; /* Dataset of the Grid */
int which; /* 0=cols, 1=rows */
int from; /* Starting column/row. */
int to; /* Ending column/row (inclusive). */
int by; /* The distance of the move. */
{
int tmp, i, s, e, incr;
int df, dt; /* Rows inside this range will be deleted
* before the given rows are moved. */
if (by == 0) {
return;
}
if (from < 0 ) {
from = 0;
}
if (to < 0 ) {
to = 0;
}
if (from > to) {
tmp = to;
to = from;
from = tmp;
}
if ((from + by) < 0) {
/*
* Delete the leading rows that will be moved beyond the top of grid.
*/
int n; /* Number of rows to delete. */
n = - (from + by);
if (n > (to - from + 1)) {
n = to - from + 1;
}
TixGridDataDeleteRange(wPtr, dataSet, which, from, (from+n-1));
from = from + n;
if (from > to) {
/*
* All the rows have been deleted.
*/
return;
}
}
/*
* Delete rows at locations where the given rows will be moved to.
*/
df = from + by;
dt = to + by;
if (by > 0) {
if (df <= to) {
df = to + 1;
}
} else {
if (dt >= from) {
dt = from - 1;
}
}
TixGridDataDeleteRange(wPtr, dataSet, which, df, dt);
/*
* Rename the rows.
*/
if (by > 0) {
s = to;
e = from-1;
incr = -1;
} else {
s = from;
e = to+1;
incr = 1;
}
for (i=s; i!=e; i+=incr) {
Tcl_HashEntry *hashPtr;
TixGridRowCol *rcPtr;
int isNew;
hashPtr = Tcl_FindHashEntry(&dataSet->index[which], FIX(i));
if (hashPtr != NULL) {
rcPtr = (TixGridRowCol *)Tcl_GetHashValue(hashPtr);
rcPtr->dispIndex = i+by;
Tcl_DeleteHashEntry(hashPtr);
hashPtr = Tcl_CreateHashEntry(&dataSet->index[which], FIX(i+by),
&isNew);
Tcl_SetHashValue(hashPtr, (char*)rcPtr);
}
}
}