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