summaryrefslogtreecommitdiffstats
path: root/generic/tkTextWind.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tkTextWind.c')
-rw-r--r--generic/tkTextWind.c1318
1 files changed, 767 insertions, 551 deletions
diff --git a/generic/tkTextWind.c b/generic/tkTextWind.c
index 9f2582e..ecafd4e 100644
--- a/generic/tkTextWind.c
+++ b/generic/tkTextWind.c
@@ -1,47 +1,37 @@
-/*
+/*
* tkTextWind.c --
*
- * This file contains code that allows arbitrary windows to be
- * nested inside text widgets. It also implements the "window"
- * widget command for texts.
+ * This file contains code that allows arbitrary windows to be nested
+ * inside text widgets. It also implements the "window" widget command
+ * for texts.
*
* Copyright (c) 1994 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
-#include "tk.h"
-#include "tkText.h"
#include "tkPort.h"
+#include "tkText.h"
/*
- * The following structure is the official type record for the
- * embedded window geometry manager:
+ * The following structure is the official type record for the embedded window
+ * geometry manager:
*/
-static void EmbWinRequestProc _ANSI_ARGS_((ClientData clientData,
- Tk_Window tkwin));
-static void EmbWinLostSlaveProc _ANSI_ARGS_((ClientData clientData,
- Tk_Window tkwin));
+static void EmbWinRequestProc(ClientData clientData,
+ Tk_Window tkwin);
+static void EmbWinLostSlaveProc(ClientData clientData,
+ Tk_Window tkwin);
-static Tk_GeomMgr textGeomType = {
+static const Tk_GeomMgr textGeomType = {
"text", /* name */
EmbWinRequestProc, /* requestProc */
EmbWinLostSlaveProc, /* lostSlaveProc */
};
/*
- * Definitions for alignment values:
- */
-
-#define ALIGN_BOTTOM 0
-#define ALIGN_CENTER 1
-#define ALIGN_TOP 2
-#define ALIGN_BASELINE 3
-
-/*
* Macro that determines the size of an embedded window segment:
*/
@@ -49,85 +39,79 @@ static Tk_GeomMgr textGeomType = {
+ sizeof(TkTextEmbWindow)))
/*
- * Prototypes for procedures defined in this file:
+ * Prototypes for functions defined in this file:
*/
-static int AlignParseProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, Tk_Window tkwin,
- CONST char *value, char *widgRec, int offset));
-static char * AlignPrintProc _ANSI_ARGS_((ClientData clientData,
- Tk_Window tkwin, char *widgRec, int offset,
- Tcl_FreeProc **freeProcPtr));
-static TkTextSegment * EmbWinCleanupProc _ANSI_ARGS_((TkTextSegment *segPtr,
- TkTextLine *linePtr));
-static void EmbWinCheckProc _ANSI_ARGS_((TkTextSegment *segPtr,
- TkTextLine *linePtr));
-static void EmbWinBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr,
- int index, int y, int lineHeight, int baseline,
- int *xPtr, int *yPtr, int *widthPtr,
- int *heightPtr));
-static int EmbWinConfigure _ANSI_ARGS_((TkText *textPtr,
- TkTextSegment *ewPtr, int argc, CONST char **argv));
-static void EmbWinDelayedUnmap _ANSI_ARGS_((
- ClientData clientData));
-static int EmbWinDeleteProc _ANSI_ARGS_((TkTextSegment *segPtr,
- TkTextLine *linePtr, int treeGone));
-static void EmbWinDisplayProc _ANSI_ARGS_((
- TkTextDispChunk *chunkPtr, int x, int y,
- int lineHeight, int baseline, Display *display,
- Drawable dst, int screenY));
-static int EmbWinLayoutProc _ANSI_ARGS_((TkText *textPtr,
+static TkTextSegment * EmbWinCleanupProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static void EmbWinCheckProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr);
+static void EmbWinBboxProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr, int index, int y,
+ int lineHeight, int baseline, int *xPtr,int *yPtr,
+ int *widthPtr, int *heightPtr);
+static int EmbWinConfigure(TkText *textPtr, TkTextSegment *ewPtr,
+ int objc, Tcl_Obj *const objv[]);
+static void EmbWinDelayedUnmap(ClientData clientData);
+static int EmbWinDeleteProc(TkTextSegment *segPtr,
+ TkTextLine *linePtr, int treeGone);
+static int EmbWinLayoutProc(TkText *textPtr,
TkTextIndex *indexPtr, TkTextSegment *segPtr,
- int offset, int maxX, int maxChars,
- int noCharsYet, TkWrapMode wrapMode,
- TkTextDispChunk *chunkPtr));
-static void EmbWinStructureProc _ANSI_ARGS_((ClientData clientData,
- XEvent *eventPtr));
-static void EmbWinUndisplayProc _ANSI_ARGS_((TkText *textPtr,
- TkTextDispChunk *chunkPtr));
+ int offset, int maxX, int maxChars,int noCharsYet,
+ TkWrapMode wrapMode, TkTextDispChunk *chunkPtr);
+static void EmbWinStructureProc(ClientData clientData,
+ XEvent *eventPtr);
+static void EmbWinUndisplayProc(TkText *textPtr,
+ TkTextDispChunk *chunkPtr);
+static TkTextEmbWindowClient* EmbWinGetClient(const TkText *textPtr,
+ TkTextSegment *ewPtr);
/*
* The following structure declares the "embedded window" segment type.
*/
-static Tk_SegType tkTextEmbWindowType = {
- "window", /* name */
- 0, /* leftGravity */
- (Tk_SegSplitProc *) NULL, /* splitProc */
- EmbWinDeleteProc, /* deleteProc */
- EmbWinCleanupProc, /* cleanupProc */
- (Tk_SegLineChangeProc *) NULL, /* lineChangeProc */
- EmbWinLayoutProc, /* layoutProc */
- EmbWinCheckProc /* checkProc */
+static const Tk_SegType tkTextEmbWindowType = {
+ "window", /* name */
+ 0, /* leftGravity */
+ NULL, /* splitProc */
+ EmbWinDeleteProc, /* deleteProc */
+ EmbWinCleanupProc, /* cleanupProc */
+ NULL, /* lineChangeProc */
+ EmbWinLayoutProc, /* layoutProc */
+ EmbWinCheckProc /* checkProc */
+};
+
+/*
+ * Definitions for alignment values:
+ */
+
+static const char *alignStrings[] = {
+ "baseline", "bottom", "center", "top", NULL
};
+typedef enum {
+ ALIGN_BASELINE, ALIGN_BOTTOM, ALIGN_CENTER, ALIGN_TOP
+} alignMode;
+
/*
* Information used for parsing window configuration options:
*/
-static Tk_CustomOption alignOption = {AlignParseProc, AlignPrintProc,
- (ClientData) NULL};
-
-static Tk_ConfigSpec configSpecs[] = {
- {TK_CONFIG_CUSTOM, "-align", (char *) NULL, (char *) NULL,
- "center", 0, TK_CONFIG_DONT_SET_DEFAULT, &alignOption},
- {TK_CONFIG_STRING, "-create", (char *) NULL, (char *) NULL,
- (char *) NULL, Tk_Offset(TkTextEmbWindow, create),
- TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
- {TK_CONFIG_INT, "-padx", (char *) NULL, (char *) NULL,
- "0", Tk_Offset(TkTextEmbWindow, padX),
- TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_INT, "-pady", (char *) NULL, (char *) NULL,
- "0", Tk_Offset(TkTextEmbWindow, padY),
- TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_BOOLEAN, "-stretch", (char *) NULL, (char *) NULL,
- "0", Tk_Offset(TkTextEmbWindow, stretch),
- TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,
- (char *) NULL, Tk_Offset(TkTextEmbWindow, tkwin),
- TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0}
+static const Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_STRING_TABLE, "-align", NULL, NULL,
+ "center", -1, Tk_Offset(TkTextEmbWindow, align),
+ 0, (ClientData) alignStrings, 0},
+ {TK_OPTION_STRING, "-create", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextEmbWindow, create), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", NULL, NULL,
+ "0", -1, Tk_Offset(TkTextEmbWindow, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", NULL, NULL,
+ "0", -1, Tk_Offset(TkTextEmbWindow, padY), 0, 0, 0},
+ {TK_OPTION_BOOLEAN, "-stretch", NULL, NULL,
+ "0", -1, Tk_Offset(TkTextEmbWindow, stretch), 0, 0, 0},
+ {TK_OPTION_WINDOW, "-window", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextEmbWindow, tkwin), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END}
};
/*
@@ -135,9 +119,8 @@ static Tk_ConfigSpec configSpecs[] = {
*
* TkTextWindowCmd --
*
- * This procedure implements the "window" widget command
- * for text widgets. See the user documentation for details
- * on what it does.
+ * This function implements the "window" widget command for text widgets.
+ * See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result or error.
@@ -149,100 +132,154 @@ static Tk_ConfigSpec configSpecs[] = {
*/
int
-TkTextWindowCmd(textPtr, interp, argc, argv)
- register TkText *textPtr; /* Information about text widget. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- CONST char **argv; /* Argument strings. Someone else has already
+TkTextWindowCmd(
+ register TkText *textPtr, /* Information about text widget. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. Someone else has already
* parsed this command enough to know that
- * argv[1] is "window". */
+ * objv[1] is "window". */
{
- size_t length;
+ int optionIndex;
+ static const char *windOptionStrings[] = {
+ "cget", "configure", "create", "names", NULL
+ };
+ enum windOptions {
+ WIND_CGET, WIND_CONFIGURE, WIND_CREATE, WIND_NAMES
+ };
register TkTextSegment *ewPtr;
- if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " window option ?arg arg ...?\"", (char *) NULL);
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[2], windOptionStrings,
+ "window option", 0, &optionIndex) != TCL_OK) {
return TCL_ERROR;
}
- length = strlen(argv[2]);
- if ((strncmp(argv[2], "cget", length) == 0) && (length >= 2)) {
+ switch ((enum windOptions) optionIndex) {
+ case WIND_CGET: {
TkTextIndex index;
TkTextSegment *ewPtr;
+ Tcl_Obj *objPtr;
+ TkTextEmbWindowClient *client;
- if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " window cget index option\"",
- (char *) NULL);
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index option");
return TCL_ERROR;
}
- if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
+ if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
return TCL_ERROR;
}
- ewPtr = TkTextIndexToSeg(&index, (int *) NULL);
+ ewPtr = TkTextIndexToSeg(&index, NULL);
if (ewPtr->typePtr != &tkTextEmbWindowType) {
Tcl_AppendResult(interp, "no embedded window at index \"",
- argv[3], "\"", (char *) NULL);
+ Tcl_GetString(objv[3]), "\"", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Copy over client specific value before querying.
+ */
+
+ client = EmbWinGetClient(textPtr, ewPtr);
+ if (client != NULL) {
+ ewPtr->body.ew.tkwin = client->tkwin;
+ } else {
+ ewPtr->body.ew.tkwin = NULL;
+ }
+
+ objPtr = Tk_GetOptionValue(interp, (char *) &ewPtr->body.ew,
+ ewPtr->body.ew.optionTable, objv[4], textPtr->tkwin);
+ if (objPtr == NULL) {
return TCL_ERROR;
}
- return Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs,
- (char *) &ewPtr->body.ew, argv[4], 0);
- } else if ((strncmp(argv[2], "configure", length) == 0) && (length >= 2)) {
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+ }
+ case WIND_CONFIGURE: {
TkTextIndex index;
TkTextSegment *ewPtr;
- if (argc < 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " window configure index ?option value ...?\"",
- (char *) NULL);
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index ?option value ...?");
return TCL_ERROR;
}
- if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
+ if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
return TCL_ERROR;
}
- ewPtr = TkTextIndexToSeg(&index, (int *) NULL);
+ ewPtr = TkTextIndexToSeg(&index, NULL);
if (ewPtr->typePtr != &tkTextEmbWindowType) {
Tcl_AppendResult(interp, "no embedded window at index \"",
- argv[3], "\"", (char *) NULL);
+ Tcl_GetString(objv[3]), "\"", NULL);
return TCL_ERROR;
}
- if (argc == 4) {
- return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
- (char *) &ewPtr->body.ew, (char *) NULL, 0);
- } else if (argc == 5) {
- return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
- (char *) &ewPtr->body.ew, argv[4], 0);
+ if (objc <= 5) {
+ TkTextEmbWindowClient *client;
+ Tcl_Obj* objPtr;
+
+ /*
+ * Copy over client specific value before querying.
+ */
+
+ client = EmbWinGetClient(textPtr, ewPtr);
+ if (client != NULL) {
+ ewPtr->body.ew.tkwin = client->tkwin;
+ } else {
+ ewPtr->body.ew.tkwin = NULL;
+ }
+
+ objPtr = Tk_GetOptionInfo(interp, (char *) &ewPtr->body.ew,
+ ewPtr->body.ew.optionTable, (objc == 5) ? objv[4] : NULL,
+ textPtr->tkwin);
+ if (objPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
} else {
- TkTextChanged(textPtr, &index, &index);
- return EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4);
+ TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index);
+
+ /*
+ * It's probably not true that all window configuration can change
+ * the line height, so we could be more efficient here and only
+ * call this when necessary.
+ */
+
+ TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
+ return EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4);
}
- } else if ((strncmp(argv[2], "create", length) == 0) && (length >= 2)) {
+ }
+ case WIND_CREATE: {
TkTextIndex index;
int lineIndex;
+ TkTextEmbWindowClient *client;
+ int res;
/*
- * Add a new window. Find where to put the new window, and
- * mark that position for redisplay.
+ * Add a new window. Find where to put the new window, and mark that
+ * position for redisplay.
*/
- if (argc < 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " window create index ?option value ...?\"",
- (char *) NULL);
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index ?option value ...?");
return TCL_ERROR;
}
- if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
+ if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
return TCL_ERROR;
}
/*
* Don't allow insertions on the last (dummy) line of the text.
*/
-
- lineIndex = TkBTreeLineIndex(index.linePtr);
- if (lineIndex == TkBTreeNumLines(textPtr->tree)) {
+
+ lineIndex = TkBTreeLinesTo(textPtr, index.linePtr);
+ if (lineIndex == TkBTreeNumLines(textPtr->sharedTextPtr->tree,
+ textPtr)) {
lineIndex--;
- TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &index);
+ TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr,
+ lineIndex, 1000000, &index);
}
/*
@@ -252,49 +289,61 @@ TkTextWindowCmd(textPtr, interp, argc, argv)
ewPtr = (TkTextSegment *) ckalloc(EW_SEG_SIZE);
ewPtr->typePtr = &tkTextEmbWindowType;
ewPtr->size = 1;
- ewPtr->body.ew.textPtr = textPtr;
+ ewPtr->body.ew.sharedTextPtr = textPtr->sharedTextPtr;
ewPtr->body.ew.linePtr = NULL;
ewPtr->body.ew.tkwin = NULL;
ewPtr->body.ew.create = NULL;
ewPtr->body.ew.align = ALIGN_CENTER;
ewPtr->body.ew.padX = ewPtr->body.ew.padY = 0;
ewPtr->body.ew.stretch = 0;
- ewPtr->body.ew.chunkCount = 0;
- ewPtr->body.ew.displayed = 0;
+ ewPtr->body.ew.optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+
+ client = (TkTextEmbWindowClient *)
+ ckalloc(sizeof(TkTextEmbWindowClient));
+ client->next = NULL;
+ client->textPtr = textPtr;
+ client->tkwin = NULL;
+ client->chunkCount = 0;
+ client->displayed = 0;
+ client->parent = ewPtr;
+ ewPtr->body.ew.clients = client;
/*
- * Link the segment into the text widget, then configure it (delete
- * it again if the configuration fails).
+ * Link the segment into the text widget, then configure it (delete it
+ * again if the configuration fails).
*/
- TkTextChanged(textPtr, &index, &index);
+ TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index);
TkBTreeLinkSegment(ewPtr, &index);
- if (EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4) != TCL_OK) {
+ res = EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4);
+ client->tkwin = ewPtr->body.ew.tkwin;
+ if (res != TCL_OK) {
TkTextIndex index2;
- TkTextIndexForwChars(&index, 1, &index2);
- TkBTreeDeleteChars(&index, &index2);
+ TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES);
+ TkBTreeDeleteIndexRange(textPtr->sharedTextPtr->tree, &index,
+ &index2);
return TCL_ERROR;
}
- } else if (strncmp(argv[2], "names", length) == 0) {
+ TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
+ break;
+ }
+ case WIND_NAMES: {
Tcl_HashSearch search;
Tcl_HashEntry *hPtr;
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " window names\"", (char *) NULL);
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
return TCL_ERROR;
}
- for (hPtr = Tcl_FirstHashEntry(&textPtr->windowTable, &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->windowTable,
+ &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
Tcl_AppendElement(interp,
- Tcl_GetHashKey(&textPtr->markTable, hPtr));
+ Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr));
}
- } else {
- Tcl_AppendResult(interp, "bad window option \"", argv[2],
- "\": must be cget, configure, create, or names",
- (char *) NULL);
- return TCL_ERROR;
+ break;
+ }
}
return TCL_OK;
}
@@ -304,76 +353,97 @@ TkTextWindowCmd(textPtr, interp, argc, argv)
*
* EmbWinConfigure --
*
- * This procedure is called to handle configuration options
- * for an embedded window, using an argc/argv list.
+ * This function is called to handle configuration options for an
+ * embedded window, using an objc/objv list.
*
* Results:
- * The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then the interp's result contains an error message..
+ * The return value is a standard Tcl result. If TCL_ERROR is returned,
+ * then the interp's result contains an error message..
*
* Side effects:
- * Configuration information for the embedded window changes,
- * such as alignment, stretching, or name of the embedded
- * window.
+ * Configuration information for the embedded window changes, such as
+ * alignment, stretching, or name of the embedded window.
+ *
+ * Note that this function may leave widget specific client information
+ * with a NULL tkwin attached to ewPtr. While we could choose to clean up
+ * the client data structure here, there is no need to do so, and it is
+ * likely that the user is going to adjust the tkwin again soon.
*
*--------------------------------------------------------------
*/
static int
-EmbWinConfigure(textPtr, ewPtr, argc, argv)
- TkText *textPtr; /* Information about text widget that
- * contains embedded window. */
- TkTextSegment *ewPtr; /* Embedded window to be configured. */
- int argc; /* Number of strings in argv. */
- CONST char **argv; /* Array of strings describing configuration
+EmbWinConfigure(
+ TkText *textPtr, /* Information about text widget that contains
+ * embedded window. */
+ TkTextSegment *ewPtr, /* Embedded window to be configured. */
+ int objc, /* Number of strings in objv. */
+ Tcl_Obj *const objv[]) /* Array of objects describing configuration
* options. */
{
Tk_Window oldWindow;
- Tcl_HashEntry *hPtr;
- int new;
+ TkTextEmbWindowClient *client;
+
+ /*
+ * Copy over client specific value before querying or setting.
+ */
+
+ client = EmbWinGetClient(textPtr, ewPtr);
+ if (client != NULL) {
+ ewPtr->body.ew.tkwin = client->tkwin;
+ } else {
+ ewPtr->body.ew.tkwin = NULL;
+ }
oldWindow = ewPtr->body.ew.tkwin;
- if (Tk_ConfigureWidget(textPtr->interp, textPtr->tkwin, configSpecs,
- argc, argv, (char *) &ewPtr->body.ew, TK_CONFIG_ARGV_ONLY)
- != TCL_OK) {
+ if (Tk_SetOptions(textPtr->interp, (char *) &ewPtr->body.ew,
+ ewPtr->body.ew.optionTable, objc, objv, textPtr->tkwin, NULL,
+ NULL) != TCL_OK) {
return TCL_ERROR;
}
+
if (oldWindow != ewPtr->body.ew.tkwin) {
if (oldWindow != NULL) {
- Tcl_DeleteHashEntry(Tcl_FindHashEntry(&textPtr->windowTable,
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(
+ &textPtr->sharedTextPtr->windowTable,
Tk_PathName(oldWindow)));
Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
- EmbWinStructureProc, (ClientData) ewPtr);
- Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,
- (ClientData) NULL);
+ EmbWinStructureProc, (ClientData) client);
+ Tk_ManageGeometry(oldWindow, NULL, (ClientData) NULL);
if (textPtr->tkwin != Tk_Parent(oldWindow)) {
Tk_UnmaintainGeometry(oldWindow, textPtr->tkwin);
} else {
Tk_UnmapWindow(oldWindow);
}
}
+ if (client != NULL) {
+ client->tkwin = NULL;
+ }
if (ewPtr->body.ew.tkwin != NULL) {
Tk_Window ancestor, parent;
+ Tcl_HashEntry *hPtr;
+ int isNew;
/*
- * Make sure that the text is either the parent of the
- * embedded window or a descendant of that parent. Also,
- * don't allow a top-level window to be managed inside
- * a text.
+ * Make sure that the text is either the parent of the embedded
+ * window or a descendant of that parent. Also, don't allow a
+ * top-level window to be managed inside a text.
*/
parent = Tk_Parent(ewPtr->body.ew.tkwin);
- for (ancestor = textPtr->tkwin; ;
- ancestor = Tk_Parent(ancestor)) {
+ for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
if (ancestor == parent) {
break;
}
if (Tk_TopWinHierarchy(ancestor)) {
- badMaster:
+ badMaster:
Tcl_AppendResult(textPtr->interp, "can't embed ",
Tk_PathName(ewPtr->body.ew.tkwin), " in ",
- Tk_PathName(textPtr->tkwin), (char *) NULL);
+ Tk_PathName(textPtr->tkwin), NULL);
ewPtr->body.ew.tkwin = NULL;
+ if (client != NULL) {
+ client->tkwin = NULL;
+ }
return TCL_ERROR;
}
}
@@ -382,28 +452,43 @@ EmbWinConfigure(textPtr, ewPtr, argc, argv)
goto badMaster;
}
+ if (client == NULL) {
+ /*
+ * Have to make the new client.
+ */
+
+ client = (TkTextEmbWindowClient *)
+ ckalloc(sizeof(TkTextEmbWindowClient));
+ client->next = ewPtr->body.ew.clients;
+ client->textPtr = textPtr;
+ client->tkwin = NULL;
+ client->chunkCount = 0;
+ client->displayed = 0;
+ client->parent = ewPtr;
+ ewPtr->body.ew.clients = client;
+ }
+ client->tkwin = ewPtr->body.ew.tkwin;
+
/*
- * Take over geometry management for the window, plus create
- * an event handler to find out when it is deleted.
+ * Take over geometry management for the window, plus create an
+ * event handler to find out when it is deleted.
*/
Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType,
- (ClientData) ewPtr);
+ (ClientData) client);
Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
- EmbWinStructureProc, (ClientData) ewPtr);
+ EmbWinStructureProc, (ClientData) client);
/*
- * Special trick! Must enter into the hash table *after*
- * calling Tk_ManageGeometry: if the window was already managed
- * elsewhere in this text, the Tk_ManageGeometry call will cause
- * the entry to be removed, which could potentially lose the new
- * entry.
+ * Special trick! Must enter into the hash table *after* calling
+ * Tk_ManageGeometry: if the window was already managed elsewhere
+ * in this text, the Tk_ManageGeometry call will cause the entry
+ * to be removed, which could potentially lose the new entry.
*/
- hPtr = Tcl_CreateHashEntry(&textPtr->windowTable,
- Tk_PathName(ewPtr->body.ew.tkwin), &new);
+ hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable,
+ Tk_PathName(ewPtr->body.ew.tkwin), &isNew);
Tcl_SetHashValue(hPtr, ewPtr);
-
}
}
return TCL_OK;
@@ -412,135 +497,54 @@ EmbWinConfigure(textPtr, ewPtr, argc, argv)
/*
*--------------------------------------------------------------
*
- * AlignParseProc --
- *
- * This procedure is invoked by Tk_ConfigureWidget during
- * option processing to handle "-align" options for embedded
- * windows.
- *
- * Results:
- * A standard Tcl return value.
- *
- * Side effects:
- * The alignment for the embedded window may change.
- *
- *--------------------------------------------------------------
- */
-
- /* ARGSUSED */
-static int
-AlignParseProc(clientData, interp, tkwin, value, widgRec, offset)
- ClientData clientData; /* Not used.*/
- Tcl_Interp *interp; /* Used for reporting errors. */
- Tk_Window tkwin; /* Window for text widget. */
- CONST char *value; /* Value of option. */
- char *widgRec; /* Pointer to TkTextEmbWindow
- * structure. */
- int offset; /* Offset into item (ignored). */
-{
- register TkTextEmbWindow *embPtr = (TkTextEmbWindow *) widgRec;
-
- if (strcmp(value, "baseline") == 0) {
- embPtr->align = ALIGN_BASELINE;
- } else if (strcmp(value, "bottom") == 0) {
- embPtr->align = ALIGN_BOTTOM;
- } else if (strcmp(value, "center") == 0) {
- embPtr->align = ALIGN_CENTER;
- } else if (strcmp(value, "top") == 0) {
- embPtr->align = ALIGN_TOP;
- } else {
- Tcl_AppendResult(interp, "bad alignment \"", value,
- "\": must be baseline, bottom, center, or top",
- (char *) NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *--------------------------------------------------------------
- *
- * AlignPrintProc --
- *
- * This procedure is invoked by the Tk configuration code
- * to produce a printable string for the "-align" configuration
- * option for embedded windows.
- *
- * Results:
- * The return value is a string describing the embedded
- * window's current alignment.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
- /* ARGSUSED */
-static char *
-AlignPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
- ClientData clientData; /* Ignored. */
- Tk_Window tkwin; /* Window for text widget. */
- char *widgRec; /* Pointer to TkTextEmbWindow
- * structure. */
- int offset; /* Ignored. */
- Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
- * information about how to reclaim
- * storage for return string. */
-{
- switch (((TkTextEmbWindow *) widgRec)->align) {
- case ALIGN_BASELINE:
- return "baseline";
- case ALIGN_BOTTOM:
- return "bottom";
- case ALIGN_CENTER:
- return "center";
- case ALIGN_TOP:
- return "top";
- default:
- return "??";
- }
-}
-
-/*
- *--------------------------------------------------------------
- *
* EmbWinStructureProc --
*
- * This procedure is invoked by the Tk event loop whenever
- * StructureNotify events occur for a window that's embedded
- * in a text widget. This procedure's only purpose is to
- * clean up when windows are deleted.
+ * This function is invoked by the Tk event loop whenever StructureNotify
+ * events occur for a window that's embedded in a text widget. This
+ * function's only purpose is to clean up when windows are deleted.
*
* Results:
* None.
*
* Side effects:
- * The window is disassociated from the window segment, and
- * the portion of the text is redisplayed.
+ * The window is disassociated from the window segment, and the portion
+ * of the text is redisplayed.
*
*--------------------------------------------------------------
*/
static void
-EmbWinStructureProc(clientData, eventPtr)
- ClientData clientData; /* Pointer to record describing window item. */
- XEvent *eventPtr; /* Describes what just happened. */
+EmbWinStructureProc(
+ ClientData clientData, /* Pointer to record describing window item. */
+ XEvent *eventPtr) /* Describes what just happened. */
{
- register TkTextSegment *ewPtr = (TkTextSegment *) clientData;
+ TkTextEmbWindowClient *client = (TkTextEmbWindowClient*)clientData;
+ TkTextSegment *ewPtr = client->parent;
TkTextIndex index;
+ Tcl_HashEntry *hPtr;
if (eventPtr->type != DestroyNotify) {
return;
}
- Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,
- Tk_PathName(ewPtr->body.ew.tkwin)));
+ hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.sharedTextPtr->windowTable,
+ Tk_PathName(client->tkwin));
+ if (hPtr != NULL) {
+ /*
+ * This may not exist if the entire widget is being deleted.
+ */
+
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
ewPtr->body.ew.tkwin = NULL;
- index.tree = ewPtr->body.ew.textPtr->tree;
+ client->tkwin = NULL;
+ index.tree = ewPtr->body.ew.sharedTextPtr->tree;
index.linePtr = ewPtr->body.ew.linePtr;
index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
- TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
+ TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index);
+ TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
}
/*
@@ -548,8 +552,8 @@ EmbWinStructureProc(clientData, eventPtr)
*
* EmbWinRequestProc --
*
- * This procedure is invoked whenever a window that's associated
- * with a window canvas item changes its requested dimensions.
+ * This function is invoked whenever a window that's associated with a
+ * window canvas item changes its requested dimensions.
*
* Results:
* None.
@@ -563,18 +567,20 @@ EmbWinStructureProc(clientData, eventPtr)
/* ARGSUSED */
static void
-EmbWinRequestProc(clientData, tkwin)
- ClientData clientData; /* Pointer to record for window item. */
- Tk_Window tkwin; /* Window that changed its desired
- * size. */
+EmbWinRequestProc(
+ ClientData clientData, /* Pointer to record for window item. */
+ Tk_Window tkwin) /* Window that changed its desired size. */
{
- TkTextSegment *ewPtr = (TkTextSegment *) clientData;
+ TkTextEmbWindowClient *client = (TkTextEmbWindowClient*)clientData;
+ TkTextSegment *ewPtr = client->parent;
TkTextIndex index;
- index.tree = ewPtr->body.ew.textPtr->tree;
+ index.tree = ewPtr->body.ew.sharedTextPtr->tree;
index.linePtr = ewPtr->body.ew.linePtr;
index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
- TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
+ TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index);
+ TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
}
/*
@@ -582,44 +588,126 @@ EmbWinRequestProc(clientData, tkwin)
*
* EmbWinLostSlaveProc --
*
- * This procedure is invoked by the Tk geometry manager when
- * a slave window managed by a text widget is claimed away
- * by another geometry manager.
+ * This function is invoked by the Tk geometry manager when a slave
+ * window managed by a text widget is claimed away by another geometry
+ * manager.
*
* Results:
* None.
*
* Side effects:
- * The window is disassociated from the window segment, and
- * the portion of the text is redisplayed.
+ * The window is disassociated from the window segment, and the portion
+ * of the text is redisplayed.
*
*--------------------------------------------------------------
*/
static void
-EmbWinLostSlaveProc(clientData, tkwin)
- ClientData clientData; /* Pointer to record describing window item. */
- Tk_Window tkwin; /* Window that was claimed away by another
+EmbWinLostSlaveProc(
+ ClientData clientData, /* Pointer to record describing window item. */
+ Tk_Window tkwin) /* Window that was claimed away by another
* geometry manager. */
{
- register TkTextSegment *ewPtr = (TkTextSegment *) clientData;
+ TkTextEmbWindowClient *client = (TkTextEmbWindowClient*)clientData;
+ TkTextSegment *ewPtr = client->parent;
TkTextIndex index;
+ Tcl_HashEntry *hPtr;
+ TkTextEmbWindowClient *loop;
- Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
- EmbWinStructureProc, (ClientData) ewPtr);
- Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr);
- if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(tkwin)) {
- Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin);
+ Tk_DeleteEventHandler(client->tkwin, StructureNotifyMask,
+ EmbWinStructureProc, (ClientData) client);
+ Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) client);
+ if (client->textPtr->tkwin != Tk_Parent(tkwin)) {
+ Tk_UnmaintainGeometry(tkwin, client->textPtr->tkwin);
} else {
Tk_UnmapWindow(tkwin);
}
- Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,
- Tk_PathName(ewPtr->body.ew.tkwin)));
+ hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.sharedTextPtr->windowTable,
+ Tk_PathName(client->tkwin));
+ Tcl_DeleteHashEntry(hPtr);
+ client->tkwin = NULL;
ewPtr->body.ew.tkwin = NULL;
- index.tree = ewPtr->body.ew.textPtr->tree;
+
+ /*
+ * Free up the memory allocation for this client.
+ */
+
+ loop = ewPtr->body.ew.clients;
+ if (loop == client) {
+ ewPtr->body.ew.clients = client->next;
+ } else {
+ while (loop->next != client) {
+ loop = loop->next;
+ }
+ loop->next = client->next;
+ }
+ ckfree((char *) client);
+
+ index.tree = ewPtr->body.ew.sharedTextPtr->tree;
index.linePtr = ewPtr->body.ew.linePtr;
index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
- TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
+ TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index);
+ TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL,
+ index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkTextWinFreeClient --
+ *
+ * Free up the hash entry and client information for a given embedded
+ * window.
+ *
+ * It is assumed the caller will manage the linked list of clients
+ * associated with the relevant TkTextSegment.
+ *
+ * Results:
+ * Nothing.
+ *
+ * Side effects:
+ * The embedded window information for a single client is deleted, if it
+ * exists, and any resources associated with it are released.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkTextWinFreeClient(
+ Tcl_HashEntry *hPtr, /* Hash entry corresponding to this client, or
+ * NULL */
+ TkTextEmbWindowClient *client)
+ /* Client data structure, with the 'tkwin'
+ * field to be cleaned up. */
+{
+ if (hPtr != NULL) {
+ /*
+ * (It's possible for there to be no hash table entry for this window,
+ * if an error occurred while creating the window segment but before
+ * the window got added to the table)
+ */
+
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ /*
+ * Delete the event handler for the window before destroying the window,
+ * so that EmbWinStructureProc doesn't get called (we'll already do
+ * everything that it would have done, and it will just get confused).
+ */
+
+ if (client->tkwin != NULL) {
+ Tk_DeleteEventHandler(client->tkwin, StructureNotifyMask,
+ EmbWinStructureProc, (ClientData) client);
+ Tk_DestroyWindow(client->tkwin);
+ }
+ Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) client);
+
+ /*
+ * Free up this client.
+ */
+
+ ckfree((char *) client);
}
/*
@@ -627,8 +715,8 @@ EmbWinLostSlaveProc(clientData, tkwin)
*
* EmbWinDeleteProc --
*
- * This procedure is invoked by the text B-tree code whenever
- * an embedded window lies in a range of characters being deleted.
+ * This function is invoked by the text B-tree code whenever an embedded
+ * window lies in a range of characters being deleted.
*
* Results:
* Returns 0 to indicate that the deletion has been accepted.
@@ -642,42 +730,37 @@ EmbWinLostSlaveProc(clientData, tkwin)
/* ARGSUSED */
static int
-EmbWinDeleteProc(ewPtr, linePtr, treeGone)
- TkTextSegment *ewPtr; /* Segment being deleted. */
- TkTextLine *linePtr; /* Line containing segment. */
- int treeGone; /* Non-zero means the entire tree is
- * being deleted, so everything must
- * get cleaned up. */
+EmbWinDeleteProc(
+ TkTextSegment *ewPtr, /* Segment being deleted. */
+ TkTextLine *linePtr, /* Line containing segment. */
+ int treeGone) /* Non-zero means the entire tree is being
+ * deleted, so everything must get cleaned
+ * up. */
{
- Tcl_HashEntry *hPtr;
+ TkTextEmbWindowClient *client;
+ client = ewPtr->body.ew.clients;
- if (ewPtr->body.ew.tkwin != NULL) {
- hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable,
- Tk_PathName(ewPtr->body.ew.tkwin));
- if (hPtr != NULL) {
- /*
- * (It's possible for there to be no hash table entry for this
- * window, if an error occurred while creating the window segment
- * but before the window got added to the table)
- */
+ while (client != NULL) {
+ TkTextEmbWindowClient *next = client->next;
+ Tcl_HashEntry *hPtr = NULL;
- Tcl_DeleteHashEntry(hPtr);
+ if (client->tkwin != NULL) {
+ hPtr = Tcl_FindHashEntry(
+ &ewPtr->body.ew.sharedTextPtr->windowTable,
+ Tk_PathName(client->tkwin));
}
+ TkTextWinFreeClient(hPtr, client);
+ client = next;
+ }
+ ewPtr->body.ew.clients = NULL;
- /*
- * Delete the event handler for the window before destroying
- * the window, so that EmbWinStructureProc doesn't get called
- * (we'll already do everything that it would have done, and
- * it will just get confused).
- */
+ Tk_FreeConfigOptions((char *) &ewPtr->body.ew, ewPtr->body.ew.optionTable,
+ NULL);
+
+ /*
+ * Free up all memory allocated.
+ */
- Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
- EmbWinStructureProc, (ClientData) ewPtr);
- Tk_DestroyWindow(ewPtr->body.ew.tkwin);
- }
- Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr);
- Tk_FreeOptions(configSpecs, (char *) &ewPtr->body.ew,
- ewPtr->body.ew.textPtr->display, 0);
ckfree((char *) ewPtr);
return 0;
}
@@ -687,9 +770,8 @@ EmbWinDeleteProc(ewPtr, linePtr, treeGone)
*
* EmbWinCleanupProc --
*
- * This procedure is invoked by the B-tree code whenever a
- * segment containing an embedded window is moved from one
- * line to another.
+ * This function is invoked by the B-tree code whenever a segment
+ * containing an embedded window is moved from one line to another.
*
* Results:
* None.
@@ -701,9 +783,9 @@ EmbWinDeleteProc(ewPtr, linePtr, treeGone)
*/
static TkTextSegment *
-EmbWinCleanupProc(ewPtr, linePtr)
- TkTextSegment *ewPtr; /* Mark segment that's being moved. */
- TkTextLine *linePtr; /* Line that now contains segment. */
+EmbWinCleanupProc(
+ TkTextSegment *ewPtr, /* Mark segment that's being moved. */
+ TkTextLine *linePtr) /* Line that now contains segment. */
{
ewPtr->body.ew.linePtr = linePtr;
return ewPtr;
@@ -714,12 +796,11 @@ EmbWinCleanupProc(ewPtr, linePtr)
*
* EmbWinLayoutProc --
*
- * This procedure is the "layoutProc" for embedded window
- * segments.
+ * This function is the "layoutProc" for embedded window segments.
*
* Results:
- * 1 is returned to indicate that the segment should be
- * displayed. The chunkPtr structure is filled in.
+ * 1 is returned to indicate that the segment should be displayed. The
+ * chunkPtr structure is filled in.
*
* Side effects:
* None, except for filling in chunkPtr.
@@ -729,49 +810,105 @@ EmbWinCleanupProc(ewPtr, linePtr)
/*ARGSUSED*/
static int
-EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
- noCharsYet, wrapMode, chunkPtr)
- TkText *textPtr; /* Text widget being layed out. */
- TkTextIndex *indexPtr; /* Identifies first character in chunk. */
- TkTextSegment *ewPtr; /* Segment corresponding to indexPtr. */
- int offset; /* Offset within segPtr corresponding to
+EmbWinLayoutProc(
+ TkText *textPtr, /* Text widget being layed out. */
+ TkTextIndex *indexPtr, /* Identifies first character in chunk. */
+ TkTextSegment *ewPtr, /* Segment corresponding to indexPtr. */
+ int offset, /* Offset within segPtr corresponding to
* indexPtr (always 0). */
- int maxX; /* Chunk must not occupy pixels at this
+ int maxX, /* Chunk must not occupy pixels at this
* position or higher. */
- int maxChars; /* Chunk must not include more than this
- * many characters. */
- int noCharsYet; /* Non-zero means no characters have been
+ int maxChars, /* Chunk must not include more than this many
+ * characters. */
+ int noCharsYet, /* Non-zero means no characters have been
* assigned to this line yet. */
- TkWrapMode wrapMode; /* Wrap mode to use for line: TEXT_WRAPMODE_CHAR,
- * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */
- register TkTextDispChunk *chunkPtr;
- /* Structure to fill in with information
- * about this chunk. The x field has already
- * been set by the caller. */
+ TkWrapMode wrapMode, /* Wrap mode to use for line:
+ * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or
+ * TEXT_WRAPMODE_WORD. */
+ register TkTextDispChunk *chunkPtr)
+ /* Structure to fill in with information about
+ * this chunk. The x field has already been
+ * set by the caller. */
{
int width, height;
+ TkTextEmbWindowClient *client;
if (offset != 0) {
- panic("Non-zero offset in EmbWinLayoutProc");
+ Tcl_Panic("Non-zero offset in EmbWinLayoutProc");
+ }
+
+ client = EmbWinGetClient(textPtr, ewPtr);
+ if (client == NULL) {
+ ewPtr->body.ew.tkwin = NULL;
+ } else {
+ ewPtr->body.ew.tkwin = client->tkwin;
}
if ((ewPtr->body.ew.tkwin == NULL) && (ewPtr->body.ew.create != NULL)) {
- int code, new;
- Tcl_DString name;
+ int code, isNew;
Tk_Window ancestor;
Tcl_HashEntry *hPtr;
+ const char *before, *string;
+ Tcl_DString name, buf, *dsPtr = NULL;
+
+ before = ewPtr->body.ew.create;
/*
- * The window doesn't currently exist. Create it by evaluating
- * the creation script. The script must return the window's
- * path name: look up that name to get back to the window
- * token. Then register ourselves as the geometry manager for
- * the window.
+ * Find everything up to the next % character and append it to the
+ * result string.
*/
- code = Tcl_GlobalEval(textPtr->interp, ewPtr->body.ew.create);
+ string = before;
+ while (*string != 0) {
+ if ((*string == '%') && (string[1] == '%' || string[1] == 'W')) {
+ if (dsPtr == NULL) {
+ Tcl_DStringInit(&buf);
+ dsPtr = &buf;
+ }
+ if (string != before) {
+ Tcl_DStringAppend(dsPtr, before, (int) (string-before));
+ before = string;
+ }
+ if (string[1] == '%') {
+ Tcl_DStringAppend(dsPtr, "%", 1);
+ } else {
+ /*
+ * Substitute string as proper Tcl list element.
+ */
+
+ int spaceNeeded, cvtFlags, length;
+ const char *str = Tk_PathName(textPtr->tkwin);
+
+ spaceNeeded = Tcl_ScanElement(str, &cvtFlags);
+ length = Tcl_DStringLength(dsPtr);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ spaceNeeded = Tcl_ConvertElement(str,
+ Tcl_DStringValue(dsPtr) + length,
+ cvtFlags | TCL_DONT_USE_BRACES);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ }
+ before += 2;
+ string++;
+ }
+ string++;
+ }
+
+ /*
+ * The window doesn't currently exist. Create it by evaluating the
+ * creation script. The script must return the window's path name:
+ * look up that name to get back to the window token. Then register
+ * ourselves as the geometry manager for the window.
+ */
+
+ if (dsPtr != NULL) {
+ Tcl_DStringAppend(dsPtr, before, (int) (string-before));
+ code = Tcl_GlobalEval(textPtr->interp, Tcl_DStringValue(dsPtr));
+ Tcl_DStringFree(dsPtr);
+ } else {
+ code = Tcl_GlobalEval(textPtr->interp, ewPtr->body.ew.create);
+ }
if (code != TCL_OK) {
- createError:
+ createError:
Tcl_BackgroundError(textPtr->interp);
goto gotWindow;
}
@@ -780,19 +917,19 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
Tcl_ResetResult(textPtr->interp);
ewPtr->body.ew.tkwin = Tk_NameToWindow(textPtr->interp,
Tcl_DStringValue(&name), textPtr->tkwin);
+ Tcl_DStringFree(&name);
if (ewPtr->body.ew.tkwin == NULL) {
goto createError;
}
- for (ancestor = textPtr->tkwin; ;
- ancestor = Tk_Parent(ancestor)) {
+ for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
if (ancestor == Tk_Parent(ewPtr->body.ew.tkwin)) {
break;
}
if (Tk_TopWinHierarchy(ancestor)) {
- badMaster:
+ badMaster:
Tcl_AppendResult(textPtr->interp, "can't embed ",
Tk_PathName(ewPtr->body.ew.tkwin), " relative to ",
- Tk_PathName(textPtr->tkwin), (char *) NULL);
+ Tk_PathName(textPtr->tkwin), NULL);
Tcl_BackgroundError(textPtr->interp);
ewPtr->body.ew.tkwin = NULL;
goto gotWindow;
@@ -802,21 +939,39 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
|| (textPtr->tkwin == ewPtr->body.ew.tkwin)) {
goto badMaster;
}
- Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType,
- (ClientData) ewPtr);
- Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
- EmbWinStructureProc, (ClientData) ewPtr);
+
+ if (client == NULL) {
+ /*
+ * We just used a '-create' script to make a new window, which we
+ * now need to add to our client list.
+ */
+
+ client = (TkTextEmbWindowClient *)
+ ckalloc(sizeof(TkTextEmbWindowClient));
+ client->next = ewPtr->body.ew.clients;
+ client->textPtr = textPtr;
+ client->tkwin = NULL;
+ client->chunkCount = 0;
+ client->displayed = 0;
+ client->parent = ewPtr;
+ ewPtr->body.ew.clients = client;
+ }
+
+ client->tkwin = ewPtr->body.ew.tkwin;
+ Tk_ManageGeometry(client->tkwin, &textGeomType,
+ (ClientData) client);
+ Tk_CreateEventHandler(client->tkwin, StructureNotifyMask,
+ EmbWinStructureProc, (ClientData) client);
/*
- * Special trick! Must enter into the hash table *after*
- * calling Tk_ManageGeometry: if the window was already managed
- * elsewhere in this text, the Tk_ManageGeometry call will cause
- * the entry to be removed, which could potentially lose the new
- * entry.
+ * Special trick! Must enter into the hash table *after* calling
+ * Tk_ManageGeometry: if the window was already managed elsewhere in
+ * this text, the Tk_ManageGeometry call will cause the entry to be
+ * removed, which could potentially lose the new entry.
*/
- hPtr = Tcl_CreateHashEntry(&textPtr->windowTable,
- Tk_PathName(ewPtr->body.ew.tkwin), &new);
+ hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable,
+ Tk_PathName(client->tkwin), &isNew);
Tcl_SetHashValue(hPtr, ewPtr);
}
@@ -824,7 +979,7 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
* See if there's room for this window on this line.
*/
- gotWindow:
+ gotWindow:
if (ewPtr->body.ew.tkwin == NULL) {
width = 0;
height = 0;
@@ -841,9 +996,9 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
* Fill in the chunk structure.
*/
- chunkPtr->displayProc = EmbWinDisplayProc;
+ chunkPtr->displayProc = TkTextEmbWinDisplayProc;
chunkPtr->undisplayProc = EmbWinUndisplayProc;
- chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL;
+ chunkPtr->measureProc = NULL;
chunkPtr->bboxProc = EmbWinBboxProc;
chunkPtr->numBytes = 1;
if (ewPtr->body.ew.align == ALIGN_BASELINE) {
@@ -859,7 +1014,9 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
chunkPtr->breakIndex = -1;
chunkPtr->breakIndex = 1;
chunkPtr->clientData = (ClientData) ewPtr;
- ewPtr->body.ew.chunkCount += 1;
+ if (client != NULL) {
+ client->chunkCount += 1;
+ }
return 1;
}
@@ -868,84 +1025,89 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
*
* EmbWinCheckProc --
*
- * This procedure is invoked by the B-tree code to perform
- * consistency checks on embedded windows.
+ * This function is invoked by the B-tree code to perform consistency
+ * checks on embedded windows.
*
* Results:
* None.
*
* Side effects:
- * The procedure panics if it detects anything wrong with
- * the embedded window.
+ * The function panics if it detects anything wrong with the embedded
+ * window.
*
*--------------------------------------------------------------
*/
static void
-EmbWinCheckProc(ewPtr, linePtr)
- TkTextSegment *ewPtr; /* Segment to check. */
- TkTextLine *linePtr; /* Line containing segment. */
+EmbWinCheckProc(
+ TkTextSegment *ewPtr, /* Segment to check. */
+ TkTextLine *linePtr) /* Line containing segment. */
{
if (ewPtr->nextPtr == NULL) {
- panic("EmbWinCheckProc: embedded window is last segment in line");
+ Tcl_Panic("EmbWinCheckProc: embedded window is last segment in line");
}
if (ewPtr->size != 1) {
- panic("EmbWinCheckProc: embedded window has size %d", ewPtr->size);
+ Tcl_Panic("EmbWinCheckProc: embedded window has size %d", ewPtr->size);
}
}
/*
*--------------------------------------------------------------
*
- * EmbWinDisplayProc --
+ * TkTextEmbWinDisplayProc --
*
- * This procedure is invoked by the text displaying code
- * when it is time to actually draw an embedded window
- * chunk on the screen.
+ * This function is invoked by the text displaying code when it is time
+ * to actually draw an embedded window chunk on the screen.
*
* Results:
* None.
*
* Side effects:
- * The embedded window gets moved to the correct location
- * and mapped onto the screen.
+ * The embedded window gets moved to the correct location and mapped onto
+ * the screen.
*
*--------------------------------------------------------------
*/
-static void
-EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY)
- TkTextDispChunk *chunkPtr; /* Chunk that is to be drawn. */
- int x; /* X-position in dst at which to
- * draw this chunk (differs from
- * the x-position in the chunk because
- * of scrolling). */
- int y; /* Top of rectangular bounding box
- * for line: tells where to draw this
- * chunk in dst (x-position is in
- * the chunk itself). */
- int lineHeight; /* Total height of line. */
- int baseline; /* Offset of baseline from y. */
- Display *display; /* Display to use for drawing. */
- Drawable dst; /* Pixmap or window in which to draw */
- int screenY; /* Y-coordinate in text window that
- * corresponds to y. */
+void
+TkTextEmbWinDisplayProc(
+ TkText *textPtr, /* Information about text widget. */
+ TkTextDispChunk *chunkPtr, /* Chunk that is to be drawn. */
+ int x, /* X-position in dst at which to draw this
+ * chunk (differs from the x-position in the
+ * chunk because of scrolling). */
+ int y, /* Top of rectangular bounding box for line:
+ * tells where to draw this chunk in dst
+ * (x-position is in the chunk itself). */
+ int lineHeight, /* Total height of line. */
+ int baseline, /* Offset of baseline from y. */
+ Display *display, /* Display to use for drawing (unused). */
+ Drawable dst, /* Pixmap or window in which to draw
+ * (unused). */
+ int screenY) /* Y-coordinate in text window that
+ * corresponds to y. */
{
- TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;
int lineX, windowX, windowY, width, height;
Tk_Window tkwin;
+ TkTextSegment *ewPtr = (TkTextSegment*) chunkPtr->clientData;
+ TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);
+
+ if (client == NULL) {
+ return;
+ }
- tkwin = ewPtr->body.ew.tkwin;
+ tkwin = client->tkwin;
if (tkwin == NULL) {
return;
}
+
if ((x + chunkPtr->width) <= 0) {
/*
- * The window is off-screen; just unmap it.
+ * The window is off-screen; just unmap it.
*/
- if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(tkwin)) {
- Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin);
+ if (textPtr->tkwin != Tk_Parent(tkwin)) {
+ Tk_UnmaintainGeometry(tkwin, textPtr->tkwin);
} else {
Tk_UnmapWindow(tkwin);
}
@@ -953,15 +1115,15 @@ EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY)
}
/*
- * Compute the window's location and size in the text widget, taking
- * into account the align and stretch values for the window.
+ * Compute the window's location and size in the text widget, taking into
+ * account the align and stretch values for the window.
*/
- EmbWinBboxProc(chunkPtr, 0, screenY, lineHeight, baseline, &lineX,
- &windowY, &width, &height);
+ EmbWinBboxProc(textPtr, chunkPtr, 0, screenY, lineHeight, baseline,
+ &lineX, &windowY, &width, &height);
windowX = lineX - chunkPtr->x + x;
- if (ewPtr->body.ew.textPtr->tkwin == Tk_Parent(tkwin)) {
+ if (textPtr->tkwin == Tk_Parent(tkwin)) {
if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin))
|| (Tk_ReqWidth(tkwin) != Tk_Width(tkwin))
|| (height != Tk_Height(tkwin))) {
@@ -969,15 +1131,15 @@ EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY)
}
Tk_MapWindow(tkwin);
} else {
- Tk_MaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin,
- windowX, windowY, width, height);
+ Tk_MaintainGeometry(tkwin, textPtr->tkwin, windowX, windowY,
+ width, height);
}
/*
* Mark the window as displayed so that it won't get unmapped.
*/
- ewPtr->body.ew.displayed = 1;
+ client->displayed = 1;
}
/*
@@ -985,9 +1147,9 @@ EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY)
*
* EmbWinUndisplayProc --
*
- * This procedure is called when the chunk for an embedded
- * window is no longer going to be displayed. It arranges
- * for the window associated with the chunk to be unmapped.
+ * This function is called when the chunk for an embedded window is no
+ * longer going to be displayed. It arranges for the window associated
+ * with the chunk to be unmapped.
*
* Results:
* None.
@@ -999,25 +1161,29 @@ EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY)
*/
static void
-EmbWinUndisplayProc(textPtr, chunkPtr)
- TkText *textPtr; /* Overall information about text
- * widget. */
- TkTextDispChunk *chunkPtr; /* Chunk that is about to be freed. */
+EmbWinUndisplayProc(
+ TkText *textPtr, /* Overall information about text widget. */
+ TkTextDispChunk *chunkPtr) /* Chunk that is about to be freed. */
{
- TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;
+ TkTextSegment *ewPtr = (TkTextSegment*) chunkPtr->clientData;
+ TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);
+
+ if (client == NULL) {
+ return;
+ }
- ewPtr->body.ew.chunkCount--;
- if (ewPtr->body.ew.chunkCount == 0) {
+ client->chunkCount--;
+ if (client->chunkCount == 0) {
/*
* Don't unmap the window immediately, since there's a good chance
- * that it will immediately be redisplayed, perhaps even in the
- * same place. Instead, schedule the window to be unmapped later;
- * the call to EmbWinDelayedUnmap will be cancelled in the likely
- * event that the unmap becomes unnecessary.
+ * that it will immediately be redisplayed, perhaps even in the same
+ * place. Instead, schedule the window to be unmapped later; the call
+ * to EmbWinDelayedUnmap will be cancelled in the likely event that
+ * the unmap becomes unnecessary.
*/
- ewPtr->body.ew.displayed = 0;
- Tcl_DoWhenIdle(EmbWinDelayedUnmap, (ClientData) ewPtr);
+ client->displayed = 0;
+ Tcl_DoWhenIdle(EmbWinDelayedUnmap, (ClientData) client);
}
}
@@ -1026,17 +1192,16 @@ EmbWinUndisplayProc(textPtr, chunkPtr)
*
* EmbWinBboxProc --
*
- * This procedure is called to compute the bounding box of
- * the area occupied by an embedded window.
+ * This function is called to compute the bounding box of the area
+ * occupied by an embedded window.
*
* Results:
- * There is no return value. *xPtr and *yPtr are filled in
- * with the coordinates of the upper left corner of the
- * window, and *widthPtr and *heightPtr are filled in with
- * the dimensions of the window in pixels. Note: not all
- * of the returned bbox is necessarily visible on the screen
- * (the rightmost part might be off-screen to the right,
- * and the bottommost part might be off-screen to the bottom).
+ * There is no return value. *xPtr and *yPtr are filled in with the
+ * coordinates of the upper left corner of the window, and *widthPtr and
+ * *heightPtr are filled in with the dimensions of the window in pixels.
+ * Note: not all of the returned bbox is necessarily visible on the
+ * screen (the rightmost part might be off-screen to the right, and the
+ * bottommost part might be off-screen to the bottom).
*
* Side effects:
* None.
@@ -1045,27 +1210,32 @@ EmbWinUndisplayProc(textPtr, chunkPtr)
*/
static void
-EmbWinBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
- widthPtr, heightPtr)
- TkTextDispChunk *chunkPtr; /* Chunk containing desired char. */
- int index; /* Index of desired character within
- * the chunk. */
- int y; /* Topmost pixel in area allocated
- * for this line. */
- int lineHeight; /* Total height of line. */
- int baseline; /* Location of line's baseline, in
- * pixels measured down from y. */
- int *xPtr, *yPtr; /* Gets filled in with coords of
- * character's upper-left pixel. */
- int *widthPtr; /* Gets filled in with width of
- * character, in pixels. */
- int *heightPtr; /* Gets filled in with height of
- * character, in pixels. */
+EmbWinBboxProc(
+ TkText *textPtr, /* Information about text widget. */
+ TkTextDispChunk *chunkPtr, /* Chunk containing desired char. */
+ int index, /* Index of desired character within the
+ * chunk. */
+ int y, /* Topmost pixel in area allocated for this
+ * line. */
+ int lineHeight, /* Total height of line. */
+ int baseline, /* Location of line's baseline, in pixels
+ * measured down from y. */
+ int *xPtr, int *yPtr, /* Gets filled in with coords of character's
+ * upper-left pixel. */
+ int *widthPtr, /* Gets filled in with width of window, in
+ * pixels. */
+ int *heightPtr) /* Gets filled in with height of window, in
+ * pixels. */
{
- TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;
Tk_Window tkwin;
+ TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData;
+ TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);
- tkwin = ewPtr->body.ew.tkwin;
+ if (client == NULL) {
+ tkwin = NULL;
+ } else {
+ tkwin = client->tkwin;
+ }
if (tkwin != NULL) {
*widthPtr = Tk_ReqWidth(tkwin);
*heightPtr = Tk_ReqHeight(tkwin);
@@ -1082,18 +1252,18 @@ EmbWinBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
}
}
switch (ewPtr->body.ew.align) {
- case ALIGN_BOTTOM:
- *yPtr = y + (lineHeight - *heightPtr - ewPtr->body.ew.padY);
- break;
- case ALIGN_CENTER:
- *yPtr = y + (lineHeight - *heightPtr)/2;
- break;
- case ALIGN_TOP:
- *yPtr = y + ewPtr->body.ew.padY;
- break;
- case ALIGN_BASELINE:
- *yPtr = y + (baseline - *heightPtr);
- break;
+ case ALIGN_BOTTOM:
+ *yPtr = y + (lineHeight - *heightPtr - ewPtr->body.ew.padY);
+ break;
+ case ALIGN_CENTER:
+ *yPtr = y + (lineHeight - *heightPtr)/2;
+ break;
+ case ALIGN_TOP:
+ *yPtr = y + ewPtr->body.ew.padY;
+ break;
+ case ALIGN_BASELINE:
+ *yPtr = y + (baseline - *heightPtr);
+ break;
}
}
@@ -1102,33 +1272,31 @@ EmbWinBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
*
* EmbWinDelayedUnmap --
*
- * This procedure is an idle handler that does the actual
- * work of unmapping an embedded window. See the comment
- * in EmbWinUndisplayProc for details.
+ * This function is an idle handler that does the actual work of
+ * unmapping an embedded window. See the comment in EmbWinUndisplayProc
+ * for details.
*
* Results:
* None.
*
* Side effects:
- * The window gets unmapped, unless its chunk reference count
- * has become non-zero again.
+ * The window gets unmapped, unless its chunk reference count has become
+ * non-zero again.
*
*--------------------------------------------------------------
*/
static void
-EmbWinDelayedUnmap(clientData)
- ClientData clientData; /* Token for the window to
- * be unmapped. */
+EmbWinDelayedUnmap(
+ ClientData clientData) /* Token for the window to be unmapped. */
{
- TkTextSegment *ewPtr = (TkTextSegment *) clientData;
+ TkTextEmbWindowClient *client = (TkTextEmbWindowClient*) clientData;
- if (!ewPtr->body.ew.displayed && (ewPtr->body.ew.tkwin != NULL)) {
- if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(ewPtr->body.ew.tkwin)) {
- Tk_UnmaintainGeometry(ewPtr->body.ew.tkwin,
- ewPtr->body.ew.textPtr->tkwin);
+ if (!client->displayed && (client->tkwin != NULL)) {
+ if (client->textPtr->tkwin != Tk_Parent(client->tkwin)) {
+ Tk_UnmaintainGeometry(client->tkwin, client->textPtr->tkwin);
} else {
- Tk_UnmapWindow(ewPtr->body.ew.tkwin);
+ Tk_UnmapWindow(client->tkwin);
}
}
}
@@ -1138,14 +1306,13 @@ EmbWinDelayedUnmap(clientData)
*
* TkTextWindowIndex --
*
- * Given the name of an embedded window within a text widget,
- * returns an index corresponding to the window's position
- * in the text.
+ * Given the name of an embedded window within a text widget, returns an
+ * index corresponding to the window's position in the text.
*
* Results:
- * The return value is 1 if there is an embedded window by
- * the given name in the text widget, 0 otherwise. If the
- * window exists, *indexPtr is filled in with its index.
+ * The return value is 1 if there is an embedded window by the given name
+ * in the text widget, 0 otherwise. If the window exists, *indexPtr is
+ * filled in with its index.
*
* Side effects:
* None.
@@ -1154,21 +1321,70 @@ EmbWinDelayedUnmap(clientData)
*/
int
-TkTextWindowIndex(textPtr, name, indexPtr)
- TkText *textPtr; /* Text widget containing window. */
- CONST char *name; /* Name of window. */
- TkTextIndex *indexPtr; /* Index information gets stored here. */
+TkTextWindowIndex(
+ TkText *textPtr, /* Text widget containing window. */
+ const char *name, /* Name of window. */
+ TkTextIndex *indexPtr) /* Index information gets stored here. */
{
Tcl_HashEntry *hPtr;
TkTextSegment *ewPtr;
- hPtr = Tcl_FindHashEntry(&textPtr->windowTable, name);
+ hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->windowTable, name);
if (hPtr == NULL) {
return 0;
}
+
ewPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
- indexPtr->tree = textPtr->tree;
+ indexPtr->tree = textPtr->sharedTextPtr->tree;
indexPtr->linePtr = ewPtr->body.ew.linePtr;
indexPtr->byteIndex = TkTextSegToOffset(ewPtr, indexPtr->linePtr);
return 1;
}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmbWinGetClient --
+ *
+ * Given a text widget and a segment which contains an embedded window,
+ * find the text-widget specific information about the embedded window,
+ * if any.
+ *
+ * This function performs a completely linear lookup for a matching data
+ * structure. If we envisage using this code with dozens of peer widgets,
+ * then performance could become an issue and a more sophisticated lookup
+ * mechanism might be desirable.
+ *
+ * Results:
+ * NULL if no widget-specific info exists, otherwise the structure is
+ * returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static TkTextEmbWindowClient*
+EmbWinGetClient(
+ const TkText *textPtr, /* Information about text widget. */
+ TkTextSegment *ewPtr) /* Segment containing embedded window. */
+{
+ TkTextEmbWindowClient *client = ewPtr->body.ew.clients;
+
+ while (client != NULL) {
+ if (client->textPtr == textPtr) {
+ return client;
+ }
+ client = client->next;
+ }
+ return NULL;
+}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */