/*
 * bltHiertable.h --
 *
 *	This module implements an hierarchy widget for the BLT toolkit.
 *
 * Copyright 1998-1999 Lucent Technologies, Inc.
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby
 * granted, provided that the above copyright notice appear in all
 * copies and that both that the copyright notice and warranty
 * disclaimer appear in supporting documentation, and that the names
 * of Lucent Technologies or any of their entities not be used in
 * advertising or publicity pertaining to distribution of the software
 * without specific, written prior permission.
 *
 * Lucent Technologies disclaims all warranties with regard to this
 * software, including all implied warranties of merchantability and
 * fitness.  In no event shall Lucent Technologies be liable for any
 * special, indirect or consequential damages or any damages
 * whatsoever resulting from loss of use, data or profits, whether in
 * an action of contract, negligence or other tortuous action, arising
 * out of or in connection with the use or performance of this
 * software.
 *
 *	The "hiertable" widget was created by George A. Howlett.
 */

/*
 * TODO:
 *
 * BUGS:
 *   1.  "open" operation should change scroll offset so that as many
 *	 new entries (up to half a screen) can be seen.
 *   2.  "open" needs to adjust the scrolloffset so that the same entry
 *	 is seen at the same place.
 */

#ifndef BLT_HIERTABLE_H
#define BLT_HIERTABLE_H

#include "bltImage.h"
#include "bltChain.h"
#include "bltTree.h"
#include "bltBind.h"


#if HAVE_UTF
#else
#define Tcl_NumUtfChars(s,n)	(((n) == -1) ? strlen((s)) : (n))
#define Tcl_UtfAtIndex(s,i)	((s) + (i))
#endif

#define SORT_MARKER_OFFSET	3
#define SORT_MARKER_WIDTH	((2 * SORT_MARKER_OFFSET) + 1)
#define SEPARATOR_NONE		((char *)-1)
#define SEPARATOR_LIST		((char *)NULL)
#define END			(-1)

#define SEARCH_Y		1

typedef char *UID;

/*
 * The macro below is used to modify a "char" value (e.g. by casting
 * it to an unsigned character) so that it can be used safely with
 * macros such as isspace.
 */
#define UCHAR(c) ((unsigned char) (c))

#define TOGGLE(x, mask)		\
	(((x) & (mask)) ? ((x) & ~(mask)) : ((x) | (mask)))


#define SCREENX(h, wx)		((wx) - (h)->xOffset + (h)->inset)
#define SCREENY(h, wy)		((wy) - (h)->yOffset + (h)->inset + (h)->titleHeight)

#define WORLDX(h, sx)		((sx) - (h)->inset + (h)->xOffset)
#define WORLDY(h, sy)		((sy) - ((h)->inset + (h)->titleHeight) + (h)->yOffset)

#define VPORTWIDTH(h)		(Tk_Width((h)->tkwin) - 2 * (h)->inset)
#define VPORTHEIGHT(h) \
	(Tk_Height((h)->tkwin) - (h)->titleHeight - 2 * (h)->inset)

#define ICONWIDTH(d)		(htabPtr->levelInfo[(d)].iconWidth)
#define LEVELX(d)		(htabPtr->levelInfo[(d)].x)

#define DEPTH(h, n)	\
	(((h)->flatView) ? 0 : Blt_TreeNodeDepth((h)->tree, (n)))

#define SELECT_MODE_SINGLE	(1<<0)
#define SELECT_MODE_MULTIPLE	(1<<1)

/*
 * ----------------------------------------------------------------------------
 *
 *  Internal hierarchy widget flags:
 *
 *	HT_LAYOUT	The layout of the hierarchy needs to be recomputed.
 *
 *	HT_REDRAW	A redraw request is pending for the widget.
 *
 *	HT_XSCROLL	X-scroll request is pending.
 *	HT_YSCROLL	Y-scroll request is pending.
 *	HT_SCROLL	Both X-scroll and  Y-scroll requests are pending.
 *
 *	HT_FOCUS	The widget is receiving keyboard events.
 *			Draw the focus highlight border around the widget.
 *
 *	HT_DIRTY	The hierarchy has changed. It may invalidate
 *			the locations and pointers to entries.  The widget 
 *			will need to recompute its layout.
 *
 *	HT_BORDERS      The borders of the widget (highlight ring and
 *			3-D border) need to be redrawn.
 *
 *
 *  Selection related flags:
 *
 *	SELECTION_EXPORT	Export the selection to X.
 *
 *	SELECTION_PENDING	A selection command idle task is pending.
 *
 *	SELECTION_CLEAR		Entry's selection flag is to be cleared.
 *
 *	SELECTION_SET		Entry's selection flag is to be set.
 *
 *	SELECTION_TOGGLE	Entry's selection flag is to be toggled.
 *
 *	SELECTION_MASK		Mask of selection set/clear/toggle flags.
 *
 * ---------------------------------------------------------------------------
 */

#define HT_LAYOUT	(1<<0)
#define HT_REDRAW	(1<<1)
#define HT_XSCROLL	(1<<2)
#define HT_YSCROLL	(1<<3)
#define HT_SCROLL	(HT_XSCROLL | HT_YSCROLL)
#define HT_FOCUS	(1<<4)
#define HT_DIRTY	(1<<5)
#define HT_UPDATE	(1<<6)
#define HT_BORDERS	(1<<7)
#define HT_VIEWPORT	(1<<8)
#define HT_DESTROYED	(1<<9)
#define HT_RULE_ACTIVE	(1<<15)
#define HT_RULE_NEEDED	(1<<16)

#define ITEM_COLUMN		1
#define ITEM_RULE		2

#define SELECTION_PENDING	(1<<15)
#define SELECTION_EXPORT	(1<<16)
#define SELECTION_CLEAR		(1<<17)
#define SELECTION_SET		(1<<18)
#define SELECTION_TOGGLE	(SELECTION_SET | SELECTION_CLEAR)
#define SELECTION_MASK		(SELECTION_SET | SELECTION_CLEAR)


/*
 * -------------------------------------------------------------------------
 *
 *  Internal entry flags:
 *
 *	ENTRY_BUTTON		Indicates that a button needs to be
 *				drawn for this entry.
 *
 *	ENTRY_CLOSED		Indicates that the entry is closed and
 *				its subentries are not displayed.
 *
 *	ENTRY_HIDDEN		Indicates that the entry is hidden (i.e.
 *				can not be viewed by opening or scrolling).
 *
 *	BUTTON_AUTO
 *	BUTTON_SHOW
 *	BUTTON_MASK
 *
 * -------------------------------------------------------------------------
 */
#define ENTRY_CLOSED	(1<<0)
#define ENTRY_HIDDEN	(1<<1)
#define ENTRY_MASK	(ENTRY_CLOSED | ENTRY_HIDDEN)

#define ENTRY_BUTTON	(1<<3)
#define ENTRY_ICON	(1<<4)
#define ENTRY_DIRTY	(1<<5)
#define ENTRY_REDRAW	(1<<6)

#define BUTTON_AUTO	(1<<8)
#define BUTTON_SHOW	(1<<9)
#define BUTTON_MASK	(BUTTON_AUTO | BUTTON_SHOW)

#define COLUMN_RULE_PICKED (1<<1)
#define COLUMN_DIRTY	(1<<2)

typedef struct HiertableRec Hiertable;
typedef struct EntryRec Entry;

typedef int (CompareProc) _ANSI_ARGS_((Tcl_Interp *interp, char *name,
	char *pattern));

typedef Entry * (IterProc) _ANSI_ARGS_((Hiertable *htabPtr, Entry *entryPtr, 
	unsigned int mask));

/*
 * HashedImage --
 *
 *	Since instances of the same Tk image can be displayed in
 *	different windows with possibly different color palettes, Tk
 *	internally stores each instance in a linked list.  But if
 *	the instances are used in the same widget and therefore use
 *	the same color palette, this adds a lot of overhead,
 *	especially when deleting instances from the linked list.
 *
 *	For the hiertable widget, we never need more than a single
 *	instance of an image, regardless of how many times it's used.
 *	So one solution is to cache the image, maintaining a reference
 *	count for each image used in the widget.  It's likely that the
 *	hierarchy widget will use many instances of the same image
 *	(for example the open/close icons).
 */

typedef struct HashedImageRec {
    Tk_Image tkImage;		/* The Tk image being cached. */

    int refCount;		/* Reference count for this image. */

    short int width, height;	/* Dimensions of the cached image. */

    Tcl_HashEntry *hashPtr;	/* Hash table pointer to the image. */

} *HashedImage;

#define ImageHeight(hImage)		((hImage)->height)
#define ImageWidth(hImage)		((hImage)->width)
#define ImageData(hImage)		((hImage)->tkImage)

typedef struct EditorRec Editor;
typedef struct ColumnRec Column;

typedef struct {
    int type;			/* HT_RULE */
    int lineWidth;
    Dashes dashes;
    GC gc;
    Column *columnPtr;
} Rule;

/*
 * Column --
 *
 *	A column is the open/close indicator at the far left of the
 *	entry.  It is displayed as a plus or minus in a solid
 *	colored box with optionally an border. It has both "active"
 *	and "normal" colors.
 */
struct ColumnRec {
    int type;			/* HT_COLUMN */
    Blt_Uid keyUid;		/* Data field identifier for current tree. */
    int position;		/* Position of column in list.  Used
				 * to indicate the first and last
				 * columns. */
    UID tags;			/* List of binding tags for this
				 * entry.  UID, not a string, because
				 * in the typical case most columns
				 * will have the same bindtags. */

    /* Title-related information */
    char *text;			/* Text displayed in column heading as its
				 * title. By default, this is the same as 
				 * the data field name. */
    Tk_Font titleFont;		/* Font to draw title in. */
    Shadow titleShadow;

    XColor *titleFgColor;	/* Foreground color of text displayed in 
				 * the heading */
    Tk_3DBorder titleBorder;	/* Background color of the column's heading. */

    GC titleGC;

    XColor *activeTitleFgColor;	/* Foreground color of text heading when 
				 * the column is activated.*/
    Tk_3DBorder activeTitleBorder;	

    GC activeTitleGC;

    TextLayout *layoutPtr;
    short int titleWidth, titleHeight;

    HashedImage hImage;		/* Image displayed in column heading */
    char *command;		/* Tcl command to be executed by the 
				 * column's "invoke" operation. */

    char *sortCmd;		/* Command to sort column by */

    /* General information */
    int hidden;			/* Indicates if the column is displayed */
    int state;			/* Indicates if column title can invoked. */
    int editable;		/* Indicates if column can be edited. */

    int max;			/* Maximum space allowed for column. */
    int reqMin, reqMax;		/* Minimum width of column.  Does not include
				 * any padding or the borderwidth of column.  
				 * Overrides the computed width. */

    int reqWidth;		/* Requested width of column. Does not include 
				 * any padding or the borderwidth of column. 
				 * Overrides computed width. */

    int maxWidth;		/* Width of the widest entry in the column. */

    int worldX;			/* Starting x-coordinate of column */

    double weight;		/* Growth factor for column.  Zero indicates
				 * that the column can not be resized. */

    int width;			/* Computed width of column. */

    Tk_3DBorder border;		/* Background color of column. */
    int borderWidth;		/* Specifies the border width of the column. */
    int relief;			/* Relief of the column. */
    Pad pad;			/* Specifies horizontal padding on either
				 * side of the column. */

    Tk_Font font;		/* Font used for entries in the column. */
    XColor *fgColor;		/* Foreground color used for entries. */
    GC gc;
    Tk_Justify justify;		/* Specifies how the text or image is
				 * justified within the column. */

    Blt_ChainLink *linkPtr;
    
    Rule rule;
    int flags;
};


typedef struct {
    Column *columnPtr;		/* Column in which the field is located. */
    short int width, height;	/* Dimensions of field. */
    HashedImage hImage;		/* If non-NULL, is a Tk_Image to be drawn
				 * in the column entry. */
    TextLayout *layoutPtr;
} Field;
    
/*
 * Entry --
 *
 *	Contains data-specific information how to represent the data
 *	of a node of the hierarchy.
 *
 */
struct EntryRec {
    Blt_TreeNode node;		/* Node containing entry */
    int worldX, worldY;		/* X-Y position in world coordinates
				 * where the entry is positioned. */

    short int width, height;	/* Dimensions of the entry. This includes
				 * the size of its columns. */

    int lineHeight;		/* Length of the vertical line segment. */

    unsigned int flags;		/* Flags for this entry. For the
				 * definitions of the various bit
				 * fields see below. */

    UID tags;			/* List of binding tags for this
				 * entry.  UID, not a string, because
				 * in the typical case most entries
				 * will have the same bindtags. */
    Hiertable *htabPtr;

    UID openCmd, closeCmd;	/* Tcl commands to invoke when entries
				 * are opened or closed. They override
				 * those specified globally. */
    /*
     * Button information:
     */
    short int buttonX, buttonY;	/* X-Y coordinate offsets from to
				 * upper left corner of the entry to
				 * the upper-left corner of the
				 * button.  Used to pick the
				 * button quickly */

    HashedImage *icons;		/* Tk images displayed for the entry.
				 * The first image is the icon
				 * displayed to the left of the
				 * entry's label. The second is icon
				 * displayed when entry is "open". */

    HashedImage *activeIcons;	/* Tk images displayed for the entry.
				 * The first image is the icon
				 * displayed to the left of the
				 * entry's label. The second is icon
				 * displayed when entry is "open". */

    short int iconWidth, iconHeight;
				/* Maximum dimensions for icons and
				 * buttons for this entry. This is
				 * used to align the button, icon, and
				 * text. */
    /*
     * Label information:
     */
    TextLayout *layoutPtr;
    short int labelWidth, labelHeight;
    UID labelUid;		/* Text displayed right of the icon. */
    Tk_Font font;		/* Font of label. Overrides global font
				 * specification. */
    char *fullName;
    int flatIndex;
    ClientData data;		/* pre-fetched data for sorting */

    XColor *color;		/* Color of label. Overrides default text color
				 * specification. */
    GC gc;

    Shadow shadow;

    Blt_Chain *chainPtr;	/* List of column-related information 
				 * for each data field in the node. 
				 * Non-NULL only there are field entries. */

};

/*
 * Button --
 *
 *	A button is the open/close indicator at the far left of the
 *	entry.  It is displayed as a plus or minus in a solid
 *	colored box with optionally an border. It has both "active"
 *	and "normal" colors.
 */
typedef struct {
    XColor *fgColor;		/* Foreground color. */
    Tk_3DBorder border;		/* Background color. */
    XColor *activeFgColor;	/* Active foreground color. */
    Tk_3DBorder activeBorder;	/* Active background color. */
    GC lineGC, normalGC, activeGC;
    int reqSize;
    int borderWidth;
    int openRelief, closeRelief;
    int width, height;
    HashedImage *hImages;
} Button;

/*
 * LevelInfo --
 *
 */
typedef struct {
    int x;
    int iconWidth;
    int labelWidth;
} LevelInfo;

/*
 * SortInfo --
 *
 */
typedef struct {
    int manual;			/* Indicates if manual or automatic sorting
				 * is performed. */

    char *field;		/* Field to be sorted. */

    int mode;			/* Type of sorting to be performed. See
				 * below for valid values. */

    char *command;		/* Sort command. */

    int decreasing;		/* Indicates entries should be sorted
				 * in decreasing order. */

    Column *columnPtr;		/* Column to be for sorting criteria. */

} SortInfo;

/*
 * Hiertable --
 *
 *	A Hiertable is a widget that displays an hierarchical table 
 *	of one or more entries.
 *
 *	Entries are positioned in "world" coordinates, referring to
 *	the virtual hiertable.  Coordinate 0,0 is the upper-left
 *	corner of the root entry and the bottom is the end of the 
 *	last entry.  The widget's Tk window acts as view port into
 *	this virtual space. The hiertable's xOffset and yOffset fields
 *	specify the location of the view port in the virtual world.
 *	Scrolling the viewport is therefore simply changing the
 *	xOffset and/or yOffset fields and redrawing.
 *
 *	Note that world coordinates are integers, not signed short
 *	integers like X11 screen coordinates.  It's very easy to
 *	create a hierarchy taller than 0x7FFF pixels.
 */

struct HiertableRec {
    Tcl_Interp *interp;
    Tcl_Command cmdToken;	/* Token for tree's Tcl command. */
    Blt_Tree tree;		/* Token holding internal tree. */

    Tcl_HashEntry *hashPtr;

    Tcl_HashTable tagsTable;
    Blt_Chain *tagChainPtr;	/* Chain of tags.  Same as hash table
				 * above but maintains the tag order
				 * and can delete entries in tag walks. */

    /* Hiertable specific fields. */ 

    Tk_Window tkwin;		/* Window that embodies the widget.
                                 * NULL means that the window has been
                                 * destroyed but the data structures
                                 * haven't yet been cleaned up.*/

    Display *display;		/* Display containing widget; needed,
                                 * among other things, to release
                                 * resources after tkwin has already
                                 * gone away. */

    Blt_Chain *chainPtr;	/* Indicates the order of the columns
				 * displayed. */
    Tcl_HashTable columnTable;

    Tk_ConfigSpec *buttonSpecs;
    Tk_ConfigSpec *entrySpecs;
    Tk_ConfigSpec *widgetSpecs;

    int flags;			/* For bitfield definitions, see below */

    int allowDups;		/* If non-zero, allow duplicate entries. */

    int autoFill;		/* If non-zero, automatically create entries 
				 * for missing path components. */

    int exportSelection;	/* Export the selection to X. */

    int hideRoot;		/* If non-zero, don't display the root entry. */

    int inset;			/* Total width of all borders,
				 * including traversal highlight and
				 * 3-D border.  Indicates how much
				 * interior stuff must be offset from
				 * outside edges to leave room for
				 * borders. */

    Tk_3DBorder border;		/* 3D border surrounding the window
				 * (viewport). */
    int borderWidth;		/* Width of 3D border. */
    int relief;			/* 3D border relief. */


    int highlightWidth;		/* Width in pixels of highlight to draw
				 * around widget when it has the focus.
				 * <= 0 means don't draw a highlight. */
    XColor *highlightBgColor;	/* Color for drawing traversal highlight
				 * area when highlight is off. */
    XColor *highlightColor;	/* Color for drawing traversal highlight. */

    char *pathSep;		/* Pathname separators */
    char *trimLeft;		/* Leading characters to trim from
				 * pathnames */

    /*
     * Entries are connected by horizontal and vertical lines. They
     * may be drawn dashed or solid.
     */
    int lineWidth;		/* Width of lines connecting entries */
    int dashes;			/* Dash on-off value. */
    XColor *lineColor;		/* Color of connecting lines. */

    /*
     * Button Information:
     *
     * The button is the open/close indicator at the far left of the
     * entry.  It is usually displayed as a plus or minus in a solid
     * colored box with optionally an border. It has both "active"
     * and "normal" colors.
     */
    Button button;

    /*
     * Selection Information:
     *
     * The selection is the rectangle that contains a selected entry.
     * There may be many selected entries.  It is displayed as a
     * solid colored box with optionally a 3D border.
     */
    Tk_3DBorder selBorder;	/* Background color of an highlighted entry.*/

    int selRelief;		/* Relief of selected items. Currently
				 * is always raised. */

    int selBorderWidth;		/* Border width of a selected entry.*/

    XColor *selFgColor;		/* Text color of a selected entry. */

    Entry *selAnchorPtr;	/* Fixed end of selection (i.e. entry
				 * at which selection was started.) */
    Entry *selMarkPtr;
    
    int sortSelection;		/* Indicates if the entries in the
				 * selection should be sorted or
				 * displayed in the order they were
				 * selected. */

    int	selectMode;		/* Selection style: "single" or "multiple".  */

    char *selectCmd;		/* Tcl script that's invoked whenever
				 * the selection changes. */
    Tcl_HashTable selectTable;
    Blt_Chain *selectPtr;

    int leader;			/* Number of pixels padding between entries */

    Tk_Cursor cursor;		/* X Cursor */
    Tk_Cursor resizeCursor;	/* Resize Cursor */
    Tk_Cursor defResizeCursor;	/* Default resize cursor. */

    int reqWidth, reqHeight;	/* Requested dimensions of the widget's
				 * window. */

    GC lineGC;			/* GC for drawing dotted line between
				 * entries. */

    XColor *activeFgColor;
    Tk_3DBorder activeBorder;

    XColor *focusColor;
    Dashes focusDashes;		/* Dash on-off value. */
    GC focusGC;			/* Graphics context for the active label */

    Editor *editPtr;

    Entry *activePtr;		/* Last active entry. */ 
    Entry *focusPtr;		/* Entry that currently has focus. */
    Entry *activeButtonPtr;	/* Pointer to last active button */

    /* Number of pixels to move for 1 scroll unit. */
    int xScrollUnits, yScrollUnits;

    /* Command strings to control horizontal and vertical scrollbars. */
    char *xScrollCmdPrefix, *yScrollCmdPrefix;

    int scrollMode;		/* Selects mode of scrolling: either
				 * SCROLL_MODE_HIERBOX, SCROLL_MODE_LISTBOX, 
				 * or SCROLL_MODE_CANVAS. */
    /*
     * Total size of all "open" entries. This represents the range of
     * world coordinates.
     */
    int worldWidth, worldHeight;
    int xOffset, yOffset;	/* Translation between view port and
				 * world origin. */

    short int minHeight;	/* Minimum entry height. Used to
				 * to compute what the y-scroll unit
				 * should be. */
    short int titleHeight;	/* Height of column titles. */
    LevelInfo *levelInfo;

    /*
     * Scanning information:
     */
    int scanAnchorX, scanAnchorY;
    /* Scan anchor in screen coordinates. */
    int scanX, scanY;		/* X-Y world coordinate where the scan
				 * started. */

    Tcl_HashTable imageTable;	/* Table of Tk images */
    Tcl_HashTable uidTable;	/* Table of strings. */


    Entry *rootPtr;		/* Root entry of tree. */

    Entry **visibleArr;		/* Array of visible entries */
    int nVisible;		/* Number of entries in the above array */
    int nEntries;		/* Number of entries in tree. */
    int nextSerial;

    int buttonFlags;		/* Global button indicator for all entries.
				 * This may be overridden by the entry's
				 * -button option. */

    char *openCmd, *closeCmd;	/* Tcl commands to invoke when entries
				 * are opened or closed. */

    HashedImage *icons;		/* Tk images displayed for the entry.
				 * The first image is the icon
				 * displayed to the left of the
				 * entry's label. The second is icon
				 * displayed when entry is "open". */
    HashedImage *activeIcons;	/* Tk images displayed for the entry.
				 * The first image is the icon
				 * displayed to the left of the
				 * entry's label. The second is icon
				 * displayed when entry is "open". */
    char *takeFocus;

    ClientData clientData;
    BindTable bindTable;	/* Table of binding information of entries. */
    BindTable buttonBindTable;	/* Table of binding information for buttons. */
    BindTable columnBindTable;	/* Table of binding information for columns. */

    int showTitles;		/* Indicates whether to draw titles over the
				 * tree view and data columns. */
    Column defColumn;
    Column *treeColumnPtr;	/* Column that displays the hierarchy. */
    Column *activeColumnPtr;	/* Column title that is currently active. */
    Column *resizeColumnPtr;	/* Column that is being resized. */

    int depth;
    int flatView;		/* Indicates if the view of the hierarchy 
				 * has been flattened. */
    Entry **flatArr;		/* Flatten array of entries. */

    SortInfo sortInfo;
    
    Pixmap drawable;		/* Pixmap used to cache the entries
				 * displayed.  The pixmap is saved
				 * so that only selected elements can be
				 * drawn quicky. */
    short int drawWidth, drawHeight;
    short int ruleAnchor, ruleMark;
};


extern UID Blt_HtGetUid _ANSI_ARGS_((Hiertable *htabPtr, char *string));
extern void Blt_HtFreeUid _ANSI_ARGS_((Hiertable *htabPtr, UID uid));

extern void Blt_HtEventuallyRedraw _ANSI_ARGS_((Hiertable *htabPtr));
extern int Blt_HtWidgetInstCmd _ANSI_ARGS_((ClientData clientdata,
	Tcl_Interp *interp, int argc, char **argv));
extern Entry *Blt_HtNearestEntry _ANSI_ARGS_((Hiertable *htabPtr,
	int x, int y, int flags));
extern char *Blt_HtGetFullName _ANSI_ARGS_((Hiertable *htabPtr, 
	Entry *entryPtr, int checkEntryLabel));
extern void Blt_HtSelectCmdProc _ANSI_ARGS_((ClientData clientData));
extern void Blt_HtInsertText _ANSI_ARGS_((Hiertable *htabPtr, 
	Entry *entryPtr, char *string, int extra, int insertPos));
extern void Blt_HtComputeLayout _ANSI_ARGS_((Hiertable *htabPtr));
extern void Blt_HtPercentSubst _ANSI_ARGS_((Hiertable *htabPtr, 
	Entry *entryPtr, char *command, Tcl_DString *dStrPtr));
extern void Blt_HtDrawButton _ANSI_ARGS_((Hiertable *htabPtr, Entry *entryPtr, 
	Drawable drawable));
extern void Blt_HtDrawOuterBorders _ANSI_ARGS_((Hiertable *htabPtr, 
	Drawable drawable));
extern int Blt_HtDrawIcon _ANSI_ARGS_((Hiertable *htabPtr, Entry *entryPtr, 
	int x, int y, Drawable drawable));
extern void Blt_HtDrawHeadings _ANSI_ARGS_((Hiertable *htabPtr, 
	Drawable drawable));
extern void Blt_HtDrawRule _ANSI_ARGS_((Hiertable *htabPtr, Column *columnPtr, 
	Drawable drawable));

extern void Blt_HtConfigureButtons _ANSI_ARGS_((Hiertable *htabPtr));
extern int Blt_HtConfigureHiertable _ANSI_ARGS_((Tcl_Interp *interp, 
	Hiertable *htabPtr, int argc, char **argv, int flags));
extern int Blt_HtScreenToIndex _ANSI_ARGS_((Hiertable *htabPtr, 
	int x, int y));

extern void Blt_HtFreeImage _ANSI_ARGS_((HashedImage hImage));
extern HashedImage Blt_HtGetImage _ANSI_ARGS_((Hiertable *htabPtr,
    char *imageName));
extern void Blt_HtAddField _ANSI_ARGS_((Entry *entryPtr, Column *columnPtr));
extern int Blt_HtInitColumn _ANSI_ARGS_((Hiertable *htabPtr, Column *columnPtr,
	char *name, char *defaultLabel, int nOptions, char **options));
extern void Blt_HtDestroyField _ANSI_ARGS_((Field *fieldPtr));
extern void Blt_HtDestroyColumns _ANSI_ARGS_((Hiertable *htabPtr));
extern void Blt_HtAllocateColumnUids _ANSI_ARGS_((Hiertable *htabPtr));
extern void Blt_HtFreeColumnUids _ANSI_ARGS_((Hiertable *htabPtr));
extern void Blt_HtConfigureColumn _ANSI_ARGS_((Hiertable *htabPtr, 
	Column *columnPtr));
extern Column *Blt_HtNearestColumn _ANSI_ARGS_((Hiertable *htabPtr,
	int x, int y, int flags));

extern void Blt_HtDrawRule _ANSI_ARGS_((Hiertable *htabPtr, Column *columnPtr, 
	Drawable drawable));
extern int Blt_HtTextOp _ANSI_ARGS_((Hiertable *htabPtr, Tcl_Interp *interp,
      int argc, char **argv));
extern Editor *Blt_HtCreateEditor _ANSI_ARGS_((Hiertable *htabPtr));
extern char *Blt_HtGetData _ANSI_ARGS_((Entry *entryPtr, Blt_Uid keyUid));

extern int Blt_HtCreateEntry _ANSI_ARGS_((Hiertable *htabPtr, 
    Blt_TreeNode node, int nOptions, char **options));
extern void Blt_HtConfigureEntry _ANSI_ARGS_((Hiertable *htabPtr, 
	Entry *entryPtr));
extern int Blt_HtOpenEntry _ANSI_ARGS_((Hiertable *htabPtr, Entry *entryPtr));
extern int Blt_HtCloseEntry _ANSI_ARGS_((Hiertable *htabPtr, 
	Entry *entryPtr));
extern Entry *Blt_HtNextEntry _ANSI_ARGS_((Hiertable *htabPtr, Entry *entryPtr,
	unsigned int mask));
extern Entry *Blt_HtPrevEntry _ANSI_ARGS_((Hiertable *htabPtr, Entry *entryPtr,
	unsigned int mask));
extern Entry *Blt_HtParentEntry _ANSI_ARGS_((Hiertable *htabPtr, 
	Entry *entryPtr));
extern int Blt_HtGetEntry _ANSI_ARGS_((Hiertable *htabPtr, char *string, 
	Entry **entryPtrPtr));
extern int Blt_HtEntryIsMapped _ANSI_ARGS_((Hiertable *htabPtr, 
	Entry *entryPtr));

extern Hiertable *bltHiertableLastInstance;

typedef int (ApplyProc) _ANSI_ARGS_((Hiertable *htabPtr, Entry *entryPtr));

extern int Blt_HtTreeApply _ANSI_ARGS_((Hiertable *htabPtr, Entry *entryPtr,
	ApplyProc *proc, unsigned int mask));

extern int Blt_HtColumnOp _ANSI_ARGS_((Hiertable *htabPtr, Tcl_Interp *interp,
	int argc, char **argv));
extern int Blt_HtSortOp _ANSI_ARGS_((Hiertable *htabPtr, Tcl_Interp *interp,
	int argc, char **argv));

extern void Blt_HtSortFlatView _ANSI_ARGS_((Hiertable *htabPtr));
extern void Blt_HtSortTreeView _ANSI_ARGS_((Hiertable *htabPtr));

extern int Blt_HtEntryIsSelected _ANSI_ARGS_((Hiertable *htabPtr, 
	Entry *entryPtr));
extern void Blt_HtSelectEntry _ANSI_ARGS_((Hiertable *htabPtr, 
	Entry *entryPtr));
extern void Blt_HtDeselectEntry _ANSI_ARGS_((Hiertable *htabPtr, 
	Entry *entryPtr));
extern void Blt_HtPruneSelection _ANSI_ARGS_((Hiertable *htabPtr, 
	Entry *entryPtr));
extern void Blt_HtClearSelection _ANSI_ARGS_((Hiertable *htabPtr));

#define GETFONT(glob, spec)	(((spec) == NULL) ? (glob) : (spec))
#define GETCOLOR(glob, spec)	(((spec) == NULL) ? (glob) : (spec))
#define GETICONS(h, e)		(((e)->icons != NULL) ? (e)->icons : (h)->icons)
#define GETACTIVEICONS(h, e)	\
	(((e)->activeIcons != NULL) ? (e)->activeIcons : (h)->activeIcons)
#define GETLABEL(e)		\
	(((e)->labelUid != NULL) ? (e)->labelUid : Blt_TreeNodeLabel((e)->node))

static INLINE Entry *
NodeToEntry(htabPtr, node)
    Hiertable *htabPtr;
    Blt_TreeNode node;
{
    Tcl_Obj *objPtr;

    if (Blt_TreeGetValueByUid(htabPtr->tree, node, 
	      htabPtr->treeColumnPtr->keyUid, &objPtr) != TCL_OK) {
	return NULL;
    }
    return (Entry *)objPtr->internalRep.otherValuePtr;
}

#endif /* BLT_HIERTABLE_H */
