1514 lines
43 KiB
C
1514 lines
43 KiB
C
|
||
/* $Id: tixImgCmp.c,v 1.7 2008/02/28 04:05:29 hobbs Exp $ */
|
||
|
||
/*
|
||
* tkImgCmp.c --
|
||
*
|
||
* This procedure implements images of type "compound" for Tix.
|
||
*
|
||
* Copyright (c) 1996, Expert Interface Technologies
|
||
*
|
||
* See the file "license.terms" for information on usage and redistribution
|
||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||
*
|
||
*/
|
||
|
||
#include <tixPort.h>
|
||
#include <tixInt.h>
|
||
#include <tixDef.h>
|
||
|
||
/*
|
||
* ToDo:
|
||
* - lineconfig and itemconfig command
|
||
*/
|
||
|
||
/*
|
||
* The following data structure represents the master for a bitmap
|
||
* image:
|
||
*/
|
||
typedef struct CmpMaster {
|
||
Tk_ImageMaster tkMaster; /* Tk's token for image master. NULL means
|
||
* the image is being deleted. */
|
||
Tcl_Interp *interp; /* Interpreter for application that is
|
||
* using image. */
|
||
Tcl_Command imageCmd; /* Token for image command (used to delete
|
||
* it when the image goes away). NULL means
|
||
* the image command has already been
|
||
* deleted. */
|
||
Display * display; /* Display of the the window associated with
|
||
* this image. We need to keep it
|
||
* because Tk_Display(CmpMaster.tkwin) may
|
||
* be invalid. */
|
||
Tk_Window tkwin; /* default options are taken from this window.
|
||
* If undefined, will use the main window
|
||
* of this application */
|
||
int width, height; /* Dimensions of image. */
|
||
int padX, padY;
|
||
struct CmpLine * lineHead;
|
||
struct CmpLine * lineTail;
|
||
|
||
/* Thde default options, etc */
|
||
int borderWidth; /* Width of 3-D borders. */
|
||
Tk_3DBorder background; /* Used for drawing background. */
|
||
int relief; /* Indicates whether window as a whole is
|
||
* raised, sunken, or flat. */
|
||
|
||
TixFont font; /* Information about text font.*/
|
||
XColor *foreground; /* Color for drawing text and bitmaps */
|
||
GC gc; /* default GC for drawing text. */
|
||
|
||
int showBackground; /* whether the background should be drawn */
|
||
unsigned int changing; /* is this image going to call Tk_ImageChanged
|
||
* in an idle event? */
|
||
unsigned int isDeleted;
|
||
} CmpMaster;
|
||
|
||
#define TYPE_TEXT 0
|
||
#define TYPE_SPACE 1
|
||
#define TYPE_IMAGE 2
|
||
#define TYPE_BITMAP 3
|
||
#define TYPE_WIDGET 4
|
||
|
||
typedef struct CmpLine {
|
||
struct CmpMaster *masterPtr;
|
||
struct CmpLine * next;
|
||
struct CmpItem * itemHead;
|
||
struct CmpItem * itemTail;
|
||
int padX, padY;
|
||
Tk_Anchor anchor;
|
||
int width, height; /* Dimensions of this line. */
|
||
|
||
} CmpLine;
|
||
|
||
/* abstract type */
|
||
|
||
#define COMMON_MEMBERS \
|
||
struct CmpLine * line; \
|
||
struct CmpItem * next; \
|
||
Tk_Anchor anchor; \
|
||
char type; \
|
||
int width; \
|
||
int height; \
|
||
int padX, padY
|
||
|
||
typedef struct CmpItem {
|
||
COMMON_MEMBERS;
|
||
} CmpItem;
|
||
|
||
typedef struct CmpBitmapItem {
|
||
COMMON_MEMBERS;
|
||
|
||
Pixmap bitmap;
|
||
XColor *foreground;
|
||
XColor *background;
|
||
GC gc; /* GC for drawing the bitmap. */
|
||
} CmpBitmapItem;
|
||
|
||
typedef struct CmpImageItem {
|
||
COMMON_MEMBERS;
|
||
|
||
Tk_Image image;
|
||
char * imageString;
|
||
} CmpImageItem;
|
||
|
||
typedef struct CmpSpaceItem {
|
||
COMMON_MEMBERS;
|
||
|
||
} CmpSpaceItem;
|
||
|
||
typedef struct CmpTextItem {
|
||
COMMON_MEMBERS;
|
||
|
||
char * text;
|
||
int numChars;
|
||
Tk_Justify justify; /* Justification to use for multi-line text. */
|
||
int wrapLength;
|
||
int underline; /* Index of character to underline. < 0 means
|
||
* don't underline anything. */
|
||
XColor *foreground;
|
||
TixFont font; /* Information about text font, or NULL. */
|
||
GC gc; /* GC for drawing the bitmap. */
|
||
} CmpTextItem;
|
||
|
||
typedef union CmpItemPtr {
|
||
CmpItem * item;
|
||
CmpBitmapItem * bitmap;
|
||
CmpImageItem * image;
|
||
CmpSpaceItem * space;
|
||
CmpTextItem * text;
|
||
} CmpItemPtr;
|
||
|
||
/*
|
||
* The type record for bitmap images:
|
||
*/
|
||
static int ImgCmpCreate _ANSI_ARGS_((Tcl_Interp *interp,
|
||
char *name, int argc, Tcl_Obj *CONST objv[],
|
||
Tk_ImageType *typePtr, Tk_ImageMaster master,
|
||
ClientData *clientDataPtr));
|
||
static ClientData ImgCmpGet _ANSI_ARGS_((Tk_Window tkwin,
|
||
ClientData clientData));
|
||
static void ImgCmpDisplay _ANSI_ARGS_((ClientData clientData,
|
||
Display *display, Drawable drawable,
|
||
int imageX, int imageY, int width, int height,
|
||
int drawableX, int drawableY));
|
||
static void ImgCmpFree _ANSI_ARGS_((ClientData clientData,
|
||
Display *display));
|
||
static void ImgCmpDelete _ANSI_ARGS_((ClientData clientData));
|
||
static void ImgCmpFreeResources _ANSI_ARGS_((ClientData clientData));
|
||
|
||
Tk_ImageType tixCompoundImageType = {
|
||
"compound", /* name */
|
||
ImgCmpCreate, /* createProc */
|
||
ImgCmpGet, /* getProc */
|
||
ImgCmpDisplay, /* displayProc */
|
||
ImgCmpFree, /* freeProc */
|
||
ImgCmpDelete, /* deleteProc */
|
||
NULL, /* postscriptProc (tk8.3 or later)*/
|
||
NULL, /* nextPtr */
|
||
NULL, /* reserved */
|
||
};
|
||
|
||
static Tk_ConfigSpec configSpecs[] = {
|
||
{TK_CONFIG_BORDER, "-background", "background", "Background",
|
||
DEF_CMPIMAGE_BG_COLOR, Tk_Offset(CmpMaster, background),
|
||
TK_CONFIG_COLOR_ONLY},
|
||
|
||
{TK_CONFIG_BORDER, "-background", "background", "Background",
|
||
DEF_CMPIMAGE_BG_MONO, Tk_Offset(CmpMaster, background),
|
||
TK_CONFIG_MONO_ONLY},
|
||
|
||
{TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
|
||
(char *) NULL, 0, 0},
|
||
|
||
{TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
|
||
(char *) NULL, 0, 0},
|
||
|
||
{TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", (char *) NULL,
|
||
"0", Tk_Offset(CmpMaster, borderWidth), 0},
|
||
|
||
{TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
|
||
(char *) NULL, 0, 0},
|
||
|
||
{TK_CONFIG_FONT, "-font", "font", "Font",
|
||
DEF_CMPIMAGE_FONT, Tk_Offset(CmpMaster, font), 0},
|
||
|
||
{TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
|
||
DEF_CMPIMAGE_FG_COLOR, Tk_Offset(CmpMaster, foreground),
|
||
TK_CONFIG_COLOR_ONLY},
|
||
|
||
{TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
|
||
DEF_CMPIMAGE_FG_MONO, Tk_Offset(CmpMaster, foreground),
|
||
TK_CONFIG_MONO_ONLY},
|
||
|
||
{TK_CONFIG_PIXELS, "-padx", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpMaster, padX), 0},
|
||
|
||
{TK_CONFIG_PIXELS, "-pady", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpMaster, padY), 0},
|
||
|
||
{TK_CONFIG_RELIEF, "-relief", (char *) NULL, (char *) NULL,
|
||
"flat", Tk_Offset(CmpMaster, relief), 0},
|
||
|
||
{TK_CONFIG_BOOLEAN, "-showbackground", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpMaster, showBackground), 0},
|
||
|
||
{TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,
|
||
(char *) NULL, Tk_Offset(CmpMaster, tkwin), TK_CONFIG_NULL_OK},
|
||
|
||
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
|
||
(char *) NULL, 0, 0}
|
||
};
|
||
|
||
static Tk_ConfigSpec lineConfigSpecs[] = {
|
||
{TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
|
||
"c", Tk_Offset(CmpLine, anchor), 0},
|
||
{TK_CONFIG_PIXELS, "-padx", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpLine, padX), 0},
|
||
{TK_CONFIG_PIXELS, "-pady", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpLine, padY), 0},
|
||
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
|
||
(char *) NULL, 0, 0}
|
||
};
|
||
|
||
static Tk_ConfigSpec bitmapConfigSpecs[] = {
|
||
{TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
|
||
"c", Tk_Offset(CmpBitmapItem, anchor), 0},
|
||
|
||
{TK_CONFIG_COLOR, "-background", "background", "Background",
|
||
"", Tk_Offset(CmpBitmapItem, background),
|
||
TK_CONFIG_NULL_OK},
|
||
|
||
{TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
|
||
(char *) NULL, 0, 0},
|
||
|
||
{TK_CONFIG_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
|
||
"", Tk_Offset(CmpBitmapItem, bitmap), TK_CONFIG_NULL_OK},
|
||
|
||
{TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
|
||
(char *) NULL, 0, 0},
|
||
|
||
{TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
|
||
"", Tk_Offset(CmpBitmapItem, foreground),
|
||
TK_CONFIG_NULL_OK},
|
||
|
||
{TK_CONFIG_PIXELS, "-padx", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpBitmapItem, padX), 0},
|
||
|
||
{TK_CONFIG_PIXELS, "-pady", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpBitmapItem, padY), 0},
|
||
|
||
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
|
||
(char *) NULL, 0, 0}
|
||
};
|
||
|
||
static Tk_ConfigSpec imageConfigSpecs[] = {
|
||
{TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
|
||
"c", Tk_Offset(CmpImageItem, anchor), 0},
|
||
{TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL,
|
||
(char *) NULL, Tk_Offset(CmpImageItem, imageString), TK_CONFIG_NULL_OK},
|
||
{TK_CONFIG_PIXELS, "-padx", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpImageItem, padX), 0},
|
||
{TK_CONFIG_PIXELS, "-pady", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpImageItem, padY), 0},
|
||
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
|
||
(char *) NULL, 0, 0}
|
||
};
|
||
|
||
static Tk_ConfigSpec spaceConfigSpecs[] = {
|
||
{TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpSpaceItem, height), 0},
|
||
{TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpSpaceItem, width), 0},
|
||
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
|
||
(char *) NULL, 0, 0}
|
||
};
|
||
|
||
static Tk_ConfigSpec textConfigSpecs[] = {
|
||
{TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
|
||
"c", Tk_Offset(CmpTextItem, anchor), 0},
|
||
|
||
{TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
|
||
(char *) NULL, 0, 0},
|
||
|
||
{TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,
|
||
"", Tk_Offset(CmpTextItem, font), TK_CONFIG_NULL_OK},
|
||
|
||
{TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
|
||
"", Tk_Offset(CmpTextItem, foreground),
|
||
TK_CONFIG_NULL_OK},
|
||
|
||
{TK_CONFIG_JUSTIFY, "-justify", (char *) NULL, (char *) NULL,
|
||
"left", Tk_Offset(CmpTextItem, justify), 0},
|
||
|
||
{TK_CONFIG_PIXELS, "-padx", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpTextItem, padX), 0},
|
||
|
||
{TK_CONFIG_PIXELS, "-pady", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpTextItem, padY), 0},
|
||
|
||
{TK_CONFIG_STRING, "-text", (char *) NULL, (char *) NULL,
|
||
"", Tk_Offset(CmpTextItem, text), TK_CONFIG_NULL_OK},
|
||
|
||
{TK_CONFIG_INT, "-underline", (char *) NULL, (char *) NULL,
|
||
"-1", Tk_Offset(CmpTextItem, underline), 0},
|
||
|
||
{TK_CONFIG_PIXELS, "-wraplength", (char *) NULL, (char *) NULL,
|
||
"0", Tk_Offset(CmpTextItem, wrapLength), 0},
|
||
|
||
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
|
||
(char *) NULL, 0, 0}
|
||
};
|
||
|
||
/*
|
||
* Prototypes for procedures used only locally in this file:
|
||
*/
|
||
|
||
static int ImgCmpCmd _ANSI_ARGS_((ClientData clientData,
|
||
Tcl_Interp *interp, int argc, CONST84 char **argv));
|
||
static void ImgCmpCmdDeletedProc _ANSI_ARGS_((
|
||
ClientData clientData));
|
||
static int ImgCmpConfigureMaster _ANSI_ARGS_((
|
||
CmpMaster *masterPtr, int argc, CONST84 char **argv,
|
||
int flags));
|
||
CmpBitmapItem * AddNewBitmap _ANSI_ARGS_((CmpMaster *masterPtr,
|
||
CmpLine *line,
|
||
int argc, CONST84 char **argv));
|
||
CmpImageItem * AddNewImage _ANSI_ARGS_((CmpMaster *masterPtr,
|
||
CmpLine *line,
|
||
int argc, CONST84 char **argv));
|
||
CmpSpaceItem * AddNewSpace _ANSI_ARGS_((CmpMaster *masterPtr,
|
||
CmpLine *line,
|
||
int argc, CONST84 char **argv));
|
||
CmpTextItem * AddNewText _ANSI_ARGS_((CmpMaster *masterPtr,
|
||
CmpLine *line,
|
||
int argc, CONST84 char **argv));
|
||
CmpLine* AddNewLine _ANSI_ARGS_((CmpMaster *masterPtr,
|
||
int argc, CONST84 char **argv));
|
||
static void CalculateMasterSize _ANSI_ARGS_((
|
||
ClientData clientData));
|
||
static void ChangeImageWhenIdle _ANSI_ARGS_((
|
||
CmpMaster *masterPtr));
|
||
static void ImageProc _ANSI_ARGS_((ClientData clientData,
|
||
int x, int y, int width, int height,
|
||
int imgWidth, int imgHeight));
|
||
static void FreeLine _ANSI_ARGS_((CmpLine * lPtr));
|
||
static void FreeItem _ANSI_ARGS_((CmpItemPtr p));
|
||
static void CmpEventProc _ANSI_ARGS_((ClientData clientData,
|
||
XEvent *eventPtr));
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* ImgCmpCreate --
|
||
*
|
||
* This procedure is called by the Tk image code to create "test"
|
||
* images.
|
||
*
|
||
* Results:
|
||
* A standard Tcl result.
|
||
*
|
||
* Side effects:
|
||
* The data structure for a new image is allocated.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
/* ARGSUSED */
|
||
static int
|
||
ImgCmpCreate(interp, name, argc, objv, typePtr, master, clientDataPtr)
|
||
Tcl_Interp *interp; /* Interpreter for application containing
|
||
* image. */
|
||
char *name; /* Name to use for image. */
|
||
int argc; /* Number of arguments. */
|
||
Tcl_Obj *CONST objv[]; /* Argument strings for options (doesn't
|
||
* include image name or type). */
|
||
Tk_ImageType *typePtr; /* Pointer to our type record (not used). */
|
||
Tk_ImageMaster master; /* Token for image, to be used by us in
|
||
* later callbacks. */
|
||
ClientData *clientDataPtr; /* Store manager's token for image here;
|
||
* it will be returned in later callbacks. */
|
||
{
|
||
CmpMaster *masterPtr;
|
||
int i;
|
||
CONST84 char *argvbuf[10];
|
||
CONST84 char **argv = argvbuf;
|
||
|
||
/*
|
||
* Convert the objv arguments into string equivalent.
|
||
*/
|
||
if (argc > 10) {
|
||
argv = (CONST84 char **) ckalloc(argc * sizeof(char *));
|
||
}
|
||
for (i = 0; i < argc; i++) {
|
||
/*
|
||
* no need to free the value returned by Tcl_GetString. It's
|
||
* managed by Tcl's object system.
|
||
*/
|
||
|
||
argv[i] = Tcl_GetString(objv[i]);
|
||
}
|
||
|
||
masterPtr = (CmpMaster *) ckalloc(sizeof(CmpMaster));
|
||
masterPtr->tkMaster = master;
|
||
masterPtr->interp = interp;
|
||
masterPtr->imageCmd = Tcl_CreateCommand(interp, name, ImgCmpCmd,
|
||
(ClientData)masterPtr, ImgCmpCmdDeletedProc);
|
||
masterPtr->tkwin = NULL;
|
||
masterPtr->display = NULL;
|
||
masterPtr->width = 0;
|
||
masterPtr->height = 0;
|
||
masterPtr->padX = 0;
|
||
masterPtr->padY = 0;
|
||
masterPtr->lineHead = NULL;
|
||
masterPtr->lineTail = NULL;
|
||
masterPtr->borderWidth = 0;
|
||
masterPtr->background = NULL;
|
||
masterPtr->relief = 0;
|
||
masterPtr->font = NULL;
|
||
masterPtr->foreground = NULL;
|
||
masterPtr->gc = None;
|
||
masterPtr->showBackground = 0;
|
||
masterPtr->changing = 0;
|
||
masterPtr->isDeleted = 0;
|
||
|
||
if (ImgCmpConfigureMaster(masterPtr, argc, argv, 0) != TCL_OK) {
|
||
ImgCmpDelete((ClientData) masterPtr);
|
||
if (argv != argvbuf) {
|
||
ckfree((char *) argv);
|
||
}
|
||
return TCL_ERROR;
|
||
}
|
||
*clientDataPtr = (ClientData) masterPtr;
|
||
if (argv != argvbuf) {
|
||
ckfree((char *) argv);
|
||
}
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* ImgCmpConfigureMaster --
|
||
*
|
||
* This procedure is called when a bitmap image is created or
|
||
* reconfigured. It process configuration options and resets
|
||
* any instances of the image.
|
||
*
|
||
* Results:
|
||
* A standard Tcl return value. If TCL_ERROR is returned then
|
||
* an error message is left in interp's result.
|
||
*
|
||
* Side effects:
|
||
* Existing instances of the image will be redisplayed to match
|
||
* the new configuration options.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
static int
|
||
ImgCmpConfigureMaster(masterPtr, argc, argv, flags)
|
||
CmpMaster *masterPtr; /* Pointer to data structure describing
|
||
* overall bitmap image to (reconfigure). */
|
||
int argc; /* Number of entries in argv. */
|
||
CONST84 char **argv; /* Pairs of configuration options for image. */
|
||
int flags; /* Flags to pass to Tk_ConfigureWidget,
|
||
* such as TK_CONFIG_ARGV_ONLY. */
|
||
{
|
||
XGCValues gcValues;
|
||
GC newGC;
|
||
int i;
|
||
|
||
if (argc %2) {
|
||
Tcl_AppendResult(masterPtr->interp, "value missing for option \"",
|
||
argv[argc-1], "\"", NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
for (i=0; i<argc; i+=2) {
|
||
size_t length = strlen(argv[i]);
|
||
if (strncmp(argv[i], "-window", length) == 0) {
|
||
masterPtr->tkwin = Tk_NameToWindow(masterPtr->interp, argv[i+1],
|
||
Tk_MainWindow(masterPtr->interp));
|
||
if (masterPtr->tkwin == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
}
|
||
if (masterPtr->tkwin == NULL) {
|
||
Tcl_AppendResult(masterPtr->interp,
|
||
"no value given for -window option.", NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
masterPtr->display = Tk_Display(masterPtr->tkwin);
|
||
|
||
if (Tk_ConfigureWidget(masterPtr->interp, masterPtr->tkwin,
|
||
configSpecs, argc, argv, (char *) masterPtr, flags) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
Tk_CreateEventHandler(masterPtr->tkwin,
|
||
StructureNotifyMask, CmpEventProc, (ClientData)masterPtr);
|
||
|
||
/*
|
||
* Get the default GC for text and bitmaps
|
||
*/
|
||
gcValues.foreground = masterPtr->foreground->pixel;
|
||
gcValues.background = Tk_3DBorderColor(masterPtr->background)->pixel;
|
||
gcValues.font = TixFontId(masterPtr->font);
|
||
gcValues.graphics_exposures = False;
|
||
newGC = Tk_GetGC(masterPtr->tkwin,
|
||
GCBackground|GCForeground|GCFont|GCGraphicsExposures,
|
||
&gcValues);
|
||
if (masterPtr->gc != None) {
|
||
Tk_FreeGC(Tk_Display(masterPtr->tkwin), masterPtr->gc);
|
||
}
|
||
masterPtr->gc = newGC;
|
||
|
||
ChangeImageWhenIdle(masterPtr);
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* ImgCmpCmd --
|
||
*
|
||
* This procedure is invoked to process the Tcl command
|
||
* that corresponds to an image 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.
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
static int
|
||
ImgCmpCmd(clientData, interp, argc, argv)
|
||
ClientData clientData; /* Information about button widget. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int argc; /* Number of arguments. */
|
||
CONST84 char **argv; /* Argument strings. */
|
||
{
|
||
CmpMaster *masterPtr = (CmpMaster *) clientData;
|
||
int c, code;
|
||
size_t length;
|
||
|
||
if (argc < 2) {
|
||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||
argv[0], " option ?arg arg ...?\"", NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
c = argv[1][0];
|
||
length = strlen(argv[1]);
|
||
if ((c == 'a') && (strncmp(argv[1], "add", length) == 0)) {
|
||
if (argc < 3) {
|
||
return Tix_ArgcError(interp, argc, argv, 2,
|
||
"type ?option value? ...");
|
||
}
|
||
c = argv[2][0];
|
||
length = strlen(argv[2]);
|
||
|
||
if ((c == 'l') && (strncmp(argv[2], "line", length) == 0)) {
|
||
CmpLine * newLine;
|
||
|
||
newLine = AddNewLine(masterPtr, argc-3, argv+3);
|
||
if (newLine == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
else {
|
||
CmpItemPtr p;
|
||
|
||
if (masterPtr->lineTail == 0) {
|
||
if (AddNewLine(masterPtr, 0, 0) == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
if ((c == 'b') && (strncmp(argv[2], "bitmap", length) == 0)) {
|
||
p.bitmap = AddNewBitmap(masterPtr, masterPtr->lineTail,
|
||
argc-3, argv+3);
|
||
if (p.bitmap == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
else if ((c == 'i') && (strncmp(argv[2], "image", length) == 0)) {
|
||
p.image = AddNewImage(masterPtr, masterPtr->lineTail,
|
||
argc-3, argv+3);
|
||
if (p.image == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
else if ((c == 's') && (strncmp(argv[2], "space", length) == 0)) {
|
||
p.space = AddNewSpace(masterPtr, masterPtr->lineTail,
|
||
argc-3, argv+3);
|
||
if (p.space == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
else if ((c == 't') && (strncmp(argv[2], "text", length) == 0)) {
|
||
p.text = AddNewText(masterPtr, masterPtr->lineTail,
|
||
argc-3, argv+3);
|
||
if (p.text == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
else {
|
||
Tcl_AppendResult(interp, "unknown option \"",
|
||
argv[2], "\", must be bitmap, image, line, ",
|
||
"space, text or widget", NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
/* append to the end of the line */
|
||
if (masterPtr->lineTail->itemHead == NULL) {
|
||
masterPtr->lineTail->itemHead = p.item;
|
||
masterPtr->lineTail->itemTail = p.item;
|
||
} else {
|
||
masterPtr->lineTail->itemTail->next = p.item;
|
||
masterPtr->lineTail->itemTail = p.item;
|
||
}
|
||
}
|
||
ChangeImageWhenIdle(masterPtr);
|
||
return TCL_OK;
|
||
} else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
|
||
&& (length >= 2)) {
|
||
if (argc != 3) {
|
||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||
argv[0], " cget option\"",
|
||
(char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
return Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
|
||
(char *) masterPtr, argv[2], 0);
|
||
} else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
|
||
&& (length >= 2)) {
|
||
if (argc == 2) {
|
||
code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
|
||
configSpecs, (char *) masterPtr, (char *) NULL, 0);
|
||
} else if (argc == 3) {
|
||
code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
|
||
configSpecs, (char *) masterPtr, argv[2], 0);
|
||
} else {
|
||
int i;
|
||
for (i=2; i<argc-2; i++) {
|
||
length = strlen(argv[i]);
|
||
if (strncmp(argv[i], "-window", length) == 0) {
|
||
Tcl_AppendResult(interp, "The -window option cannot ",
|
||
"be changed.", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
code = ImgCmpConfigureMaster(masterPtr, argc-2, argv+2,
|
||
TK_CONFIG_ARGV_ONLY);
|
||
}
|
||
return code;
|
||
} else if ((c == 'i') && (strncmp(argv[1], "itemconfigure", length)== 0)) {
|
||
Tcl_AppendResult(interp, "unimplemented", NULL);
|
||
return TCL_ERROR;
|
||
} else if ((c == 'l') && (strncmp(argv[1], "lineconfigure", length)== 0)) {
|
||
Tcl_AppendResult(interp, "unimplemented", NULL);
|
||
return TCL_ERROR;
|
||
} else {
|
||
Tcl_AppendResult(interp, "bad option \"", argv[1],
|
||
"\": must be cget or configure", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------
|
||
*
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
CmpLine *
|
||
AddNewLine(masterPtr, argc, argv)
|
||
CmpMaster *masterPtr;
|
||
int argc; /* Number of arguments. */
|
||
CONST84 char **argv; /* Argument strings. */
|
||
{
|
||
CmpLine * lPtr = (CmpLine *)ckalloc(sizeof(CmpLine));
|
||
|
||
lPtr->masterPtr = masterPtr;
|
||
lPtr->next = NULL;
|
||
lPtr->itemHead = NULL;
|
||
lPtr->itemTail = NULL;
|
||
lPtr->padX = 0;
|
||
lPtr->padY = 0;
|
||
lPtr->width = 1;
|
||
lPtr->height = 1;
|
||
|
||
lPtr->anchor = TK_ANCHOR_CENTER;
|
||
|
||
if (Tk_ConfigureWidget(masterPtr->interp, masterPtr->tkwin,
|
||
lineConfigSpecs, argc, argv, (char *) lPtr,
|
||
TK_CONFIG_ARGV_ONLY) != TCL_OK) {
|
||
FreeLine(lPtr);
|
||
return NULL;
|
||
}
|
||
|
||
/*
|
||
* Append to the end of the master's lines
|
||
*/
|
||
if (masterPtr->lineHead == NULL) {
|
||
masterPtr->lineHead = masterPtr->lineTail = lPtr;
|
||
} else {
|
||
masterPtr->lineTail->next = lPtr;
|
||
masterPtr->lineTail = lPtr;
|
||
}
|
||
|
||
return lPtr;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------
|
||
*
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
CmpBitmapItem *
|
||
AddNewBitmap(masterPtr, line, argc, argv)
|
||
CmpMaster *masterPtr;
|
||
CmpLine *line;
|
||
int argc; /* Number of arguments. */
|
||
CONST84 char **argv; /* Argument strings. */
|
||
{
|
||
CmpItemPtr p;
|
||
XGCValues gcValues;
|
||
|
||
p.bitmap = (CmpBitmapItem*) ckalloc(sizeof(CmpBitmapItem));
|
||
p.bitmap->line = line;
|
||
p.bitmap->next = NULL;
|
||
p.bitmap->anchor = TK_ANCHOR_CENTER;
|
||
p.bitmap->type = TYPE_BITMAP;
|
||
p.bitmap->padX = 0;
|
||
p.bitmap->padY = 0;
|
||
p.bitmap->width = 0;
|
||
p.bitmap->height = 0;
|
||
|
||
p.bitmap->bitmap = None;
|
||
p.bitmap->foreground = NULL;
|
||
p.bitmap->background = NULL;
|
||
p.bitmap->gc = None;
|
||
|
||
if (Tk_ConfigureWidget(masterPtr->interp, masterPtr->tkwin,
|
||
bitmapConfigSpecs, argc, argv, (char *) p.bitmap,
|
||
TK_CONFIG_ARGV_ONLY) != TCL_OK) {
|
||
goto error;
|
||
}
|
||
|
||
/* Get the GC for the bitmap */
|
||
if (p.bitmap->background) {
|
||
gcValues.background = p.bitmap->background->pixel;
|
||
} else {
|
||
gcValues.background = Tk_3DBorderColor(masterPtr->background)->pixel;
|
||
}
|
||
if (p.bitmap->foreground) {
|
||
gcValues.foreground = p.bitmap->foreground->pixel;
|
||
} else {
|
||
gcValues.foreground = masterPtr->foreground->pixel;
|
||
}
|
||
gcValues.graphics_exposures = False;
|
||
p.bitmap->gc = Tk_GetGC(masterPtr->tkwin,
|
||
GCBackground|GCForeground|GCGraphicsExposures,
|
||
&gcValues);
|
||
|
||
return p.bitmap;
|
||
|
||
error:
|
||
|
||
FreeItem(p);
|
||
return NULL;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------
|
||
*
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
CmpImageItem *
|
||
AddNewImage(masterPtr, line, argc, argv)
|
||
CmpMaster *masterPtr;
|
||
CmpLine *line;
|
||
int argc; /* Number of arguments. */
|
||
CONST84 char **argv; /* Argument strings. */
|
||
{
|
||
CmpItemPtr p;
|
||
|
||
|
||
p.image = (CmpImageItem*) ckalloc(sizeof(CmpImageItem));
|
||
p.image->line = line;
|
||
p.image->next = NULL;
|
||
p.image->anchor = TK_ANCHOR_CENTER;
|
||
p.image->type = TYPE_IMAGE;
|
||
p.image->padX = 0;
|
||
p.image->padY = 0;
|
||
p.image->width = 0;
|
||
p.image->height = 0;
|
||
|
||
p.image->imageString = NULL;
|
||
p.image->image = NULL;
|
||
|
||
if (Tk_ConfigureWidget(masterPtr->interp, masterPtr->tkwin,
|
||
imageConfigSpecs, argc, argv, (char *) p.image,
|
||
TK_CONFIG_ARGV_ONLY) != TCL_OK) {
|
||
goto error;
|
||
}
|
||
|
||
/* Get the image */
|
||
if (p.image->imageString != NULL) {
|
||
p.image->image = Tk_GetImage(masterPtr->interp, masterPtr->tkwin,
|
||
p.image->imageString, ImageProc, (ClientData)p.image);
|
||
if (p.image->image == NULL) {
|
||
goto error;
|
||
}
|
||
}
|
||
|
||
return p.image;
|
||
|
||
error:
|
||
|
||
FreeItem(p);
|
||
return NULL;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------
|
||
*
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
CmpSpaceItem *
|
||
AddNewSpace(masterPtr, line, argc, argv)
|
||
CmpMaster *masterPtr;
|
||
CmpLine *line;
|
||
int argc; /* Number of arguments. */
|
||
CONST84 char **argv; /* Argument strings. */
|
||
{
|
||
CmpItemPtr p;
|
||
|
||
p.space = (CmpSpaceItem*) ckalloc(sizeof(CmpSpaceItem));
|
||
p.space->line = line;
|
||
p.space->next = NULL;
|
||
p.space->anchor = TK_ANCHOR_CENTER;
|
||
p.space->type = TYPE_SPACE;
|
||
p.space->padX = 0;
|
||
p.space->padY = 0;
|
||
p.space->width = 0;
|
||
p.space->height = 0;
|
||
|
||
if (Tk_ConfigureWidget(masterPtr->interp, masterPtr->tkwin,
|
||
spaceConfigSpecs, argc, argv, (char *)p.space,
|
||
TK_CONFIG_ARGV_ONLY) != TCL_OK) {
|
||
goto error;
|
||
}
|
||
|
||
return p.space;
|
||
|
||
error:
|
||
|
||
FreeItem(p);
|
||
return NULL;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------
|
||
*
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
CmpTextItem *
|
||
AddNewText(masterPtr, line, argc, argv)
|
||
CmpMaster *masterPtr;
|
||
CmpLine *line;
|
||
int argc; /* Number of arguments. */
|
||
CONST84 char **argv; /* Argument strings. */
|
||
{
|
||
CmpItemPtr p;
|
||
XGCValues gcValues;
|
||
|
||
p.text = (CmpTextItem*) ckalloc(sizeof(CmpTextItem));
|
||
p.text->line = line;
|
||
p.text->next = NULL;
|
||
p.text->anchor = TK_ANCHOR_CENTER;
|
||
p.text->type = TYPE_TEXT;
|
||
p.text->padX = 0;
|
||
p.text->padY = 0;
|
||
p.text->width = 0;
|
||
p.text->height = 0;
|
||
|
||
p.text->text = NULL;
|
||
p.text->numChars = 0;
|
||
p.text->justify = TK_JUSTIFY_CENTER;
|
||
p.text->underline = -1;
|
||
p.text->wrapLength = 0;
|
||
|
||
p.text->foreground = NULL;
|
||
p.text->font = NULL;
|
||
p.text->gc = None;
|
||
|
||
if (Tk_ConfigureWidget(masterPtr->interp, masterPtr->tkwin,
|
||
textConfigSpecs, argc, argv, (char *) p.text,
|
||
TK_CONFIG_ARGV_ONLY) != TCL_OK) {
|
||
|
||
goto error;
|
||
}
|
||
|
||
/* Get the GC for the text */
|
||
if (p.text->foreground) {
|
||
gcValues.foreground = p.text->foreground->pixel;
|
||
} else {
|
||
gcValues.foreground = masterPtr->foreground->pixel;
|
||
}
|
||
if (p.text->font) {
|
||
gcValues.font = TixFontId(p.text->font);
|
||
} else {
|
||
gcValues.font = TixFontId(masterPtr->font);
|
||
}
|
||
gcValues.graphics_exposures = False;
|
||
p.text->gc = Tk_GetGC(masterPtr->tkwin,
|
||
GCFont|GCForeground|GCGraphicsExposures,
|
||
&gcValues);
|
||
|
||
return p.text;
|
||
|
||
error:
|
||
|
||
FreeItem(p);
|
||
return NULL;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* ImgCmpGet --
|
||
*
|
||
* This procedure is called for each use of a bitmap image in a
|
||
* widget.
|
||
*
|
||
* Results:
|
||
* The return value is a token for the instance, which is passed
|
||
* back to us in calls to ImgCmpDisplay and ImgCmpFree.
|
||
*
|
||
* Side effects:
|
||
* A data structure is set up for the instance (or, an existing
|
||
* instance is re-used for the new one).
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
static ClientData
|
||
ImgCmpGet(tkwin, masterData)
|
||
Tk_Window tkwin; /* Window in which the instance will be
|
||
* used. */
|
||
ClientData masterData; /* Pointer to our master structure for the
|
||
* image. */
|
||
{
|
||
CmpMaster *masterPtr = (CmpMaster *)masterData;
|
||
|
||
if (tkwin == masterPtr->tkwin) {
|
||
return masterData;
|
||
}
|
||
|
||
Tcl_AppendResult(masterPtr->interp,
|
||
"Image \"",
|
||
Tk_NameOfImage(masterPtr->tkMaster),
|
||
"\" can only be assigned to window \"",
|
||
Tk_PathName(masterPtr->tkwin), "\"", NULL);
|
||
Tcl_AddErrorInfo(masterPtr->interp, "\n (while configuring image \"");
|
||
Tcl_AddErrorInfo(masterPtr->interp, Tk_NameOfImage(masterPtr->tkMaster));
|
||
Tcl_AddErrorInfo(masterPtr->interp, "\")");
|
||
Tk_BackgroundError(masterPtr->interp);
|
||
|
||
return NULL;
|
||
}
|
||
|
||
static void
|
||
CalculateMasterSize(clientData)
|
||
ClientData clientData;
|
||
{
|
||
CmpMaster *masterPtr = (CmpMaster *)clientData;
|
||
CmpLine *lPtr;
|
||
CmpItemPtr p;
|
||
|
||
masterPtr->width = 0;
|
||
masterPtr->height = 0;
|
||
|
||
for (lPtr = masterPtr->lineHead; lPtr; lPtr=lPtr->next) {
|
||
lPtr->width = 0;
|
||
lPtr->height = 0;
|
||
for (p.item = lPtr->itemHead; p.item; p.item=p.item->next) {
|
||
|
||
switch (p.item->type) {
|
||
case TYPE_IMAGE:
|
||
Tk_SizeOfImage(p.image->image,
|
||
&p.image->width, &p.image->height);
|
||
break;
|
||
|
||
case TYPE_SPACE:
|
||
/* Do nothing */
|
||
break;
|
||
|
||
case TYPE_TEXT:
|
||
{
|
||
TixFont font;
|
||
|
||
if (p.text->text == NULL) {
|
||
break;
|
||
}
|
||
|
||
if (p.text->font) {
|
||
font = p.text->font;
|
||
} else {
|
||
font = masterPtr->font;
|
||
}
|
||
|
||
p.text->numChars = -1;
|
||
TixComputeTextGeometry(font, p.text->text,
|
||
p.text->numChars,
|
||
p.text->wrapLength,
|
||
&p.text->width, &p.text->height);
|
||
}
|
||
break;
|
||
|
||
case TYPE_BITMAP:
|
||
Tk_SizeOfBitmap(Tk_Display(masterPtr->tkwin),
|
||
p.bitmap->bitmap, &p.bitmap->width,
|
||
&p.bitmap->height);
|
||
break;
|
||
|
||
case TYPE_WIDGET:
|
||
|
||
|
||
break;
|
||
}
|
||
p.item->width += 2*p.item->padX;
|
||
p.item->height += 2*p.item->padY;
|
||
|
||
lPtr->width += p.item->width;
|
||
if (lPtr->height < p.item->height) {
|
||
lPtr->height = p.item->height;
|
||
}
|
||
}
|
||
lPtr->width += 2*lPtr->padX;
|
||
lPtr->height += 2*lPtr->padY;
|
||
|
||
if (masterPtr->width < lPtr->width) {
|
||
masterPtr->width = lPtr->width;
|
||
}
|
||
masterPtr->height += lPtr->height;
|
||
}
|
||
masterPtr->width += 2*masterPtr->padX + 2*masterPtr->borderWidth;
|
||
masterPtr->height += 2*masterPtr->padY + 2*masterPtr->borderWidth;
|
||
|
||
Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width,
|
||
masterPtr->height, masterPtr->width, masterPtr->height);
|
||
masterPtr->changing = 0;
|
||
}
|
||
|
||
static void
|
||
ChangeImageWhenIdle(masterPtr)
|
||
CmpMaster *masterPtr;
|
||
{
|
||
if (!masterPtr->changing) {
|
||
masterPtr->changing = 1;
|
||
Tk_DoWhenIdle(CalculateMasterSize, (ClientData)masterPtr);
|
||
}
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* ImgCmpDisplay --
|
||
*
|
||
* This procedure is invoked to draw a bitmap image.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* A portion of the image gets rendered in a pixmap or window.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
static void
|
||
ImgCmpDisplay(clientData, display, drawable, imageX, imageY, width,
|
||
height, drawableX, drawableY)
|
||
ClientData clientData; /* Pointer to CmpInstance structure for
|
||
* for instance to be displayed. */
|
||
Display *display; /* Display on which to draw image. */
|
||
Drawable drawable; /* Pixmap or window in which to draw image. */
|
||
int imageX, imageY; /* Upper-left corner of region within image
|
||
* to draw. */
|
||
int width, height; /* Dimensions of region within image to draw.*/
|
||
int drawableX, drawableY; /* Coordinates within drawable that
|
||
* correspond to imageX and imageY. */
|
||
{
|
||
CmpMaster * masterPtr = (CmpMaster*)clientData;
|
||
CmpLine *lPtr;
|
||
CmpItemPtr p;
|
||
int dx, dy, extraX;
|
||
|
||
if (masterPtr == NULL) {
|
||
/* attempting to draw into a invalid window (can only be drawn into
|
||
* the original window set by the -window option */
|
||
return;
|
||
}
|
||
|
||
if (masterPtr->showBackground) {
|
||
Tk_Fill3DRectangle(masterPtr->tkwin, drawable,
|
||
masterPtr->background,
|
||
drawableX + masterPtr->padX - imageX,
|
||
drawableY + masterPtr->padY - imageY,
|
||
masterPtr->width - 2*masterPtr->padX,
|
||
masterPtr->height - 2*masterPtr->padY,
|
||
masterPtr->borderWidth, masterPtr->relief);
|
||
}
|
||
|
||
/* ToDo: Set the clipping region according to the imageX,Y, and
|
||
* width, height */
|
||
dy = drawableY + masterPtr->padY + masterPtr->borderWidth - imageY;
|
||
|
||
for (lPtr = masterPtr->lineHead; lPtr; lPtr=lPtr->next) {
|
||
dx = drawableX + masterPtr->padX - imageX;
|
||
dx += lPtr->padX;
|
||
dy += lPtr->padY;
|
||
|
||
extraX = masterPtr->width - 2*masterPtr->padX - lPtr->width;
|
||
switch (lPtr->anchor) {
|
||
case TK_ANCHOR_SW: case TK_ANCHOR_W: case TK_ANCHOR_NW:
|
||
extraX = 0;
|
||
break;
|
||
case TK_ANCHOR_N: case TK_ANCHOR_CENTER: case TK_ANCHOR_S:
|
||
extraX /= 2;
|
||
break;
|
||
case TK_ANCHOR_SE: case TK_ANCHOR_E: case TK_ANCHOR_NE:
|
||
break;
|
||
}
|
||
dx += extraX;
|
||
|
||
for (p.item = lPtr->itemHead; p.item; p.item=p.item->next) {
|
||
int extraY;
|
||
dx += p.item->padX;
|
||
|
||
extraY = lPtr->height - 2*lPtr->padY - p.item->height;
|
||
switch (p.item->anchor) {
|
||
case TK_ANCHOR_SW: case TK_ANCHOR_S: case TK_ANCHOR_SE:
|
||
break;
|
||
case TK_ANCHOR_W: case TK_ANCHOR_CENTER: case TK_ANCHOR_E:
|
||
extraY /= 2;
|
||
break;
|
||
case TK_ANCHOR_NW: case TK_ANCHOR_N: case TK_ANCHOR_NE:
|
||
extraY = 0;
|
||
break;
|
||
}
|
||
|
||
switch (p.item->type) {
|
||
case TYPE_IMAGE:
|
||
Tk_RedrawImage(p.image->image, 0, 0,
|
||
p.image->width - 2*p.item->padX,
|
||
p.image->height - 2*p.item->padY,
|
||
drawable, dx, dy+extraY);
|
||
break;
|
||
|
||
case TYPE_SPACE:
|
||
/* Do nothing */
|
||
break;
|
||
|
||
case TYPE_TEXT:
|
||
{
|
||
TixFont font;
|
||
|
||
if (p.text->text == NULL) {
|
||
break;
|
||
}
|
||
|
||
if (p.text->font) {
|
||
font = p.text->font;
|
||
} else {
|
||
font = masterPtr->font;
|
||
}
|
||
|
||
TixDisplayText(Tk_Display(masterPtr->tkwin), drawable,
|
||
font, p.text->text, p.text->numChars,
|
||
dx, dy+extraY,
|
||
p.text->width - 2*p.item->padX,
|
||
p.text->justify,
|
||
p.text->underline,
|
||
p.text->gc);
|
||
}
|
||
break;
|
||
|
||
case TYPE_BITMAP:
|
||
XCopyPlane(Tk_Display(masterPtr->tkwin), p.bitmap->bitmap,
|
||
drawable, p.bitmap->gc, 0, 0,
|
||
(unsigned) p.bitmap->width - 2*p.item->padX,
|
||
(unsigned) p.bitmap->height - 2*p.item->padY,
|
||
dx, dy+extraY, 1);
|
||
|
||
break;
|
||
|
||
case TYPE_WIDGET:
|
||
|
||
|
||
break;
|
||
}
|
||
dx += p.item->width - p.item->padX;
|
||
}
|
||
dy += lPtr->height - lPtr->padY;
|
||
}
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* ImgCmpFree --
|
||
*
|
||
* This procedure is called when a widget ceases to use a
|
||
* particular instance of an image.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Internal data structures get cleaned up.
|
||
*
|
||
* Arguments:
|
||
* clientData -- Pointer to CmpInstance for instance to be displayed
|
||
* display -- Display containing image window
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static void
|
||
ImgCmpFree(clientData, display)
|
||
ClientData clientData;
|
||
Display *display;
|
||
{
|
||
/*
|
||
* Since one compound image can only be used in one window, when
|
||
* that window is deleted, this image is now useless and should be
|
||
* deleted as well
|
||
*/
|
||
}
|
||
|
||
static void FreeLine(lPtr)
|
||
CmpLine * lPtr;
|
||
{
|
||
Tk_FreeOptions(lineConfigSpecs, (char *)lPtr,
|
||
Tk_Display(lPtr->masterPtr->tkwin), 0);
|
||
ckfree((char *) lPtr);
|
||
}
|
||
|
||
static void FreeItem(p)
|
||
CmpItemPtr p;
|
||
{
|
||
switch (p.item->type) {
|
||
case TYPE_IMAGE:
|
||
if (p.image->image) {
|
||
Tk_FreeImage(p.image->image);
|
||
}
|
||
Tk_FreeOptions(imageConfigSpecs, (char *)p.image,
|
||
Tk_Display(p.item->line->masterPtr->tkwin), 0);
|
||
break;
|
||
|
||
case TYPE_SPACE:
|
||
Tk_FreeOptions(spaceConfigSpecs, (char *)p.space,
|
||
Tk_Display(p.item->line->masterPtr->tkwin), 0);
|
||
break;
|
||
|
||
case TYPE_TEXT:
|
||
if (p.text->gc != None) {
|
||
Tk_FreeGC(Tk_Display(p.text->line->masterPtr->tkwin),
|
||
p.text->gc);
|
||
}
|
||
Tk_FreeOptions(textConfigSpecs, (char *)p.text,
|
||
Tk_Display(p.item->line->masterPtr->tkwin), 0);
|
||
break;
|
||
|
||
case TYPE_BITMAP:
|
||
if (p.bitmap->gc != None) {
|
||
Tk_FreeGC(Tk_Display(p.bitmap->line->masterPtr->tkwin),
|
||
p.bitmap->gc);
|
||
}
|
||
Tk_FreeOptions(bitmapConfigSpecs, (char *)p.bitmap,
|
||
Tk_Display(p.item->line->masterPtr->tkwin), 0);
|
||
break;
|
||
|
||
case TYPE_WIDGET:
|
||
break;
|
||
}
|
||
ckfree((char *) p.item);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* ImgCmpFreeResources --
|
||
*
|
||
* This procedure frees resources associated with the window
|
||
* specified with the -window arg to "image create compound ..."
|
||
*
|
||
* This procedure must be called from both ImgCmpDelete and from
|
||
* the destroy notifier CmpEventProc() (for the -window window)
|
||
* in order to ensure resources are freed under all circumstances.
|
||
*
|
||
* The way Tk shuts down windows (in tkWindow.c) does not allow
|
||
* the destroy notifier CmpEventProc() to just delete the TCL
|
||
* command associated with the image. The destroy notifier for
|
||
* the TCL command calls Tk_DeleteImage(). This command has no
|
||
* effect when Tk is shutting down (see tkImage.c) since the main
|
||
* window has already been removed from the main window list. As
|
||
* a result, ImgCmpDelete() doesn't get called when we want it to.
|
||
*
|
||
* Later, tkWindow.c will call tkDeleteAllImages() to delete all
|
||
* images, but by then the window referred to by masterPtr->tkwin
|
||
* is gone. ImgCmdDelete cannot free the resources.
|
||
*
|
||
* By allowing CmpEventProc() to do most of the cleanup, we avoid
|
||
* this situation.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Resources associated with the image get freed, new image command
|
||
* is removed from interpreter.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
static void
|
||
ImgCmpFreeResources(masterData)
|
||
ClientData masterData; /* Pointer to CmpMaster structure for
|
||
* image. Must not have any more instances. */
|
||
{
|
||
CmpMaster *masterPtr = (CmpMaster *) masterData;
|
||
CmpLine * lPtr;
|
||
CmpItemPtr p;
|
||
|
||
if (masterPtr->tkwin == NULL) {
|
||
return ;
|
||
}
|
||
|
||
Tk_Preserve((ClientData) masterPtr);
|
||
|
||
if (masterPtr->isDeleted == 0) {
|
||
masterPtr->isDeleted = 1;
|
||
|
||
Tk_DeleteEventHandler(masterPtr->tkwin,
|
||
StructureNotifyMask,
|
||
CmpEventProc, (ClientData)masterPtr);
|
||
for (lPtr=masterPtr->lineHead; lPtr;) {
|
||
CmpLine * toDelete = lPtr;
|
||
lPtr = lPtr->next;
|
||
|
||
for (p.item=toDelete->itemHead; p.item;) {
|
||
CmpItemPtr toDelete;
|
||
|
||
toDelete.item = p.item;
|
||
p.item=p.item->next;
|
||
|
||
FreeItem(toDelete);
|
||
}
|
||
FreeLine(toDelete);
|
||
}
|
||
|
||
if (masterPtr->changing) {
|
||
Tk_CancelIdleCall(CalculateMasterSize, (ClientData)masterPtr);
|
||
}
|
||
masterPtr->tkMaster = NULL;
|
||
|
||
if (masterPtr->imageCmd != NULL) {
|
||
CONST84 char * cmd = Tcl_GetCommandName(masterPtr->interp,
|
||
masterPtr->imageCmd);
|
||
masterPtr->imageCmd = NULL;
|
||
Tcl_DeleteCommand(masterPtr->interp, cmd);
|
||
}
|
||
|
||
if (masterPtr->gc != None) {
|
||
Tk_FreeGC(masterPtr->display, masterPtr->gc);
|
||
}
|
||
|
||
Tk_FreeOptions(configSpecs, (char *) masterPtr, masterPtr->display, 0);
|
||
}
|
||
|
||
Tk_Release((ClientData) masterPtr);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* ImgCmpDelete --
|
||
*
|
||
* This procedure is called by the image code to delete the
|
||
* master structure for an image.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Resources associated with the image get freed.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
static void
|
||
ImgCmpDelete(masterData)
|
||
ClientData masterData; /* Pointer to CmpMaster structure for
|
||
* image. Must not have any more instances. */
|
||
{
|
||
CmpMaster *masterPtr = (CmpMaster *) masterData;
|
||
|
||
ImgCmpFreeResources(masterData);
|
||
ckfree((char *) masterPtr);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* ImgCmpCmdDeletedProc --
|
||
*
|
||
* This procedure is invoked when the image command for an image
|
||
* is deleted. It deletes the image.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* The image is deleted.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
static void
|
||
ImgCmpCmdDeletedProc(clientData)
|
||
ClientData clientData; /* Pointer to CmpMaster structure for
|
||
* image. */
|
||
{
|
||
CmpMaster *masterPtr = (CmpMaster *) clientData;
|
||
|
||
masterPtr->imageCmd = NULL;
|
||
|
||
if (masterPtr->tkMaster != NULL) {
|
||
Tk_DeleteImage(masterPtr->interp,
|
||
Tk_NameOfImage(masterPtr->tkMaster));
|
||
}
|
||
}
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* ImageProc --
|
||
*
|
||
* This procedure is invoked by the image code whenever the manager
|
||
* for an image does something that affects the size or contents
|
||
* of an image displayed in a button.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Arranges for the HList to get redisplayed.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
static void
|
||
ImageProc(clientData, x, y, width, height, imgWidth, imgHeight)
|
||
ClientData clientData; /* Pointer to widget record. */
|
||
int x, y; /* Upper left pixel (within image)
|
||
* that must be redisplayed. */
|
||
int width, height; /* Dimensions of area to redisplay
|
||
* (may be <= 0). */
|
||
int imgWidth, imgHeight; /* New dimensions of image. */
|
||
{
|
||
CmpItemPtr p;
|
||
|
||
p.image = (CmpImageItem *)clientData;
|
||
|
||
ChangeImageWhenIdle(p.item->line->masterPtr);
|
||
}
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* CmpEventProc --
|
||
*
|
||
* This procedure is invoked by the Tk dispatcher for various
|
||
* events on the window that employs this compound image.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* When the window gets deleted, internal structures get
|
||
* cleaned up.
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
|
||
static void
|
||
CmpEventProc(clientData, eventPtr)
|
||
ClientData clientData; /* Information about window. */
|
||
XEvent *eventPtr; /* Information about event. */
|
||
{
|
||
/* CmpMaster *masterPtr = (CmpMaster *)clientData; */
|
||
|
||
if (eventPtr->type == DestroyNotify) {
|
||
ImgCmpFreeResources(clientData);
|
||
}
|
||
}
|