summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordgp <dgp@noemail.net>2016-07-21 20:06:34 (GMT)
committerdgp <dgp@noemail.net>2016-07-21 20:06:34 (GMT)
commit6e21967c0573ca7a2744d318dc3ee0222875e273 (patch)
treecd7aaee28e7876e8bfdd77e835c534b13cbe5f98 /generic
parent5ad0f56fe1463cf9fb13dee7ee3319665e7d8fd6 (diff)
parent6ddcf9ad5374d63e332d9cf75792b0eb445efd5e (diff)
downloadtk-6e21967c0573ca7a2744d318dc3ee0222875e273.zip
tk-6e21967c0573ca7a2744d318dc3ee0222875e273.tar.gz
tk-6e21967c0573ca7a2744d318dc3ee0222875e273.tar.bz2
merge 8.6
FossilOrigin-Name: 0cb77e7f99a32d51ab693f35524f4e7138da07b4
Diffstat (limited to 'generic')
-rw-r--r--generic/tk.h4
-rw-r--r--generic/tkBind.c16
-rw-r--r--generic/tkEvent.c6
-rw-r--r--generic/tkFrame.c24
-rw-r--r--generic/tkImgPNG.c2
-rw-r--r--generic/tkImgPhInstance.c25
-rw-r--r--generic/tkInt.h5
-rw-r--r--generic/tkListbox.c121
-rw-r--r--generic/tkOption.c42
-rw-r--r--generic/tkPanedWindow.c8
-rw-r--r--generic/tkScale.c15
-rw-r--r--generic/tkText.c351
-rw-r--r--generic/tkText.h13
-rw-r--r--generic/tkTextDisp.c184
-rw-r--r--generic/tkTextTag.c40
-rw-r--r--generic/tkUndo.c52
-rw-r--r--generic/tkUndo.h4
-rw-r--r--generic/tkUtil.c9
-rw-r--r--generic/tkWindow.c309
-rw-r--r--generic/ttk/ttkGenStubs.tcl2
-rw-r--r--generic/ttk/ttkNotebook.c2
21 files changed, 808 insertions, 426 deletions
diff --git a/generic/tk.h b/generic/tk.h
index 4a655a4..75d82ba 100644
--- a/generic/tk.h
+++ b/generic/tk.h
@@ -75,10 +75,10 @@ extern "C" {
#define TK_MAJOR_VERSION 8
#define TK_MINOR_VERSION 6
#define TK_RELEASE_LEVEL TCL_FINAL_RELEASE
-#define TK_RELEASE_SERIAL 4
+#define TK_RELEASE_SERIAL 5
#define TK_VERSION "8.6"
-#define TK_PATCH_LEVEL "8.6.4"
+#define TK_PATCH_LEVEL "8.6.5"
/*
* A special definition used to allow this header file to be included from
diff --git a/generic/tkBind.c b/generic/tkBind.c
index 9cd3b7b..3b05066 100644
--- a/generic/tkBind.c
+++ b/generic/tkBind.c
@@ -3535,8 +3535,20 @@ DoWarp(
{
TkDisplay *dispPtr = clientData;
- TkpWarpPointer(dispPtr);
- XForceScreenSaver(dispPtr->display, ScreenSaverReset);
+ /*
+ * DoWarp was scheduled only if the window was mapped. It needs to be
+ * still mapped at the time the present idle callback is executed. Also
+ * one needs to guard against window destruction in the meantime.
+ * Finally, the case warpWindow == NULL is special in that it means
+ * the whole screen.
+ */
+
+ if ((dispPtr->warpWindow == NULL) ||
+ (Tk_IsMapped(dispPtr->warpWindow)
+ && (Tk_WindowId(dispPtr->warpWindow) != None))) {
+ TkpWarpPointer(dispPtr);
+ XForceScreenSaver(dispPtr->display, ScreenSaverReset);
+ }
dispPtr->flags &= ~TK_DISPLAY_IN_WARP;
}
diff --git a/generic/tkEvent.c b/generic/tkEvent.c
index bcc6d98..95aeda1 100644
--- a/generic/tkEvent.c
+++ b/generic/tkEvent.c
@@ -2039,6 +2039,12 @@ TkFinalize(
{
ExitHandler *exitPtr;
+#if defined(_WIN32) && !defined(STATIC_BUILD)
+ if (!tclStubsPtr) {
+ return;
+ }
+#endif
+
Tcl_DeleteExitHandler(TkFinalize, NULL);
Tcl_MutexLock(&exitMutex);
diff --git a/generic/tkFrame.c b/generic/tkFrame.c
index 057b4b8..f6edfb0 100644
--- a/generic/tkFrame.c
+++ b/generic/tkFrame.c
@@ -447,6 +447,30 @@ TkCreateFrame(
return result;
}
+int
+TkListCreateFrame(
+ ClientData clientData, /* Either NULL or pointer to option table. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ Tcl_Obj *listObj, /* List of arguments. */
+ int toplevel, /* Non-zero means create a toplevel window,
+ * zero means create a frame. */
+ Tcl_Obj *nameObj) /* Should only be non-NULL if there is no main
+ * window associated with the interpreter.
+ * Gives the base name to use for the new
+ * application. */
+
+{
+ int objc;
+ Tcl_Obj **objv;
+
+ if (TCL_OK != Tcl_ListObjGetElements(interp, listObj, &objc, &objv)) {
+ return TCL_ERROR;
+ }
+ return CreateFrame(clientData, interp, objc, objv,
+ toplevel ? TYPE_TOPLEVEL : TYPE_FRAME,
+ nameObj ? Tcl_GetString(nameObj) : NULL);
+}
+
static int
CreateFrame(
ClientData clientData, /* NULL. */
diff --git a/generic/tkImgPNG.c b/generic/tkImgPNG.c
index 2ee515b..c6e3029 100644
--- a/generic/tkImgPNG.c
+++ b/generic/tkImgPNG.c
@@ -335,7 +335,7 @@ InitPNGImage(
if (Tcl_ZlibStreamInit(NULL, dir, TCL_ZLIB_FORMAT_ZLIB,
TCL_ZLIB_COMPRESS_DEFAULT, NULL, &pngPtr->stream) != TCL_OK) {
- if (interp) {
+ if (interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"zlib initialization failed", -1));
Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "ZLIB_INIT", NULL);
diff --git a/generic/tkImgPhInstance.c b/generic/tkImgPhInstance.c
index 666a9b0..bd152f2 100644
--- a/generic/tkImgPhInstance.c
+++ b/generic/tkImgPhInstance.c
@@ -404,6 +404,9 @@ TkImgPhotoGet(
*
* Note that Win32 pre-defines those operations that we really need.
*
+ * Note that on MacOS, if the background comes from a Retina display
+ * then it will be twice as wide and twice as high as the photoimage.
+ *
*----------------------------------------------------------------------
*/
@@ -433,7 +436,16 @@ BlendComplexAlpha(
unsigned long pixel;
unsigned char r, g, b, alpha, unalpha, *masterPtr;
unsigned char *alphaAr = iPtr->masterPtr->pix32;
-
+#if defined(MAC_OSX_TK)
+ /* Background "pixels" are actually 2^pp x 2^pp blocks of subpixels. Each
+ * block gets blended with the color of one image pixel. Since we iterate
+ * over the background subpixels, we reset the width and height to the
+ * subpixel dimensions of the background image we are using.
+ */
+ int pp = bgImg->pixelpower;
+ width = width << pp;
+ height = height << pp;
+#endif
/*
* This blending is an integer version of the Source-Over compositing rule
* (see Porter&Duff, "Compositing Digital Images", proceedings of SIGGRAPH
@@ -532,9 +544,16 @@ BlendComplexAlpha(
#endif /* !_WIN32 && !MAC_OSX_TK */
for (y = 0; y < height; y++) {
+# if !defined(MAC_OSX_TK)
line = (y + yOffset) * iPtr->masterPtr->width;
for (x = 0; x < width; x++) {
masterPtr = alphaAr + ((line + x + xOffset) * 4);
+#else
+ /* Repeat each image row and column 2^pp times. */
+ line = ((y>>pp) + yOffset) * iPtr->masterPtr->width;
+ for (x = 0; x < width; x++) {
+ masterPtr = alphaAr + ((line + (x>>pp) + xOffset) * 4);
+#endif
alpha = masterPtr[3];
/*
@@ -635,7 +654,9 @@ TkImgPhotoDisplay(
(unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
if (bgImg == NULL) {
Tk_DeleteErrorHandler(handler);
- /* We failed to get the image so draw without blending alpha. It's the best we can do */
+ /* We failed to get the image, so draw without blending alpha.
+ * It's the best we can do.
+ */
goto fallBack;
}
diff --git a/generic/tkInt.h b/generic/tkInt.h
index b644c5b..dd5dcad 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -1208,7 +1208,7 @@ MODULE_SCOPE void TkpCreateBusy(Tk_FakeWin *winPtr, Tk_Window tkRef,
MODULE_SCOPE int TkBackgroundEvalObjv(Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv, int flags);
MODULE_SCOPE void TkSendVirtualEvent(Tk_Window tgtWin,
- const char *eventName);
+ const char *eventName, Tcl_Obj *detail);
MODULE_SCOPE Tcl_Command TkMakeEnsemble(Tcl_Interp *interp,
const char *nsname, const char *name,
ClientData clientData, const TkEnsemble *map);
@@ -1217,6 +1217,9 @@ MODULE_SCOPE int TkInitTkCmd(Tcl_Interp *interp,
MODULE_SCOPE int TkInitFontchooser(Tcl_Interp *interp,
ClientData clientData);
MODULE_SCOPE void TkpWarpPointer(TkDisplay *dispPtr);
+MODULE_SCOPE int TkListCreateFrame(ClientData clientData,
+ Tcl_Interp *interp, Tcl_Obj *listObj,
+ int toplevel, Tcl_Obj *nameObj);
#ifdef _WIN32
#define TkParseColor XParseColor
diff --git a/generic/tkListbox.c b/generic/tkListbox.c
index 95f7862..b059727 100644
--- a/generic/tkListbox.c
+++ b/generic/tkListbox.c
@@ -90,14 +90,14 @@ typedef struct {
* display. */
int topIndex; /* Index of top-most element visible in
* window. */
- int fullLines; /* Number of lines that fit are completely
+ int fullLines; /* Number of lines that are completely
* visible in window. There may be one
* additional line at the bottom that is
* partially visible. */
int partialLine; /* 0 means that the window holds exactly
* fullLines lines. 1 means that there is one
* additional line that is partially
- * visble. */
+ * visible. */
int setGrid; /* Non-zero means pass gridding information to
* window manager. */
@@ -114,7 +114,8 @@ typedef struct {
int xOffset; /* The left edge of each string in the listbox
* is offset to the left by this many pixels
* (0 means no offset, positive means there is
- * an offset). */
+ * an offset). This is x scrolling information
+ * is not linked to justification. */
/*
* Information about what's selected or active, if any.
@@ -131,7 +132,7 @@ typedef struct {
int active; /* Index of "active" element (the one that has
* been selected by keyboard traversal). -1
* means none. */
- int activeStyle; /* style in which to draw the active element.
+ int activeStyle; /* Style in which to draw the active element.
* One of: underline, none, dotbox */
/*
@@ -165,6 +166,7 @@ typedef struct {
Pixmap gray; /* Pixmap for displaying disabled text. */
int flags; /* Various flag bits: see below for
* definitions. */
+ Tk_Justify justify; /* Justification. */
} Listbox;
/*
@@ -197,7 +199,7 @@ typedef struct {
* be updated.
* GOT_FOCUS: Non-zero means this widget currently has the
* input focus.
- * MAXWIDTH_IS_STALE: Stored maxWidth may be out-of-date
+ * MAXWIDTH_IS_STALE: Stored maxWidth may be out-of-date.
* LISTBOX_DELETED: This listbox has been effectively destroyed.
*/
@@ -275,6 +277,8 @@ static const Tk_OptionSpec optionSpecs[] = {
{TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
"HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, -1,
Tk_Offset(Listbox, highlightWidth), 0, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_LISTBOX_JUSTIFY, -1, Tk_Offset(Listbox, justify), 0, 0, 0},
{TK_OPTION_RELIEF, "-relief", "relief", "Relief",
DEF_LISTBOX_RELIEF, -1, Tk_Offset(Listbox, relief), 0, 0, 0},
{TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
@@ -313,7 +317,7 @@ static const Tk_OptionSpec optionSpecs[] = {
/*
* The itemAttrOptionSpecs table defines the valid configuration options for
- * listbox items
+ * listbox items.
*/
static const Tk_OptionSpec itemAttrOptionSpecs[] = {
@@ -340,7 +344,7 @@ static const Tk_OptionSpec itemAttrOptionSpecs[] = {
};
/*
- * The following tables define the listbox widget commands (and sub- commands)
+ * The following tables define the listbox widget commands (and sub-commands)
* and map the indexes into the string tables into enumerated types used to
* dispatch the listbox widget command.
*/
@@ -436,6 +440,7 @@ static char * ListboxListVarProc(ClientData clientData,
const char *name2, int flags);
static void MigrateHashEntries(Tcl_HashTable *table,
int first, int last, int offset);
+static int GetMaxOffset(Listbox *listPtr);
/*
* The structure below defines button class behavior by means of procedures
@@ -546,6 +551,7 @@ Tk_ListboxObjCmd(
listPtr->cursor = None;
listPtr->state = STATE_NORMAL;
listPtr->gray = None;
+ listPtr->justify = TK_JUSTIFY_LEFT;
/*
* Keep a hold of the associated tkwin until we destroy the listbox,
@@ -613,7 +619,7 @@ ListboxWidgetObjCmd(
/*
* Parse the command by looking up the second argument in the list of
- * valid subcommand names
+ * valid subcommand names.
*/
result = Tcl_GetIndexFromObj(interp, objv[1], commandNames,
@@ -1076,6 +1082,7 @@ ListboxBboxSubCmd(
Listbox *listPtr, /* Information about the listbox */
int index) /* Index of the element to get bbox info on */
{
+ register Tk_Window tkwin = listPtr->tkwin;
int lastVisibleIndex;
/*
@@ -1111,7 +1118,15 @@ ListboxBboxSubCmd(
Tk_GetFontMetrics(listPtr->tkfont, &fm);
pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen);
- x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset;
+ if (listPtr->justify == TK_JUSTIFY_LEFT) {
+ x = (listPtr->inset + listPtr->selBorderWidth) - listPtr->xOffset;
+ } else if (listPtr->justify == TK_JUSTIFY_RIGHT) {
+ x = Tk_Width(tkwin) - (listPtr->inset + listPtr->selBorderWidth)
+ - pixelWidth - listPtr->xOffset + GetMaxOffset(listPtr);
+ } else {
+ x = (Tk_Width(tkwin) - pixelWidth)/2
+ - listPtr->xOffset + GetMaxOffset(listPtr)/2;
+ }
y = ((index - listPtr->topIndex)*listPtr->lineHeight)
+ listPtr->inset + listPtr->selBorderWidth;
results[0] = Tcl_NewIntObj(x);
@@ -1837,6 +1852,7 @@ DisplayListbox(
* or right edge of the listbox is
* off-screen. */
Pixmap pixmap;
+ int textWidth;
listPtr->flags &= ~REDRAW_PENDING;
if (listPtr->flags & LISTBOX_DELETED) {
@@ -2016,7 +2032,7 @@ DisplayListbox(
} else {
/*
* If there is an item attributes record for this item, draw
- * the background box and set the foreground color accordingly
+ * the background box and set the foreground color accordingly.
*/
if (entry != NULL) {
@@ -2056,12 +2072,24 @@ DisplayListbox(
* Draw the actual text of this item.
*/
+ Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement);
+ stringRep = Tcl_GetStringFromObj(curElement, &stringLen);
+ textWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen);
+
Tk_GetFontMetrics(listPtr->tkfont, &fm);
y += fm.ascent + listPtr->selBorderWidth;
- x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset;
- Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement);
- stringRep = Tcl_GetStringFromObj(curElement, &stringLen);
- Tk_DrawChars(listPtr->display, pixmap, gc, listPtr->tkfont,
+
+ if (listPtr->justify == TK_JUSTIFY_LEFT) {
+ x = (listPtr->inset + listPtr->selBorderWidth) - listPtr->xOffset;
+ } else if (listPtr->justify == TK_JUSTIFY_RIGHT) {
+ x = Tk_Width(tkwin) - (listPtr->inset + listPtr->selBorderWidth)
+ - textWidth - listPtr->xOffset + GetMaxOffset(listPtr);
+ } else {
+ x = (Tk_Width(tkwin) - textWidth)/2
+ - listPtr->xOffset + GetMaxOffset(listPtr)/2;
+ }
+
+ Tk_DrawChars(listPtr->display, pixmap, gc, listPtr->tkfont,
stringRep, stringLen, x, y);
/*
@@ -2458,7 +2486,7 @@ ListboxDeleteSubCmd(
/*
* Check width of the element. We only have to check if widthChanged
* has not already been set to 1, because we only need one maxWidth
- * element to disappear for us to have to recompute the width
+ * element to disappear for us to have to recompute the width.
*/
if (widthChanged == 0) {
@@ -2735,7 +2763,11 @@ GetListboxIndex(
stringRep = Tcl_GetString(indexObj);
if (stringRep[0] == '@') {
- /* @x,y index */
+
+ /*
+ * @x,y index
+ */
+
int y;
const char *start;
char *end;
@@ -2844,9 +2876,7 @@ ChangeListboxOffset(
*/
offset += listPtr->xScrollUnit / 2;
- maxOffset = listPtr->maxWidth - (Tk_Width(listPtr->tkwin) -
- 2*listPtr->inset - 2*listPtr->selBorderWidth)
- + listPtr->xScrollUnit - 1;
+ maxOffset = GetMaxOffset(listPtr);
if (offset > maxOffset) {
offset = maxOffset;
}
@@ -2887,9 +2917,7 @@ ListboxScanTo(
int newTopIndex, newOffset, maxIndex, maxOffset;
maxIndex = listPtr->nElements - listPtr->fullLines;
- maxOffset = listPtr->maxWidth + (listPtr->xScrollUnit - 1)
- - (Tk_Width(listPtr->tkwin) - 2*listPtr->inset
- - 2*listPtr->selBorderWidth - listPtr->xScrollUnit);
+ maxOffset = GetMaxOffset(listPtr);
/*
* Compute new top line for screen by amplifying the difference between
@@ -3195,16 +3223,7 @@ static void
GenerateListboxSelectEvent(
Listbox *listPtr) /* Information about widget. */
{
- union {XEvent general; XVirtualEvent virtual;} event;
-
- memset(&event, 0, sizeof(event));
- event.general.xany.type = VirtualEvent;
- event.general.xany.serial = NextRequest(Tk_Display(listPtr->tkwin));
- event.general.xany.send_event = False;
- event.general.xany.window = Tk_WindowId(listPtr->tkwin);
- event.general.xany.display = Tk_Display(listPtr->tkwin);
- event.virtual.name = Tk_GetUid("ListboxSelect");
- Tk_HandleEvent(&event.general);
+ TkSendVirtualEvent(listPtr->tkwin, "ListboxSelect", NULL);
}
/*
@@ -3465,7 +3484,7 @@ ListboxListVarProc(
/*
* If the list length has decreased, then we should clean up selection and
- * attributes information for elements past the end of the new list
+ * attributes information for elements past the end of the new list.
*/
oldLength = listPtr->nElements;
@@ -3583,6 +3602,42 @@ MigrateHashEntries(
}
/*
+ *----------------------------------------------------------------------
+ *
+ * GetMaxOffset --
+ *
+ * Passing in a listbox pointer, returns the maximum offset for the box,
+ * i.e. the maximum possible horizontal scrolling value (in pixels).
+ *
+ * Results:
+ * Listbox's maxOffset.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+*/
+static int GetMaxOffset(
+ register Listbox *listPtr)
+{
+ int maxOffset;
+
+ maxOffset = listPtr->maxWidth -
+ (Tk_Width(listPtr->tkwin) - 2*listPtr->inset -
+ 2*listPtr->selBorderWidth) + listPtr->xScrollUnit - 1;
+ if (maxOffset < 0) {
+
+ /*
+ * Listbox is larger in width than its largest width item.
+ */
+
+ maxOffset = 0;
+ }
+ maxOffset -= maxOffset % listPtr->xScrollUnit;
+
+ return maxOffset;
+}
+/*
* Local Variables:
* mode: c
* c-basic-offset: 4
diff --git a/generic/tkOption.c b/generic/tkOption.c
index d758b6f..24e7fb3 100644
--- a/generic/tkOption.c
+++ b/generic/tkOption.c
@@ -560,7 +560,7 @@ Tk_GetOption(
count -= levelPtr[-1].bases[currentStack];
}
- if (currentStack && CLASS) {
+ if (currentStack & CLASS) {
nodeId = winClassId;
} else {
nodeId = winNameId;
@@ -1080,10 +1080,10 @@ ReadOptionFile(
* TK_MAX_PRIO. */
{
const char *realName;
- char *buffer;
+ Tcl_Obj *buffer;
int result, bufferSize;
Tcl_Channel chan;
- Tcl_DString newName, optString;
+ Tcl_DString newName;
/*
* Prevent file system access in a safe interpreter.
@@ -1108,24 +1108,10 @@ ReadOptionFile(
return TCL_ERROR;
}
- /*
- * Compute size of file by seeking to the end of the file. This will
- * overallocate if we are performing CRLF translation.
- */
-
- bufferSize = (int) Tcl_Seek(chan, (Tcl_WideInt) 0, SEEK_END);
- Tcl_Seek(chan, (Tcl_WideInt) 0, SEEK_SET);
-
- if (bufferSize < 0) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "error seeking to end of file \"%s\": %s",
- fileName, Tcl_PosixError(interp)));
- Tcl_Close(NULL, chan);
- return TCL_ERROR;
- }
-
- buffer = ckalloc(bufferSize + 1);
- bufferSize = Tcl_Read(chan, buffer, bufferSize);
+ buffer = Tcl_NewObj();
+ Tcl_IncrRefCount(buffer);
+ Tcl_SetChannelOption(NULL, chan, "-encoding", "utf-8");
+ bufferSize = Tcl_ReadChars(chan, buffer, -1, 0);
if (bufferSize < 0) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"error reading file \"%s\": %s",
@@ -1134,18 +1120,8 @@ ReadOptionFile(
return TCL_ERROR;
}
Tcl_Close(NULL, chan);
- buffer[bufferSize] = 0;
- if ((bufferSize>2) && !memcmp(buffer, "\357\273\277", 3)) {
- /* File starts with UTF-8 BOM */
- result = AddFromString(interp, tkwin, buffer+3, priority);
- } else {
- Tcl_DStringInit(&optString);
- Tcl_ExternalToUtfDString(NULL, buffer, bufferSize, &optString);
- result = AddFromString(interp, tkwin, Tcl_DStringValue(&optString),
- priority);
- Tcl_DStringFree(&optString);
- }
- ckfree(buffer);
+ result = AddFromString(interp, tkwin, Tcl_GetString(buffer), priority);
+ Tcl_DecrRefCount(buffer);
return result;
}
diff --git a/generic/tkPanedWindow.c b/generic/tkPanedWindow.c
index 2451647..f350d0a 100644
--- a/generic/tkPanedWindow.c
+++ b/generic/tkPanedWindow.c
@@ -1370,11 +1370,15 @@ PanedWindowEventProc(
DestroyPanedWindow(pwPtr);
} else if (eventPtr->type == UnmapNotify) {
for (i = 0; i < pwPtr->numSlaves; i++) {
- Tk_UnmapWindow(pwPtr->slaves[i]->tkwin);
+ if (!pwPtr->slaves[i]->hide) {
+ Tk_UnmapWindow(pwPtr->slaves[i]->tkwin);
+ }
}
} else if (eventPtr->type == MapNotify) {
for (i = 0; i < pwPtr->numSlaves; i++) {
- Tk_MapWindow(pwPtr->slaves[i]->tkwin);
+ if (!pwPtr->slaves[i]->hide) {
+ Tk_MapWindow(pwPtr->slaves[i]->tkwin);
+ }
}
}
}
diff --git a/generic/tkScale.c b/generic/tkScale.c
index cc7c294..cbc5202 100644
--- a/generic/tkScale.c
+++ b/generic/tkScale.c
@@ -303,6 +303,12 @@ Tk_ScaleObjCmd(
return TCL_ERROR;
}
+ /*
+ * The widget was just created, no command callback must be invoked.
+ */
+
+ scalePtr->flags &= ~INVOKE_COMMAND;
+
Tcl_SetObjResult(interp, TkNewWindowObj(scalePtr->tkwin));
return TCL_OK;
}
@@ -1268,7 +1274,14 @@ TkScaleSetValue(
return;
}
scalePtr->value = value;
- if (invokeCommand) {
+
+ /*
+ * Schedule command callback invocation only if there is such a command
+ * already registered, otherwise the callback would trigger later when
+ * configuring the widget -command option even if the value did not change.
+ */
+
+ if ((invokeCommand) && (scalePtr->command != NULL)) {
scalePtr->flags |= INVOKE_COMMAND;
}
TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
diff --git a/generic/tkText.c b/generic/tkText.c
index 3079417..5ad527a 100644
--- a/generic/tkText.c
+++ b/generic/tkText.c
@@ -122,7 +122,8 @@ static const Tk_ObjCustomOption lineOption = {
static const Tk_OptionSpec optionSpecs[] = {
{TK_OPTION_BOOLEAN, "-autoseparators", "autoSeparators",
"AutoSeparators", DEF_TEXT_AUTO_SEPARATORS, -1,
- Tk_Offset(TkText, autoSeparators), 0, 0, 0},
+ Tk_Offset(TkText, autoSeparators),
+ TK_OPTION_DONT_SET_DEFAULT, 0, 0},
{TK_OPTION_BORDER, "-background", "background", "Background",
DEF_TEXT_BG_COLOR, -1, Tk_Offset(TkText, border),
0, DEF_TEXT_BG_MONO, 0},
@@ -193,7 +194,8 @@ static const Tk_OptionSpec optionSpecs[] = {
DEF_TEXT_INSERT_WIDTH, -1, Tk_Offset(TkText, insertWidth),
0, 0, 0},
{TK_OPTION_INT, "-maxundo", "maxUndo", "MaxUndo",
- DEF_TEXT_MAX_UNDO, -1, Tk_Offset(TkText, maxUndo), 0, 0, 0},
+ DEF_TEXT_MAX_UNDO, -1, Tk_Offset(TkText, maxUndo),
+ TK_OPTION_DONT_SET_DEFAULT, 0, 0},
{TK_OPTION_PIXELS, "-padx", "padX", "Pad",
DEF_TEXT_PADX, -1, Tk_Offset(TkText, padX), 0, 0,
TK_TEXT_LINE_GEOMETRY},
@@ -239,7 +241,8 @@ static const Tk_OptionSpec optionSpecs[] = {
DEF_TEXT_TAKE_FOCUS, -1, Tk_Offset(TkText, takeFocus),
TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_BOOLEAN, "-undo", "undo", "Undo",
- DEF_TEXT_UNDO, -1, Tk_Offset(TkText, undo), 0, 0 , 0},
+ DEF_TEXT_UNDO, -1, Tk_Offset(TkText, undo),
+ TK_OPTION_DONT_SET_DEFAULT, 0 , 0},
{TK_OPTION_INT, "-width", "width", "Width",
DEF_TEXT_WIDTH, -1, Tk_Offset(TkText, width), 0, 0,
TK_TEXT_LINE_GEOMETRY},
@@ -401,6 +404,7 @@ static Tcl_Obj * TextGetText(const TkText *textPtr,
const TkTextIndex *index1,
const TkTextIndex *index2, int visibleOnly);
static void GenerateModifiedEvent(TkText *textPtr);
+static void GenerateUndoStackEvent(TkText *textPtr);
static void UpdateDirtyFlag(TkSharedText *sharedPtr);
static void RunAfterSyncCmd(ClientData clientData);
static void TextPushUndoAction(TkText *textPtr,
@@ -919,43 +923,43 @@ TextWidgetObjCmd(
* We're going to count up all display lines in the logical
* line of 'indexFromPtr' up to, but not including the logical
* line of 'indexToPtr' (except if this line is elided), and
- * then subtract off what came in too much from elided lines,
- * also subtract off what we didn't want from 'from' and add
+ * then subtract off what came in too much from elided lines,
+ * also subtract off what we didn't want from 'from' and add
* on what we didn't count from 'to'.
*/
- while (TkTextIndexCmp(&index,indexToPtr) < 0) {
+ while (TkTextIndexCmp(&index,indexToPtr) < 0) {
value += TkTextUpdateOneLine(textPtr, index.linePtr,
- 0, &index, 0);
+ 0, &index, 0);
}
- index2 = index;
-
- /*
- * Now we need to adjust the count to:
- * - subtract off the number of display lines between
- * indexToPtr and index2, since we might have skipped past
- * indexToPtr, if we have several logical lines in a
- * single display line
- * - subtract off the number of display lines overcounted
- * in the first logical line
- * - add on the number of display lines in the last logical
- * line
- * This logic is still ok if both indexFromPtr and indexToPtr
- * are in the same logical line.
- */
-
- index = *indexToPtr;
- index.byteIndex = 0;
- while (TkTextIndexCmp(&index,&index2) < 0) {
- value -= TkTextUpdateOneLine(textPtr, index.linePtr,
- 0, &index, 0);
- }
+ index2 = index;
+
+ /*
+ * Now we need to adjust the count to:
+ * - subtract off the number of display lines between
+ * indexToPtr and index2, since we might have skipped past
+ * indexToPtr, if we have several logical lines in a
+ * single display line
+ * - subtract off the number of display lines overcounted
+ * in the first logical line
+ * - add on the number of display lines in the last logical
+ * line
+ * This logic is still ok if both indexFromPtr and indexToPtr
+ * are in the same logical line.
+ */
+
+ index = *indexToPtr;
+ index.byteIndex = 0;
+ while (TkTextIndexCmp(&index,&index2) < 0) {
+ value -= TkTextUpdateOneLine(textPtr, index.linePtr,
+ 0, &index, 0);
+ }
index.linePtr = indexFromPtr->linePtr;
index.byteIndex = 0;
while (1) {
TkTextFindDisplayLineEnd(textPtr, &index, 1, NULL);
- if (TkTextIndexCmp(&index,indexFromPtr) >= 0) {
+ if (TkTextIndexCmp(&index,indexFromPtr) >= 0) {
break;
}
TkTextIndexForwBytes(textPtr, &index, 1, &index);
@@ -967,7 +971,7 @@ TextWidgetObjCmd(
index.byteIndex = 0;
while (1) {
TkTextFindDisplayLineEnd(textPtr, &index, 1, NULL);
- if (TkTextIndexCmp(&index,indexToPtr) >= 0) {
+ if (TkTextIndexCmp(&index,indexToPtr) >= 0) {
break;
}
TkTextIndexForwBytes(textPtr, &index, 1, &index);
@@ -1395,14 +1399,14 @@ TextWidgetObjCmd(
result = TextPeerCmd(textPtr, interp, objc, objv);
break;
case TEXT_PENDINGSYNC: {
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- result = TCL_ERROR;
- goto done;
- }
- Tcl_SetObjResult(interp,
- Tcl_NewBooleanObj(TkTextPendingsync(textPtr)));
- break;
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ Tcl_SetObjResult(interp,
+ Tcl_NewBooleanObj(TkTextPendingsync(textPtr)));
+ break;
}
case TEXT_REPLACE: {
const TkTextIndex *indexFromPtr, *indexToPtr;
@@ -1535,7 +1539,7 @@ TextWidgetObjCmd(
textPtr->afterSyncCmd = cmd;
} else {
textPtr->afterSyncCmd = cmd;
- Tcl_DoWhenIdle(RunAfterSyncCmd, (ClientData) textPtr);
+ Tcl_DoWhenIdle(RunAfterSyncCmd, (ClientData) textPtr);
}
break;
} else if (objc != 2) {
@@ -2093,7 +2097,7 @@ ConfigureText(
textPtr->sharedTextPtr->maxUndo = textPtr->maxUndo;
textPtr->sharedTextPtr->autoSeparators = textPtr->autoSeparators;
- TkUndoSetDepth(textPtr->sharedTextPtr->undoStack,
+ TkUndoSetMaxDepth(textPtr->sharedTextPtr->undoStack,
textPtr->sharedTextPtr->maxUndo);
/*
@@ -2191,10 +2195,10 @@ ConfigureText(
* Also, clamp the insert and current (unshared) marks to the new
* -startline/-endline range limits of the widget. All other (shared)
* marks are unchanged.
- * The return value of TkTextMarkNameToIndex does not need to be
- * checked: "insert" and "current" marks always exist, and the
- * purpose of the code below precisely is to move them inside the
- * -startline/-endline range.
+ * The return value of TkTextMarkNameToIndex does not need to be
+ * checked: "insert" and "current" marks always exist, and the
+ * purpose of the code below precisely is to move them inside the
+ * -startline/-endline range.
*/
textPtr->sharedTextPtr->stateEpoch++;
@@ -2253,12 +2257,20 @@ ConfigureText(
* replaced in the widget record.
*/
- textPtr->selTagPtr->border = textPtr->selBorder;
+ if (textPtr->selTagPtr->selBorder == NULL) {
+ textPtr->selTagPtr->border = textPtr->selBorder;
+ } else {
+ textPtr->selTagPtr->selBorder = textPtr->selBorder;
+ }
if (textPtr->selTagPtr->borderWidthPtr != textPtr->selBorderWidthPtr) {
textPtr->selTagPtr->borderWidthPtr = textPtr->selBorderWidthPtr;
textPtr->selTagPtr->borderWidth = textPtr->selBorderWidth;
}
- textPtr->selTagPtr->fgColor = textPtr->selFgColorPtr;
+ if (textPtr->selTagPtr->selFgColor == NULL) {
+ textPtr->selTagPtr->fgColor = textPtr->selFgColorPtr;
+ } else {
+ textPtr->selTagPtr->selFgColor = textPtr->selFgColorPtr;
+ }
textPtr->selTagPtr->affectsDisplay = 0;
textPtr->selTagPtr->affectsDisplayGeometry = 0;
if ((textPtr->selTagPtr->elideString != NULL)
@@ -2277,12 +2289,18 @@ ConfigureText(
textPtr->selTagPtr->affectsDisplayGeometry = 1;
}
if ((textPtr->selTagPtr->border != NULL)
+ || (textPtr->selTagPtr->selBorder != NULL)
|| (textPtr->selTagPtr->reliefString != NULL)
|| (textPtr->selTagPtr->bgStipple != None)
|| (textPtr->selTagPtr->fgColor != NULL)
+ || (textPtr->selTagPtr->selFgColor != NULL)
|| (textPtr->selTagPtr->fgStipple != None)
|| (textPtr->selTagPtr->overstrikeString != NULL)
- || (textPtr->selTagPtr->underlineString != NULL)) {
+ || (textPtr->selTagPtr->overstrikeColor != NULL)
+ || (textPtr->selTagPtr->underlineString != NULL)
+ || (textPtr->selTagPtr->underlineColor != NULL)
+ || (textPtr->selTagPtr->lMarginColor != NULL)
+ || (textPtr->selTagPtr->rMarginColor != NULL)) {
textPtr->selTagPtr->affectsDisplay = 1;
}
TkTextRedrawTag(NULL, textPtr, NULL, NULL, textPtr->selTagPtr, 1);
@@ -2406,7 +2424,7 @@ TextWorldChanged(
textPtr->charHeight = 1;
}
if (textPtr->charHeight != oldCharHeight) {
- TkBTreeClientRangeChanged(textPtr, textPtr->charHeight);
+ TkBTreeClientRangeChanged(textPtr, textPtr->charHeight);
}
border = textPtr->borderWidth + textPtr->highlightWidth;
Tk_GeometryRequest(textPtr->tkwin,
@@ -2755,6 +2773,7 @@ TextPushUndoAction(
/* Index describing second location. */
{
TkUndoSubAtom *iAtom, *dAtom;
+ int canUndo, canRedo;
/*
* Create the helpers.
@@ -2841,6 +2860,9 @@ TextPushUndoAction(
Tcl_DecrRefCount(index1Obj);
Tcl_DecrRefCount(index2Obj);
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
+
/*
* Depending whether the action is to insert or delete, we provide the
* appropriate second and third arguments to TkUndoPushAction. (The first
@@ -2852,6 +2874,10 @@ TextPushUndoAction(
} else {
TkUndoPushAction(textPtr->sharedTextPtr->undoStack, dAtom, iAtom);
}
+
+ if (!canUndo || canRedo) {
+ GenerateUndoStackEvent(textPtr);
+ }
}
/*
@@ -3075,11 +3101,16 @@ DeleteIndexRange(
* The code below is ugly, but it's needed to make sure there is always a
* dummy empty line at the end of the text. If the final newline of the
* file (just before the dummy line) is being deleted, then back up index
- * to just before the newline. Furthermore, remove any tags that are
- * present on the newline that isn't going to be deleted after all (this
- * simulates deleting the newline and then adding a "clean" one back
- * again). Note that index1 and index2 might now be equal again which
- * means that no text will be deleted but tags might be removed.
+ * to just before the newline. If there is a newline just before the first
+ * character being deleted, then back up the first index too. The idea is
+ * that a deletion involving a range starting at a line start and
+ * including the final \n (i.e. index2 is "end") is an attempt to delete
+ * complete lines, so the \n before the deleted block shall become the new
+ * final \n. Furthermore, remove any tags that are present on the newline
+ * that isn't going to be deleted after all (this simulates deleting the
+ * newline and then adding a "clean" one back again). Note that index1 and
+ * index2 might now be equal again which means that no text will be
+ * deleted but tags might be removed.
*/
line1 = TkBTreeLinesTo(textPtr, index1.linePtr);
@@ -3092,6 +3123,10 @@ DeleteIndexRange(
oldIndex2 = index2;
TkTextIndexBackChars(NULL, &oldIndex2, 1, &index2, COUNT_INDICES);
line2--;
+ if ((index1.byteIndex == 0) && (line1 != 0)) {
+ TkTextIndexBackChars(NULL, &index1, 1, &index1, COUNT_INDICES);
+ line1--;
+ }
arrayPtr = TkBTreeGetTags(&index2, NULL, &arraySize);
if (arrayPtr != NULL) {
for (i = 0; i < arraySize; i++) {
@@ -3179,11 +3214,11 @@ DeleteIndexRange(
resetView = 1;
line = line1;
byteIndex = tPtr->topIndex.byteIndex;
- } else {
- /*
- * Deletion range starts after the top line. This peers's view
- * will not need to be reset. Nothing to do.
- */
+ } else {
+ /*
+ * Deletion range starts after the top line. This peers's view
+ * will not need to be reset. Nothing to do.
+ */
}
} else if (index2.linePtr == tPtr->topIndex.linePtr) {
/*
@@ -3200,11 +3235,11 @@ DeleteIndexRange(
} else {
byteIndex -= (index2.byteIndex - index1.byteIndex);
}
- } else {
- /*
- * Deletion range ends before the top line. This peers's view
- * will not need to be reset. Nothing to do.
- */
+ } else {
+ /*
+ * Deletion range ends before the top line. This peers's view
+ * will not need to be reset. Nothing to do.
+ */
}
if (resetView) {
lineAndByteIndex[resetViewCount] = line;
@@ -3249,43 +3284,43 @@ DeleteIndexRange(
TkTextIndex indexTmp;
if (tPtr == textPtr) {
- if (viewUpdate) {
- /*
- * line cannot be before -startline of textPtr because
- * this line corresponds to an index which is necessarily
- * between "1.0" and "end" relative to textPtr.
- * Therefore no need to clamp line to the -start/-end
- * range.
- */
+ if (viewUpdate) {
+ /*
+ * line cannot be before -startline of textPtr because
+ * this line corresponds to an index which is necessarily
+ * between "1.0" and "end" relative to textPtr.
+ * Therefore no need to clamp line to the -start/-end
+ * range.
+ */
TkTextMakeByteIndex(sharedTextPtr->tree, textPtr, line,
byteIndex, &indexTmp);
TkTextSetYView(tPtr, &indexTmp, 0);
}
} else {
- TkTextMakeByteIndex(sharedTextPtr->tree, tPtr, line,
+ TkTextMakeByteIndex(sharedTextPtr->tree, tPtr, line,
byteIndex, &indexTmp);
- /*
- * line may be before -startline of tPtr and must be
- * clamped to -startline before providing it to
- * TkTextSetYView otherwise lines before -startline
- * would be displayed.
- * There is no need to worry about -endline however,
- * because the view will only be reset if the deletion
- * involves the TOP line of the screen
- */
-
- if (tPtr->start != NULL) {
- int start;
- TkTextIndex indexStart;
-
- start = TkBTreeLinesTo(NULL, tPtr->start);
- TkTextMakeByteIndex(sharedTextPtr->tree, NULL, start,
+ /*
+ * line may be before -startline of tPtr and must be
+ * clamped to -startline before providing it to
+ * TkTextSetYView otherwise lines before -startline
+ * would be displayed.
+ * There is no need to worry about -endline however,
+ * because the view will only be reset if the deletion
+ * involves the TOP line of the screen
+ */
+
+ if (tPtr->start != NULL) {
+ int start;
+ TkTextIndex indexStart;
+
+ start = TkBTreeLinesTo(NULL, tPtr->start);
+ TkTextMakeByteIndex(sharedTextPtr->tree, NULL, start,
0, &indexStart);
- if (TkTextIndexCmp(&indexTmp, &indexStart) < 0) {
- indexTmp = indexStart;
- }
- }
+ if (TkTextIndexCmp(&indexTmp, &indexStart) < 0) {
+ indexTmp = indexStart;
+ }
+ }
TkTextSetYView(tPtr, &indexTmp, 0);
}
}
@@ -3531,16 +3566,7 @@ TkTextSelectionEvent(
* event generate $textWidget <<Selection>>
*/
- union {XEvent general; XVirtualEvent virtual;} event;
-
- memset(&event, 0, sizeof(event));
- event.general.xany.type = VirtualEvent;
- event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
- event.general.xany.send_event = False;
- event.general.xany.window = Tk_WindowId(textPtr->tkwin);
- event.general.xany.display = Tk_Display(textPtr->tkwin);
- event.virtual.name = Tk_GetUid("Selection");
- Tk_HandleEvent(&event.general);
+ TkSendVirtualEvent(textPtr->tkwin, "Selection", NULL);
}
/*
@@ -5141,11 +5167,16 @@ TextEditCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
int index, setModified, oldModified;
+ int canRedo = 0;
+ int canUndo = 0;
+
static const char *const editOptionStrings[] = {
- "modified", "redo", "reset", "separator", "undo", NULL
+ "canundo", "canredo", "modified", "redo", "reset", "separator",
+ "undo", NULL
};
enum editOptions {
- EDIT_MODIFIED, EDIT_REDO, EDIT_RESET, EDIT_SEPARATOR, EDIT_UNDO
+ EDIT_CANUNDO, EDIT_CANREDO, EDIT_MODIFIED, EDIT_REDO, EDIT_RESET,
+ EDIT_SEPARATOR, EDIT_UNDO
};
if (objc < 3) {
@@ -5159,6 +5190,26 @@ TextEditCmd(
}
switch ((enum editOptions) index) {
+ case EDIT_CANREDO:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ if (textPtr->sharedTextPtr->undo) {
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(canRedo));
+ break;
+ case EDIT_CANUNDO:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ if (textPtr->sharedTextPtr->undo) {
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(canUndo));
+ break;
case EDIT_MODIFIED:
if (objc == 3) {
Tcl_SetObjResult(interp,
@@ -5200,18 +5251,28 @@ TextEditCmd(
Tcl_WrongNumArgs(interp, 3, objv, NULL);
return TCL_ERROR;
}
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
if (TextEditRedo(textPtr)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to redo", -1));
Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_REDO", NULL);
return TCL_ERROR;
}
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
+ if (!canUndo || !canRedo) {
+ GenerateUndoStackEvent(textPtr);
+ }
break;
case EDIT_RESET:
if (objc != 3) {
Tcl_WrongNumArgs(interp, 3, objv, NULL);
return TCL_ERROR;
}
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
TkUndoClearStacks(textPtr->sharedTextPtr->undoStack);
+ if (canUndo || canRedo) {
+ GenerateUndoStackEvent(textPtr);
+ }
break;
case EDIT_SEPARATOR:
if (objc != 3) {
@@ -5225,11 +5286,16 @@ TextEditCmd(
Tcl_WrongNumArgs(interp, 3, objv, NULL);
return TCL_ERROR;
}
+ canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack);
if (TextEditUndo(textPtr)) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to undo", -1));
Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_UNDO", NULL);
return TCL_ERROR;
}
+ canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack);
+ if (!canRedo || !canUndo) {
+ GenerateUndoStackEvent(textPtr);
+ }
break;
}
return TCL_OK;
@@ -5324,6 +5390,7 @@ TextGetText(
*
* Send an event that the text was modified. This is equivalent to:
* event generate $textWidget <<Modified>>
+ * for all peers of $textWidget.
*
* Results:
* None
@@ -5338,21 +5405,41 @@ static void
GenerateModifiedEvent(
TkText *textPtr) /* Information about text widget. */
{
- union {
- XEvent general;
- XVirtualEvent virtual;
- } event;
-
- Tk_MakeWindowExist(textPtr->tkwin);
-
- memset(&event, 0, sizeof(event));
- event.general.xany.type = VirtualEvent;
- event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
- event.general.xany.send_event = False;
- event.general.xany.window = Tk_WindowId(textPtr->tkwin);
- event.general.xany.display = Tk_Display(textPtr->tkwin);
- event.virtual.name = Tk_GetUid("Modified");
- Tk_HandleEvent(&event.general);
+ for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;
+ textPtr = textPtr->next) {
+ Tk_MakeWindowExist(textPtr->tkwin);
+ TkSendVirtualEvent(textPtr->tkwin, "Modified", NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GenerateUndoStackEvent --
+ *
+ * Send an event that the undo or redo stack became empty or unempty.
+ * This is equivalent to:
+ * event generate $textWidget <<UndoStack>>
+ * for all peers of $textWidget.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * May force the text window (and all peers) into existence.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+GenerateUndoStackEvent(
+ TkText *textPtr) /* Information about text widget. */
+{
+ for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL;
+ textPtr = textPtr->next) {
+ Tk_MakeWindowExist(textPtr->tkwin);
+ TkSendVirtualEvent(textPtr->tkwin, "UndoStack", NULL);
+ }
}
/*
@@ -5376,7 +5463,6 @@ UpdateDirtyFlag(
TkSharedText *sharedTextPtr)/* Information about text widget. */
{
int oldDirtyFlag;
- TkText *textPtr;
/*
* If we've been forced to be dirty, we stay dirty (until explicitly
@@ -5407,10 +5493,7 @@ UpdateDirtyFlag(
}
if (sharedTextPtr->isDirty == 0 || oldDirtyFlag == 0) {
- for (textPtr = sharedTextPtr->peers; textPtr != NULL;
- textPtr = textPtr->next) {
- GenerateModifiedEvent(textPtr);
- }
+ GenerateModifiedEvent(sharedTextPtr->peers);
}
}
@@ -5439,21 +5522,21 @@ RunAfterSyncCmd(
int code;
if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) {
- /*
- * The widget has been deleted. Don't do anything.
- */
+ /*
+ * The widget has been deleted. Don't do anything.
+ */
- if (--textPtr->refCount == 0) {
- ckfree((char *) textPtr);
- }
- return;
+ if (--textPtr->refCount == 0) {
+ ckfree((char *) textPtr);
+ }
+ return;
}
Tcl_Preserve((ClientData) textPtr->interp);
code = Tcl_EvalObjEx(textPtr->interp, textPtr->afterSyncCmd, TCL_EVAL_GLOBAL);
if (code == TCL_ERROR) {
- Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)");
- Tcl_BackgroundError(textPtr->interp);
+ Tcl_AddErrorInfo(textPtr->interp, "\n (text sync)");
+ Tcl_BackgroundError(textPtr->interp);
}
Tcl_Release((ClientData) textPtr->interp);
Tcl_DecrRefCount(textPtr->afterSyncCmd);
diff --git a/generic/tkText.h b/generic/tkText.h
index fc92644..5d88784 100644
--- a/generic/tkText.h
+++ b/generic/tkText.h
@@ -347,6 +347,9 @@ typedef struct TkTextTag {
int lMargin2; /* Left margin for second and later display
* lines of each text line, in pixels. Only
* valid if lMargin2String is non-NULL. */
+ Tk_3DBorder lMarginColor; /* Used for drawing background in left margins.
+ * This is used for both lmargin1 and lmargin2.
+ * NULL means no value specified here. */
char *offsetString; /* -offset option string (malloc-ed). NULL
* means option not specified. */
int offset; /* Vertical offset of text's baseline from
@@ -358,10 +361,18 @@ typedef struct TkTextTag {
int overstrike; /* Non-zero means draw horizontal line through
* middle of text. Only valid if
* overstrikeString is non-NULL. */
+ XColor *overstrikeColor; /* Color for the overstrike. NULL means same
+ * color as foreground. */
char *rMarginString; /* -rmargin option string (malloc-ed). NULL
* means option not specified. */
int rMargin; /* Right margin for text, in pixels. Only
* valid if rMarginString is non-NULL. */
+ Tk_3DBorder rMarginColor; /* Used for drawing background in right margin.
+ * NULL means no value specified here. */
+ Tk_3DBorder selBorder; /* Used for drawing background for selected text.
+ * NULL means no value specified here. */
+ XColor *selFgColor; /* Foreground color for selected text. NULL means
+ * no value specified here. */
char *spacing1String; /* -spacing1 option string (malloc-ed). NULL
* means option not specified. */
int spacing1; /* Extra spacing above first display line for
@@ -389,6 +400,8 @@ typedef struct TkTextTag {
int underline; /* Non-zero means draw underline underneath
* text. Only valid if underlineString is
* non-NULL. */
+ XColor *underlineColor; /* Color for the underline. NULL means same
+ * color as foreground. */
TkWrapMode wrapMode; /* How to handle wrap-around for this tag.
* Must be TEXT_WRAPMODE_CHAR,
* TEXT_WRAPMODE_NONE, TEXT_WRAPMODE_WORD, or
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c
index 18b373f..81bce94 100644
--- a/generic/tkTextDisp.c
+++ b/generic/tkTextDisp.c
@@ -136,11 +136,15 @@ typedef struct StyleValues {
* line of each text line. */
int lMargin2; /* Left margin, in pixels, for second and
* later display lines of each text line. */
+ Tk_3DBorder lMarginColor; /* Color of left margins (1 and 2). */
int offset; /* Offset in pixels of baseline, relative to
* baseline of line. */
int overstrike; /* Non-zero means draw overstrike through
* text. */
+ XColor *overstrikeColor; /* Foreground color for overstrike through
+ * text. */
int rMargin; /* Right margin, in pixels. */
+ Tk_3DBorder rMarginColor; /* Color of right margin. */
int spacing1; /* Spacing above first dline in text line. */
int spacing2; /* Spacing between lines of dline. */
int spacing3; /* Spacing below last dline in text line. */
@@ -149,6 +153,8 @@ typedef struct StyleValues {
int tabStyle; /* One of TABULAR or WORDPROCESSOR. */
int underline; /* Non-zero means draw underline underneath
* text. */
+ XColor *underlineColor; /* Foreground color for underline underneath
+ * text. */
int elide; /* Zero means draw text, otherwise not. */
TkWrapMode wrapMode; /* How to handle wrap-around for this tag.
* One of TEXT_WRAPMODE_CHAR,
@@ -167,6 +173,8 @@ typedef struct TextStyle {
GC bgGC; /* Graphics context for background. None means
* use widget background. */
GC fgGC; /* Graphics context for foreground. */
+ GC ulGC; /* Graphics context for underline. */
+ GC ovGC; /* Graphics context for overstrike. */
StyleValues *sValuePtr; /* Raw information from which GCs were
* derived. */
Tcl_HashEntry *hPtr; /* Pointer to entry in styleTable. Used to
@@ -234,6 +242,14 @@ typedef struct DLine {
int spaceBelow; /* How much extra space was added to the
* bottom of the line because of spacing
* options. This is included in height. */
+ Tk_3DBorder lMarginColor; /* Background color of the area corresponding
+ * to the left margin of the display line. */
+ int lMarginWidth; /* Pixel width of the area corresponding to
+ * the left margin. */
+ Tk_3DBorder rMarginColor; /* Background color of the area corresponding
+ * to the right margin of the display line. */
+ int rMarginWidth; /* Pixel width of the area corresponding to
+ * the right margin. */
int length; /* Total length of line, in pixels. */
TkTextDispChunk *chunkPtr; /* Pointer to first chunk in list of all of
* those that are displayed on this line of
@@ -748,6 +764,7 @@ GetStyle(
TextStyle *stylePtr;
Tcl_HashEntry *hPtr;
int numTags, isNew, i;
+ int isSelected;
XGCValues gcValues;
unsigned long mask;
/*
@@ -758,6 +775,7 @@ GetStyle(
int fgPrio, fontPrio, fgStipplePrio;
int underlinePrio, elidePrio, justifyPrio, offsetPrio;
int lMargin1Prio, lMargin2Prio, rMarginPrio;
+ int lMarginColorPrio, rMarginColorPrio;
int spacing1Prio, spacing2Prio, spacing3Prio;
int overstrikePrio, tabPrio, tabStylePrio, wrapPrio;
@@ -772,11 +790,14 @@ GetStyle(
fgPrio = fontPrio = fgStipplePrio = -1;
underlinePrio = elidePrio = justifyPrio = offsetPrio = -1;
lMargin1Prio = lMargin2Prio = rMarginPrio = -1;
+ lMarginColorPrio = rMarginColorPrio = -1;
spacing1Prio = spacing2Prio = spacing3Prio = -1;
overstrikePrio = tabPrio = tabStylePrio = wrapPrio = -1;
memset(&styleValues, 0, sizeof(StyleValues));
styleValues.relief = TK_RELIEF_FLAT;
styleValues.fgColor = textPtr->fgColor;
+ styleValues.underlineColor = textPtr->fgColor;
+ styleValues.overstrikeColor = textPtr->fgColor;
styleValues.tkfont = textPtr->tkfont;
styleValues.justify = TK_JUSTIFY_LEFT;
styleValues.spacing1 = textPtr->spacing1;
@@ -786,12 +807,22 @@ GetStyle(
styleValues.tabStyle = textPtr->tabStyle;
styleValues.wrapMode = textPtr->wrapMode;
styleValues.elide = 0;
+ isSelected = 0;
+
+ for (i = 0 ; i < numTags; i++) {
+ if (textPtr->selTagPtr == tagPtrs[i]) {
+ isSelected = 1;
+ break;
+ }
+ }
for (i = 0 ; i < numTags; i++) {
Tk_3DBorder border;
+ XColor *fgColor;
tagPtr = tagPtrs[i];
border = tagPtr->border;
+ fgColor = tagPtr->fgColor;
/*
* If this is the selection tag, and inactiveSelBorder is NULL (the
@@ -811,6 +842,14 @@ GetStyle(
border = textPtr->inactiveSelBorder;
}
+ if ((tagPtr->selBorder != NULL) && (isSelected)) {
+ border = tagPtr->selBorder;
+ }
+
+ if ((tagPtr->selFgColor != None) && (isSelected)) {
+ fgColor = tagPtr->selFgColor;
+ }
+
if ((border != NULL) && (tagPtr->priority > borderPrio)) {
styleValues.border = border;
borderPrio = tagPtr->priority;
@@ -834,8 +873,8 @@ GetStyle(
styleValues.bgStipple = tagPtr->bgStipple;
bgStipplePrio = tagPtr->priority;
}
- if ((tagPtr->fgColor != None) && (tagPtr->priority > fgPrio)) {
- styleValues.fgColor = tagPtr->fgColor;
+ if ((fgColor != None) && (tagPtr->priority > fgPrio)) {
+ styleValues.fgColor = fgColor;
fgPrio = tagPtr->priority;
}
if ((tagPtr->tkfont != None) && (tagPtr->priority > fontPrio)) {
@@ -862,6 +901,11 @@ GetStyle(
styleValues.lMargin2 = tagPtr->lMargin2;
lMargin2Prio = tagPtr->priority;
}
+ if ((tagPtr->lMarginColor != NULL)
+ && (tagPtr->priority > lMarginColorPrio)) {
+ styleValues.lMarginColor = tagPtr->lMarginColor;
+ lMarginColorPrio = tagPtr->priority;
+ }
if ((tagPtr->offsetString != NULL)
&& (tagPtr->priority > offsetPrio)) {
styleValues.offset = tagPtr->offset;
@@ -871,12 +915,22 @@ GetStyle(
&& (tagPtr->priority > overstrikePrio)) {
styleValues.overstrike = tagPtr->overstrike;
overstrikePrio = tagPtr->priority;
+ if (tagPtr->overstrikeColor != None) {
+ styleValues.overstrikeColor = tagPtr->overstrikeColor;
+ } else if (fgColor != None) {
+ styleValues.overstrikeColor = fgColor;
+ }
}
if ((tagPtr->rMarginString != NULL)
&& (tagPtr->priority > rMarginPrio)) {
styleValues.rMargin = tagPtr->rMargin;
rMarginPrio = tagPtr->priority;
}
+ if ((tagPtr->rMarginColor != NULL)
+ && (tagPtr->priority > rMarginColorPrio)) {
+ styleValues.rMarginColor = tagPtr->rMarginColor;
+ rMarginColorPrio = tagPtr->priority;
+ }
if ((tagPtr->spacing1String != NULL)
&& (tagPtr->priority > spacing1Prio)) {
styleValues.spacing1 = tagPtr->spacing1;
@@ -906,6 +960,11 @@ GetStyle(
&& (tagPtr->priority > underlinePrio)) {
styleValues.underline = tagPtr->underline;
underlinePrio = tagPtr->priority;
+ if (tagPtr->underlineColor != None) {
+ styleValues.underlineColor = tagPtr->underlineColor;
+ } else if (fgColor != None) {
+ styleValues.underlineColor = fgColor;
+ }
}
if ((tagPtr->elideString != NULL)
&& (tagPtr->priority > elidePrio)) {
@@ -962,6 +1021,11 @@ GetStyle(
mask |= GCStipple|GCFillStyle;
}
stylePtr->fgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
+ mask = GCForeground;
+ gcValues.foreground = styleValues.underlineColor->pixel;
+ stylePtr->ulGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
+ gcValues.foreground = styleValues.overstrikeColor->pixel;
+ stylePtr->ovGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
stylePtr->sValuePtr = (StyleValues *)
Tcl_GetHashKey(&textPtr->dInfoPtr->styleTable, hPtr);
stylePtr->hPtr = hPtr;
@@ -1002,6 +1066,12 @@ FreeStyle(
if (stylePtr->fgGC != None) {
Tk_FreeGC(textPtr->display, stylePtr->fgGC);
}
+ if (stylePtr->ulGC != None) {
+ Tk_FreeGC(textPtr->display, stylePtr->ulGC);
+ }
+ if (stylePtr->ovGC != None) {
+ Tk_FreeGC(textPtr->display, stylePtr->ovGC);
+ }
Tcl_DeleteHashEntry(stylePtr->hPtr);
ckfree(stylePtr);
}
@@ -1113,6 +1183,10 @@ LayoutDLine(
dlPtr->nextPtr = NULL;
dlPtr->flags = NEW_LAYOUT | OLD_Y_INVALID;
dlPtr->logicalLinesMerged = 0;
+ dlPtr->lMarginColor = NULL;
+ dlPtr->lMarginWidth = 0;
+ dlPtr->rMarginColor = NULL;
+ dlPtr->rMarginWidth = 0;
/*
* This is not necessarily totally correct, where we have merged logical
@@ -1387,6 +1461,7 @@ LayoutDLine(
x = chunkPtr->stylePtr->sValuePtr->lMargin2;
}
+ dlPtr->lMarginWidth = x;
if (wrapMode == TEXT_WRAPMODE_NONE) {
maxX = -1;
} else {
@@ -1640,7 +1715,7 @@ LayoutDLine(
* Make one more pass over the line to recompute various things like its
* height, length, and total number of bytes. Also modify the x-locations
* of chunks to reflect justification. If we're not wrapping, I'm not sure
- * what is the best way to handle left and center justification: should
+ * what is the best way to handle right and center justification: should
* the total length, for purposes of justification, be (a) the window
* width, (b) the length of the longest line in the window, or (c) the
* length of the longest line in the text? (c) isn't available, (b) seems
@@ -1698,6 +1773,11 @@ LayoutDLine(
}
dlPtr->height += dlPtr->spaceAbove + dlPtr->spaceBelow;
dlPtr->baseline += dlPtr->spaceAbove;
+ dlPtr->lMarginColor = sValuePtr->lMarginColor;
+ dlPtr->rMarginColor = sValuePtr->rMarginColor;
+ if (wrapMode != TEXT_WRAPMODE_NONE) {
+ dlPtr->rMarginWidth = rMargin;
+ }
/*
* Recompute line length: may have changed because of justification.
@@ -2384,6 +2464,20 @@ DisplayDLine(
Tk_Width(textPtr->tkwin), dlPtr->height, 0, TK_RELIEF_FLAT);
/*
+ * Second, draw the background color of the left and right margins.
+ */
+ if (dlPtr->lMarginColor != NULL) {
+ Tk_Fill3DRectangle(textPtr->tkwin, pixmap, dlPtr->lMarginColor, 0, y,
+ dlPtr->lMarginWidth + dInfoPtr->x - dInfoPtr->curXPixelOffset,
+ dlPtr->height, 0, TK_RELIEF_FLAT);
+ }
+ if (dlPtr->rMarginColor != NULL) {
+ Tk_Fill3DRectangle(textPtr->tkwin, pixmap, dlPtr->rMarginColor,
+ dInfoPtr->maxX - dlPtr->rMarginWidth + dInfoPtr->curXPixelOffset,
+ y, dlPtr->rMarginWidth, dlPtr->height, 0, TK_RELIEF_FLAT);
+ }
+
+ /*
* Next, draw background information for the whole line.
*/
@@ -3010,7 +3104,7 @@ AsyncUpdateLineMetrics(
* Send the <<WidgetViewSync>> event related to the text widget
* line metrics asynchronous update.
* This is equivalent to:
- * event generate $textWidget <<WidgetViewSync>> -detail $s
+ * event generate $textWidget <<WidgetViewSync>> -data $s
* where $s is the sync status: true (when the widget view is in
* sync with its internal data) or false (when it is not).
*
@@ -3026,19 +3120,10 @@ AsyncUpdateLineMetrics(
static void
GenerateWidgetViewSyncEvent(
TkText *textPtr, /* Information about text widget. */
- Bool InSync) /* True if in sync, false otherwise */
+ Bool InSync) /* true if in sync, false otherwise */
{
- union {XEvent general; XVirtualEvent virtual;} event;
-
- memset(&event, 0, sizeof(event));
- event.general.xany.type = VirtualEvent;
- event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
- event.general.xany.send_event = False;
- event.general.xany.window = Tk_WindowId(textPtr->tkwin);
- event.general.xany.display = Tk_Display(textPtr->tkwin);
- event.virtual.name = Tk_GetUid("WidgetViewSync");
- event.virtual.user_data = Tcl_NewBooleanObj(InSync);
- Tk_HandleEvent(&event.general);
+ TkSendVirtualEvent(textPtr->tkwin, "WidgetViewSync",
+ Tcl_NewBooleanObj(InSync));
}
/*
@@ -4869,16 +4954,9 @@ TextRedrawTag(
/*
* Round up the starting position if it's before the first line visible on
- * the screen (we only care about what's on the screen). Beware that the
- * display info structure might need update, for instance if we arrived
- * here from an 'after idle' script removing tags in a range whose
- * display lines (and dInfo) were partially invalidated by a previous
- * delete operation in the text widget.
+ * the screen (we only care about what's on the screen).
*/
- if (dInfoPtr->flags & DINFO_OUT_OF_DATE) {
- UpdateDisplayInfo(textPtr);
- }
dlPtr = dInfoPtr->dLinePtr;
if (dlPtr == NULL) {
return;
@@ -5240,7 +5318,10 @@ TkTextSetYView(
dInfoPtr->newTopPixelOffset = 0;
goto scheduleUpdate;
- }
+ }
+ /*
+ * The line is already on screen, with no need to scroll.
+ */
return;
}
}
@@ -6703,6 +6784,7 @@ FindDLine(
const TkTextIndex *indexPtr)/* Index of desired character. */
{
DLine *dlPtrPrev;
+ TkTextIndex indexPtr2;
if (dlPtr == NULL) {
return NULL;
@@ -6727,24 +6809,58 @@ FindDLine(
dlPtrPrev = dlPtr;
dlPtr = dlPtr->nextPtr;
if (dlPtr == NULL) {
- TkTextIndex indexPtr2;
/*
* We're past the last display line, either because the desired
* index lies past the visible text, or because the desired index
- * is on the last display line showing the last logical line.
+ * is on the last display line.
*/
indexPtr2 = dlPtrPrev->index;
TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount,
&indexPtr2);
if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) {
+ /*
+ * The desired index is on the last display line.
+ * --> return this display line.
+ */
dlPtr = dlPtrPrev;
- break;
} else {
- return NULL;
+ /*
+ * The desired index is past the visible text. There is no
+ * display line displaying something at the desired index.
+ * --> return NULL.
+ */
}
+ break;
}
if (TkTextIndexCmp(&dlPtr->index,indexPtr) > 0) {
- dlPtr = dlPtrPrev;
+ /*
+ * If we're here then we would normally expect that:
+ * dlPtrPrev->index <= indexPtr < dlPtr->index
+ * i.e. we have found the searched display line being dlPtr.
+ * However it is possible that some DLines were unlinked
+ * previously, leading to a situation where going through
+ * the list of display lines skips display lines that did
+ * exist just a moment ago.
+ */
+ indexPtr2 = dlPtrPrev->index;
+ TkTextIndexForwBytes(textPtr, &indexPtr2, dlPtrPrev->byteCount,
+ &indexPtr2);
+ if (TkTextIndexCmp(&indexPtr2,indexPtr) > 0) {
+ /*
+ * Confirmed:
+ * dlPtrPrev->index <= indexPtr < dlPtr->index
+ * --> return dlPtrPrev.
+ */
+ dlPtr = dlPtrPrev;
+ } else {
+ /*
+ * The last (rightmost) index shown by dlPtrPrev is still
+ * before the desired index. This may be because there was
+ * previously a display line between dlPtrPrev and dlPtr
+ * and this display line has been unlinked.
+ * --> return dlPtr.
+ */
+ }
break;
}
}
@@ -7814,7 +7930,7 @@ CharDisplayProc(
y + baseline - sValuePtr->offset);
if (sValuePtr->underline) {
- TkUnderlineCharsInContext(display, dst, stylePtr->fgGC,
+ TkUnderlineCharsInContext(display, dst, stylePtr->ulGC,
sValuePtr->tkfont, string, numBytes,
ciPtr->baseChunkPtr->x + xDisplacement,
y + baseline - sValuePtr->offset,
@@ -7824,7 +7940,7 @@ CharDisplayProc(
Tk_FontMetrics fm;
Tk_GetFontMetrics(sValuePtr->tkfont, &fm);
- TkUnderlineCharsInContext(display, dst, stylePtr->fgGC,
+ TkUnderlineCharsInContext(display, dst, stylePtr->ovGC,
sValuePtr->tkfont, string, numBytes,
ciPtr->baseChunkPtr->x + xDisplacement,
y + baseline - sValuePtr->offset
@@ -7841,7 +7957,7 @@ CharDisplayProc(
Tk_DrawChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, string,
numBytes, offsetX, y + baseline - sValuePtr->offset);
if (sValuePtr->underline) {
- Tk_UnderlineChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont,
+ Tk_UnderlineChars(display, dst, stylePtr->ulGC, sValuePtr->tkfont,
string, offsetX,
y + baseline - sValuePtr->offset,
0, numBytes);
@@ -7851,7 +7967,7 @@ CharDisplayProc(
Tk_FontMetrics fm;
Tk_GetFontMetrics(sValuePtr->tkfont, &fm);
- Tk_UnderlineChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont,
+ Tk_UnderlineChars(display, dst, stylePtr->ovGC, sValuePtr->tkfont,
string, offsetX,
y + baseline - sValuePtr->offset
- fm.descent - (fm.ascent * 3) / 10,
diff --git a/generic/tkTextTag.c b/generic/tkTextTag.c
index 3363d25..a212615 100644
--- a/generic/tkTextTag.c
+++ b/generic/tkTextTag.c
@@ -61,15 +61,26 @@ static const Tk_OptionSpec tagOptionSpecs[] = {
NULL, -1, Tk_Offset(TkTextTag, lMargin1String), TK_OPTION_NULL_OK,0,0},
{TK_OPTION_STRING, "-lmargin2", NULL, NULL,
NULL, -1, Tk_Offset(TkTextTag, lMargin2String), TK_OPTION_NULL_OK,0,0},
+ {TK_OPTION_BORDER, "-lmargincolor", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, lMarginColor), TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_STRING, "-offset", NULL, NULL,
NULL, -1, Tk_Offset(TkTextTag, offsetString), TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_STRING, "-overstrike", NULL, NULL,
NULL, -1, Tk_Offset(TkTextTag, overstrikeString),
TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-overstrikefg", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, overstrikeColor),
+ TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_STRING, "-relief", NULL, NULL,
NULL, -1, Tk_Offset(TkTextTag, reliefString), TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_STRING, "-rmargin", NULL, NULL,
NULL, -1, Tk_Offset(TkTextTag, rMarginString), TK_OPTION_NULL_OK, 0,0},
+ {TK_OPTION_BORDER, "-rmargincolor", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, rMarginColor), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BORDER, "-selectbackground", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, selBorder), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-selectforeground", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, selFgColor), TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_STRING, "-spacing1", NULL, NULL,
NULL, -1, Tk_Offset(TkTextTag, spacing1String), TK_OPTION_NULL_OK,0,0},
{TK_OPTION_STRING, "-spacing2", NULL, NULL,
@@ -84,6 +95,9 @@ static const Tk_OptionSpec tagOptionSpecs[] = {
{TK_OPTION_STRING, "-underline", NULL, NULL,
NULL, -1, Tk_Offset(TkTextTag, underlineString),
TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-underlinefg", NULL, NULL,
+ NULL, -1, Tk_Offset(TkTextTag, underlineColor),
+ TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_STRING_TABLE, "-wrap", NULL, NULL,
NULL, -1, Tk_Offset(TkTextTag, wrapMode),
TK_OPTION_NULL_OK, wrapStrings, 0},
@@ -484,10 +498,18 @@ TkTextTagCmd(
*/
if (tagPtr == textPtr->selTagPtr) {
- textPtr->selBorder = tagPtr->border;
+ if (tagPtr->selBorder == NULL) {
+ textPtr->selBorder = tagPtr->border;
+ } else {
+ textPtr->selBorder = tagPtr->selBorder;
+ }
textPtr->selBorderWidth = tagPtr->borderWidth;
textPtr->selBorderWidthPtr = tagPtr->borderWidthPtr;
- textPtr->selFgColorPtr = tagPtr->fgColor;
+ if (tagPtr->selFgColor == NULL) {
+ textPtr->selFgColorPtr = tagPtr->fgColor;
+ } else {
+ textPtr->selFgColorPtr = tagPtr->selFgColor;
+ }
}
tagPtr->affectsDisplay = 0;
@@ -509,12 +531,18 @@ TkTextTagCmd(
tagPtr->affectsDisplayGeometry = 1;
}
if ((tagPtr->border != NULL)
+ || (tagPtr->selBorder != NULL)
|| (tagPtr->reliefString != NULL)
|| (tagPtr->bgStipple != None)
|| (tagPtr->fgColor != NULL)
+ || (tagPtr->selFgColor != NULL)
|| (tagPtr->fgStipple != None)
|| (tagPtr->overstrikeString != NULL)
- || (tagPtr->underlineString != NULL)) {
+ || (tagPtr->overstrikeColor != NULL)
+ || (tagPtr->underlineString != NULL)
+ || (tagPtr->underlineColor != NULL)
+ || (tagPtr->lMarginColor != NULL)
+ || (tagPtr->rMarginColor != NULL)) {
tagPtr->affectsDisplay = 1;
}
if (!newTag) {
@@ -1011,12 +1039,17 @@ TkTextCreateTag(
tagPtr->lMargin1 = 0;
tagPtr->lMargin2String = NULL;
tagPtr->lMargin2 = 0;
+ tagPtr->lMarginColor = NULL;
tagPtr->offsetString = NULL;
tagPtr->offset = 0;
tagPtr->overstrikeString = NULL;
tagPtr->overstrike = 0;
+ tagPtr->overstrikeColor = NULL;
tagPtr->rMarginString = NULL;
tagPtr->rMargin = 0;
+ tagPtr->rMarginColor = NULL;
+ tagPtr->selBorder = NULL;
+ tagPtr->selFgColor = NULL;
tagPtr->spacing1String = NULL;
tagPtr->spacing1 = 0;
tagPtr->spacing2String = NULL;
@@ -1028,6 +1061,7 @@ TkTextCreateTag(
tagPtr->tabStyle = TK_TEXT_TABSTYLE_NONE;
tagPtr->underlineString = NULL;
tagPtr->underline = 0;
+ tagPtr->underlineColor = NULL;
tagPtr->elideString = NULL;
tagPtr->elide = 0;
tagPtr->wrapMode = TEXT_WRAPMODE_NULL;
diff --git a/generic/tkUndo.c b/generic/tkUndo.c
index 8359e0a..c66905d 100644
--- a/generic/tkUndo.c
+++ b/generic/tkUndo.c
@@ -353,7 +353,7 @@ TkUndoInitStack(
/*
*----------------------------------------------------------------------
*
- * TkUndoSetDepth --
+ * TkUndoSetMaxDepth --
*
* Set the maximum depth of stack.
*
@@ -368,7 +368,7 @@ TkUndoInitStack(
*/
void
-TkUndoSetDepth(
+TkUndoSetMaxDepth(
TkUndoRedoStack *stack, /* An Undo/Redo stack */
int maxdepth) /* The maximum stack depth */
{
@@ -478,6 +478,52 @@ TkUndoFreeStack(
/*
*----------------------------------------------------------------------
*
+ * TkUndoCanRedo --
+ *
+ * Returns true if redo is possible, i.e. if the redo stack is not empty.
+ *
+ * Results:
+ * A boolean.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkUndoCanRedo(
+ TkUndoRedoStack *stack) /* An Undo/Redo stack */
+{
+ return stack->redoStack != NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkUndoCanUndo --
+ *
+ * Returns true if undo is possible, i.e. if the undo stack is not empty.
+ *
+ * Results:
+ * A boolean.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkUndoCanUndo(
+ TkUndoRedoStack *stack) /* An Undo/Redo stack */
+{
+ return stack->undoStack != NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkUndoInsertUndoSeparator --
*
* Insert a separator on the undo stack, indicating a border for an
@@ -498,7 +544,7 @@ TkUndoInsertUndoSeparator(
{
if (TkUndoInsertSeparator(&stack->undoStack)) {
stack->depth++;
- TkUndoSetDepth(stack, stack->maxdepth);
+ TkUndoSetMaxDepth(stack, stack->maxdepth);
}
}
diff --git a/generic/tkUndo.h b/generic/tkUndo.h
index e63aac4..490ede9 100644
--- a/generic/tkUndo.h
+++ b/generic/tkUndo.h
@@ -96,9 +96,11 @@ MODULE_SCOPE void TkUndoClearStack(TkUndoAtom **stack);
*/
MODULE_SCOPE TkUndoRedoStack *TkUndoInitStack(Tcl_Interp *interp, int maxdepth);
-MODULE_SCOPE void TkUndoSetDepth(TkUndoRedoStack *stack, int maxdepth);
+MODULE_SCOPE void TkUndoSetMaxDepth(TkUndoRedoStack *stack, int maxdepth);
MODULE_SCOPE void TkUndoClearStacks(TkUndoRedoStack *stack);
MODULE_SCOPE void TkUndoFreeStack(TkUndoRedoStack *stack);
+MODULE_SCOPE int TkUndoCanRedo(TkUndoRedoStack *stack);
+MODULE_SCOPE int TkUndoCanUndo(TkUndoRedoStack *stack);
MODULE_SCOPE void TkUndoInsertUndoSeparator(TkUndoRedoStack *stack);
MODULE_SCOPE TkUndoSubAtom *TkUndoMakeCmdSubAtom(Tcl_Command command,
Tcl_Obj *actionScript, TkUndoSubAtom *subAtomList);
diff --git a/generic/tkUtil.c b/generic/tkUtil.c
index 7ff9ecb..6563165 100644
--- a/generic/tkUtil.c
+++ b/generic/tkUtil.c
@@ -1162,7 +1162,8 @@ TkMakeEnsemble(
* TkSendVirtualEvent --
*
* Send a virtual event notification to the specified target window.
- * Equivalent to "event generate $target <<$eventName>>"
+ * Equivalent to:
+ * "event generate $target <<$eventName>> -data $detail"
*
* Note that we use Tk_QueueWindowEvent, not Tk_HandleEvent, so this
* routine does not reenter the interpreter.
@@ -1173,7 +1174,8 @@ TkMakeEnsemble(
void
TkSendVirtualEvent(
Tk_Window target,
- const char *eventName)
+ const char *eventName,
+ Tcl_Obj *detail)
{
union {XEvent general; XVirtualEvent virtual;} event;
@@ -1184,6 +1186,9 @@ TkSendVirtualEvent(
event.general.xany.window = Tk_WindowId(target);
event.general.xany.display = Tk_Display(target);
event.virtual.name = Tk_GetUid(eventName);
+ if (detail != NULL) {
+ event.virtual.user_data = detail;
+ }
Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL);
}
diff --git a/generic/tkWindow.c b/generic/tkWindow.c
index 1e88844..0c60321 100644
--- a/generic/tkWindow.c
+++ b/generic/tkWindow.c
@@ -54,12 +54,6 @@ typedef struct ThreadSpecificData {
static Tcl_ThreadDataKey dataKey;
/*
- * The Mutex below is used to lock access to the Tk_Uid structs above.
- */
-
-TCL_DECLARE_MUTEX(windowMutex)
-
-/*
* Default values for "changes" and "atts" fields of TkWindows. Note that Tk
* always requests all events for all windows, except StructureNotify events
* on internal windows: these events are generated internally.
@@ -206,40 +200,6 @@ static const TkCmd commands[] = {
};
/*
- * The variables and table below are used to parse arguments from the "argv"
- * variable in Tk_Init.
- */
-
-static int synchronize = 0;
-static char *name = NULL;
-static char *display = NULL;
-static char *geometry = NULL;
-static char *colormap = NULL;
-static char *use = NULL;
-static char *visual = NULL;
-static int rest = 0;
-
-static const Tk_ArgvInfo argTable[] = {
- {"-colormap", TK_ARGV_STRING, NULL, (char *) &colormap,
- "Colormap for main window"},
- {"-display", TK_ARGV_STRING, NULL, (char *) &display,
- "Display to use"},
- {"-geometry", TK_ARGV_STRING, NULL, (char *) &geometry,
- "Initial geometry for window"},
- {"-name", TK_ARGV_STRING, NULL, (char *) &name,
- "Name to use for application"},
- {"-sync", TK_ARGV_CONSTANT, (char *) 1, (char *) &synchronize,
- "Use synchronous mode for display server"},
- {"-visual", TK_ARGV_STRING, NULL, (char *) &visual,
- "Visual for main window"},
- {"-use", TK_ARGV_STRING, NULL, (char *) &use,
- "Id of window in which to embed application"},
- {"--", TK_ARGV_REST, (char *) 1, (char *) &rest,
- "Pass all remaining arguments through to script"},
- {NULL, TK_ARGV_END, NULL, NULL, NULL}
-};
-
-/*
* Forward declarations to functions defined later in this file:
*/
@@ -3031,16 +2991,51 @@ MODULE_SCOPE const TkStubs tkStubs;
*/
static int
+CopyValue(
+ ClientData dummy,
+ Tcl_Obj *objPtr,
+ void *dstPtr)
+{
+ *(Tcl_Obj **)dstPtr = objPtr;
+ return 1;
+}
+
+static int
Initialize(
Tcl_Interp *interp) /* Interpreter to initialize. */
{
- char *p;
- int argc, code;
- const char **argv;
- const char *args[20];
- const char *argString = NULL;
- Tcl_DString class;
+ int code = TCL_OK;
ThreadSpecificData *tsdPtr;
+ Tcl_Obj *value = NULL;
+ Tcl_Obj *cmd;
+
+ Tcl_Obj *nameObj = NULL;
+ Tcl_Obj *classObj = NULL;
+ Tcl_Obj *displayObj = NULL;
+ Tcl_Obj *colorMapObj = NULL;
+ Tcl_Obj *useObj = NULL;
+ Tcl_Obj *visualObj = NULL;
+ Tcl_Obj *geometryObj = NULL;
+
+ int sync = 0;
+
+ const Tcl_ArgvInfo table[] = {
+ {TCL_ARGV_CONSTANT, "-sync", INT2PTR(1), &sync,
+ "Use synchronous mode for display server", NULL},
+ {TCL_ARGV_FUNC, "-colormap", CopyValue, &colorMapObj,
+ "Colormap for main window", NULL},
+ {TCL_ARGV_FUNC, "-display", CopyValue, &displayObj,
+ "Display to use", NULL},
+ {TCL_ARGV_FUNC, "-geometry", CopyValue, &geometryObj,
+ "Initial geometry for window", NULL},
+ {TCL_ARGV_FUNC, "-name", CopyValue, &nameObj,
+ "Name to use for application", NULL},
+ {TCL_ARGV_FUNC, "-visual", CopyValue, &visualObj,
+ "Visual for main window", NULL},
+ {TCL_ARGV_FUNC, "-use", CopyValue, &useObj,
+ "Id of window in which to embed application", NULL},
+ TCL_ARGV_AUTO_REST, TCL_ARGV_AUTO_HELP, TCL_ARGV_TABLE_END
+ };
/*
* Ensure that we are getting a compatible version of Tcl.
@@ -3059,23 +3054,6 @@ Initialize(
tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
- * Start by initializing all the static variables to default acceptable
- * values so that no information is leaked from a previous run of this
- * code.
- */
-
- Tcl_MutexLock(&windowMutex);
- synchronize = 0;
- name = NULL;
- display = NULL;
- geometry = NULL;
- colormap = NULL;
- use = NULL;
- visual = NULL;
- rest = 0;
- argv = NULL;
-
- /*
* We start by resetting the result because it might not be clean.
*/
@@ -3087,8 +3065,6 @@ Initialize(
* master.
*/
- Tcl_DString ds;
-
/*
* Step 1 : find the master and construct the interp name (could be a
* function if new APIs were ok). We could also construct the path
@@ -3098,18 +3074,13 @@ Initialize(
Tcl_Interp *master = interp;
- while (1) {
+ while (Tcl_IsSafe(master)) {
master = Tcl_GetMaster(master);
if (master == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"no controlling master interpreter", -1));
Tcl_SetErrorCode(interp, "TK", "SAFE", "NO_MASTER", NULL);
- code = TCL_ERROR;
- goto done;
- }
- if (!Tcl_IsSafe(master)) {
- /* Found the trusted master. */
- break;
+ return TCL_ERROR;
}
}
@@ -3119,39 +3090,30 @@ Initialize(
code = Tcl_GetInterpPath(master, interp);
if (code != TCL_OK) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "error in Tcl_GetInterpPath", -1));
- Tcl_SetErrorCode(interp, "TK", "SAFE", "FAILED", NULL);
- goto done;
+ Tcl_Panic("Tcl_GetInterpPath broken!");
}
/*
- * Build the string to eval.
+ * Build the command to eval in trusted master.
*/
- Tcl_DStringInit(&ds);
- Tcl_DStringAppendElement(&ds, "::safe::TkInit");
- Tcl_DStringAppendElement(&ds, Tcl_GetString(Tcl_GetObjResult(master)));
-
+ cmd = Tcl_NewListObj(2, NULL);
+ Tcl_ListObjAppendElement(NULL, cmd,
+ Tcl_NewStringObj("::safe::TkInit", -1));
+ Tcl_ListObjAppendElement(NULL, cmd, Tcl_GetObjResult(master));
+
/*
* Step 2 : Eval in the master. The argument is the *reversed* interp
* path of the slave.
*/
- code = Tcl_EvalEx(master, Tcl_DStringValue(&ds), -1, 0);
+ Tcl_IncrRefCount(cmd);
+ code = Tcl_EvalObjEx(master, cmd, 0);
+ Tcl_DecrRefCount(cmd);
+ Tcl_TransferResult(master, code, interp);
if (code != TCL_OK) {
- /*
- * We might want to transfer the error message or not. We don't.
- * (No API to do it and maybe security reasons).
- */
-
- Tcl_DStringFree(&ds);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "not allowed to start Tk by master's safe::TkInit", -1));
- Tcl_SetErrorCode(interp, "TK", "SAFE", "FAILED", NULL);
- goto done;
+ return code;
}
- Tcl_DStringFree(&ds);
/*
* Use the master's result as argv. Note: We don't use the Obj
@@ -3159,7 +3121,7 @@ Initialize(
* changing the code below.
*/
- argString = Tcl_GetString(Tcl_GetObjResult(master));
+ value = Tcl_GetObjResult(interp);
} else {
/*
* If there is an "argv" variable, get its value, extract out relevant
@@ -3167,50 +3129,67 @@ Initialize(
* that we used.
*/
- argString = Tcl_GetVar2(interp, "argv", NULL, TCL_GLOBAL_ONLY);
+ value = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY);
}
- if (argString != NULL) {
- char buffer[TCL_INTEGER_SPACE];
- if (Tcl_SplitList(interp, argString, &argc, &argv) != TCL_OK) {
- argError:
+ if (value) {
+ int objc;
+ Tcl_Obj **objv, **rest;
+ Tcl_Obj *parseList = Tcl_NewListObj(1, NULL);
+
+ Tcl_ListObjAppendElement(NULL, parseList, Tcl_NewObj());
+
+ Tcl_IncrRefCount(value);
+ if (TCL_OK != Tcl_ListObjAppendList(interp, parseList, value) ||
+ TCL_OK != Tcl_ListObjGetElements(NULL, parseList, &objc, &objv) ||
+ TCL_OK != Tcl_ParseArgsObjv(interp, table, &objc, objv, &rest)) {
Tcl_AddErrorInfo(interp,
"\n (processing arguments in argv variable)");
code = TCL_ERROR;
- goto done;
}
- if (Tk_ParseArgv(interp, (Tk_Window) NULL, &argc, argv,
- argTable, TK_ARGV_DONT_SKIP_FIRST_ARG|TK_ARGV_NO_DEFAULTS)
- != TCL_OK) {
- goto argError;
+ if (code == TCL_OK) {
+ Tcl_SetVar2Ex(interp, "argv", NULL,
+ Tcl_NewListObj(objc-1, rest+1), TCL_GLOBAL_ONLY);
+ Tcl_SetVar2Ex(interp, "argc", NULL,
+ Tcl_NewIntObj(objc-1), TCL_GLOBAL_ONLY);
+ ckfree(rest);
+ }
+ Tcl_DecrRefCount(parseList);
+ if (code != TCL_OK) {
+ goto done;
}
- p = Tcl_Merge(argc, argv);
- Tcl_SetVar2(interp, "argv", NULL, p, TCL_GLOBAL_ONLY);
- sprintf(buffer, "%d", argc);
- Tcl_SetVar2(interp, "argc", NULL, buffer, TCL_GLOBAL_ONLY);
- ckfree(p);
}
/*
* Figure out the application's name and class.
*/
- Tcl_DStringInit(&class);
- if (name == NULL) {
- int offset;
+ /*
+ * If we got no -name argument, fetch from TkpGetAppName().
+ */
- TkpGetAppName(interp, &class);
- offset = Tcl_DStringLength(&class)+1;
- Tcl_DStringSetLength(&class, offset);
- Tcl_DStringAppend(&class, Tcl_DStringValue(&class), offset-1);
- name = Tcl_DStringValue(&class) + offset;
- } else {
- Tcl_DStringAppend(&class, name, -1);
+ if (nameObj == NULL) {
+ Tcl_DString nameDS;
+
+ Tcl_DStringInit(&nameDS);
+ TkpGetAppName(interp, &nameDS);
+ nameObj = Tcl_NewStringObj(Tcl_DStringValue(&nameDS),
+ Tcl_DStringLength(&nameDS));
+ Tcl_DStringFree(&nameDS);
}
- p = Tcl_DStringValue(&class);
- if (*p) {
- Tcl_UtfToTitle(p);
+ /*
+ * The -class argument is always the ToTitle of the -name
+ */
+
+ {
+ int numBytes;
+ const char *bytes = Tcl_GetStringFromObj(nameObj, &numBytes);
+
+ classObj = Tcl_NewStringObj(bytes, numBytes);
+
+ numBytes = Tcl_UtfToTitle(Tcl_GetString(classObj));
+ Tcl_SetObjLength(classObj, numBytes);
}
/*
@@ -3218,15 +3197,14 @@ Initialize(
* information parsed from argv, if any.
*/
- args[0] = "toplevel";
- args[1] = ".";
- args[2] = "-class";
- args[3] = Tcl_DStringValue(&class);
- argc = 4;
- if (display != NULL) {
- args[argc] = "-screen";
- args[argc+1] = display;
- argc += 2;
+ cmd = Tcl_NewStringObj("toplevel . -class", -1);
+
+ Tcl_ListObjAppendElement(NULL, cmd, classObj);
+ classObj = NULL;
+
+ if (displayObj) {
+ Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-screen", -1));
+ Tcl_ListObjAppendElement(NULL, cmd, displayObj);
/*
* If this is the first application for this process, save the display
@@ -3235,36 +3213,35 @@ Initialize(
*/
if (tsdPtr->numMainWindows == 0) {
- Tcl_SetVar2(interp, "env", "DISPLAY", display, TCL_GLOBAL_ONLY);
+ Tcl_SetVar2Ex(interp, "env", "DISPLAY", displayObj, TCL_GLOBAL_ONLY);
}
+ displayObj = NULL;
}
- if (colormap != NULL) {
- args[argc] = "-colormap";
- args[argc+1] = colormap;
- argc += 2;
- colormap = NULL;
+ if (colorMapObj) {
+ Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-colormap", -1));
+ Tcl_ListObjAppendElement(NULL, cmd, colorMapObj);
+ colorMapObj = NULL;
}
- if (use != NULL) {
- args[argc] = "-use";
- args[argc+1] = use;
- argc += 2;
- use = NULL;
+ if (useObj) {
+ Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-use", -1));
+ Tcl_ListObjAppendElement(NULL, cmd, useObj);
+ useObj = NULL;
}
- if (visual != NULL) {
- args[argc] = "-visual";
- args[argc+1] = visual;
- argc += 2;
- visual = NULL;
+ if (visualObj) {
+ Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-visual", -1));
+ Tcl_ListObjAppendElement(NULL, cmd, visualObj);
+ visualObj = NULL;
}
- args[argc] = NULL;
- code = TkCreateFrame(NULL, interp, argc, args, 1, name);
- Tcl_DStringFree(&class);
+ code = TkListCreateFrame(NULL, interp, cmd, 1, nameObj);
+
+ Tcl_DecrRefCount(cmd);
+
if (code != TCL_OK) {
goto done;
}
Tcl_ResetResult(interp);
- if (synchronize) {
+ if (sync) {
XSynchronize(Tk_Display(Tk_MainWindow(interp)), True);
}
@@ -3273,19 +3250,19 @@ Initialize(
* geometry into the "geometry" variable.
*/
- if (geometry != NULL) {
- Tcl_DString buf;
+ if (geometryObj) {
+
+ Tcl_SetVar2Ex(interp, "geometry", NULL, geometryObj, TCL_GLOBAL_ONLY);
- Tcl_SetVar2(interp, "geometry", NULL, geometry, TCL_GLOBAL_ONLY);
- Tcl_DStringInit(&buf);
- Tcl_DStringAppend(&buf, "wm geometry . ", -1);
- Tcl_DStringAppend(&buf, geometry, -1);
- code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
- Tcl_DStringFree(&buf);
+ cmd = Tcl_NewStringObj("wm geometry .", -1);
+ Tcl_ListObjAppendElement(NULL, cmd, geometryObj);
+ Tcl_IncrRefCount(cmd);
+ code = Tcl_EvalObjEx(interp, cmd, 0);
+ Tcl_DecrRefCount(cmd);
+ geometryObj = NULL;
if (code != TCL_OK) {
goto done;
}
- geometry = NULL;
}
/*
@@ -3322,10 +3299,6 @@ Initialize(
* console window interpreter.
*/
- Tcl_MutexUnlock(&windowMutex);
- if (argv != NULL) {
- ckfree(argv);
- }
code = TkpInit(interp);
if (code == TCL_OK) {
@@ -3358,12 +3331,10 @@ tkInit", -1, 0);
TkCreateThreadExitHandler(DeleteWindowsExitProc, tsdPtr);
}
- return code;
-
done:
- Tcl_MutexUnlock(&windowMutex);
- if (argv != NULL) {
- ckfree(argv);
+ if (value) {
+ Tcl_DecrRefCount(value);
+ value = NULL;
}
return code;
}
diff --git a/generic/ttk/ttkGenStubs.tcl b/generic/ttk/ttkGenStubs.tcl
index 56ba2fa..8047e3f 100644
--- a/generic/ttk/ttkGenStubs.tcl
+++ b/generic/ttk/ttkGenStubs.tcl
@@ -18,8 +18,6 @@
# + Allow trailing semicolon in function declarations
#
-package require Tcl 8.4
-
namespace eval genStubs {
# libraryName --
#
diff --git a/generic/ttk/ttkNotebook.c b/generic/ttk/ttkNotebook.c
index 16a8bfe..81a8b64 100644
--- a/generic/ttk/ttkNotebook.c
+++ b/generic/ttk/ttkNotebook.c
@@ -901,7 +901,7 @@ static int NotebookAddCommand(
if (tab->state == TAB_STATE_HIDDEN) {
tab->state = TAB_STATE_NORMAL;
}
- if (ConfigureTab(interp, nb, tab, slaveWindow, objc-4,objv+4) != TCL_OK) {
+ if (ConfigureTab(interp, nb, tab, slaveWindow, objc-3,objv+3) != TCL_OK) {
return TCL_ERROR;
}