tktable added
--HG-- branch : aspn
This commit is contained in:
723
tktable/generic/tkTableEdit.c
Normal file
723
tktable/generic/tkTableEdit.c
Normal file
@@ -0,0 +1,723 @@
|
||||
/*
|
||||
* tkTableEdit.c --
|
||||
*
|
||||
* This module implements editing functions of a table widget.
|
||||
*
|
||||
* Copyright (c) 1998-2000 Jeffrey Hobbs
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*
|
||||
* RCS: @(#) $Id: tkTableEdit.c,v 1.7 2002/10/16 07:30:56 hobbs Exp $
|
||||
*/
|
||||
|
||||
#include "tkTable.h"
|
||||
|
||||
static void TableModifyRC _ANSI_ARGS_((register Table *tablePtr,
|
||||
int doRows, int movetag,
|
||||
Tcl_HashTable *tagTblPtr, Tcl_HashTable *dimTblPtr,
|
||||
int offset, int from, int to, int lo, int hi,
|
||||
int outOfBounds));
|
||||
|
||||
/* insert/delete subcommands */
|
||||
static CONST84 char *modCmdNames[] = {
|
||||
"active", "cols", "rows", (char *)NULL
|
||||
};
|
||||
enum modCmd {
|
||||
MOD_ACTIVE, MOD_COLS, MOD_ROWS
|
||||
};
|
||||
|
||||
/* insert/delete row/col switches */
|
||||
static CONST84 char *rcCmdNames[] = {
|
||||
"-keeptitles", "-holddimensions", "-holdselection",
|
||||
"-holdtags", "-holdwindows", "--",
|
||||
(char *) NULL
|
||||
};
|
||||
enum rcCmd {
|
||||
OPT_TITLES, OPT_DIMS, OPT_SEL,
|
||||
OPT_TAGS, OPT_WINS, OPT_LAST
|
||||
};
|
||||
|
||||
#define HOLD_TITLES 1<<0
|
||||
#define HOLD_DIMS 1<<1
|
||||
#define HOLD_TAGS 1<<2
|
||||
#define HOLD_WINS 1<<3
|
||||
#define HOLD_SEL 1<<4
|
||||
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
*
|
||||
* Table_EditCmd --
|
||||
* This procedure is invoked to process the insert/delete method
|
||||
* that corresponds to a table widget managed by this module.
|
||||
* See the user documentation for details on what it does.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* See the user documentation.
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
Table_EditCmd(ClientData clientData, register Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *CONST objv[])
|
||||
{
|
||||
register Table *tablePtr = (Table *) clientData;
|
||||
int doInsert, cmdIndex, first, last;
|
||||
|
||||
if (objc < 4) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv,
|
||||
"option ?switches? arg ?arg?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[2], modCmdNames,
|
||||
"option", 0, &cmdIndex) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
doInsert = (*(Tcl_GetString(objv[1])) == 'i');
|
||||
switch ((enum modCmd) cmdIndex) {
|
||||
case MOD_ACTIVE:
|
||||
if (doInsert) {
|
||||
/* INSERT */
|
||||
if (objc != 5) {
|
||||
Tcl_WrongNumArgs(interp, 3, objv, "index string");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (TableGetIcursorObj(tablePtr, objv[3], &first) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
} else if ((tablePtr->flags & HAS_ACTIVE) &&
|
||||
!(tablePtr->flags & ACTIVE_DISABLED) &&
|
||||
tablePtr->state == STATE_NORMAL) {
|
||||
TableInsertChars(tablePtr, first, Tcl_GetString(objv[4]));
|
||||
}
|
||||
} else {
|
||||
/* DELETE */
|
||||
if (objc > 5) {
|
||||
Tcl_WrongNumArgs(interp, 3, objv, "first ?last?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (TableGetIcursorObj(tablePtr, objv[3], &first) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objc == 4) {
|
||||
last = first+1;
|
||||
} else if (TableGetIcursorObj(tablePtr, objv[4],
|
||||
&last) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if ((last >= first) && (tablePtr->flags & HAS_ACTIVE) &&
|
||||
!(tablePtr->flags & ACTIVE_DISABLED) &&
|
||||
tablePtr->state == STATE_NORMAL) {
|
||||
TableDeleteChars(tablePtr, first, last-first);
|
||||
}
|
||||
}
|
||||
break; /* EDIT ACTIVE */
|
||||
|
||||
case MOD_COLS:
|
||||
case MOD_ROWS: {
|
||||
/*
|
||||
* ROW/COL INSERTION/DELETION
|
||||
* FIX: This doesn't handle spans
|
||||
*/
|
||||
int i, lo, hi, argsLeft, offset, minkeyoff, doRows;
|
||||
int maxrow, maxcol, maxkey, minkey, flags, count, *dimPtr;
|
||||
Tcl_HashTable *tagTblPtr, *dimTblPtr;
|
||||
Tcl_HashSearch search;
|
||||
|
||||
doRows = (cmdIndex == MOD_ROWS);
|
||||
flags = 0;
|
||||
for (i = 3; i < objc; i++) {
|
||||
if (*(Tcl_GetString(objv[i])) != '-') {
|
||||
break;
|
||||
}
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], rcCmdNames,
|
||||
"switch", 0, &cmdIndex) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (cmdIndex == OPT_LAST) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
switch (cmdIndex) {
|
||||
case OPT_TITLES:
|
||||
flags |= HOLD_TITLES;
|
||||
break;
|
||||
case OPT_DIMS:
|
||||
flags |= HOLD_DIMS;
|
||||
break;
|
||||
case OPT_SEL:
|
||||
flags |= HOLD_SEL;
|
||||
break;
|
||||
case OPT_TAGS:
|
||||
flags |= HOLD_TAGS;
|
||||
break;
|
||||
case OPT_WINS:
|
||||
flags |= HOLD_WINS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
argsLeft = objc - i;
|
||||
if (argsLeft < 1 || argsLeft > 2) {
|
||||
Tcl_WrongNumArgs(interp, 3, objv, "?switches? index ?count?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
count = 1;
|
||||
maxcol = tablePtr->cols-1+tablePtr->colOffset;
|
||||
maxrow = tablePtr->rows-1+tablePtr->rowOffset;
|
||||
if (strcmp(Tcl_GetString(objv[i]), "end") == 0) {
|
||||
/* allow "end" to be specified as an index */
|
||||
first = (doRows) ? maxrow : maxcol;
|
||||
} else if (Tcl_GetIntFromObj(interp, objv[i], &first) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (argsLeft == 2 &&
|
||||
Tcl_GetIntFromObj(interp, objv[++i], &count) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (count == 0 || (tablePtr->state == STATE_DISABLED)) {
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (doRows) {
|
||||
maxkey = maxrow;
|
||||
minkey = tablePtr->rowOffset;
|
||||
minkeyoff = tablePtr->rowOffset+tablePtr->titleRows;
|
||||
offset = tablePtr->rowOffset;
|
||||
tagTblPtr = tablePtr->rowStyles;
|
||||
dimTblPtr = tablePtr->rowHeights;
|
||||
dimPtr = &(tablePtr->rows);
|
||||
lo = tablePtr->colOffset
|
||||
+ ((flags & HOLD_TITLES) ? tablePtr->titleCols : 0);
|
||||
hi = maxcol;
|
||||
} else {
|
||||
maxkey = maxcol;
|
||||
minkey = tablePtr->colOffset;
|
||||
minkeyoff = tablePtr->colOffset+tablePtr->titleCols;
|
||||
offset = tablePtr->colOffset;
|
||||
tagTblPtr = tablePtr->colStyles;
|
||||
dimTblPtr = tablePtr->colWidths;
|
||||
dimPtr = &(tablePtr->cols);
|
||||
lo = tablePtr->rowOffset
|
||||
+ ((flags & HOLD_TITLES) ? tablePtr->titleRows : 0);
|
||||
hi = maxrow;
|
||||
}
|
||||
|
||||
/* constrain the starting index */
|
||||
if (first > maxkey) {
|
||||
first = maxkey;
|
||||
} else if (first < minkey) {
|
||||
first = minkey;
|
||||
}
|
||||
if (doInsert) {
|
||||
/* +count means insert after index,
|
||||
* -count means insert before index */
|
||||
if (count < 0) {
|
||||
count = -count;
|
||||
} else {
|
||||
first++;
|
||||
}
|
||||
if ((flags & HOLD_TITLES) && (first < minkeyoff)) {
|
||||
count -= minkeyoff-first;
|
||||
if (count <= 0) {
|
||||
return TCL_OK;
|
||||
}
|
||||
first = minkeyoff;
|
||||
}
|
||||
if (!(flags & HOLD_DIMS)) {
|
||||
maxkey += count;
|
||||
*dimPtr += count;
|
||||
}
|
||||
/*
|
||||
* We need to call TableAdjustParams before TableModifyRC to
|
||||
* ensure that side effect code like var traces that might get
|
||||
* called will access the correct new dimensions.
|
||||
*/
|
||||
if (*dimPtr < 1) {
|
||||
*dimPtr = 1;
|
||||
}
|
||||
TableAdjustParams(tablePtr);
|
||||
for (i = maxkey; i >= first; i--) {
|
||||
/* move row/col style && width/height here */
|
||||
TableModifyRC(tablePtr, doRows, flags, tagTblPtr, dimTblPtr,
|
||||
offset, i, i-count, lo, hi, ((i-count) < first));
|
||||
}
|
||||
if (!(flags & HOLD_WINS)) {
|
||||
/*
|
||||
* This may be a little severe, but it does unmap the
|
||||
* windows that need to be unmapped, and those that should
|
||||
* stay do remap correctly. [Bug #551325]
|
||||
*/
|
||||
if (doRows) {
|
||||
EmbWinUnmap(tablePtr,
|
||||
first - tablePtr->rowOffset,
|
||||
maxkey - tablePtr->rowOffset,
|
||||
lo - tablePtr->colOffset,
|
||||
hi - tablePtr->colOffset);
|
||||
} else {
|
||||
EmbWinUnmap(tablePtr,
|
||||
lo - tablePtr->rowOffset,
|
||||
hi - tablePtr->rowOffset,
|
||||
first - tablePtr->colOffset,
|
||||
maxkey - tablePtr->colOffset);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* (index = i && count = 1) == (index = i && count = -1) */
|
||||
if (count < 0) {
|
||||
/* if the count is negative, make sure that the col count will
|
||||
* delete no greater than the original index */
|
||||
if (first+count < minkey) {
|
||||
if (first-minkey < abs(count)) {
|
||||
/*
|
||||
* In this case, the user is asking to delete more rows
|
||||
* than exist before the minkey, so we have to shrink
|
||||
* the count down to the existing rows up to index.
|
||||
*/
|
||||
count = first-minkey;
|
||||
} else {
|
||||
count += first-minkey;
|
||||
}
|
||||
first = minkey;
|
||||
} else {
|
||||
first += count;
|
||||
count = -count;
|
||||
}
|
||||
}
|
||||
if ((flags & HOLD_TITLES) && (first <= minkeyoff)) {
|
||||
count -= minkeyoff-first;
|
||||
if (count <= 0) {
|
||||
return TCL_OK;
|
||||
}
|
||||
first = minkeyoff;
|
||||
}
|
||||
if (count > maxkey-first+1) {
|
||||
count = maxkey-first+1;
|
||||
}
|
||||
if (!(flags & HOLD_DIMS)) {
|
||||
*dimPtr -= count;
|
||||
}
|
||||
/*
|
||||
* We need to call TableAdjustParams before TableModifyRC to
|
||||
* ensure that side effect code like var traces that might get
|
||||
* called will access the correct new dimensions.
|
||||
*/
|
||||
if (*dimPtr < 1) {
|
||||
*dimPtr = 1;
|
||||
}
|
||||
TableAdjustParams(tablePtr);
|
||||
for (i = first; i <= maxkey; i++) {
|
||||
TableModifyRC(tablePtr, doRows, flags, tagTblPtr, dimTblPtr,
|
||||
offset, i, i+count, lo, hi, ((i+count) > maxkey));
|
||||
}
|
||||
}
|
||||
if (!(flags & HOLD_SEL) &&
|
||||
Tcl_FirstHashEntry(tablePtr->selCells, &search) != NULL) {
|
||||
/* clear selection - forceful, but effective */
|
||||
Tcl_DeleteHashTable(tablePtr->selCells);
|
||||
Tcl_InitHashTable(tablePtr->selCells, TCL_STRING_KEYS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the modified dimension is actually legal
|
||||
* after removing all that stuff.
|
||||
*/
|
||||
if (*dimPtr < 1) {
|
||||
*dimPtr = 1;
|
||||
TableAdjustParams(tablePtr);
|
||||
}
|
||||
|
||||
/* change the geometry */
|
||||
TableGeometryRequest(tablePtr);
|
||||
/* FIX:
|
||||
* This has to handle when the previous rows/cols resize because
|
||||
* of the *stretchmode. InvalidateAll does that, but could be
|
||||
* more efficient.
|
||||
*/
|
||||
TableInvalidateAll(tablePtr, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TableDeleteChars --
|
||||
* Remove one or more characters from an table widget.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Memory gets freed, the table gets modified and (eventually)
|
||||
* redisplayed.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
TableDeleteChars(tablePtr, index, count)
|
||||
register Table *tablePtr; /* Table widget to modify. */
|
||||
int index; /* Index of first character to delete. */
|
||||
int count; /* How many characters to delete. */
|
||||
{
|
||||
#ifdef TCL_UTF_MAX
|
||||
int byteIndex, byteCount, newByteCount, numBytes, numChars;
|
||||
char *new, *string;
|
||||
|
||||
string = tablePtr->activeBuf;
|
||||
numBytes = strlen(string);
|
||||
numChars = Tcl_NumUtfChars(string, numBytes);
|
||||
if ((index + count) > numChars) {
|
||||
count = numChars - index;
|
||||
}
|
||||
if (count <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
byteIndex = Tcl_UtfAtIndex(string, index) - string;
|
||||
byteCount = Tcl_UtfAtIndex(string + byteIndex, count)
|
||||
- (string + byteIndex);
|
||||
|
||||
newByteCount = numBytes + 1 - byteCount;
|
||||
new = (char *) ckalloc((unsigned) newByteCount);
|
||||
memcpy(new, string, (size_t) byteIndex);
|
||||
strcpy(new + byteIndex, string + byteIndex + byteCount);
|
||||
#else
|
||||
int oldlen;
|
||||
char *new;
|
||||
|
||||
/* this gets the length of the string, as well as ensuring that
|
||||
* the cursor isn't beyond the end char */
|
||||
TableGetIcursor(tablePtr, "end", &oldlen);
|
||||
|
||||
if ((index+count) > oldlen)
|
||||
count = oldlen-index;
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
new = (char *) ckalloc((unsigned)(oldlen-count+1));
|
||||
strncpy(new, tablePtr->activeBuf, (size_t) index);
|
||||
strcpy(new+index, tablePtr->activeBuf+index+count);
|
||||
/* make sure this string is null terminated */
|
||||
new[oldlen-count] = '\0';
|
||||
#endif
|
||||
/* This prevents deletes on BREAK or validation error. */
|
||||
if (tablePtr->validate &&
|
||||
TableValidateChange(tablePtr, tablePtr->activeRow+tablePtr->rowOffset,
|
||||
tablePtr->activeCol+tablePtr->colOffset,
|
||||
tablePtr->activeBuf, new, index) != TCL_OK) {
|
||||
ckfree(new);
|
||||
return;
|
||||
}
|
||||
|
||||
ckfree(tablePtr->activeBuf);
|
||||
tablePtr->activeBuf = new;
|
||||
|
||||
/* mark the text as changed */
|
||||
tablePtr->flags |= TEXT_CHANGED;
|
||||
|
||||
if (tablePtr->icursor >= index) {
|
||||
if (tablePtr->icursor >= (index+count)) {
|
||||
tablePtr->icursor -= count;
|
||||
} else {
|
||||
tablePtr->icursor = index;
|
||||
}
|
||||
}
|
||||
|
||||
TableSetActiveIndex(tablePtr);
|
||||
|
||||
TableRefresh(tablePtr, tablePtr->activeRow, tablePtr->activeCol, CELL);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TableInsertChars --
|
||||
* Add new characters to the active cell of a table widget.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* New information gets added to tablePtr; it will be redisplayed
|
||||
* soon, but not necessarily immediately.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
TableInsertChars(tablePtr, index, value)
|
||||
register Table *tablePtr; /* Table that is to get the new elements. */
|
||||
int index; /* Add the new elements before this element. */
|
||||
char *value; /* New characters to add (NULL-terminated
|
||||
* string). */
|
||||
{
|
||||
#ifdef TCL_UTF_MAX
|
||||
int oldlen, byteIndex, byteCount;
|
||||
char *new, *string;
|
||||
|
||||
byteCount = strlen(value);
|
||||
if (byteCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is this an autoclear and this is the first update */
|
||||
/* Note that this clears without validating */
|
||||
if (tablePtr->autoClear && !(tablePtr->flags & TEXT_CHANGED)) {
|
||||
/* set the buffer to be empty */
|
||||
tablePtr->activeBuf = (char *)ckrealloc(tablePtr->activeBuf, 1);
|
||||
tablePtr->activeBuf[0] = '\0';
|
||||
/* the insert position now has to be 0 */
|
||||
index = 0;
|
||||
tablePtr->icursor = 0;
|
||||
}
|
||||
|
||||
string = tablePtr->activeBuf;
|
||||
byteIndex = Tcl_UtfAtIndex(string, index) - string;
|
||||
|
||||
oldlen = strlen(string);
|
||||
new = (char *) ckalloc((unsigned)(oldlen + byteCount + 1));
|
||||
memcpy(new, string, (size_t) byteIndex);
|
||||
strcpy(new + byteIndex, value);
|
||||
strcpy(new + byteIndex + byteCount, string + byteIndex);
|
||||
|
||||
/* validate potential new active buffer */
|
||||
/* This prevents inserts on either BREAK or validation error. */
|
||||
if (tablePtr->validate &&
|
||||
TableValidateChange(tablePtr, tablePtr->activeRow+tablePtr->rowOffset,
|
||||
tablePtr->activeCol+tablePtr->colOffset,
|
||||
tablePtr->activeBuf, new, byteIndex) != TCL_OK) {
|
||||
ckfree(new);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following construction is used because inserting improperly
|
||||
* formed UTF-8 sequences between other improperly formed UTF-8
|
||||
* sequences could result in actually forming valid UTF-8 sequences;
|
||||
* the number of characters added may not be Tcl_NumUtfChars(string, -1),
|
||||
* because of context. The actual number of characters added is how
|
||||
* many characters were are in the string now minus the number that
|
||||
* used to be there.
|
||||
*/
|
||||
|
||||
if (tablePtr->icursor >= index) {
|
||||
tablePtr->icursor += Tcl_NumUtfChars(new, oldlen+byteCount)
|
||||
- Tcl_NumUtfChars(tablePtr->activeBuf, oldlen);
|
||||
}
|
||||
|
||||
ckfree(string);
|
||||
tablePtr->activeBuf = new;
|
||||
|
||||
#else
|
||||
int oldlen, newlen;
|
||||
char *new;
|
||||
|
||||
newlen = strlen(value);
|
||||
if (newlen == 0) return;
|
||||
|
||||
/* Is this an autoclear and this is the first update */
|
||||
/* Note that this clears without validating */
|
||||
if (tablePtr->autoClear && !(tablePtr->flags & TEXT_CHANGED)) {
|
||||
/* set the buffer to be empty */
|
||||
tablePtr->activeBuf = (char *)ckrealloc(tablePtr->activeBuf, 1);
|
||||
tablePtr->activeBuf[0] = '\0';
|
||||
/* the insert position now has to be 0 */
|
||||
index = 0;
|
||||
}
|
||||
oldlen = strlen(tablePtr->activeBuf);
|
||||
/* get the buffer to at least the right length */
|
||||
new = (char *) ckalloc((unsigned)(oldlen+newlen+1));
|
||||
strncpy(new, tablePtr->activeBuf, (size_t) index);
|
||||
strcpy(new+index, value);
|
||||
strcpy(new+index+newlen, (tablePtr->activeBuf)+index);
|
||||
/* make sure this string is null terminated */
|
||||
new[oldlen+newlen] = '\0';
|
||||
|
||||
/* validate potential new active buffer */
|
||||
/* This prevents inserts on either BREAK or validation error. */
|
||||
if (tablePtr->validate &&
|
||||
TableValidateChange(tablePtr, tablePtr->activeRow+tablePtr->rowOffset,
|
||||
tablePtr->activeCol+tablePtr->colOffset,
|
||||
tablePtr->activeBuf, new, index) != TCL_OK) {
|
||||
ckfree(new);
|
||||
return;
|
||||
}
|
||||
ckfree(tablePtr->activeBuf);
|
||||
tablePtr->activeBuf = new;
|
||||
|
||||
if (tablePtr->icursor >= index) {
|
||||
tablePtr->icursor += newlen;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* mark the text as changed */
|
||||
tablePtr->flags |= TEXT_CHANGED;
|
||||
|
||||
TableSetActiveIndex(tablePtr);
|
||||
|
||||
TableRefresh(tablePtr, tablePtr->activeRow, tablePtr->activeCol, CELL);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TableModifyRC --
|
||||
* Helper function that does the core work of moving rows/cols
|
||||
* and associated tags.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Moves cell data and possibly tag data
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
TableModifyRC(tablePtr, doRows, flags, tagTblPtr, dimTblPtr,
|
||||
offset, from, to, lo, hi, outOfBounds)
|
||||
Table *tablePtr; /* Information about text widget. */
|
||||
int doRows; /* rows (1) or cols (0) */
|
||||
int flags; /* flags indicating what to move */
|
||||
Tcl_HashTable *tagTblPtr, *dimTblPtr; /* Pointers to the row/col tags
|
||||
* and width/height tags */
|
||||
int offset; /* appropriate offset */
|
||||
int from, to; /* the from and to row/col */
|
||||
int lo, hi; /* the lo and hi col/row */
|
||||
int outOfBounds; /* the boundary check for shifting items */
|
||||
{
|
||||
int j, new;
|
||||
char buf[INDEX_BUFSIZE], buf1[INDEX_BUFSIZE];
|
||||
Tcl_HashEntry *entryPtr, *newPtr;
|
||||
TableEmbWindow *ewPtr;
|
||||
|
||||
/*
|
||||
* move row/col style && width/height here
|
||||
* If -holdtags is specified, we don't move the user-set widths/heights
|
||||
* of the absolute rows/columns, otherwise we enter here to move the
|
||||
* dimensions appropriately
|
||||
*/
|
||||
if (!(flags & HOLD_TAGS)) {
|
||||
entryPtr = Tcl_FindHashEntry(tagTblPtr, (char *)from);
|
||||
if (entryPtr != NULL) {
|
||||
Tcl_DeleteHashEntry(entryPtr);
|
||||
}
|
||||
entryPtr = Tcl_FindHashEntry(dimTblPtr, (char *)from-offset);
|
||||
if (entryPtr != NULL) {
|
||||
Tcl_DeleteHashEntry(entryPtr);
|
||||
}
|
||||
if (!outOfBounds) {
|
||||
entryPtr = Tcl_FindHashEntry(tagTblPtr, (char *)to);
|
||||
if (entryPtr != NULL) {
|
||||
newPtr = Tcl_CreateHashEntry(tagTblPtr, (char *)from, &new);
|
||||
Tcl_SetHashValue(newPtr, Tcl_GetHashValue(entryPtr));
|
||||
Tcl_DeleteHashEntry(entryPtr);
|
||||
}
|
||||
entryPtr = Tcl_FindHashEntry(dimTblPtr, (char *)to-offset);
|
||||
if (entryPtr != NULL) {
|
||||
newPtr = Tcl_CreateHashEntry(dimTblPtr, (char *)from-offset,
|
||||
&new);
|
||||
Tcl_SetHashValue(newPtr, Tcl_GetHashValue(entryPtr));
|
||||
Tcl_DeleteHashEntry(entryPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j = lo; j <= hi; j++) {
|
||||
if (doRows /* rows */) {
|
||||
TableMakeArrayIndex(from, j, buf);
|
||||
TableMakeArrayIndex(to, j, buf1);
|
||||
TableMoveCellValue(tablePtr, to, j, buf1, from, j, buf,
|
||||
outOfBounds);
|
||||
} else {
|
||||
TableMakeArrayIndex(j, from, buf);
|
||||
TableMakeArrayIndex(j, to, buf1);
|
||||
TableMoveCellValue(tablePtr, j, to, buf1, j, from, buf,
|
||||
outOfBounds);
|
||||
}
|
||||
/*
|
||||
* If -holdselection is specified, we leave the selected cells in the
|
||||
* absolute cell values, otherwise we enter here to move the
|
||||
* selection appropriately
|
||||
*/
|
||||
if (!(flags & HOLD_SEL)) {
|
||||
entryPtr = Tcl_FindHashEntry(tablePtr->selCells, buf);
|
||||
if (entryPtr != NULL) {
|
||||
Tcl_DeleteHashEntry(entryPtr);
|
||||
}
|
||||
if (!outOfBounds) {
|
||||
entryPtr = Tcl_FindHashEntry(tablePtr->selCells, buf1);
|
||||
if (entryPtr != NULL) {
|
||||
Tcl_CreateHashEntry(tablePtr->selCells, buf, &new);
|
||||
Tcl_DeleteHashEntry(entryPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If -holdtags is specified, we leave the tags in the
|
||||
* absolute cell values, otherwise we enter here to move the
|
||||
* tags appropriately
|
||||
*/
|
||||
if (!(flags & HOLD_TAGS)) {
|
||||
entryPtr = Tcl_FindHashEntry(tablePtr->cellStyles, buf);
|
||||
if (entryPtr != NULL) {
|
||||
Tcl_DeleteHashEntry(entryPtr);
|
||||
}
|
||||
if (!outOfBounds) {
|
||||
entryPtr = Tcl_FindHashEntry(tablePtr->cellStyles, buf1);
|
||||
if (entryPtr != NULL) {
|
||||
newPtr = Tcl_CreateHashEntry(tablePtr->cellStyles, buf,
|
||||
&new);
|
||||
Tcl_SetHashValue(newPtr, Tcl_GetHashValue(entryPtr));
|
||||
Tcl_DeleteHashEntry(entryPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If -holdwindows is specified, we leave the windows in the
|
||||
* absolute cell values, otherwise we enter here to move the
|
||||
* windows appropriately
|
||||
*/
|
||||
if (!(flags & HOLD_WINS)) {
|
||||
/*
|
||||
* Delete whatever window might be in our destination
|
||||
*/
|
||||
Table_WinDelete(tablePtr, buf);
|
||||
if (!outOfBounds) {
|
||||
/*
|
||||
* buf1 is where the window is
|
||||
* buf is where we want it to be
|
||||
*
|
||||
* This is an adaptation of Table_WinMove, which we can't
|
||||
* use because we are intermediately fiddling with boundaries
|
||||
*/
|
||||
entryPtr = Tcl_FindHashEntry(tablePtr->winTable, buf1);
|
||||
if (entryPtr != NULL) {
|
||||
/*
|
||||
* If there was a window in our source,
|
||||
* get the window pointer to move it
|
||||
*/
|
||||
ewPtr = (TableEmbWindow *) Tcl_GetHashValue(entryPtr);
|
||||
/* and free the old hash table entry */
|
||||
Tcl_DeleteHashEntry(entryPtr);
|
||||
|
||||
entryPtr = Tcl_CreateHashEntry(tablePtr->winTable, buf,
|
||||
&new);
|
||||
/*
|
||||
* We needn't check if a window was in buf, since the
|
||||
* Table_WinDelete above should guarantee that no window
|
||||
* is there. Just set the new entry's value.
|
||||
*/
|
||||
Tcl_SetHashValue(entryPtr, (ClientData) ewPtr);
|
||||
ewPtr->hPtr = entryPtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user