tktable added

--HG--
branch : aspn
This commit is contained in:
baloan
2011-03-14 23:41:59 +01:00
parent 648a39a1f3
commit d19378fbab
46 changed files with 39160 additions and 2 deletions

132
tktable/generic/tkAppInit.c Normal file
View File

@@ -0,0 +1,132 @@
/*
* tkAppInit.c --
*
* Provides a default version of the Tcl_AppInit procedure for
* use in wish and similar Tk-based applications.
*
* Copyright (c) 1993 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: @(#) tkAppInit.c 1.24 98/01/13 17:21:40
*/
#include "tk.h"
#include "locale.h"
/*
* The following variable is a special hack that is needed in order for
* Sun shared libraries to be used for Tcl.
*/
extern int matherr();
int *tclDummyMathPtr = (int *) matherr;
EXTERN int Tktable_Init _ANSI_ARGS_((Tcl_Interp *interp));
#ifdef TK_TEST
EXTERN int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp));
EXTERN int Tktest_Init _ANSI_ARGS_((Tcl_Interp *interp));
#endif /* TK_TEST */
/*
*----------------------------------------------------------------------
*
* main --
*
* This is the main program for the application.
*
* Results:
* None: Tk_Main never returns here, so this procedure never
* returns either.
*
* Side effects:
* Whatever the application does.
*
*----------------------------------------------------------------------
*/
int
main(argc, argv)
int argc; /* Number of command-line arguments. */
char **argv; /* Values of command-line arguments. */
{
Tk_Main(argc, argv, Tcl_AppInit);
return 0; /* Needed only to prevent compiler warning. */
}
/*
*----------------------------------------------------------------------
*
* Tcl_AppInit --
*
* This procedure performs application-specific initialization.
* Most applications, especially those that incorporate additional
* packages, will have their own version of this procedure.
*
* Results:
* Returns a standard Tcl completion code, and leaves an error
* message in interp->result if an error occurs.
*
* Side effects:
* Depends on the startup script.
*
*----------------------------------------------------------------------
*/
int
Tcl_AppInit(interp)
Tcl_Interp *interp; /* Interpreter for application. */
{
if (Tcl_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
if (Tk_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_StaticPackage(interp, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL);
#ifdef TK_TEST
if (Tcltest_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init,
(Tcl_PackageInitProc *) NULL);
if (Tktest_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_StaticPackage(interp, "Tktest", Tktest_Init,
(Tcl_PackageInitProc *) NULL);
#endif /* TK_TEST */
/*
* Call the init procedures for included packages. Each call should
* look like this:
*
* if (Mod_Init(interp) == TCL_ERROR) {
* return TCL_ERROR;
* }
*
* where "Mod" is the name of the module.
*/
if (Tktable_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_StaticPackage(interp, "Tktable", Tktable_Init, Tktable_SafeInit);
/*
* Call Tcl_CreateCommand for application-specific commands, if
* they weren't already created by the init procedures called above.
*/
/*
* Specify a user-specific startup file to invoke if the application
* is run interactively. Typically the startup file is "~/.apprc"
* where "app" is the name of the application. If this line is deleted
* then no user-specific startup file will be run under any conditions.
*/
Tcl_SetVar(interp, "tcl_rcFileName", "~/.wishrc", TCL_GLOBAL_ONLY);
return TCL_OK;
}

4090
tktable/generic/tkTable.c Normal file

File diff suppressed because it is too large Load Diff

658
tktable/generic/tkTable.h Normal file
View File

@@ -0,0 +1,658 @@
/*
* tkTable.h --
*
* This is the header file for the module that implements
* table widgets for the Tk toolkit.
*
* Copyright (c) 1997-2002 Jeffrey Hobbs
*
* See the file "license.txt" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tkTable.h,v 1.17 2004/07/20 20:46:21 hobbs Exp $
*/
#ifndef _TKTABLE_H_
#define _TKTABLE_H_
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <tk.h>
#ifdef MAC_TCL
# include <Xatom.h>
#else
# include <X11/Xatom.h>
#endif /* MAC_TCL */
#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION == 0) /* Tcl8.0 stuff */
#define Tcl_GetString(objPtr) Tcl_GetStringFromObj(objPtr, (int *)NULL)
#endif
#if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4))
# define HAVE_TCL84
#endif
/*
* Tcl/Tk 8.4 introduced better CONST-ness in the APIs, but we use CONST84 in
* some cases for compatibility with earlier Tcl headers to prevent warnings.
*/
#ifndef CONST84
# define CONST84
#endif
/* This EXTERN declaration is needed for Tcl < 8.0.3 */
#ifndef EXTERN
# ifdef __cplusplus
# define EXTERN extern "C"
# else
# define EXTERN extern
# endif
#endif
#ifdef TCL_STORAGE_CLASS
# undef TCL_STORAGE_CLASS
#endif
#ifdef BUILD_Tktable
# define TCL_STORAGE_CLASS DLLEXPORT
#else
# define TCL_STORAGE_CLASS DLLIMPORT
#endif
#ifdef WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# undef WIN32_LEAN_AND_MEAN
/* VC++ has an entry point called DllMain instead of DllEntryPoint */
# if defined(_MSC_VER)
# define DllEntryPoint DllMain
# endif
#endif
#if defined(WIN32) || defined(MAC_TCL) || defined(MAC_OSX_TK)
/* XSync call defined in the internals for some reason */
# ifndef XSync
# define XSync(display, bool) {display->request++;}
# endif
#endif /* defn of XSync */
#ifndef NORMAL_BG
# ifdef WIN32
# define NORMAL_BG "SystemButtonFace"
# define ACTIVE_BG NORMAL_BG
# define SELECT_BG "SystemHighlight"
# define SELECT_FG "SystemHighlightText"
# define DISABLED "SystemDisabledText"
# define HIGHLIGHT "SystemWindowFrame"
# define DEF_TABLE_FONT "{MS Sans Serif} 8"
# elif defined(MAC_TCL) || defined(MAC_OSX_TK)
# define NORMAL_BG "systemWindowBody"
# define ACTIVE_BG "#ececec"
# define SELECT_BG "systemHighlight"
# define SELECT_FG "systemHighlightText"
# define DISABLED "#a3a3a3"
# define HIGHLIGHT "Black"
# define DEF_TABLE_FONT "Helvetica 12"
# else
# define NORMAL_BG "#d9d9d9"
# define ACTIVE_BG "#fcfcfc"
# define SELECT_BG "#c3c3c3"
# define SELECT_FG "Black"
# define DISABLED "#a3a3a3"
# define HIGHLIGHT "Black"
# define DEF_TABLE_FONT "Helvetica -12"
# endif
#endif /* NORMAL_BG */
#define MAX(A,B) (((A)>(B))?(A):(B))
#define MIN(A,B) (((A)>(B))?(B):(A))
#define BETWEEN(val,min,max) ( ((val)<(min)) ? (min) : \
( ((val)>(max)) ? (max) : (val) ) )
#define CONSTRAIN(val,min,max) if ((val) < (min)) { (val) = (min); } \
else if ((val) > (max)) { (val) = (max); }
#define STREQ(s1, s2) (strcmp((s1), (s2)) == 0)
#define ARSIZE(A) (sizeof(A)/sizeof(*A))
#define INDEX_BUFSIZE 32 /* max size of buffer for indices */
#define TEST_KEY "#TEST KEY#" /* index for testing array existence */
/*
* Assigned bits of "flags" fields of Table structures, and what those
* bits mean:
*
* REDRAW_PENDING: Non-zero means a DoWhenIdle handler has
* already been queued to redisplay the table.
* REDRAW_BORDER: Non-zero means 3-D border must be redrawn
* around window during redisplay. Normally
* only text portion needs to be redrawn.
* CURSOR_ON: Non-zero means insert cursor is displayed at
* present. 0 means it isn't displayed.
* TEXT_CHANGED: Non-zero means the active cell text is being edited.
* HAS_FOCUS: Non-zero means this window has the input focus.
* HAS_ACTIVE: Non-zero means the active cell is set.
* HAS_ANCHOR: Non-zero means the anchor cell is set.
* BROWSE_CMD: Non-zero means we're evaluating the -browsecommand.
* VALIDATING: Non-zero means we are in a valCmd
* SET_ACTIVE: About to set the active array element internally
* ACTIVE_DISABLED: Non-zero means the active cell is -state disabled
* OVER_BORDER: Non-zero means we are over a table cell border
* REDRAW_ON_MAP: Forces a redraw on the unmap
* AVOID_SPANS: prevent cell spans from being used
*
* FIX - consider adding UPDATE_SCROLLBAR a la entry
*/
#define REDRAW_PENDING (1L<<0)
#define CURSOR_ON (1L<<1)
#define HAS_FOCUS (1L<<2)
#define TEXT_CHANGED (1L<<3)
#define HAS_ACTIVE (1L<<4)
#define HAS_ANCHOR (1L<<5)
#define BROWSE_CMD (1L<<6)
#define REDRAW_BORDER (1L<<7)
#define VALIDATING (1L<<8)
#define SET_ACTIVE (1L<<9)
#define ACTIVE_DISABLED (1L<<10)
#define OVER_BORDER (1L<<11)
#define REDRAW_ON_MAP (1L<<12)
#define AVOID_SPANS (1L<<13)
/* Flags for TableInvalidate && TableRedraw */
#define ROW (1L<<0)
#define COL (1L<<1)
#define CELL (1L<<2)
#define CELL_BAD (1<<0)
#define CELL_OK (1<<1)
#define CELL_SPAN (1<<2)
#define CELL_HIDDEN (1<<3)
#define CELL_VIEWABLE (CELL_OK|CELL_SPAN)
#define INV_FILL (1L<<3) /* use for Redraw when the affected
* row/col will affect neighbors */
#define INV_FORCE (1L<<4)
#define INV_HIGHLIGHT (1L<<5)
#define INV_NO_ERR_MSG (1L<<5) /* Don't leave an error message */
/* These alter how the selection set/clear commands behave */
#define SEL_ROW (1<<0)
#define SEL_COL (1<<1)
#define SEL_BOTH (1<<2)
#define SEL_CELL (1<<3)
#define SEL_NONE (1<<4)
/*
* Definitions for tablePtr->dataSource, by bit
*/
#define DATA_NONE 0
#define DATA_CACHE (1<<1)
#define DATA_ARRAY (1<<2)
#define DATA_COMMAND (1<<3)
/*
* Definitions for configuring -borderwidth
*/
#define BD_TABLE 0
#define BD_TABLE_TAG (1<<1)
#define BD_TABLE_WIN (1<<2)
/*
* Possible state values for tags
*/
typedef enum {
STATE_UNUSED, STATE_UNKNOWN, STATE_HIDDEN,
STATE_NORMAL, STATE_DISABLED, STATE_ACTIVE, STATE_LAST
} TableState;
/*
* Structure for use in parsing table commands/values.
* Accessor functions defined in tkTableUtil.c
*/
typedef struct {
char *name; /* name of the command/value */
int value; /* >0 because 0 represents an error or proc */
} Cmd_Struct;
/*
* The tag structure
*/
typedef struct {
Tk_3DBorder bg; /* background color */
Tk_3DBorder fg; /* foreground color */
char * borderStr; /* border style */
int borders; /* number of borders specified (1, 2 or 4) */
int bd[4]; /* cell border width */
int relief; /* relief type */
Tk_Font tkfont; /* Information about text font, or NULL. */
Tk_Anchor anchor; /* default anchor point */
char * imageStr; /* name of image */
Tk_Image image; /* actual pointer to image, if any */
TableState state; /* state of the cell */
Tk_Justify justify; /* justification of text in the cell */
int multiline; /* wrapping style of multiline text */
int wrap; /* wrapping style of multiline text */
int showtext; /* whether to display text over image */
char * ellipsis; /* ellipsis to display on clipped text */
} TableTag;
/* The widget structure for the table Widget */
typedef struct {
/* basic information about the window and the interpreter */
Tk_Window tkwin;
Display *display;
Tcl_Interp *interp;
Tcl_Command widgetCmd; /* Token for entry's widget command. */
/*
* Configurable Options
*/
int autoClear;
char *selectMode; /* single, browse, multiple, or extended */
int selectType; /* row, col, both, or cell */
int selectTitles; /* whether to do automatic title selection */
int rows, cols; /* number of rows and columns */
int defRowHeight; /* default row height in chars (positive)
* or pixels (negative) */
int defColWidth; /* default column width in chars (positive)
* or pixels (negative) */
int maxReqCols; /* the requested # cols to display */
int maxReqRows; /* the requested # rows to display */
int maxReqWidth; /* the maximum requested width in pixels */
int maxReqHeight; /* the maximum requested height in pixels */
char *arrayVar; /* name of traced array variable */
char *rowSep; /* separator string to place between
* rows when getting selection */
char *colSep; /* separator string to place between
* cols when getting selection */
TableTag defaultTag; /* the default tag colors/fonts etc */
char *yScrollCmd; /* the y-scroll command */
char *xScrollCmd; /* the x-scroll command */
char *browseCmd; /* the command that is called when the
* active cell changes */
int caching; /* whether to cache values of table */
char *command; /* A command to eval when get/set occurs
* for table values */
int useCmd; /* Signals whether to use command or the
* array variable, will be 0 if command errs */
char *selCmd; /* the command that is called to when a
* [selection get] call occurs for a table */
char *valCmd; /* Command prefix to use when invoking
* validate command. NULL means don't
* invoke commands. Malloc'ed. */
int validate; /* Non-zero means try to validate */
Tk_3DBorder insertBg; /* the cursor color */
Tk_Cursor cursor; /* the regular mouse pointer */
Tk_Cursor bdcursor; /* the mouse pointer when over borders */
#ifdef TITLE_CURSOR
Tk_Cursor titleCursor; /* the mouse pointer when over titles */
#endif
int exportSelection; /* Non-zero means tie internal table
* to X selection. */
TableState state; /* Normal or disabled. Table is read-only
* when disabled. */
int insertWidth; /* Total width of insert cursor. */
int insertBorderWidth; /* Width of 3-D border around insert cursor. */
int insertOnTime; /* Number of milliseconds cursor should spend
* in "on" state for each blink. */
int insertOffTime; /* Number of milliseconds cursor should spend
* in "off" state for each blink. */
int invertSelected; /* Whether to draw selected cells swapping
* foreground and background */
int colStretch; /* The way to stretch columns if the window
* is too large */
int rowStretch; /* The way to stretch rows if the window is
* too large */
int colOffset; /* X index of leftmost col in the display */
int rowOffset; /* Y index of topmost row in the display */
int drawMode; /* The mode to use when redrawing */
int flashMode; /* Specifies whether flashing is enabled */
int flashTime; /* The number of ms to flash a cell for */
int resize; /* -resizeborders option for interactive
* resizing of borders */
int sparse; /* Whether to use "sparse" arrays by
* deleting empty array elements (default) */
char *rowTagCmd, *colTagCmd;/* script to eval for getting row/tag cmd */
int highlightWidth; /* Width in pixels of highlight to draw
* around widget when it has the focus.
* <= 0 means don't draw a highlight. */
XColor *highlightBgColorPtr;/* Color for drawing traversal highlight
* area when highlight is off. */
XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
char *takeFocus; /* Used only in Tcl to check if this
* widget will accept focus */
int padX, padY; /* Extra space around text (pixels to leave
* on each side). Ignored for bitmaps and
* images. */
int ipadX, ipadY; /* Space to leave empty around cell borders.
* This differs from pad* in that it is always
* present for the cell (except windows). */
/*
* Cached Information
*/
#ifdef TITLE_CURSOR
Tk_Cursor *lastCursorPtr; /* pointer to last cursor defined. */
#endif
int titleRows, titleCols; /* the number of rows|cols to use as a title */
/* these are kept in real coords */
int topRow, leftCol; /* The topleft cell to display excluding the
* fixed title rows. This is just the
* config request. The actual cell used may
* be different to keep the screen full */
int anchorRow, anchorCol; /* the row,col of the anchor cell */
int activeRow, activeCol; /* the row,col of the active cell */
int oldTopRow, oldLeftCol; /* cached by TableAdjustParams */
int oldActRow, oldActCol; /* cached by TableAdjustParams */
int icursor; /* The index of the insertion cursor in the
* active cell */
int flags; /* An or'ed combination of flags concerning
* redraw/cursor etc. */
int dataSource; /* where our data comes from:
* DATA_{NONE,CACHE,ARRAY,COMMAND} */
int maxWidth, maxHeight; /* max width|height required in pixels */
int charWidth, charHeight; /* size of a character in the default font */
int *colPixels, *rowPixels; /* Array of the pixel widths/heights */
int *colStarts, *rowStarts; /* Array of start pixels for rows|columns */
int scanMarkX, scanMarkY; /* Used by "scan" and "border" to mark */
int scanMarkRow, scanMarkCol;/* necessary information for dragto */
/* values in these are kept in user coords */
Tcl_HashTable *cache; /* value cache */
/*
* colWidths and rowHeights are indexed from 0, so always adjust numbers
* by the appropriate *Offset factor
*/
Tcl_HashTable *colWidths; /* hash table of non default column widths */
Tcl_HashTable *rowHeights; /* hash table of non default row heights */
Tcl_HashTable *spanTbl; /* table for spans */
Tcl_HashTable *spanAffTbl; /* table for cells affected by spans */
Tcl_HashTable *tagTable; /* table for style tags */
Tcl_HashTable *winTable; /* table for embedded windows */
Tcl_HashTable *rowStyles; /* table for row styles */
Tcl_HashTable *colStyles; /* table for col styles */
Tcl_HashTable *cellStyles; /* table for cell styles */
Tcl_HashTable *flashCells; /* table of flashing cells */
Tcl_HashTable *selCells; /* table of selected cells */
Tcl_TimerToken cursorTimer; /* timer token for the cursor blinking */
Tcl_TimerToken flashTimer; /* timer token for the cell flashing */
char *activeBuf; /* buffer where the selection is kept
* for editing the active cell */
char **tagPrioNames; /* list of tag names in priority order */
TableTag **tagPrios; /* list of tag pointers in priority order */
TableTag *activeTagPtr; /* cache of active composite tag */
int activeX, activeY; /* cache offset of active layout in cell */
int tagPrioSize; /* size of tagPrios list */
int tagPrioMax; /* max allocated size of tagPrios list */
/* The invalid rectangle if there is an update pending */
int invalidX, invalidY, invalidWidth, invalidHeight;
int seen[4]; /* see TableUndisplay */
#ifdef POSTSCRIPT
/* Pointer to information used for generating Postscript for the canvas.
* NULL means no Postscript is currently being generated. */
struct TkPostscriptInfo *psInfoPtr;
#endif
#ifdef PROCS
Tcl_HashTable *inProc; /* cells where proc is being evaled */
int showProcs; /* whether to show embedded proc (1) or
* its calculated value (0) */
int hasProcs; /* whether table has embedded procs or not */
#endif
} Table;
/*
* HEADERS FOR EMBEDDED WINDOWS
*/
/*
* A structure of the following type holds information for each window
* embedded in a table widget.
*/
typedef struct TableEmbWindow {
Table *tablePtr; /* Information about the overall table
* widget. */
Tk_Window tkwin; /* Window for this segment. NULL means that
* the window hasn't been created yet. */
Tcl_HashEntry *hPtr; /* entry into winTable */
char *create; /* Script to create window on-demand.
* NULL means no such script.
* Malloc-ed. */
Tk_3DBorder bg; /* background color */
char *borderStr; /* border style */
int borders; /* number of borders specified (1, 2 or 4) */
int bd[4]; /* border width for cell around window */
int relief; /* relief type */
int sticky; /* How to align window in space */
int padX, padY; /* Padding to leave around each side
* of window, in pixels. */
int displayed; /* Non-zero means that the window has been
* displayed on the screen recently. */
} TableEmbWindow;
extern Tk_ConfigSpec tableSpecs[];
extern void EmbWinDisplay(Table *tablePtr, Drawable window,
TableEmbWindow *ewPtr, TableTag *tagPtr,
int x, int y, int width, int height);
extern void EmbWinUnmap(register Table *tablePtr,
int rlo, int rhi, int clo, int chi);
extern void EmbWinDelete(register Table *tablePtr, TableEmbWindow *ewPtr);
extern int Table_WinMove(register Table *tablePtr,
char *CONST srcPtr, char *CONST destPtr, int flags);
extern int Table_WinDelete(register Table *tablePtr, char *CONST idxPtr);
extern int Table_WindowCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int TableValidateChange(Table *tablePtr, int r,
int c, char *oldVal, char *newVal, int idx);
extern void TableLostSelection(ClientData clientData);
extern void TableSetActiveIndex(register Table *tablePtr);
/*
* HEADERS IN tkTableCmds.c
*/
extern int Table_ActivateCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_AdjustCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_BboxCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_BorderCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_ClearCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_CurselectionCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_CurvalueCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_GetCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_ScanCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_SeeCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_SelAnchorCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_SelClearCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_SelIncludesCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_SelSetCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_ViewCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
/*
* HEADERS IN tkTableEdit.c
*/
extern int Table_EditCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern void TableDeleteChars(register Table *tablePtr,
int idx, int count);
extern void TableInsertChars(register Table *tablePtr,
int idx, char *string);
/*
* HEADERS IN tkTableTag.c
*/
extern TableTag *TableNewTag(Table *tablePtr);
extern void TableResetTag(Table *tablePtr, TableTag *tagPtr);
extern void TableMergeTag(Table *tablePtr, TableTag *baseTag,
TableTag *addTag);
extern void TableInvertTag(TableTag *baseTag);
extern int TableGetTagBorders(TableTag *tagPtr,
int *left, int *right, int *top, int *bottom);
extern void TableInitTags(Table *tablePtr);
extern TableTag *FindRowColTag(Table *tablePtr,
int cell, int type);
extern void TableCleanupTag(Table *tablePtr,
TableTag *tagPtr);
extern int Table_TagCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
/*
* HEADERS IN tkTableUtil.c
*/
extern void Table_ClearHashTable(Tcl_HashTable *hashTblPtr);
extern int TableOptionBdSet(ClientData clientData,
Tcl_Interp *interp, Tk_Window tkwin,
CONST84 char *value, char *widgRec, int offset);
extern char * TableOptionBdGet(ClientData clientData,
Tk_Window tkwin, char *widgRec, int offset,
Tcl_FreeProc **freeProcPtr);
extern int TableTagConfigureBd(Table *tablePtr,
TableTag *tagPtr, char *oldValue, int nullOK);
extern int Cmd_OptionSet(ClientData clientData,
Tcl_Interp *interp,
Tk_Window unused, CONST84 char *value,
char *widgRec, int offset);
extern char * Cmd_OptionGet(ClientData clientData,
Tk_Window unused, char *widgRec,
int offset, Tcl_FreeProc **freeProcPtr);
/*
* HEADERS IN tkTableCell.c
*/
extern int TableTrueCell(Table *tablePtr, int row, int col,
int *trow, int *tcol);
extern int TableCellCoords(Table *tablePtr, int row,
int col, int *rx, int *ry, int *rw, int *rh);
extern int TableCellVCoords(Table *tablePtr, int row,
int col, int *rx, int *ry,
int *rw, int *rh, int full);
extern void TableWhatCell(register Table *tablePtr,
int x, int y, int *row, int *col);
extern int TableAtBorder(Table *tablePtr, int x, int y,
int *row, int *col);
extern char * TableGetCellValue(Table *tablePtr, int r, int c);
extern int TableSetCellValue(Table *tablePtr, int r, int c,
char *value);
extern int TableMoveCellValue(Table *tablePtr,
int fromr, int fromc, char *frombuf,
int tor, int toc, char *tobuf, int outOfBounds);
extern int TableGetIcursor(Table *tablePtr, char *arg,
int *posn);
#define TableGetIcursorObj(tablePtr, objPtr, posnPtr) \
TableGetIcursor(tablePtr, Tcl_GetString(objPtr), posnPtr)
extern int TableGetIndex(register Table *tablePtr,
char *str, int *row_p, int *col_p);
#define TableGetIndexObj(tablePtr, objPtr, rowPtr, colPtr) \
TableGetIndex(tablePtr, Tcl_GetString(objPtr), rowPtr, colPtr)
extern int Table_SetCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_HiddenCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern int Table_SpanCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern void TableSpanSanCheck(register Table *tablePtr);
/*
* HEADERS IN TKTABLECELLSORT
*/
/*
* We keep the old CellSort true because it is used for grabbing
* the selection, so we really want them ordered
*/
extern char * TableCellSort(Table *tablePtr, char *str);
#ifdef NO_SORT_CELLS
# define TableCellSortObj(interp, objPtr) (objPtr)
#else
extern Tcl_Obj* TableCellSortObj(Tcl_Interp *interp, Tcl_Obj *listObjPtr);
#endif
/*
* HEADERS IN TKTABLEPS
*/
#ifdef POSTSCRIPT
extern int Table_PostscriptCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
extern void Tcl_DStringAppendAllTCL_VARARGS(Tcl_DString *, arg1);
#endif
/*
* HEADERS IN TKTABLE
*/
EXTERN int Tktable_Init(Tcl_Interp *interp);
EXTERN int Tktable_SafeInit(Tcl_Interp *interp);
extern void TableGetActiveBuf(register Table *tablePtr);
extern void ExpandPercents(Table *tablePtr, char *before,
int r, int c, char *oldVal, char *newVal, int idx,
Tcl_DString *dsPtr, int cmdType);
extern void TableInvalidate(Table *tablePtr, int x, int y,
int width, int height, int force);
extern void TableRefresh(register Table *tablePtr,
int arg1, int arg2, int mode);
extern void TableGeometryRequest(Table *tablePtr);
extern void TableAdjustActive(register Table *tablePtr);
extern void TableAdjustParams(register Table *tablePtr);
extern void TableConfigCursor(register Table *tablePtr);
extern void TableAddFlash(Table *tablePtr, int row, int col);
#define TableInvalidateAll(tablePtr, flags) \
TableInvalidate((tablePtr), 0, 0, Tk_Width((tablePtr)->tkwin),\
Tk_Height((tablePtr)->tkwin), (flags))
/*
* Turn row/col into an index into the table
*/
#define TableMakeArrayIndex(r, c, i) sprintf((i), "%d,%d", (r), (c))
/*
* Turn array index back into row/col
* return the number of args parsed (should be two)
*/
#define TableParseArrayIndex(r, c, i) sscanf((i), "%d,%d", (r), (c))
/*
* Macro for finding the last cell of the table
*/
#define TableGetLastCell(tablePtr, rowPtr, colPtr) \
TableWhatCell((tablePtr),\
Tk_Width((tablePtr)->tkwin)-(tablePtr)->highlightWidth-1,\
Tk_Height((tablePtr)->tkwin)-(tablePtr)->highlightWidth-1,\
(rowPtr), (colPtr))
/*
* end of header
* reset TCL_STORAGE_CLASS to DLLIMPORT.
*/
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TKTABLE_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,400 @@
/*
* tkTableCell.c --
*
* This module implements cell sort functions for table
* widgets. The MergeSort algorithm and other aux sorting
* functions were taken from tclCmdIL.c lsort command:
* tclCmdIL.c --
*
* This file contains the top-level command routines for most of
* the Tcl built-in commands whose names begin with the letters
* I through L. It contains only commands in the generic core
* (i.e. those that don't depend much upon UNIX facilities).
*
* Copyright (c) 1987-1993 The Regents of the University of California.
* Copyright (c) 1993-1997 Lucent Technologies.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
* Copyright (c) 1998-1999 by Scriptics Corporation.
*
* Copyright (c) 1998-2002 Jeffrey Hobbs
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#include "tkTable.h"
#ifndef UCHAR
#define UCHAR(c) ((unsigned char) (c))
#endif
/*
* During execution of the "lsort" command, structures of the following
* type are used to arrange the objects being sorted into a collection
* of linked lists.
*/
typedef struct SortElement {
Tcl_Obj *objPtr; /* Object being sorted. */
struct SortElement *nextPtr; /* Next element in the list, or
* NULL for end of list. */
} SortElement;
static int TableSortCompareProc _ANSI_ARGS_((CONST VOID *first,
CONST VOID *second));
static SortElement * MergeSort _ANSI_ARGS_((SortElement *headPt));
static SortElement * MergeLists _ANSI_ARGS_((SortElement *leftPtr,
SortElement *rightPtr));
static int DictionaryCompare _ANSI_ARGS_((char *left,
char *right));
/*
*----------------------------------------------------------------------
*
* TableSortCompareProc --
* This procedure is invoked by qsort to determine the proper
* ordering between two elements.
*
* Results:
* < 0 means first is "smaller" than "second", > 0 means "first"
* is larger than "second", and 0 means they should be treated
* as equal.
*
* Side effects:
* None, unless a user-defined comparison command does something
* weird.
*
*----------------------------------------------------------------------
*/
static int
TableSortCompareProc(first, second)
CONST VOID *first, *second; /* Elements to be compared. */
{
char *str1 = *((char **) first);
char *str2 = *((char **) second);
return DictionaryCompare(str1, str2);
}
/*
*----------------------------------------------------------------------
*
* TableCellSort --
* Sort a list of table cell elements (of form row,col)
*
* Results:
* Returns the sorted list of elements. Because Tcl_Merge allocs
* the space for result, it must later be Tcl_Free'd by caller.
*
* Side effects:
* Behaviour undefined for ill-formed input list of elements.
*
*----------------------------------------------------------------------
*/
char *
TableCellSort(Table *tablePtr, char *str)
{
int listArgc;
CONST84 char **listArgv;
char *result;
if (Tcl_SplitList(tablePtr->interp, str, &listArgc, &listArgv) != TCL_OK) {
return str;
}
/* Thread safety: qsort is reportedly not thread-safe... */
qsort((VOID *) listArgv, (size_t) listArgc, sizeof (char *),
TableSortCompareProc);
result = Tcl_Merge(listArgc, listArgv);
ckfree((char *) listArgv);
return result;
}
/*
*----------------------------------------------------------------------
*
* DictionaryCompare - Not the Unicode version
*
* This function compares two strings as if they were being used in
* an index or card catalog. The case of alphabetic characters is
* ignored, except to break ties. Thus "B" comes before "b" but
* after "a". Also, integers embedded in the strings compare in
* numerical order. In other words, "x10y" comes after "x9y", not
* before it as it would when using strcmp().
*
* Results:
* A negative result means that the first element comes before the
* second, and a positive result means that the second element
* should come first. A result of zero means the two elements
* are equal and it doesn't matter which comes first.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static int
DictionaryCompare(left, right)
char *left, *right; /* The strings to compare */
{
int diff, zeros;
int secondaryDiff = 0;
while (1) {
if (isdigit(UCHAR(*right)) && isdigit(UCHAR(*left))) {
/*
* There are decimal numbers embedded in the two
* strings. Compare them as numbers, rather than
* strings. If one number has more leading zeros than
* the other, the number with more leading zeros sorts
* later, but only as a secondary choice.
*/
zeros = 0;
while ((*right == '0') && (isdigit(UCHAR(right[1])))) {
right++;
zeros--;
}
while ((*left == '0') && (isdigit(UCHAR(left[1])))) {
left++;
zeros++;
}
if (secondaryDiff == 0) {
secondaryDiff = zeros;
}
/*
* The code below compares the numbers in the two
* strings without ever converting them to integers. It
* does this by first comparing the lengths of the
* numbers and then comparing the digit values.
*/
diff = 0;
while (1) {
if (diff == 0) {
diff = UCHAR(*left) - UCHAR(*right);
}
right++;
left++;
if (!isdigit(UCHAR(*right))) {
if (isdigit(UCHAR(*left))) {
return 1;
} else {
/*
* The two numbers have the same length. See
* if their values are different.
*/
if (diff != 0) {
return diff;
}
break;
}
} else if (!isdigit(UCHAR(*left))) {
return -1;
}
}
continue;
}
diff = UCHAR(*left) - UCHAR(*right);
if (diff) {
if (isupper(UCHAR(*left)) && islower(UCHAR(*right))) {
diff = UCHAR(tolower(*left)) - UCHAR(*right);
if (diff) {
return diff;
} else if (secondaryDiff == 0) {
secondaryDiff = -1;
}
} else if (isupper(UCHAR(*right)) && islower(UCHAR(*left))) {
diff = UCHAR(*left) - UCHAR(tolower(UCHAR(*right)));
if (diff) {
return diff;
} else if (secondaryDiff == 0) {
secondaryDiff = 1;
}
} else {
return diff;
}
}
if (*left == 0) {
break;
}
left++;
right++;
}
if (diff == 0) {
diff = secondaryDiff;
}
return diff;
}
/*
*----------------------------------------------------------------------
*
* MergeLists -
*
* This procedure combines two sorted lists of SortElement structures
* into a single sorted list.
*
* Results:
* The unified list of SortElement structures.
*
* Side effects:
* None, unless a user-defined comparison command does something
* weird.
*
*----------------------------------------------------------------------
*/
static SortElement *
MergeLists(leftPtr, rightPtr)
SortElement *leftPtr; /* First list to be merged; may be
* NULL. */
SortElement *rightPtr; /* Second list to be merged; may be
* NULL. */
{
SortElement *headPtr;
SortElement *tailPtr;
if (leftPtr == NULL) {
return rightPtr;
}
if (rightPtr == NULL) {
return leftPtr;
}
if (DictionaryCompare(Tcl_GetString(leftPtr->objPtr),
Tcl_GetString(rightPtr->objPtr)) > 0) {
tailPtr = rightPtr;
rightPtr = rightPtr->nextPtr;
} else {
tailPtr = leftPtr;
leftPtr = leftPtr->nextPtr;
}
headPtr = tailPtr;
while ((leftPtr != NULL) && (rightPtr != NULL)) {
if (DictionaryCompare(Tcl_GetString(leftPtr->objPtr),
Tcl_GetString(rightPtr->objPtr)) > 0) {
tailPtr->nextPtr = rightPtr;
tailPtr = rightPtr;
rightPtr = rightPtr->nextPtr;
} else {
tailPtr->nextPtr = leftPtr;
tailPtr = leftPtr;
leftPtr = leftPtr->nextPtr;
}
}
if (leftPtr != NULL) {
tailPtr->nextPtr = leftPtr;
} else {
tailPtr->nextPtr = rightPtr;
}
return headPtr;
}
/*
*----------------------------------------------------------------------
*
* MergeSort -
*
* This procedure sorts a linked list of SortElement structures
* use the merge-sort algorithm.
*
* Results:
* A pointer to the head of the list after sorting is returned.
*
* Side effects:
* None, unless a user-defined comparison command does something
* weird.
*
*----------------------------------------------------------------------
*/
static SortElement *
MergeSort(headPtr)
SortElement *headPtr; /* First element on the list */
{
/*
* The subList array below holds pointers to temporary lists built
* during the merge sort. Element i of the array holds a list of
* length 2**i.
*/
# define NUM_LISTS 30
SortElement *subList[NUM_LISTS];
SortElement *elementPtr;
int i;
for(i = 0; i < NUM_LISTS; i++){
subList[i] = NULL;
}
while (headPtr != NULL) {
elementPtr = headPtr;
headPtr = headPtr->nextPtr;
elementPtr->nextPtr = 0;
for (i = 0; (i < NUM_LISTS) && (subList[i] != NULL); i++){
elementPtr = MergeLists(subList[i], elementPtr);
subList[i] = NULL;
}
if (i >= NUM_LISTS) {
i = NUM_LISTS-1;
}
subList[i] = elementPtr;
}
elementPtr = NULL;
for (i = 0; i < NUM_LISTS; i++){
elementPtr = MergeLists(subList[i], elementPtr);
}
return elementPtr;
}
#ifndef NO_SORT_CELLS
/*
*----------------------------------------------------------------------
*
* TableCellSortObj --
* Sorts a list of table cell elements (of form row,col) in place
*
* Results:
* Sorts list of elements in place.
*
* Side effects:
* Behaviour undefined for ill-formed input list of elements.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
TableCellSortObj(Tcl_Interp *interp, Tcl_Obj *listObjPtr)
{
int length, i;
Tcl_Obj *sortedObjPtr, **listObjPtrs;
SortElement *elementArray;
SortElement *elementPtr;
if (Tcl_ListObjGetElements(interp, listObjPtr,
&length, &listObjPtrs) != TCL_OK) {
return NULL;
}
if (length <= 0) {
return listObjPtr;
}
elementArray = (SortElement *) ckalloc(length * sizeof(SortElement));
for (i=0; i < length; i++){
elementArray[i].objPtr = listObjPtrs[i];
elementArray[i].nextPtr = &elementArray[i+1];
}
elementArray[length-1].nextPtr = NULL;
elementPtr = MergeSort(elementArray);
sortedObjPtr = Tcl_NewObj();
for (; elementPtr != NULL; elementPtr = elementPtr->nextPtr){
Tcl_ListObjAppendElement(NULL, sortedObjPtr, elementPtr->objPtr);
}
ckfree((char*) elementArray);
return sortedObjPtr;
}
#endif

File diff suppressed because it is too large Load Diff

View 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;
}
}
}
}
}

View File

@@ -0,0 +1,90 @@
/*
* tkTableInitScript.h --
*
* This file contains common init script for tkTable
*
* Copyright (c) 1998 Jeffrey Hobbs
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
/*
* The following string is the startup script executed when the table is
* loaded. It looks on disk in several different directories for a script
* "TBL_RUNTIME" (as defined in Makefile) that is compatible with this
* version of tkTable. The sourced script has all key bindings defined.
*/
static char tkTableInitScript[] = "if {[info proc tkTableInit]==\"\"} {\n\
proc tkTableInit {} {\n\
global tk_library tcl_pkgPath errorInfo env\n\
rename tkTableInit {}\n\
set errors {}\n\
if {![info exists env(TK_TABLE_LIBRARY_FILE)]} {\n\
set env(TK_TABLE_LIBRARY_FILE) " TBL_RUNTIME "\n\
}\n\
if {[info exists env(TK_TABLE_LIBRARY)]} {\n\
lappend dirs $env(TK_TABLE_LIBRARY)\n\
}\n\
lappend dirs " TBL_RUNTIME_DIR "\n\
if {[info exists tcl_pkgPath]} {\n\
foreach i $tcl_pkgPath {\n\
lappend dirs [file join $i Tktable" PACKAGE_VERSION "] \\\n\
[file join $i Tktable] $i\n\
}\n\
}\n\
lappend dirs $tk_library [pwd]\n\
foreach i $dirs {\n\
set try [file join $i $env(TK_TABLE_LIBRARY_FILE)]\n\
if {[file exists $try]} {\n\
if {![catch {uplevel #0 [list source $try]} msg]} {\n\
set env(TK_TABLE_LIBRARY) $i\n\
return\n\
} else {\n\
append errors \"$try: $msg\n$errorInfo\n\"\n\
}\n\
}\n\
}\n"
#ifdef NO_EMBEDDED_RUNTIME
" set msg \"Can't find a $env(TK_TABLE_LIBRARY_FILE) in the following directories: \n\"\n\
append msg \" $dirs\n\n$errors\n\n\"\n\
append msg \"This probably means that TkTable wasn't installed properly.\"\n\
return -code error $msg\n"
#else
" set env(TK_TABLE_LIBRARY) EMBEDDED_RUNTIME\n"
# ifdef MAC_TCL
" source -rsrc tkTable"
# else
" uplevel #0 {"
# include "tkTable.tcl.h"
" }"
# endif
#endif
" }\n\
}\n\
tkTableInit";
/*
* The init script can't make certain calls in a safe interpreter,
* so we always have to use the embedded runtime for it
*/
static char tkTableSafeInitScript[] = "if {[info proc tkTableInit]==\"\"} {\n\
proc tkTableInit {} {\n\
set env(TK_TABLE_LIBRARY) EMBEDDED_RUNTIME\n"
#ifdef NO_EMBEDDED_RUNTIME
" append msg \"tkTable requires embedded runtime to be compiled for\"\n\
append msg \" use in safe interpreters\"\n\
return -code error $msg\n"
#endif
# ifdef MAC_TCL
" source -rsrc tkTable"
# else
" uplevel #0 {"
# include "tkTable.tcl.h"
" }"
# endif
" }\n\
}\n\
tkTableInit";

1299
tktable/generic/tkTablePs.c Normal file

File diff suppressed because it is too large Load Diff

1354
tktable/generic/tkTableTag.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,372 @@
/*
* tkTableUtil.c --
*
* This module contains utility functions for table widgets.
*
* Copyright (c) 2000-2002 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: tkTableUtil.c,v 1.4 2002/10/16 07:31:48 hobbs Exp $
*/
#include "tkTable.h"
static char * Cmd_GetName _ANSI_ARGS_((const Cmd_Struct *cmds, int val));
static int Cmd_GetValue _ANSI_ARGS_((const Cmd_Struct *cmds,
const char *arg));
static void Cmd_GetError _ANSI_ARGS_((Tcl_Interp *interp,
const Cmd_Struct *cmds, const char *arg));
/*
*--------------------------------------------------------------
*
* Table_ClearHashTable --
* This procedure is invoked to clear a STRING_KEY hash table,
* freeing the string entries and then deleting the hash table.
* The hash table cannot be used after calling this, except to
* be freed or reinitialized.
*
* Results:
* Cached info will be lost.
*
* Side effects:
* Can cause redraw.
* See the user documentation.
*
*--------------------------------------------------------------
*/
void
Table_ClearHashTable(Tcl_HashTable *hashTblPtr)
{
Tcl_HashEntry *entryPtr;
Tcl_HashSearch search;
char *value;
for (entryPtr = Tcl_FirstHashEntry(hashTblPtr, &search);
entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
value = (char *) Tcl_GetHashValue(entryPtr);
if (value != NULL) ckfree(value);
}
Tcl_DeleteHashTable(hashTblPtr);
}
/*
*----------------------------------------------------------------------
*
* TableOptionBdSet --
*
* This routine configures the borderwidth value for a tag.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* It may adjust the tag struct values of bd[0..4] and borders.
*
*----------------------------------------------------------------------
*/
int
TableOptionBdSet(clientData, interp, tkwin, value, widgRec, offset)
ClientData clientData; /* Type of struct being set. */
Tcl_Interp *interp; /* Used for reporting errors. */
Tk_Window tkwin; /* Window containing table widget. */
CONST84 char *value; /* Value of option. */
char *widgRec; /* Pointer to record for item. */
int offset; /* Offset into item. */
{
char **borderStr;
int *bordersPtr, *bdPtr;
int type = (int) clientData;
int result = TCL_OK;
int argc;
CONST84 char **argv;
if ((type == BD_TABLE) && (value[0] == '\0')) {
/*
* NULL strings aren't allowed for the table global -bd
*/
Tcl_AppendResult(interp, "borderwidth value may not be empty",
(char *) NULL);
return TCL_ERROR;
}
if ((type == BD_TABLE) || (type == BD_TABLE_TAG)) {
TableTag *tagPtr = (TableTag *) (widgRec + offset);
borderStr = &(tagPtr->borderStr);
bordersPtr = &(tagPtr->borders);
bdPtr = tagPtr->bd;
} else if (type == BD_TABLE_WIN) {
TableEmbWindow *tagPtr = (TableEmbWindow *) widgRec;
borderStr = &(tagPtr->borderStr);
bordersPtr = &(tagPtr->borders);
bdPtr = tagPtr->bd;
} else {
panic("invalid type given to TableOptionBdSet\n");
return TCL_ERROR; /* lint */
}
result = Tcl_SplitList(interp, value, &argc, &argv);
if (result == TCL_OK) {
int i, bd[4];
if (((type == BD_TABLE) && (argc == 0)) || (argc == 3) || (argc > 4)) {
Tcl_AppendResult(interp,
"1, 2 or 4 values must be specified for borderwidth",
(char *) NULL);
result = TCL_ERROR;
} else {
/*
* We use the shadow bd array first, in case we have an error
* parsing arguments half way through.
*/
for (i = 0; i < argc; i++) {
if (Tk_GetPixels(interp, tkwin, argv[i], &(bd[i])) != TCL_OK) {
result = TCL_ERROR;
break;
}
}
/*
* If everything is OK, store the parsed and given values for
* easy retrieval.
*/
if (result == TCL_OK) {
for (i = 0; i < argc; i++) {
bdPtr[i] = MAX(0, bd[i]);
}
if (*borderStr) {
ckfree(*borderStr);
}
if (value) {
*borderStr = (char *) ckalloc(strlen(value) + 1);
strcpy(*borderStr, value);
} else {
*borderStr = NULL;
}
*bordersPtr = argc;
}
}
ckfree ((char *) argv);
}
return result;
}
/*
*----------------------------------------------------------------------
*
* TableOptionBdGet --
*
* Results:
* Value of the -bd option.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
char *
TableOptionBdGet(clientData, tkwin, widgRec, offset, freeProcPtr)
ClientData clientData; /* Type of struct being set. */
Tk_Window tkwin; /* Window containing canvas widget. */
char *widgRec; /* Pointer to record for item. */
int offset; /* Offset into item. */
Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
* information about how to reclaim
* storage for return string. */
{
register int type = (int) clientData;
if (type == BD_TABLE) {
return ((TableTag *) (widgRec + offset))->borderStr;
} else if (type == BD_TABLE_TAG) {
return ((TableTag *) widgRec)->borderStr;
} else if (type == BD_TABLE_WIN) {
return ((TableEmbWindow *) widgRec)->borderStr;
} else {
panic("invalid type given to TableOptionBdSet\n");
return NULL; /* lint */
}
}
/*
*----------------------------------------------------------------------
*
* TableTagConfigureBd --
* This routine configures the border values based on a tag.
* The previous value of the bd string (oldValue) is assumed to
* be a valid value for this tag.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* It may adjust the value used by -bd.
*
*----------------------------------------------------------------------
*/
int
TableTagConfigureBd(Table *tablePtr, TableTag *tagPtr,
char *oldValue, int nullOK)
{
int i, argc, result = TCL_OK;
CONST84 char **argv;
/*
* First check to see if the value really changed.
*/
if (strcmp(tagPtr->borderStr ? tagPtr->borderStr : "",
oldValue ? oldValue : "") == 0) {
return TCL_OK;
}
tagPtr->borders = 0;
if (!nullOK && ((tagPtr->borderStr == NULL)
|| (*(tagPtr->borderStr) == '\0'))) {
/*
* NULL strings aren't allowed for this tag
*/
result = TCL_ERROR;
} else if (tagPtr->borderStr) {
result = Tcl_SplitList(tablePtr->interp, tagPtr->borderStr,
&argc, &argv);
if (result == TCL_OK) {
if ((!nullOK && (argc == 0)) || (argc == 3) || (argc > 4)) {
Tcl_SetResult(tablePtr->interp,
"1, 2 or 4 values must be specified to -borderwidth",
TCL_STATIC);
result = TCL_ERROR;
} else {
for (i = 0; i < argc; i++) {
if (Tk_GetPixels(tablePtr->interp, tablePtr->tkwin,
argv[i], &(tagPtr->bd[i])) != TCL_OK) {
result = TCL_ERROR;
break;
}
tagPtr->bd[i] = MAX(0, tagPtr->bd[i]);
}
tagPtr->borders = argc;
}
ckfree ((char *) argv);
}
}
if (result != TCL_OK) {
if (tagPtr->borderStr) {
ckfree ((char *) tagPtr->borderStr);
}
if (oldValue != NULL) {
size_t length = strlen(oldValue) + 1;
/*
* We are making the assumption that oldValue is correct.
* We have to reparse in case the bad new value had a couple
* of correct args before failing on a bad pixel value.
*/
Tcl_SplitList(tablePtr->interp, oldValue, &argc, &argv);
for (i = 0; i < argc; i++) {
Tk_GetPixels(tablePtr->interp, tablePtr->tkwin,
argv[i], &(tagPtr->bd[i]));
}
ckfree ((char *) argv);
tagPtr->borders = argc;
tagPtr->borderStr = (char *) ckalloc(length);
memcpy(tagPtr->borderStr, oldValue, length);
} else {
tagPtr->borders = 0;
tagPtr->borderStr = (char *) NULL;
}
}
return result;
}
/*
*----------------------------------------------------------------------
*
* Cmd_OptionSet --
*
*
* Results:
* A standard Tcl result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
Cmd_OptionSet(ClientData clientData, Tcl_Interp *interp,
Tk_Window unused, CONST84 char *value, char *widgRec, int offset)
{
Cmd_Struct *p = (Cmd_Struct *)clientData;
int mode = Cmd_GetValue(p,value);
if (!mode) {
Cmd_GetError(interp,p,value);
return TCL_ERROR;
}
*((int*)(widgRec+offset)) = mode;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Cmd_OptionGet --
*
*
* Results:
* Value of the option.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
char *
Cmd_OptionGet(ClientData clientData, Tk_Window unused,
char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
{
Cmd_Struct *p = (Cmd_Struct *)clientData;
int mode = *((int*)(widgRec+offset));
return Cmd_GetName(p,mode);
}
/*
* simple Cmd_Struct lookup functions
*/
char *
Cmd_GetName(const Cmd_Struct *cmds, int val)
{
for(;cmds->name && cmds->name[0];cmds++) {
if (cmds->value==val) return cmds->name;
}
return NULL;
}
int
Cmd_GetValue(const Cmd_Struct *cmds, const char *arg)
{
unsigned int len = strlen(arg);
for(;cmds->name && cmds->name[0];cmds++) {
if (!strncmp(cmds->name, arg, len)) return cmds->value;
}
return 0;
}
void
Cmd_GetError(Tcl_Interp *interp, const Cmd_Struct *cmds, const char *arg)
{
int i;
Tcl_AppendResult(interp, "bad option \"", arg, "\" must be ", (char *) 0);
for(i=0;cmds->name && cmds->name[0];cmds++,i++) {
Tcl_AppendResult(interp, (i?", ":""), cmds->name, (char *) 0);
}
}

View File

@@ -0,0 +1,955 @@
/*
* tkTableWin.c --
*
* This module implements embedded windows for table widgets.
* Much of this code is adapted from tkGrid.c and tkTextWind.c.
*
* Copyright (c) 1998-2002 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: tkTableWin.c,v 1.6 2004/06/11 00:24:44 hobbs Exp $
*/
#include "tkTable.h"
static int StickyParseProc _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, Tk_Window tkwin,
CONST84 char *value, char *widgRec, int offset));
static char * StickyPrintProc _ANSI_ARGS_((ClientData clientData,
Tk_Window tkwin, char *widgRec, int offset,
Tcl_FreeProc **freeProcPtr));
static void EmbWinLostSlaveProc _ANSI_ARGS_((ClientData clientData,
Tk_Window tkwin));
static void EmbWinRequestProc _ANSI_ARGS_((ClientData clientData,
Tk_Window tkwin));
static void EmbWinCleanup _ANSI_ARGS_((Table *tablePtr,
TableEmbWindow *ewPtr));
static int EmbWinConfigure _ANSI_ARGS_((Table *tablePtr,
TableEmbWindow *ewPtr,
int objc, Tcl_Obj *CONST objv[]));
static void EmbWinStructureProc _ANSI_ARGS_((ClientData clientData,
XEvent *eventPtr));
static void EmbWinUnmapNow _ANSI_ARGS_((Tk_Window ewTkwin,
Tk_Window tkwin));
static Tk_GeomMgr tableGeomType = {
"table", /* name */
EmbWinRequestProc, /* requestProc */
EmbWinLostSlaveProc, /* lostSlaveProc */
};
/* windows subcommands */
static CONST84 char *winCmdNames[] = {
"cget", "configure", "delete", "move", "names", (char *) NULL
};
enum winCommand {
WIN_CGET, WIN_CONFIGURE, WIN_DELETE, WIN_MOVE, WIN_NAMES
};
/* Flag values for "sticky"ness The 16 combinations subsume the packer's
* notion of anchor and fill.
*
* STICK_NORTH This window sticks to the top of its cavity.
* STICK_EAST This window sticks to the right edge of its cavity.
* STICK_SOUTH This window sticks to the bottom of its cavity.
* STICK_WEST This window sticks to the left edge of its cavity.
*/
#define STICK_NORTH (1<<0)
#define STICK_EAST (1<<1)
#define STICK_SOUTH (1<<2)
#define STICK_WEST (1<<3)
/*
* The default specification for configuring embedded windows
* Done like this to make the command line parsing easy
*/
static Tk_CustomOption stickyOption = { StickyParseProc, StickyPrintProc,
(ClientData) NULL };
static Tk_CustomOption tagBdOpt = { TableOptionBdSet, TableOptionBdGet,
(ClientData) BD_TABLE_WIN };
static Tk_ConfigSpec winConfigSpecs[] = {
{TK_CONFIG_BORDER, "-background", "background", "Background", NULL,
Tk_Offset(TableEmbWindow, bg),
TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK },
{TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL, 0, 0},
{TK_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0},
{TK_CONFIG_CUSTOM, "-borderwidth", "borderWidth", "BorderWidth", "",
0 /* no offset */,
TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK, &tagBdOpt },
{TK_CONFIG_STRING, "-create", (char *)NULL, (char *)NULL, (char *)NULL,
Tk_Offset(TableEmbWindow, create),
TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK },
{TK_CONFIG_PIXELS, "-padx", (char *)NULL, (char *)NULL, (char *)NULL,
Tk_Offset(TableEmbWindow, padX), TK_CONFIG_DONT_SET_DEFAULT },
{TK_CONFIG_PIXELS, "-pady", (char *)NULL, (char *)NULL, (char *)NULL,
Tk_Offset(TableEmbWindow, padY), TK_CONFIG_DONT_SET_DEFAULT },
{TK_CONFIG_CUSTOM, "-sticky", (char *)NULL, (char *)NULL, (char *)NULL,
Tk_Offset(TableEmbWindow, sticky), TK_CONFIG_DONT_SET_DEFAULT,
&stickyOption},
{TK_CONFIG_RELIEF, "-relief", "relief", "Relief", NULL,
Tk_Offset(TableEmbWindow, relief), 0 },
{TK_CONFIG_WINDOW, "-window", (char *)NULL, (char *)NULL, (char *)NULL,
Tk_Offset(TableEmbWindow, tkwin),
TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK },
{TK_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
(char *)NULL, 0, 0 }
};
/*
*----------------------------------------------------------------------
*
* StickyPrintProc --
* Converts the internal boolean combination of "sticky" bits onto
* a TCL string element containing zero or more of n, s, e, or w.
*
* Results:
* A string is placed into the "result" pointer.
*
* Side effects:
* none.
*
*----------------------------------------------------------------------
*/
static char *
StickyPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
ClientData clientData; /* Ignored. */
Tk_Window tkwin; /* Window for text widget. */
char *widgRec; /* Pointer to TkTextEmbWindow
* structure. */
int offset; /* Ignored. */
Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
* information about how to reclaim
* storage for return string. */
{
int flags = ((TableEmbWindow *) widgRec)->sticky;
int count = 0;
char *result = (char *) ckalloc(5*sizeof(char));
if (flags&STICK_NORTH) result[count++] = 'n';
if (flags&STICK_EAST) result[count++] = 'e';
if (flags&STICK_SOUTH) result[count++] = 's';
if (flags&STICK_WEST) result[count++] = 'w';
*freeProcPtr = TCL_DYNAMIC;
result[count] = '\0';
return result;
}
/*
*----------------------------------------------------------------------
*
* StringParseProc --
* Converts an ascii string representing a widgets stickyness
* into the boolean result.
*
* Results:
* The boolean combination of the "sticky" bits is retuned. If an
* error occurs, such as an invalid character, -1 is returned instead.
*
* Side effects:
* none
*
*----------------------------------------------------------------------
*/
static int
StickyParseProc(clientData, interp, tkwin, value, widgRec, offset)
ClientData clientData; /* Not used.*/
Tcl_Interp *interp; /* Used for reporting errors. */
Tk_Window tkwin; /* Window for text widget. */
CONST84 char *value; /* Value of option. */
char *widgRec; /* Pointer to TkTextEmbWindow
* structure. */
int offset; /* Offset into item (ignored). */
{
register TableEmbWindow *ewPtr = (TableEmbWindow *) widgRec;
int sticky = 0;
char c;
while ((c = *value++) != '\0') {
switch (c) {
case 'n': case 'N': sticky |= STICK_NORTH; break;
case 'e': case 'E': sticky |= STICK_EAST; break;
case 's': case 'S': sticky |= STICK_SOUTH; break;
case 'w': case 'W': sticky |= STICK_WEST; break;
case ' ': case ',': case '\t': case '\r': case '\n': break;
default:
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"bad sticky value \"", --value,
"\": must contain n, s, e or w",
(char *) NULL);
return TCL_ERROR;
}
}
ewPtr->sticky = sticky;
return TCL_OK;
}
/*
* ckallocs space for a new embedded window structure and clears the structure
* returns the pointer to the new structure
*/
static TableEmbWindow *
TableNewEmbWindow(Table *tablePtr)
{
TableEmbWindow *ewPtr = (TableEmbWindow *) ckalloc(sizeof(TableEmbWindow));
memset((VOID *) ewPtr, 0, sizeof(TableEmbWindow));
/*
* Set the values that aren't 0/NULL by default
*/
ewPtr->tablePtr = tablePtr;
ewPtr->relief = -1;
ewPtr->padX = -1;
ewPtr->padY = -1;
return ewPtr;
}
/*
*----------------------------------------------------------------------
*
* EmbWinCleanup --
* Releases resources used by an embedded window before it is freed up.
*
* Results:
* Window will no longer be valid.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static void
EmbWinCleanup(Table *tablePtr, TableEmbWindow *ewPtr)
{
Tk_FreeOptions(winConfigSpecs, (char *) ewPtr, tablePtr->display, 0);
}
/*
*--------------------------------------------------------------
*
* EmbWinDisplay --
*
* This procedure is invoked by TableDisplay for
* mapping windows into cells.
*
* Results:
* Displays or moves window on table screen.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void
EmbWinDisplay(Table *tablePtr, Drawable window, TableEmbWindow *ewPtr,
TableTag *tagPtr, int x, int y, int width, int height)
{
Tk_Window tkwin = tablePtr->tkwin;
Tk_Window ewTkwin = ewPtr->tkwin;
int diffx=0; /* Cavity width - slave width. */
int diffy=0; /* Cavity hight - slave height. */
int sticky = ewPtr->sticky;
int padx, pady;
if (ewPtr->bg) tagPtr->bg = ewPtr->bg;
if (ewPtr->relief != -1) tagPtr->relief = ewPtr->relief;
if (ewPtr->borders) {
tagPtr->borderStr = ewPtr->borderStr;
tagPtr->borders = ewPtr->borders;
tagPtr->bd[0] = ewPtr->bd[0];
tagPtr->bd[1] = ewPtr->bd[1];
tagPtr->bd[2] = ewPtr->bd[2];
tagPtr->bd[3] = ewPtr->bd[3];
}
padx = (ewPtr->padX < 0) ? tablePtr->padX : ewPtr->padX;
pady = (ewPtr->padY < 0) ? tablePtr->padY : ewPtr->padY;
x += padx;
width -= padx*2;
y += pady;
height -= pady*2;
if (width > Tk_ReqWidth(ewPtr->tkwin)) {
diffx = width - Tk_ReqWidth(ewPtr->tkwin);
width = Tk_ReqWidth(ewPtr->tkwin);
}
if (height > Tk_ReqHeight(ewPtr->tkwin)) {
diffy = height - Tk_ReqHeight(ewPtr->tkwin);
height = Tk_ReqHeight(ewPtr->tkwin);
}
if (sticky&STICK_EAST && sticky&STICK_WEST) {
width += diffx;
}
if (sticky&STICK_NORTH && sticky&STICK_SOUTH) {
height += diffy;
}
if (!(sticky&STICK_WEST)) {
x += (sticky&STICK_EAST) ? diffx : diffx/2;
}
if (!(sticky&STICK_NORTH)) {
y += (sticky&STICK_SOUTH) ? diffy : diffy/2;
}
/*
* If we fall below a specific minimum width/height requirement,
* we just unmap the window
*/
if (width < 2 || height < 2) {
if (ewPtr->displayed) {
EmbWinUnmapNow(ewTkwin, tkwin);
}
return;
}
if (tkwin == Tk_Parent(ewTkwin)) {
if ((x != Tk_X(ewTkwin)) || (y != Tk_Y(ewTkwin))
|| (width != Tk_Width(ewTkwin))
|| (height != Tk_Height(ewTkwin))) {
Tk_MoveResizeWindow(ewTkwin, x, y, width, height);
}
Tk_MapWindow(ewTkwin);
} else {
Tk_MaintainGeometry(ewTkwin, tkwin, x, y, width, height);
}
ewPtr->displayed = 1;
}
/*
*--------------------------------------------------------------
*
* EmbWinUnmapNow --
* Handles unmapping the window depending on parent.
* tkwin should be tablePtr->tkwin.
* ewTkwin should be ewPtr->tkwin.
*
* Results:
* Removes the window.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static void
EmbWinUnmapNow(Tk_Window ewTkwin, Tk_Window tkwin)
{
if (tkwin != Tk_Parent(ewTkwin)) {
Tk_UnmaintainGeometry(ewTkwin, tkwin);
}
Tk_UnmapWindow(ewTkwin);
}
/*
*--------------------------------------------------------------
*
* EmbWinUnmap --
* This procedure is invoked by TableAdjustParams for
* unmapping windows managed moved offscreen.
* rlo, ... should be in real coords.
*
* Results:
* None.
*
* Side effects:
* Unmaps embedded windows.
*
*--------------------------------------------------------------
*/
void
EmbWinUnmap(Table *tablePtr, int rlo, int rhi, int clo, int chi)
{
register TableEmbWindow *ewPtr;
Tcl_HashEntry *entryPtr;
int row, col, trow, tcol;
char buf[INDEX_BUFSIZE];
/*
* Transform numbers from real to user user coords
*/
rlo += tablePtr->rowOffset;
rhi += tablePtr->rowOffset;
clo += tablePtr->colOffset;
chi += tablePtr->colOffset;
for (row = rlo; row <= rhi; row++) {
for (col = clo; col <= chi; col++) {
TableTrueCell(tablePtr, row, col, &trow, &tcol);
TableMakeArrayIndex(trow, tcol, buf);
entryPtr = Tcl_FindHashEntry(tablePtr->winTable, buf);
if (entryPtr != NULL) {
ewPtr = (TableEmbWindow *) Tcl_GetHashValue(entryPtr);
if (ewPtr->displayed) {
ewPtr->displayed = 0;
if (ewPtr->tkwin != NULL && tablePtr->tkwin != NULL) {
EmbWinUnmapNow(ewPtr->tkwin, tablePtr->tkwin);
}
}
}
}
}
}
/*
*--------------------------------------------------------------
*
* EmbWinRequestProc --
* This procedure is invoked by Tk_GeometryRequest for
* windows managed by the Table.
*
* Results:
* None.
*
* Side effects:
* Arranges for tkwin, and all its managed siblings, to
* be re-arranged at the next idle point.
*
*--------------------------------------------------------------
*/
static void
EmbWinRequestProc(clientData, tkwin)
ClientData clientData; /* Table's information about
* window that got new preferred
* geometry. */
Tk_Window tkwin; /* Other Tk-related information
* about the window. */
{
register TableEmbWindow *ewPtr = (TableEmbWindow *) clientData;
/*
* Resize depends on the sticky
*/
if (ewPtr->displayed && ewPtr->hPtr != NULL) {
Table *tablePtr = ewPtr->tablePtr;
int row, col, x, y, width, height;
TableParseArrayIndex(&row, &col,
Tcl_GetHashKey(tablePtr->winTable, ewPtr->hPtr));
if (TableCellVCoords(tablePtr, row-tablePtr->rowOffset,
col-tablePtr->colOffset, &x, &y, &width, &height,
0)) {
TableInvalidate(tablePtr, x, y, width, height, 0);
}
}
}
static void
EmbWinRemove(TableEmbWindow *ewPtr)
{
Table *tablePtr = ewPtr->tablePtr;
if (ewPtr->tkwin != NULL) {
Tk_DeleteEventHandler(ewPtr->tkwin, StructureNotifyMask,
EmbWinStructureProc, (ClientData) ewPtr);
ewPtr->tkwin = NULL;
}
ewPtr->displayed = 0;
if (tablePtr->tkwin != NULL) {
int row, col, x, y, width, height;
TableParseArrayIndex(&row, &col,
Tcl_GetHashKey(tablePtr->winTable, ewPtr->hPtr));
/* this will cause windows removed from the table to actually
* cause the associated embdedded window hash data to be removed */
Tcl_DeleteHashEntry(ewPtr->hPtr);
if (TableCellVCoords(tablePtr, row-tablePtr->rowOffset,
col-tablePtr->colOffset, &x, &y, &width, &height,
0))
TableInvalidate(tablePtr, x, y, width, height, 1);
}
/* this will cause windows removed from the table to actually
* cause the associated embdedded window hash data to be removed */
EmbWinCleanup(tablePtr, ewPtr);
ckfree((char *) ewPtr);
}
/*
*--------------------------------------------------------------
*
* EmbWinLostSlaveProc --
* This procedure is invoked by Tk whenever some other geometry
* claims control over a slave that used to be managed by us.
*
* Results:
* None.
*
* Side effects:
* Forgets all table-related information about the slave.
*
*--------------------------------------------------------------
*/
static void
EmbWinLostSlaveProc(clientData, tkwin)
ClientData clientData; /* Table structure for slave window that
* was stolen away. */
Tk_Window tkwin; /* Tk's handle for the slave window. */
{
register TableEmbWindow *ewPtr = (TableEmbWindow *) clientData;
#if 0
Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr);
#endif
EmbWinUnmapNow(tkwin, ewPtr->tablePtr->tkwin);
EmbWinRemove(ewPtr);
}
/*
*--------------------------------------------------------------
*
* EmbWinStructureProc --
* This procedure is invoked by the Tk event loop whenever
* StructureNotify events occur for a window that's embedded
* in a table widget. This procedure's only purpose is to
* clean up when windows are deleted.
*
* Results:
* None.
*
* Side effects:
* The window is disassociated from the window segment, and
* the portion of the table is redisplayed.
*
*--------------------------------------------------------------
*/
static void
EmbWinStructureProc(clientData, eventPtr)
ClientData clientData; /* Pointer to record describing window item. */
XEvent *eventPtr; /* Describes what just happened. */
{
register TableEmbWindow *ewPtr = (TableEmbWindow *) clientData;
if (eventPtr->type != DestroyNotify) {
return;
}
EmbWinRemove(ewPtr);
}
/*
*--------------------------------------------------------------
*
* EmbWinDelete --
* This procedure is invoked by ... whenever
* an embedded window is being deleted.
*
* Results:
* None.
*
* Side effects:
* The embedded window is deleted, if it exists, and any resources
* associated with it are released.
*
*--------------------------------------------------------------
*/
void
EmbWinDelete(register Table *tablePtr, TableEmbWindow *ewPtr)
{
Tcl_HashEntry *entryPtr = ewPtr->hPtr;
if (ewPtr->tkwin != NULL) {
Tk_Window tkwin = ewPtr->tkwin;
/*
* Delete the event handler for the window before destroying
* the window, so that EmbWinStructureProc doesn't get called
* (we'll already do everything that it would have done, and
* it will just get confused).
*/
ewPtr->tkwin = NULL;
Tk_DeleteEventHandler(tkwin, StructureNotifyMask,
EmbWinStructureProc, (ClientData) ewPtr);
Tk_DestroyWindow(tkwin);
}
if (tablePtr->tkwin != NULL && entryPtr != NULL) {
int row, col, x, y, width, height;
TableParseArrayIndex(&row, &col,
Tcl_GetHashKey(tablePtr->winTable, entryPtr));
Tcl_DeleteHashEntry(entryPtr);
if (TableCellVCoords(tablePtr, row-tablePtr->rowOffset,
col-tablePtr->colOffset,
&x, &y, &width, &height, 0))
TableInvalidate(tablePtr, x, y, width, height, 0);
}
#if 0
Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr);
#endif
EmbWinCleanup(tablePtr, ewPtr);
ckfree((char *) ewPtr);
}
/*
*--------------------------------------------------------------
*
* EmbWinConfigure --
* This procedure is called to handle configuration options
* for an embedded window.
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
* returned, then the interp's result contains an error message..
*
* Side effects:
* Configuration information for the embedded window changes,
* such as alignment, stretching, or name of the embedded
* window.
*
*--------------------------------------------------------------
*/
static int
EmbWinConfigure(tablePtr, ewPtr, objc, objv)
Table *tablePtr; /* Information about table widget that
* contains embedded window. */
TableEmbWindow *ewPtr; /* Embedded window to be configured. */
int objc; /* Number of objs in objv. */
Tcl_Obj *CONST objv[]; /* Obj type options. */
{
Tcl_Interp *interp = tablePtr->interp;
Tk_Window oldWindow;
int i, result;
CONST84 char **argv;
oldWindow = ewPtr->tkwin;
/* Stringify */
argv = (CONST84 char **) ckalloc((objc + 1) * sizeof(char *));
for (i = 0; i < objc; i++)
argv[i] = Tcl_GetString(objv[i]);
argv[i] = NULL;
result = Tk_ConfigureWidget(interp, tablePtr->tkwin,
winConfigSpecs, objc, argv, (char *) ewPtr,
TK_CONFIG_ARGV_ONLY);
ckfree((char *) argv);
if (result != TCL_OK) {
return TCL_ERROR;
}
if (oldWindow != ewPtr->tkwin) {
ewPtr->displayed = 0;
if (oldWindow != NULL) {
Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
EmbWinStructureProc, (ClientData) ewPtr);
Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,
(ClientData) NULL);
EmbWinUnmapNow(oldWindow, tablePtr->tkwin);
}
if (ewPtr->tkwin != NULL) {
Tk_Window ancestor, parent;
/*
* Make sure that the table is either the parent of the
* embedded window or a descendant of that parent. Also,
* don't allow a top-level window to be managed inside
* a table.
*/
parent = Tk_Parent(ewPtr->tkwin);
for (ancestor = tablePtr->tkwin; ;
ancestor = Tk_Parent(ancestor)) {
if (ancestor == parent) {
break;
}
if (Tk_IsTopLevel(ancestor)) {
badMaster:
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"can't embed ",
Tk_PathName(ewPtr->tkwin), " in ",
Tk_PathName(tablePtr->tkwin),
(char *)NULL);
ewPtr->tkwin = NULL;
return TCL_ERROR;
}
}
if (Tk_IsTopLevel(ewPtr->tkwin) ||
(ewPtr->tkwin == tablePtr->tkwin)) {
goto badMaster;
}
/*
* Take over geometry management for the window, plus create
* an event handler to find out when it is deleted.
*/
Tk_ManageGeometry(ewPtr->tkwin, &tableGeomType, (ClientData)ewPtr);
Tk_CreateEventHandler(ewPtr->tkwin, StructureNotifyMask,
EmbWinStructureProc, (ClientData) ewPtr);
}
}
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
* Table_WinMove --
* This procedure is invoked by ... whenever
* an embedded window is being moved.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* If an embedded window is in the dest cell, it is deleted.
*
*--------------------------------------------------------------
*/
int
Table_WinMove(register Table *tablePtr, char *CONST srcPtr,
char *CONST destPtr, int flags)
{
int srow, scol, row, col, new;
Tcl_HashEntry *entryPtr;
TableEmbWindow *ewPtr;
if (TableGetIndex(tablePtr, srcPtr, &srow, &scol) != TCL_OK ||
TableGetIndex(tablePtr, destPtr, &row, &col) != TCL_OK) {
return TCL_ERROR;
}
entryPtr = Tcl_FindHashEntry(tablePtr->winTable, srcPtr);
if (entryPtr == NULL) {
if (flags & INV_NO_ERR_MSG) {
return TCL_OK;
} else {
Tcl_AppendStringsToObj(Tcl_GetObjResult(tablePtr->interp),
"no window at index \"", srcPtr, "\"", (char *) NULL);
return TCL_ERROR;
}
}
/* avoid moving it to the same location */
if (srow == row && scol == col) {
return TCL_OK;
}
/* get the window pointer */
ewPtr = (TableEmbWindow *) Tcl_GetHashValue(entryPtr);
/* and free the old hash table entry */
Tcl_DeleteHashEntry(entryPtr);
entryPtr = Tcl_CreateHashEntry(tablePtr->winTable, destPtr, &new);
if (!new) {
/* window already there - just delete it */
TableEmbWindow *ewPtrDel;
ewPtrDel = (TableEmbWindow *) Tcl_GetHashValue(entryPtr);
/* This prevents the deletion of it's own entry, since we need it */
ewPtrDel->hPtr = NULL;
EmbWinDelete(tablePtr, ewPtrDel);
}
/* set the new entry's value */
Tcl_SetHashValue(entryPtr, (ClientData) ewPtr);
ewPtr->hPtr = entryPtr;
if (flags & INV_FORCE) {
int x, y, w, h;
/* Invalidate old cell */
if (TableCellVCoords(tablePtr, srow-tablePtr->rowOffset,
scol-tablePtr->colOffset, &x, &y, &w, &h, 0)) {
TableInvalidate(tablePtr, x, y, w, h, 0);
}
/* Invalidate new cell */
if (TableCellVCoords(tablePtr, row-tablePtr->rowOffset,
col-tablePtr->colOffset, &x, &y, &w, &h, 0)) {
TableInvalidate(tablePtr, x, y, w, h, 0);
}
}
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
* Table_WinDelete --
* This procedure is invoked by ... whenever
* an embedded window is being delete.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* Window info will be deleted.
*
*--------------------------------------------------------------
*/
int
Table_WinDelete(register Table *tablePtr, char *CONST idxPtr)
{
Tcl_HashEntry *entryPtr;
entryPtr = Tcl_FindHashEntry(tablePtr->winTable, idxPtr);
if (entryPtr != NULL) {
/* get the window pointer & clean up data associated with it */
EmbWinDelete(tablePtr, (TableEmbWindow *) Tcl_GetHashValue(entryPtr));
}
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
* Table_WindowCmd --
* This procedure is invoked to process the window method
* that corresponds to a 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_WindowCmd(ClientData clientData, register Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[])
{
register Table *tablePtr = (Table *)clientData;
int result = TCL_OK, cmdIndex, row, col, x, y, width, height, i, new;
TableEmbWindow *ewPtr;
Tcl_HashEntry *entryPtr;
Tcl_HashSearch search;
char buf[INDEX_BUFSIZE], *keybuf, *winname;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?");
return TCL_ERROR;
}
/* parse the next argument */
if (Tcl_GetIndexFromObj(interp, objv[2], winCmdNames,
"option", 0, &cmdIndex) != TCL_OK) {
return TCL_ERROR;
}
switch ((enum winCommand) cmdIndex) {
case WIN_CGET:
if (objc != 5) {
Tcl_WrongNumArgs(interp, 3, objv, "index option");
return TCL_ERROR;
}
entryPtr = Tcl_FindHashEntry(tablePtr->winTable,
Tcl_GetString(objv[3]));
if (entryPtr == NULL) {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"no window at index \"",
Tcl_GetString(objv[3]), "\"", (char *)NULL);
return TCL_ERROR;
} else {
ewPtr = (TableEmbWindow *) Tcl_GetHashValue(entryPtr);
result = Tk_ConfigureValue(interp, tablePtr->tkwin, winConfigSpecs,
(char *) ewPtr,
Tcl_GetString(objv[4]), 0);
}
return result; /* CGET */
case WIN_CONFIGURE:
if (objc < 4) {
Tcl_WrongNumArgs(interp, 3, objv, "index ?arg arg ...?");
return TCL_ERROR;
}
if (TableGetIndexObj(tablePtr, objv[3], &row, &col) == TCL_ERROR) {
return TCL_ERROR;
}
TableMakeArrayIndex(row, col, buf);
entryPtr = Tcl_CreateHashEntry(tablePtr->winTable, buf, &new);
if (new) {
/* create the structure */
ewPtr = TableNewEmbWindow(tablePtr);
/* insert it into the table */
Tcl_SetHashValue(entryPtr, (ClientData) ewPtr);
ewPtr->hPtr = entryPtr;
/* configure the window structure */
result = EmbWinConfigure(tablePtr, ewPtr, objc-4, objv+4);
if (result == TCL_ERROR) {
/* release the structure */
EmbWinCleanup(tablePtr, ewPtr);
ckfree((char *) ewPtr);
/* and free the hash table entry */
Tcl_DeleteHashEntry(entryPtr);
}
} else {
/* window exists, do a reconfig if we have enough args */
/* get the window pointer from the table */
ewPtr = (TableEmbWindow *) Tcl_GetHashValue(entryPtr);
/* 5 args means that there are values to replace */
if (objc > 5) {
/* and do a reconfigure */
result = EmbWinConfigure(tablePtr, ewPtr, objc-4, objv+4);
}
}
if (result == TCL_ERROR) {
return TCL_ERROR;
}
/*
* If there were less than 6 args, we need
* to do a printout of the config, even for new windows
*/
if (objc < 6) {
result = Tk_ConfigureInfo(interp, tablePtr->tkwin, winConfigSpecs,
(char *) ewPtr, (objc == 5)?
Tcl_GetString(objv[4]) : NULL, 0);
} else {
/* Otherwise we reconfigured so invalidate
* the table for a redraw */
if (TableCellVCoords(tablePtr, row-tablePtr->rowOffset,
col-tablePtr->colOffset,
&x, &y, &width, &height, 0)) {
TableInvalidate(tablePtr, x, y, width, height, 1);
}
}
return result; /* CONFIGURE */
case WIN_DELETE:
if (objc < 4) {
Tcl_WrongNumArgs(interp, 3, objv, "index ?index ...?");
return TCL_ERROR;
}
for (i = 3; i < objc; i++) {
Table_WinDelete(tablePtr, Tcl_GetString(objv[i]));
}
break;
case WIN_MOVE:
if (objc != 5) {
Tcl_WrongNumArgs(interp, 3, objv, "srcIndex destIndex");
return TCL_ERROR;
}
result = Table_WinMove(tablePtr, Tcl_GetString(objv[3]),
Tcl_GetString(objv[4]), INV_FORCE);
break;
case WIN_NAMES: {
Tcl_Obj *objPtr = Tcl_NewObj();
/* just print out the window names */
if (objc < 3 || objc > 4) {
Tcl_WrongNumArgs(interp, 3, objv, "?pattern?");
return TCL_ERROR;
}
winname = (objc == 4) ? Tcl_GetString(objv[3]) : NULL;
entryPtr = Tcl_FirstHashEntry(tablePtr->winTable, &search);
while (entryPtr != NULL) {
keybuf = Tcl_GetHashKey(tablePtr->winTable, entryPtr);
if (objc == 3 || Tcl_StringMatch(keybuf, winname)) {
Tcl_ListObjAppendElement(NULL, objPtr,
Tcl_NewStringObj(keybuf, -1));
}
entryPtr = Tcl_NextHashEntry(&search);
}
Tcl_SetObjResult(interp, TableCellSortObj(interp, objPtr));
break;
}
}
return TCL_OK;
}

View File

@@ -0,0 +1,8 @@
#if 0
TBL_MAJOR_VERSION = 2
TBL_MINOR_VERSION = 10
PACKAGE_VERSION = $(TBL_MAJOR_VERSION).$(TBL_MINOR_VERSION)
#endif
#define TBL_MAJOR_VERSION 2
#define TBL_MINOR_VERSION 10
#define PACKAGE_VERSION "2.10"