URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [insight/] [tix/] [generic/] [tixGrData.c] - Rev 578
Go to most recent revision | Compare with Previous | Blame | View Log
/* * 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> 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) { fprintf(stderr, "Grid hash entry leaked: %d : %d\n", i, rcPtr->dispIndex); } 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], (char*)x))) { return NULL; } col = (TixGridRowCol *)Tcl_GetHashValue(hashPtr); if (!(hashPtr = Tcl_FindHashEntry(&dataSet->index[1], (char*)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], (char*)x); if (hashPtrs[0] != NULL) { rowcol[0] = (TixGridRowCol *)Tcl_GetHashValue(hashPtrs[0]); } else { return 0; } hashPtrs[1] = Tcl_FindHashEntry(&dataSet->index[1], (char*)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], (char*)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. */ int i; 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); } #if 0 /* * Can't do this, otherwise the size info of this row/col is lost. */ for (i=0; i<2; i++) { if (rowcol[i]->table.numEntries == 0) { Tcl_DeleteHashEntry(hashPtrs[i]); Tcl_DeleteHashTable(&rowcol[i]->table); ckfree((char*)rowcol[i]); } } #endif #if 0 printf("%d %d\n", dataSet->index[0].numEntries, dataSet->index[1].numEntries); #endif 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; 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], (char*)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], (char*)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], (char*)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; char * xStr; char * yStr; int * xPtr; int * yPtr; { char * 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(str[i], "max") == 0) { *ptr[i] = wPtr->dataSet->maxIdx[i]; if (*ptr[i] < wPtr->hdrSize[i]) { *ptr[i] = wPtr->hdrSize[i]; } } else if (strcmp(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_GetInt(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],(char*)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], (char*)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], (char*)i); if (hashPtr != NULL) { rcPtr = (TixGridRowCol *)Tcl_GetHashValue(hashPtr); rcPtr->dispIndex = i+by; Tcl_DeleteHashEntry(hashPtr); hashPtr = Tcl_CreateHashEntry(&dataSet->index[which],(char*)(i+by), &isNew); Tcl_SetHashValue(hashPtr, (char*)rcPtr); } } }
Go to most recent revision | Compare with Previous | Blame | View Log