/*
* tkCanvas.c --
*
* This module implements canvas widgets for the Tk toolkit.
* A canvas displays a background and a collection of graphical
* objects such as rectangles, lines, and texts.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1995 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: @(#) tkCanvas.c 1.119 96/03/21 11:26:39
*/
#include "tkInt.h"
#include "tkCanvas.h"
#include "tkDefault.h"
/*
* See tkCanvas.h for key data structures used to implement canvases.
*/
/*
* The structure defined below is used to keep track of a tag search
* in progress. Only the "prevPtr" field should be accessed by anyone
* other than StartTagSearch and NextItem.
*/
typedef struct TagSearch {
* all items. */
* if last one found was first in the item
* list of canvasPtr). */
* return NULL. */
} TagSearch;
/*
* Information used for argv parsing.
*/
(char *) NULL, 0, 0},
(char *) NULL, 0, 0},
"HighlightBackground", DEF_CANVAS_HIGHLIGHT_BG,
"HighlightThickness",
"ScrollIncrement",
0},
"ScrollIncrement",
0},
(char *) NULL, 0, 0}
};
/*
* List of all the item types known at present:
*/
* been done yet. */
/*
* Standard item types provided by Tk:
*/
/*
* Various Tk_Uid's used by this module (set up during initialization):
*/
/*
* Statistics counters:
*/
static int numIdSearches;
static int numSlowSearches;
/*
* Prototypes for procedures defined later in this file:
*/
static void CanvasCmdDeletedProc _ANSI_ARGS_((
static int CanvasFetchSelection _ANSI_ARGS_((
double coords[2]));
int gotFocus));
static void CanvasLostSelection _ANSI_ARGS_((
static void CanvasUpdateScrollbars _ANSI_ARGS_((
int flags));
int enclosed));
static void InitCanvas _ANSI_ARGS_((void));
char *string));
/*
*--------------------------------------------------------------
*
* Tk_CanvasCmd --
*
* This procedure is invoked to process the "canvas" Tcl
* command. See the user documentation for details on what
* it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*--------------------------------------------------------------
*/
int
* interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
InitCanvas();
}
if (argc < 2) {
return TCL_ERROR;
}
return TCL_ERROR;
}
/*
* Initialize fields that won't be initialized by ConfigureCanvas,
* or which ConfigureCanvas expects to have reasonable values
* (e.g. resource pointers).
*/
canvasPtr->borderWidth = 0;
canvasPtr->highlightWidth = 0;
canvasPtr->insertOnTime = 0;
canvasPtr->insertOffTime = 0;
canvasPtr->xScrollIncrement = 0;
canvasPtr->yScrollIncrement = 0;
canvasPtr->scanXOrigin = 0;
canvasPtr->scanYOrigin = 0;
(ClientData) canvasPtr);
goto error;
}
return TCL_OK;
return TCL_ERROR;
}
/*
*--------------------------------------------------------------
*
* CanvasWidgetCmd --
*
* This procedure is invoked to process the Tcl command
* 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.
*
*--------------------------------------------------------------
*/
static int
* widget. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
int c, result;
* prevent compiler warning. */
if (argc < 2) {
return TCL_ERROR;
}
c = argv[1][0];
if (argc < 4) {
argv[0], " addtags tag searchCommand ?arg arg ...?\"",
(char *) NULL);
goto error;
}
" addtag tag");
&& (length >= 2)) {
int i, gotAny;
* only to prevent compiler
* warnings. */
if (argc < 3) {
argv[0], " bbox tagOrId ?tagOrId ...?\"",
(char *) NULL);
goto error;
}
gotAny = 0;
for (i = 2; i < argc; i++) {
continue;
}
if (!gotAny) {
gotAny = 1;
} else {
}
}
}
}
}
}
}
if (gotAny) {
}
&& (length >= 2)) {
argv[0], " bind tagOrId ?sequence? ?command?\"",
(char *) NULL);
goto error;
}
/*
* Figure out what object to use for the binding (individual
* item vs. tag).
*/
object = 0;
int id;
char *end;
if (*end != 0) {
goto bindByTag;
}
break;
}
}
if (object == 0) {
"\" doesn't exist", (char *) NULL);
goto error;
}
} else {
}
/*
* Make a binding table if the canvas doesn't already have
* one.
*/
}
if (argc == 5) {
int append = 0;
unsigned long mask;
if (argv[4][0] == 0) {
goto done;
}
argv[4]++;
append = 1;
}
if (mask == 0) {
goto error;
}
"events may be used", (char *) NULL);
goto error;
}
} else if (argc == 4) {
char *command;
goto error;
}
} else {
}
int x;
double grid;
argv[0], " canvasx screenx ?gridspacing?\"",
(char *) NULL);
goto error;
}
goto error;
}
if (argc == 4) {
goto error;
}
} else {
grid = 0.0;
}
int y;
double grid;
argv[0], " canvasy screeny ?gridspacing?\"",
(char *) NULL);
goto error;
}
goto error;
}
if (argc == 4) {
goto error;
}
} else {
grid = 0.0;
}
&& (length >= 2)) {
if (argc != 3) {
argv[0], " cget option\"",
(char *) NULL);
goto error;
}
&& (length >= 3)) {
if (argc == 2) {
} else if (argc == 3) {
} else {
}
&& (length >= 3)) {
if (argc < 3) {
argv[0], " coords tagOrId ?x y x y ...?\"",
(char *) NULL);
goto error;
}
if (argc != 3) {
}
}
if (argc != 3) {
}
}
&& (length >= 2)) {
if (argc < 3) {
goto error;
}
c = argv[2][0];
"unknown or ambiguous item type \"",
goto error;
}
}
}
goto badType;
}
goto error;
}
} else {
}
&& (length >= 2)) {
argv[0], " dchars tagOrId first ?last?\"",
(char *) NULL);
goto error;
}
continue;
}
goto error;
}
if (argc == 5) {
!= TCL_OK) {
goto error;
}
} else {
}
/*
* Redraw both item's old and new areas: it's possible
* that a delete could result in a new area larger than
* the old area.
*/
}
&& (length >= 2)) {
int i;
for (i = 2; i < argc; i++) {
(ClientData) itemPtr);
}
}
}
} else {
}
}
}
}
}
}
}
}
}
&& (length >= 2)) {
int i;
argv[0], " dtag tagOrId ?tagToDelete?\"",
(char *) NULL);
goto error;
}
if (argc == 4) {
} else {
}
}
}
}
&& (length >= 2)) {
if (argc < 3) {
argv[0], " find searchCommand ?arg arg ...?\"",
(char *) NULL);
goto error;
}
argv[0]," find");
&& (length >= 2)) {
if (argc > 3) {
argv[0], " focus ?tagOrId?\"",
(char *) NULL);
goto error;
}
if (argc == 2) {
}
goto done;
}
}
if (argv[2][0] == 0) {
goto done;
}
break;
}
}
goto done;
}
}
if (argc != 3) {
goto error;
}
int i;
}
}
&& (length >= 2)) {
int index;
if (argc != 4) {
argv[0], " icursor tagOrId index\"",
(char *) NULL);
goto error;
}
goto done;
}
goto error;
}
index);
}
}
&& (length >= 3)) {
int index;
if (argc != 4) {
argv[0], " index tagOrId string\"",
(char *) NULL);
goto error;
}
break;
}
}
goto error;
}
goto error;
}
&& (length >= 3)) {
int beforeThis;
if (argc != 5) {
argv[0], " insert tagOrId beforeThis string\"",
(char *) NULL);
goto error;
}
continue;
}
goto error;
}
/*
* Redraw both item's old and new areas: it's possible
* that an insertion could result in a new area either
* larger or smaller than the old area.
*/
}
&& (length >= 6)) {
if (argc != 4) {
argv[0], " itemcget tagOrId option\"",
(char *) NULL);
return TCL_ERROR;
}
argv[3], 0);
}
&& (length >= 6)) {
if (argc < 3) {
argv[0], " itemconfigure tagOrId ?option value ...?\"",
(char *) NULL);
goto error;
}
if (argc == 3) {
(char *) NULL, 0);
} else if (argc == 4) {
argv[3], 0);
} else {
}
break;
}
}
argv[0], " lower tagOrId ?belowThis?\"",
(char *) NULL);
goto error;
}
/*
* First find the item just after which we'll insert the
* named items.
*/
if (argc == 3) {
} else {
} else {
"\" doesn't match any items", (char *) NULL);
goto error;
}
}
if (argc != 5) {
argv[0], " move tagOrId xAmount yAmount\"",
(char *) NULL);
goto error;
}
goto error;
}
}
argv[0], " raise tagOrId ?aboveThis?\"",
(char *) NULL);
goto error;
}
/*
* First find the item just after which we'll insert the
* named items.
*/
if (argc == 3) {
} else {
}
"\" doesn't match any items", (char *) NULL);
goto error;
}
}
&& (length >= 3)) {
if (argc != 7) {
argv[0], " scale tagOrId xOrigin yOrigin xScale yScale\"",
(char *) NULL);
goto error;
}
goto error;
}
goto error;
}
}
&& (length >= 3)) {
int x, y;
if (argc != 5) {
goto error;
}
goto error;
}
/*
* Compute a new view origin for the canvas, amplifying the
* mouse motion.
*/
} else {
"\": must be mark or dragto", (char *) NULL);
goto error;
}
&& (length >= 2)) {
int index;
if (argc < 3) {
goto error;
}
if (argc >= 4) {
break;
}
}
"can't find an indexable and selectable item \"",
goto error;
}
}
if (argc == 5) {
goto error;
}
}
c = argv[2][0];
if (argc != 5) {
argv[0], " select adjust tagOrId index\"",
(char *) NULL);
goto error;
}
} else {
}
}
if (argc != 3) {
goto error;
}
}
goto done;
if (argc != 5) {
argv[0], " select from tagOrId index\"",
(char *) NULL);
goto error;
}
if (argc != 3) {
goto error;
}
}
if (argc != 5) {
argv[0], " select to tagOrId index\"",
(char *) NULL);
goto error;
}
} else {
"\": must be adjust, clear, from, item, or to",
(char *) NULL);
goto error;
}
if (argc != 3) {
goto error;
}
}
* gcc warnings. */
double fraction;
if (argc == 2) {
} else {
switch (type) {
case TK_SCROLL_ERROR:
goto error;
case TK_SCROLL_MOVETO:
break;
case TK_SCROLL_PAGES:
break;
case TK_SCROLL_UNITS:
if (canvasPtr->xScrollIncrement > 0) {
} else {
}
break;
}
}
* gcc warnings. */
double fraction;
if (argc == 2) {
} else {
switch (type) {
case TK_SCROLL_ERROR:
goto error;
case TK_SCROLL_MOVETO:
break;
case TK_SCROLL_PAGES:
break;
case TK_SCROLL_UNITS:
if (canvasPtr->yScrollIncrement > 0) {
} else {
}
break;
}
}
} else {
"\": must be addtag, bbox, bind, ",
"canvasx, canvasy, cget, configure, coords, create, ",
"dchars, delete, dtag, find, focus, ",
"gettags, icursor, index, insert, itemcget, itemconfigure, ",
"lower, move, postscript, raise, scale, scan, ",
"select, type, xview, or yview",
(char *) NULL);
goto error;
}
done:
return result;
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* DestroyCanvas --
*
* This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
* to clean up the internal structure of a canvas at a safe time
* (when no-one is using it anymore).
*
* Results:
* None.
*
* Side effects:
* Everything associated with the canvas is freed up.
*
*----------------------------------------------------------------------
*/
static void
char *memPtr; /* Info about canvas widget. */
{
/*
* Free up all of the items in the canvas.
*/
}
}
/*
* Free up all the stuff that requires special handling,
* then let Tk_FreeOptions handle all the standard option-related
* stuff.
*/
}
}
}
/*
*----------------------------------------------------------------------
*
* ConfigureCanvas --
*
* the Tk option database, in order to configure (or
* reconfigure) a canvas widget.
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
* returned, then interp->result contains an error message.
*
* Side effects:
* Configuration information, such as colors, border width,
* etc. get set for canvasPtr; old resources get freed,
* if there were any.
*
*----------------------------------------------------------------------
*/
static int
* not already have values for some fields. */
int argc; /* Number of valid entries in argv. */
char **argv; /* Arguments. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
return TCL_ERROR;
}
/*
* A few options need special processing, such as setting the
* background from a 3-D border and creating a GC for copying
* bits to the screen.
*/
if (canvasPtr->highlightWidth < 0) {
canvasPtr->highlightWidth = 0;
}
}
/*
* Reset the desired dimensions for the window.
*/
/*
* Restart the cursor timing sequence in case the on-time or off-time
* just changed.
*/
}
/*
* Recompute the scroll region.
*/
int argc2;
char **argv2;
return TCL_ERROR;
}
if (argc2 != 4) {
return TCL_ERROR;
}
goto badRegion;
}
}
/*
* Reset the canvas's origin (this is a no-op unless confine
* mode has just been turned on or the scroll region has changed).
*/
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
* DisplayCanvas --
*
* This procedure redraws the contents of a canvas window.
* It is invoked as a do-when-idle handler, so it only runs
* when there's nothing else for the application to do.
*
* Results:
* None.
*
* Side effects:
* Information appears on the screen.
*
*--------------------------------------------------------------
*/
static void
{
return;
}
if (!Tk_IsMapped(tkwin)) {
goto done;
}
/*
* Choose a new current item if that is needed (this could cause
* event handlers to be invoked).
*/
return;
}
}
/*
* Compute the intersection between the area that needs redrawing
* and the area that's visible on the screen.
*/
}
}
}
}
goto borders;
}
/*
* Redrawing is done in a temporary pixmap that is allocated
* here and freed at the end of the procedure. All drawing
* is done to the pixmap, and the pixmap is copied to the
* screen at the end of the procedure. The temporary pixmap
* serves two purposes:
*
* 1. It provides a smoother visual effect (no clearing and
* gradual redraw will be visible to users).
* 2. It allows us to redraw only the objects that overlap
* the redraw area. Otherwise incorrect results could
* occur from redrawing things that stick outside of
* the redraw area (we'd have to redraw everything in
* order to make the overlaps look right).
*
* Some tricky points about the pixmap:
*
* 1. We only allocate a large enough pixmap to hold the
* area that has to be redisplayed. This saves time in
* in the X server for large objects that cover much
* more than the area being redisplayed: only the area
* of the pixmap will actually have to be redrawn.
* 2. Some X servers (e.g. the one for DECstations) have troubles
* with characters that overlap an edge of the pixmap (on the
* DEC servers, as of 8/18/92, such characters are drawn one
* pixel too far to the right). To handle this problem,
* make the pixmap a bit larger than is absolutely needed
* so that for normal-sized fonts the characters that overlap
* the edge of the pixmap will be outside the area we care
* about.
*/
/*
* Clear the area to be redrawn.
*/
(unsigned int) height);
/*
* Scan through the item list, redrawing those items that need it.
* An item must be redraw if either (a) it intersects the smaller
* on-screen area or (b) it intersects the full canvas area and its
* type requests that it be redrawn always (e.g. so subwindows can
* be unmapped when they move off-screen).
*/
continue;
}
}
height);
}
/*
* Copy from the temporary pixmap to the screen, then free up
* the temporary pixmap.
*/
}
/*
* Draw the window borders, if needed.
*/
if (canvasPtr->borderWidth > 0) {
}
if (canvasPtr->highlightWidth != 0) {
Tk_WindowId(tkwin));
} else {
Tk_WindowId(tkwin));
}
Tk_WindowId(tkwin));
}
}
done:
}
}
/*
*--------------------------------------------------------------
*
* CanvasEventProc --
*
* This procedure is invoked by the Tk dispatcher for various
* events on canvases.
*
* Results:
* None.
*
* Side effects:
* When the window gets deleted, internal structures get
* cleaned up. When it gets exposed, it is redisplayed.
*
*--------------------------------------------------------------
*/
static void
{
int x, y;
}
}
}
/*
* The call below is needed in order to recenter the canvas if
* it's confined and its scroll region is smaller than the window.
*/
}
CanvasFocusProc(canvasPtr, 0);
}
/*
* Special hack: if the canvas is unmapped, then must notify
* all items with "alwaysRedraw" set, so that they know that
* they are no longer displayed.
*/
}
}
}
}
/*
*----------------------------------------------------------------------
*
* CanvasCmdDeletedProc --
*
* This procedure is invoked when a widget command is deleted. If
* the widget isn't already in the process of being destroyed,
* this command destroys it.
*
* Results:
* None.
*
* Side effects:
* The widget is destroyed.
*
*----------------------------------------------------------------------
*/
static void
{
/*
* This procedure could be invoked either because the window was
* destroyed and the command was then deleted (in which case tkwin
* is NULL) or because the command was deleted, and then this procedure
* destroys the widget.
*/
}
}
/*
*--------------------------------------------------------------
*
* Tk_CanvasEventuallyRedraw --
*
* Arrange for part or all of a canvas widget to redrawn at
* some convenient time in the future.
*
* Results:
* None.
*
* Side effects:
* The screen will eventually be refreshed.
*
*--------------------------------------------------------------
*/
void
* Pixels on edge are redrawn. */
* Pixels on edge are not redrawn. */
{
return;
}
}
}
}
}
} else {
}
}
/*
*--------------------------------------------------------------
*
* Tk_CreateItemType --
*
* This procedure may be invoked to add a new kind of canvas
* element to the core item types supported by Tk.
*
* Results:
* None.
*
* Side effects:
* From now on, the new item type will be useable in canvas
* widgets (e.g. typePtr->name can be used as the item type
* in "create" widget commands). If there was already a
* type with the same name as in typePtr, it is replaced with
* the new type.
*
*--------------------------------------------------------------
*/
void
* storage must be statically
* allocated (must live forever). */
{
InitCanvas();
}
/*
* If there's already an item type with the given name, remove it.
*/
} else {
}
break;
}
}
}
/*
*----------------------------------------------------------------------
*
* Tk_GetItemTypes --
*
* This procedure returns a pointer to the list of all item
* types.
*
* Results:
* The return value is a pointer to the first in the list
* of item types currently supported by canvases.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
{
InitCanvas();
}
return typeList;
}
/*
*--------------------------------------------------------------
*
* InitCanvas --
*
* This procedure is invoked to perform once-only-ever
* initialization for the module, such as setting up
* the type table.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static void
{
return;
}
}
/*
*--------------------------------------------------------------
*
* StartTagSearch --
*
* This procedure is called to initiate an enumeration of
* all items in a given canvas that contain a given tag.
*
* Results:
* The return value is a pointer to the first item in
* canvasPtr that matches tag, or NULL if there is no
* such item. The information at *searchPtr is initialized
* such that successive calls to NextItem will return
* successive items that match tag.
*
* Side effects:
* SearchPtr is linked into a list of searches in progress
* on canvasPtr, so that elements can safely be deleted
* while the search is in progress. EndTagSearch must be
* called at the end of the search to unlink searchPtr from
* this list.
*
*--------------------------------------------------------------
*/
static Tk_Item *
* searched. */
char *tag; /* String giving tag value. */
* will be initialized here. */
{
int id;
int count;
/*
* Initialize the search.
*/
searchPtr->searchOver = 0;
/*
* Find the first matching item in one of several ways. If the tag
* is a number then it selects the single item with the matching
* identifier. In this case see if the item being requested is the
* hot item, in which case the search can be skipped.
*/
char *end;
if (*end == 0) {
break;
}
}
}
return itemPtr;
}
}
/*
* All items match.
*/
return canvasPtr->firstItemPtr;
}
/*
* None of the above. Search for an item with a matching tag.
*/
return itemPtr;
}
}
}
return NULL;
}
/*
*--------------------------------------------------------------
*
* NextItem --
*
* This procedure returns successive items that match a given
* tag; it should be called only after StartTagSearch has been
* used to begin a search.
*
* Results:
* The return value is a pointer to the next item that matches
* the tag specified to StartTagSearch, or NULL if no such
* item exists. *SearchPtr is updated so that the next call
* to this procedure will return the next item.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static Tk_Item *
* progress. */
{
int count;
/*
* Find next item in list (this may not actually be a suitable
* one to return), and return if there are no items left.
*/
} else {
}
return NULL;
}
/*
* The structure of the list has changed. Probably the
* previously-returned item was removed from the list.
* In this case, don't advance prevPtr; just return
* its new successor (i.e. do nothing here).
*/
} else {
}
/*
* Handle special case of "all" search by returning next item.
*/
return itemPtr;
}
/*
* Look for an item with a particular tag.
*/
return itemPtr;
}
}
}
return NULL;
}
/*
*--------------------------------------------------------------
*
* DoItem --
*
* This is a utility procedure called by FindItems. It
* either adds itemPtr's id to the result forming in interp,
* or it adds a new tag to itemPtr, depending on the value
* of tag.
*
* Results:
* None.
*
* Side effects:
* If tag is NULL then itemPtr's id is added as a list element
* to interp->result; otherwise tag is added to itemPtr's
* list of tags.
*
*--------------------------------------------------------------
*/
static void
* record item id. */
* present for item, or NULL. */
{
int count;
/*
* Handle the "add-to-result" case and return, if appropriate.
*/
return;
}
return;
}
}
/*
* Grow the tag space if there's no more room left in the current
* block.
*/
}
}
/*
* Add in the new tag.
*/
}
/*
*--------------------------------------------------------------
*
* FindItems --
*
* This procedure does all the work of implementing the
* "find" and "addtag" options of the canvas widget command,
* which locate items that have certain features (location,
* tags, position in display list, etc.).
*
* Results:
* A standard Tcl return value. If newTag is NULL, then a
* returned in interp->result. If newTag is NULL, then
* the normal interp->result is an empty string. If an error
* occurs, then interp->result will hold an error message.
*
* Side effects:
* If newTag is non-NULL, then all the items that match the
* lists of tags.
*
*--------------------------------------------------------------
*/
static int
* searched. */
int argc; /* Number of entries in argv. Must be
* greater than zero. */
char **argv; /* Arguments that describe what items
* to search for (see user doc on
* "find" and "addtag" options). */
char *newTag; /* If non-NULL, gives new tag to set
* on all found items; if NULL, then
* ids of found items are returned
* in interp->result. */
char *cmdName; /* Name of original Tcl command, for
* use in error messages. */
char *option; /* For error messages: gives option
* from Tcl command and other stuff
{
int c;
} else {
}
c = argv[0][0];
&& (length >= 2)) {
if (argc != 2) {
return TCL_ERROR;
}
}
}
&& (length >= 2)) {
if (argc != 1) {
return TCL_ERROR;
}
}
if (argc != 2) {
return TCL_ERROR;
}
}
double closestDist;
(char *) NULL);
return TCL_ERROR;
}
return TCL_ERROR;
}
if (argc > 3) {
return TCL_ERROR;
}
if (halo < 0.0) {
return TCL_ERROR;
}
} else {
halo = 0.0;
}
/*
* Find the item at which to start the search.
*/
if (argc == 5) {
}
}
/*
* The code below is optimized so that it can eliminate most
* items without having to call their item-specific procedures.
* This is done by keeping a bounding box (x1, y1, x2, y2) that
* an item's bbox must overlap if the item is to have any
* chance of being closer than the closest so far.
*/
return TCL_OK;
}
if (closestDist < 0.0) {
closestDist = 0.0;
}
while (1) {
double newDist;
/*
* Update the bounding box using itemPtr, which is the
* new closest item.
*/
/*
* Search for an item that beats the current closest one.
* Work circularly through the canvas's item list until
* getting back to the starting item.
*/
while (1) {
}
return TCL_OK;
}
continue;
}
if (newDist < 0.0) {
newDist = 0.0;
}
if (newDist <= closestDist) {
break;
}
}
}
if (argc != 5) {
return TCL_ERROR;
}
if (argc != 5) {
(char *) NULL);
return TCL_ERROR;
}
if (argc != 2) {
return TCL_ERROR;
}
}
} else {
"\": must be above, all, below, closest, enclosed, ",
"overlapping, or withtag", (char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
* FindArea --
*
* This procedure implements area searches for the "find"
* and "addtag" options.
*
* Results:
* A standard Tcl return value. If newTag is NULL, then a
* list of ids from all the items overlapping or enclosed
* by the rectangle given by argc is returned in interp->result.
* If newTag is NULL, then the normal interp->result is an
* empty string. If an error occurs, then interp->result will
* hold an error message.
*
* Side effects:
* If uid is non-NULL, then all the items overlapping
* or enclosed by the area in argv have that tag added to
* their lists of tags.
*
*--------------------------------------------------------------
*/
static int
* and result storing. */
* searched. */
char **argv; /* Array of four arguments that
* give the coordinates of the
* rectangular area to search. */
* on all found items; if NULL, then
* ids of found items are returned
* in interp->result. */
int enclosed; /* 0 means overlapping or enclosed
* items are OK, 1 means only enclosed
* items are OK. */
{
return TCL_ERROR;
}
}
}
/*
* Use an integer bounding box for a quick test, to avoid
* calling item-specific code except for items that are close.
*/
continue;
}
>= enclosed) {
}
}
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
* RelinkItems --
*
* Move one or more items to a different place in the
* display order for a canvas.
*
* Results:
* None.
*
* Side effects:
* The items identified by "tag" are moved so that they
* are all together in the display list and immediately
* after prevPtr. The order of the moved items relative
* to each other is not changed.
*
*--------------------------------------------------------------
*/
static void
char *tag; /* Tag identifying items to be moved
* in the redisplay list. */
* go just after this item (NULL means
* put at beginning of list). */
{
/*
* Find all of the items to be moved and remove them from
* the list, making an auxiliary list running from firstMovePtr
* to lastMovePtr. Record their areas for redisplay.
*/
/*
* Item after which insertion is to occur is being
* moved! Switch to insert after its predecessor.
*/
}
} else {
}
}
if (firstMovePtr == NULL) {
} else {
}
}
/*
* Insert the list of to-be-moved items back into the canvas's
* at the desired position.
*/
if (firstMovePtr == NULL) {
return;
}
} else {
}
}
}
/*
*--------------------------------------------------------------
*
* CanvasBindProc --
*
* This procedure is invoked by the Tk dispatcher to handle
* events associated with bindings on items.
*
* Results:
* None.
*
* Side effects:
* Depends on the command invoked as part of the binding
* (if there was any).
*
*--------------------------------------------------------------
*/
static void
* happened. */
{
/*
* This code below keeps track of the current modifier state in
* canvasPtr>state. This information is used to defer repicks of
* the current item while buttons are down.
*/
int mask;
case Button1:
mask = Button1Mask;
break;
case Button2:
mask = Button2Mask;
break;
case Button3:
mask = Button3Mask;
break;
case Button4:
mask = Button4Mask;
break;
case Button5:
mask = Button5Mask;
break;
default:
mask = 0;
break;
}
/*
* For button press events, repick the current item using the
* button state before the event, then process the event. For
* button release events, first process the event, then repick
* the current item using the button state *after* the event
* (the button has logically gone up before we change the
* current item).
*/
/*
* On a button press, first repick the current item using
* the button state before the event, the process the event.
*/
} else {
/*
* Button release: first process the event, with the button
* still considered to be down. Then repick the current
* item under the assumption that the button is no longer down.
*/
}
goto done;
goto done;
}
done:
}
/*
*--------------------------------------------------------------
*
* PickCurrentItem --
*
* Find the topmost item in a canvas that contains a given
* location and mark the the current item. If the current
* item has changed, generate a fake exit event on the old
* current item and a fake enter event on the new current
* item.
*
* Results:
* None.
*
* Side effects:
* The current item for canvasPtr may change. If it does,
* then the commands associated with item entry and exit
* could do just about anything. A binding script could
* delete the canvas, so callers should protect themselves
* with Tcl_Preserve and Tcl_Release.
*
*--------------------------------------------------------------
*/
static void
* current item. */
* mouse cursor. Must be EnterWindow,
* LeaveWindow, ButtonRelease, or
* MotionNotify. */
{
int buttonDown;
/*
* Check whether or not a button is down. If so, we'll log entry
* and exit into and out of the current item, but not entry into
* any other item. This implements a form of grabbing equivalent
* to what the X server does for windows.
*/
if (!buttonDown) {
}
/*
* Save information about this event in the canvas. The event in
* the canvas is used for two purposes:
*
* 1. Event bindings: if the current item changes, fake events are
* generated to allow item-enter and item-leave bindings to trigger.
* 2. Reselection: if the current item gets deleted, can use the
* saved event to find a new current item.
* Translate MotionNotify events into EnterNotify events, since that's
* what gets reported to item handlers.
*/
} else {
}
}
/*
* If this is a recursive call (there's already a partially completed
* call pending on the stack; it's in the middle of processing a
* Leave event handler for the old current item) then just return;
* the pending call will do everything that's needed.
*/
return;
}
/*
* A LeaveNotify event automatically means that there's no current
* object, so the check for closest item can be skipped.
*/
} else {
}
/*
* Nothing to do: the current item hasn't changed.
*/
return;
}
/*
* Simulate a LeaveNotify event on the previous current item and
* an EnterNotify event on the new current item. Remove the "current"
* tag from the previous current item and place it on the new current
* item.
*/
int i;
/*
* If the event's detail happens to be NotifyInferior the
* binding mechanism will discard the event. To be consistent,
* always use NotifyAncestor.
*/
/*
* The check below is needed because there could be an event
* handler for <LeaveNotify> that deletes the current item.
*/
break;
}
}
}
/*
* Note: during CanvasDoEvent above, it's possible that
* canvasPtr->newCurrentPtr got reset to NULL because the
* item was deleted.
*/
}
return;
}
/*
* Special note: it's possible that canvasPtr->newCurrentPtr ==
* canvasPtr->currentItemPtr here. This can happen, for example,
* if LEFT_GRABBED_ITEM was set.
*/
}
}
/*
*----------------------------------------------------------------------
*
* CanvasFindClosest --
*
* Given x and y coordinates, find the topmost canvas item that
* is "close" to the coordinates.
*
* Results:
* The return value is a pointer to the topmost item that is
* close to (x,y), or NULL if no item is close.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static Tk_Item *
* not screen, coordinates.) */
{
continue;
}
}
}
return bestPtr;
}
/*
*--------------------------------------------------------------
*
* CanvasDoEvent --
*
* This procedure is called to invoke binding processing
* for a new event that is associated with the current item
* for a canvas.
*
* Results:
* None.
*
* Side effects:
* Depends on the bindings for the canvas. A binding script
* could delete the canvas, so callers should protect themselves
* with Tcl_Preserve and Tcl_Release.
*
*--------------------------------------------------------------
*/
static void
* occurred. */
* is to be processed. */
{
int numObjects, i;
return;
}
}
return;
}
/*
* Set up an array with all the relevant objects for processing
* this event. The relevant objects are (a) the event's item,
* (b) the tags associated with the event's item, and (c) the
* tag "all". If there are a lot of tags then malloc an array
* to hold all of the objects.
*/
if (numObjects <= NUM_STATIC) {
} else {
(numObjects * sizeof(ClientData)));
}
}
/*
* Invoke the binding system, then free up the object array if
* it was malloc-ed.
*/
}
if (objectPtr != staticObjects) {
}
}
/*
*----------------------------------------------------------------------
*
* CanvasBlinkProc --
*
* This procedure is called as a timer handler to blink the
* insertion cursor off and on.
*
* Results:
* None.
*
* Side effects:
* The cursor gets turned on or off, redisplay gets invoked,
* and this procedure reschedules itself.
*
*----------------------------------------------------------------------
*/
static void
{
return;
}
(ClientData) canvasPtr);
} else {
(ClientData) canvasPtr);
}
}
}
/*
*----------------------------------------------------------------------
*
* CanvasFocusProc --
*
* This procedure is called whenever a canvas gets or loses the
* input focus. It's also called whenever the window is
* reconfigured while it has the focus.
*
* Results:
* None.
*
* Side effects:
* The cursor gets turned on or off.
*
*----------------------------------------------------------------------
*/
static void
int gotFocus; /* 1 means window is getting focus, 0 means
* it's losing it. */
{
if (gotFocus) {
if (canvasPtr->insertOffTime != 0) {
(ClientData) canvasPtr);
}
} else {
}
}
if (canvasPtr->highlightWidth > 0) {
}
}
}
/*
*----------------------------------------------------------------------
*
* CanvasSelectTo --
*
* Modify the selection by moving its un-anchored end. This could
* make the selection either larger or smaller.
*
* Results:
* None.
*
* Side effects:
* The selection changes.
*
*----------------------------------------------------------------------
*/
static void
int index; /* Index of element that is to become the
* "other" end of the selection. */
{
/*
* Grab the selection if we don't own it already.
*/
(ClientData) canvasPtr);
}
}
} else {
}
}
}
/*
*--------------------------------------------------------------
*
* CanvasFetchSelection --
*
* This procedure is invoked by Tk to return part or all of
* the selection, when the selection is in a canvas widget.
* This procedure always returns the selection as a STRING.
*
* Results:
* The return value is the number of non-NULL bytes stored
* at buffer. Buffer is filled (or partially filled) with a
* NULL-terminated string containing part or all of the selection,
* as given by offset and maxBytes.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static int
int offset; /* Offset within selection of first
* character to be returned. */
char *buffer; /* Location in which to place
* selection. */
int maxBytes; /* Maximum number of bytes to place
* at buffer, not including terminating
* NULL character. */
{
return -1;
}
return -1;
}
}
/*
*----------------------------------------------------------------------
*
* CanvasLostSelection --
*
* This procedure is called back by Tk when the selection is
* grabbed away from a canvas widget.
*
* Results:
* None.
*
* Side effects:
* The existing selection is unhighlighted, and the window is
* marked as not containing a selection.
*
*----------------------------------------------------------------------
*/
static void
{
}
}
/*
*--------------------------------------------------------------
*
* GridAlign --
*
* Given a coordinate and a grid spacing, this procedure
* computes the location of the nearest grid line to the
* coordinate.
*
* Results:
* The return value is the location of the grid line nearest
* to coord.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static double
double coord; /* Coordinate to grid-align. */
double spacing; /* Spacing between grid lines. If <= 0
* then no alignment is done. */
{
if (spacing <= 0.0) {
return coord;
}
if (coord < 0) {
}
}
/*
*----------------------------------------------------------------------
*
* PrintScrollFractions --
*
* Given the range that's visible in the window and the "100%
* range" for what's in the canvas, print a string containing
* the scroll fractions. This procedure is used for both x
* and y scrolling.
*
* Results:
* The memory pointed to by string is modified to hold
* two real numbers containing the scroll fractions (between
* 0 and 1) corresponding to the other arguments.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static void
int screen1; /* Lowest coordinate visible in the window. */
int screen2; /* Highest coordinate visible in the window. */
int object1; /* Lowest coordinate in the object. */
int object2; /* Highest coordinate in the object. */
char *string; /* Two real numbers get printed here. Must
* have enough storage for two %g
* conversions. */
{
if (range <= 0) {
f1 = 0;
f2 = 1.0;
} else {
if (f1 < 0) {
f1 = 0.0;
}
if (f2 > 1.0) {
f2 = 1.0;
}
}
}
}
/*
*--------------------------------------------------------------
*
* CanvasUpdateScrollbars --
*
* This procedure is invoked whenever a canvas has changed in
* a way that requires scrollbars to be redisplayed (e.g. the
* view in the canvas has changed).
*
* Results:
* None.
*
* Side effects:
* If there are scrollbars associated with the canvas, then
* their scrolling commands are invoked to cause them to
* redisplay. If errors occur, additional Tcl commands may
* be invoked to process the errors.
*
*--------------------------------------------------------------
*/
static void
{
int result;
/*
* Save all the relevant values from the canvasPtr, because it might be
* deleted as part of either of the two calls to Tcl_VarEval below.
*/
if (xScrollCmd != (char *) NULL) {
}
if (yScrollCmd != (char *) NULL) {
}
}
}
if (yScrollCmd != NULL) {
}
}
}
/*
*--------------------------------------------------------------
*
* CanvasSetOrigin --
*
* This procedure is invoked to change the mapping between
* canvas coordinates and screen coordinates in the canvas
* window.
*
* Results:
* None.
*
* Side effects:
* The canvas will be redisplayed to reflect the change in
* view. In addition, scrollbars will be updated if there
* are any.
*
*--------------------------------------------------------------
*/
static void
int xOrigin; /* New X origin for canvas (canvas x-coord
* corresponding to left edge of canvas
* window). */
int yOrigin; /* New Y origin for canvas (canvas y-coord
* corresponding to top edge of canvas
* window). */
{
/*
* If scroll increments have been set, round the window origin
* to the nearest multiple of the increments. Remember, the
* origin is the place just inside the borders, not the upper
* left corner.
*/
if (canvasPtr->xScrollIncrement > 0) {
if (xOrigin >= 0) {
} else {
}
}
if (canvasPtr->yScrollIncrement > 0) {
if (yOrigin >= 0) {
} else {
}
}
/*
* Adjust the origin if necessary to keep as much as possible of the
* canvas in the view. The variables left, right, etc. keep track of
* how much extra space there is on each side of the view before it
* will stick out past the scroll region. If one side sticks out past
* the edge of the scroll region, adjust the view to bring that side
* back to the edge of the scrollregion (but don't move it so much that
* the other side sticks out now). If scroll increments are in effect,
* be sure to adjust only by full increments.
*/
if (canvasPtr->xScrollIncrement > 0) {
}
if (canvasPtr->xScrollIncrement > 0) {
}
}
if (canvasPtr->yScrollIncrement > 0) {
}
if (canvasPtr->yScrollIncrement > 0) {
}
}
}
return;
}
/*
* Tricky point: must redisplay not only everything that's visible
* in the window's final configuration, but also everything that was
* visible in the initial configuration. This is needed because some
* item types, like windows, need to know when they move off-screen
* so they can explicitly undisplay themselves.
*/
}