summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorgcramer <remarcg@gmx.net>2017-06-10 11:57:27 (GMT)
committergcramer <remarcg@gmx.net>2017-06-10 11:57:27 (GMT)
commit0cc579edbf11ac3855bc857fc2fc44cfd2f489fc (patch)
tree9b2cfbcb17e26514076f35dfde8aebf378b9a1d0 /generic
parent388d5cda26e21bca70ecfbab1def0ff634341dfa (diff)
downloadtk-0cc579edbf11ac3855bc857fc2fc44cfd2f489fc.zip
tk-0cc579edbf11ac3855bc857fc2fc44cfd2f489fc.tar.gz
tk-0cc579edbf11ac3855bc857fc2fc44cfd2f489fc.tar.bz2
Bugfix [0bc9df5fe3]: (1) Fix in deletion algorithm. (2) Additional macro for tracing segment allocation/deallocation. (3) Fix in load algorithm concerning handling of first newline. (4) Fix in load algorithm when configuring tags.
Diffstat (limited to 'generic')
-rw-r--r--generic/tkAlloc.h4
-rw-r--r--generic/tkText.c7
-rw-r--r--generic/tkText.h9
-rw-r--r--generic/tkTextBTree.c35
-rw-r--r--generic/tkTextDisp.c2
-rw-r--r--generic/tkTextImage.c3
-rw-r--r--generic/tkTextMark.c6
-rw-r--r--generic/tkTextPriv.h25
-rw-r--r--generic/tkTextTag.c7
-rw-r--r--generic/tkTextUndo.c2
-rw-r--r--generic/tkTextWind.c9
11 files changed, 79 insertions, 30 deletions
diff --git a/generic/tkAlloc.h b/generic/tkAlloc.h
index 93e0c5d..727d07f 100644
--- a/generic/tkAlloc.h
+++ b/generic/tkAlloc.h
@@ -22,6 +22,7 @@
#include <tcl.h>
#include <tclDecls.h> /* needed for the Tcl_Alloc macros */
#include <stdlib.h>
+#include <string.h>
#if TK_VALGRIND /* ===========================================================*/
@@ -64,12 +65,13 @@
/*
* If valgrind mode is disabled, then we use the Tcl allocations functions.
- * This means that malloc/realloc/free are simply wrappers to the Tcl
+ * This means that malloc/calloc/realloc/free are simply wrappers to the Tcl
* functions ckalloc/ckrealloc/ckfree.
*/
/* the main reason for these definitions is portability to 8.5 */
# define malloc(size) ((void *) (ckalloc(size)))
+# define calloc(nmemb, size) ((void *) (memset(ckalloc(nmemb*size), 0, nmemb*size)))
# define realloc(ptr, size) ((void *) (ckrealloc((char *) (ptr), size)))
# define free(ptr) ckfree((char *) (ptr))
diff --git a/generic/tkText.c b/generic/tkText.c
index f0acb0b..61ac530 100644
--- a/generic/tkText.c
+++ b/generic/tkText.c
@@ -1013,7 +1013,7 @@ CreateWidget(
}
if (!sharedTextPtr) {
- sharedTextPtr = memset(malloc(sizeof(TkSharedText)), 0, sizeof(TkSharedText));
+ sharedTextPtr = calloc(1, sizeof(TkSharedText));
Tcl_InitHashTable(&sharedTextPtr->tagTable, TCL_STRING_KEYS);
Tcl_InitHashTable(&sharedTextPtr->markTable, TCL_STRING_KEYS);
@@ -1044,7 +1044,7 @@ CreateWidget(
DEBUG(memset(sharedTextPtr->tagLookup, 0, TK_TEXT_SET_MAX_BIT_SIZE*sizeof(TkTextTag *)));
- sharedTextPtr->mainPeer = memset(malloc(sizeof(TkText)), 0, sizeof(TkText));
+ sharedTextPtr->mainPeer = calloc(1, sizeof(TkText));
sharedTextPtr->mainPeer->startMarker = sharedTextPtr->startMarker;
sharedTextPtr->mainPeer->endMarker = sharedTextPtr->endMarker;
sharedTextPtr->mainPeer->sharedTextPtr = sharedTextPtr;
@@ -1079,7 +1079,7 @@ CreateWidget(
* and 'insert', 'current' mark pointers are all NULL to start.
*/
- textPtr = memset(malloc(sizeof(TkText)), 0, sizeof(TkText));
+ textPtr = calloc(1, sizeof(TkText));
textPtr->tkwin = newWin;
textPtr->display = Tk_Display(newWin);
textPtr->interp = interp;
@@ -11951,6 +11951,7 @@ extern unsigned TkBTreeCountLines(const TkTextBTree tree, const TkTextLine *lin
extern bool TkTextGetIndexFromObj(Tcl_Interp *interp, TkText *textPtr, Tcl_Obj *objPtr,
TkTextIndex *indexPtr);
extern bool TkTextIsDeadPeer(const TkText *textPtr);
+extern bool TkTextIsMark(const TkTextSegment *segPtr);
extern bool TkTextIsStartEndMarker(const TkTextSegment *segPtr);
extern bool TkTextIsSpecialMark(const TkTextSegment *segPtr);
extern bool TkTextIsPrivateMark(const TkTextSegment *segPtr);
diff --git a/generic/tkText.h b/generic/tkText.h
index a6d5392..d764006 100644
--- a/generic/tkText.h
+++ b/generic/tkText.h
@@ -1728,14 +1728,18 @@ MODULE_SCOPE const Tk_SegType tkTextProtectionMarkType;
enum { DISP_LINE_START = false, DISP_LINE_END = true };
/*
- * Helper for guarded deallocation.
+ * Helper for guarded allocation/deallocation.
*/
#define FREE_SEGMENT(ptr) { \
+ /* printf("destroy(%p) %s:%d\n", ptr, __FILE__, __LINE__); */ \
assert(ptr->typePtr); \
assert(!(ptr->typePtr = NULL)); \
free(ptr); }
+#define NEW_SEGMENT(ptr) \
+ /* printf("alloc(%p) %s:%d\n", ptr, __FILE__, __LINE__) */
+
/*
* We need a callback function for tag changes. The return value informs whether
* this operation is undoable.
@@ -1923,7 +1927,7 @@ MODULE_SCOPE void TkTextUpdateTagDisplayFlags(TkTextTag *tagPtr);
MODULE_SCOPE TkTextTag * TkTextCreateTag(TkText *textPtr, const char *tagName, bool *newTag);
MODULE_SCOPE TkTextTag * TkTextFindTag(const TkText *textPtr, const char *tagName);
MODULE_SCOPE int TkConfigureTag(Tcl_Interp *interp, TkText *textPtr, const char *tagName,
- int objc, Tcl_Obj *const objv[]);
+ bool redraw, int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE void TkTextEnableTag(TkSharedText *sharedTextPtr, TkTextTag *tagPtr);
MODULE_SCOPE void TkTextSortTags(unsigned numTags, TkTextTag **tagArrayPtr);
MODULE_SCOPE void TkTextFreeDInfo(TkText *textPtr);
@@ -2022,6 +2026,7 @@ MODULE_SCOPE TkTextSegment * TkTextMakeStartEndMark(TkText *textPtr, Tk_SegType
MODULE_SCOPE TkTextSegment * TkTextMakeMark(TkText *textPtr, const char *name);
MODULE_SCOPE TkTextSegment * TkTextMakeNewMark(TkSharedText *sharedTextPtr, const char *name);
MODULE_SCOPE void TkTextUnsetMark(TkText *textPtr, TkTextSegment *markPtr);
+inline bool TkTextIsMark(const TkTextSegment *segPtr);
inline bool TkTextIsStartEndMarker(const TkTextSegment *segPtr);
inline bool TkTextIsSpecialMark(const TkTextSegment *segPtr);
inline bool TkTextIsPrivateMark(const TkTextSegment *segPtr);
diff --git a/generic/tkTextBTree.c b/generic/tkTextBTree.c
index 900d3b3..2283547 100644
--- a/generic/tkTextBTree.c
+++ b/generic/tkTextBTree.c
@@ -1191,7 +1191,8 @@ MakeSegment(
assert(segType != &tkTextCharType);
- segPtr = memset(malloc(segByteSize), 0, segByteSize);
+ segPtr = calloc(1, segByteSize);
+ NEW_SEGMENT(segPtr);
segPtr->typePtr = segType;
segPtr->size = contentSize;
segPtr->refCount = 1;
@@ -2070,10 +2071,10 @@ TkBTreeCreate(
* pointers are simply NULL.
*/
- rootPtr = memset(malloc(sizeof(Node)), 0, sizeof(Node));
+ rootPtr = calloc(1, sizeof(Node));
DEBUG_ALLOC(tkTextCountNewNode++);
- treePtr = memset(malloc(sizeof(BTree)), 0, sizeof(BTree));
+ treePtr = calloc(1, sizeof(BTree));
treePtr->rootPtr = rootPtr;
treePtr->sharedTextPtr = sharedTextPtr;
treePtr->stateEpoch = epoch;
@@ -2803,6 +2804,7 @@ DestroyNode(
while (segPtr) {
TkTextSegment *nextPtr = segPtr->nextPtr;
assert(segPtr->typePtr); /* still existing? */
+ assert(segPtr->sectionPtr);
assert(segPtr->sectionPtr->linePtr == linePtr);
assert(segPtr->typePtr->deleteProc);
segPtr->typePtr->deleteProc(TkBTreeGetShared(tree), segPtr, TREE_GONE);
@@ -3401,7 +3403,7 @@ InsertNewLine(
segPtr->prevPtr = NULL;
}
- newLinePtr = memset(malloc(sizeof(TkTextLine)), 0, sizeof(TkTextLine));
+ newLinePtr = calloc(1, sizeof(TkTextLine));
newLinePtr->parentPtr = nodePtr;
newLinePtr->prevPtr = prevLinePtr;
newLinePtr->segPtr = segPtr;
@@ -3807,6 +3809,8 @@ TkBTreeLoad(
while (segPtr->nextPtr->typePtr != &tkTextCharType) {
segPtr = segPtr->nextPtr;
}
+ TkBTreeFreeSegment(segPtr->nextPtr);
+ segPtr->nextPtr = NULL;
charSegPtr = NULL;
for (i = 0; i < objc; ++i) {
@@ -3897,6 +3901,7 @@ TkBTreeLoad(
}
}
changeToLineCount += 1;
+
if (!isElided) {
changeToLogicalLineCount += 1;
}
@@ -3957,7 +3962,8 @@ TkBTreeLoad(
return LoadError(interp, NULL, i, 2, -1, tagInfoPtr);
} else {
for (k = 0; k < objc - 1; k += 2) {
- if (TkConfigureTag(interp, textPtr, Tcl_GetString(argv[1]), 2, &objv[k]) != TCL_OK
+ if (TkConfigureTag(interp, textPtr, Tcl_GetString(argv[1]),
+ false, 2, &objv[k]) != TCL_OK
&& !validOptions) {
return LoadError(interp, NULL, i, 2, -1, tagInfoPtr);
}
@@ -4270,10 +4276,10 @@ TkBTreeLoad(
linePtr = newLinePtr;
}
}
- size += 1;
RecomputeLineTagInfo(linePtr, NULL, sharedTextPtr);
} else {
changeToLineCount -= 1;
+ size -= 1;
if (!isElided) {
changeToLogicalLineCount -= 1;
}
@@ -5867,7 +5873,7 @@ RebuildSections(
if (!sectionPtr) {
TkTextSection *newSectionPtr;
- newSectionPtr = memset(malloc(sizeof(TkTextSection)), 0, sizeof(TkTextSection));
+ newSectionPtr = calloc(1, sizeof(TkTextSection));
if (prevSectionPtr) {
prevSectionPtr->nextPtr = newSectionPtr;
} else {
@@ -6072,7 +6078,8 @@ MakeCharSeg(
assert(length <= newSize);
capacity = CSEG_CAPACITY(newSize);
- newPtr = memset(malloc(CSEG_SIZE(capacity)), 0, SEG_SIZE(0));
+ newPtr = calloc(1, CSEG_SIZE(capacity));
+ NEW_SEGMENT(newPtr);
newPtr->typePtr = &tkTextCharType;
newPtr->sectionPtr = sectionPtr;
newPtr->size = newSize;
@@ -6568,7 +6575,8 @@ TkBTreeMakeCharSegment(
assert(string);
assert(tagInfoPtr);
- newPtr = memset(malloc(memsize), 0, memsize);
+ newPtr = calloc(1, memsize);
+ NEW_SEGMENT(newPtr);
newPtr->typePtr = &tkTextCharType;
newPtr->size = length;
newPtr->refCount = 1;
@@ -7027,8 +7035,11 @@ DeleteRange(
TkTextSegment *savePtr;
bool reInserted = false;
- if ((savePtr = (undoInfo && !TkTextIsSpecialOrPrivateMark(segPtr)) ? segPtr : NULL)) {
- savePtr->refCount += 1;
+ if (undoInfo
+ && !(steadyMarks ? TkTextIsSpecialOrPrivateMark(segPtr) : TkTextIsMark(segPtr))) {
+ (savePtr = segPtr)->refCount += 1;
+ } else {
+ savePtr = NULL;
}
assert(segPtr->sectionPtr->linePtr == curLinePtr);
@@ -13804,7 +13815,7 @@ Rebalance(
newPtr->numBranches = nodePtr->numBranches;
nodePtr->nextPtr = newPtr;
nodePtr->numChildren = MIN_CHILDREN;
- nodePtr->pixelInfo = memset(malloc(pixelSize), 0, pixelSize);
+ nodePtr->pixelInfo = calloc(1, pixelSize);
TagSetAssign(&nodePtr->tagonPtr, treePtr->sharedTextPtr->emptyTagInfoPtr);
TagSetAssign(&nodePtr->tagoffPtr, treePtr->sharedTextPtr->emptyTagInfoPtr);
DEBUG_ALLOC(tkTextCountNewNode++);
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c
index 5eca56f..eba9da4 100644
--- a/generic/tkTextDisp.c
+++ b/generic/tkTextDisp.c
@@ -1518,7 +1518,7 @@ TkTextCreateDInfo(
XGCValues gcValues;
bool isMonospaced;
- dInfoPtr = memset(malloc(sizeof(TextDInfo)), 0, sizeof(TextDInfo));
+ dInfoPtr = calloc(1, sizeof(TextDInfo));
Tcl_InitHashTable(&dInfoPtr->styleTable, sizeof(StyleValues)/sizeof(int));
gcValues.graphics_exposures = True;
dInfoPtr->copyGC = None;
diff --git a/generic/tkTextImage.c b/generic/tkTextImage.c
index 3e5edd4..4582e6b4 100644
--- a/generic/tkTextImage.c
+++ b/generic/tkTextImage.c
@@ -575,7 +575,8 @@ MakeImage(
{
TkTextSegment *eiPtr;
- eiPtr = memset(malloc(SEG_SIZE(TkTextEmbImage)), 0, SEG_SIZE(TkTextEmbImage));
+ eiPtr = calloc(1, SEG_SIZE(TkTextEmbImage));
+ NEW_SEGMENT(eiPtr);
eiPtr->typePtr = &tkTextEmbImageType;
eiPtr->size = 1;
eiPtr->refCount = 1;
diff --git a/generic/tkTextMark.c b/generic/tkTextMark.c
index 7b9c041..00139a4 100644
--- a/generic/tkTextMark.c
+++ b/generic/tkTextMark.c
@@ -1163,7 +1163,8 @@ MakeMark(
{
TkTextSegment *markPtr;
- markPtr = memset(malloc(SEG_SIZE(TkTextMark)), 0, SEG_SIZE(TkTextMark));
+ markPtr = calloc(1, SEG_SIZE(TkTextMark));
+ NEW_SEGMENT(markPtr);
markPtr->typePtr = &tkTextRightMarkType;
markPtr->refCount = 1;
markPtr->body.mark.textPtr = textPtr;
@@ -1239,6 +1240,7 @@ TkTextMakeNewMark(
markPtr = MakeMark(NULL);
markPtr->body.mark.ptr = PTR_TO_INT(hPtr);
+ markPtr->normalMarkFlag = true;
Tcl_SetHashValue(hPtr, markPtr);
sharedTextPtr->numMarks += 1;
@@ -1301,7 +1303,7 @@ MakeUndoToggleGravity(
TkTextMarkChange *changePtr = MakeChangeItem(sharedTextPtr, markPtr);
UndoTokenToggleGravity *token;
- token = memset(malloc(sizeof(UndoTokenToggleGravity)), 0, sizeof(UndoTokenToggleGravity));
+ token = calloc(1, sizeof(UndoTokenToggleGravity));
token->undoType = &undoTokenToggleGravityType;
(token->markPtr = markPtr)->refCount += 1;
DEBUG_ALLOC(tkTextCountNewUndoToken++);
diff --git a/generic/tkTextPriv.h b/generic/tkTextPriv.h
index bfb63f1..d7e0e2d 100644
--- a/generic/tkTextPriv.h
+++ b/generic/tkTextPriv.h
@@ -55,6 +55,31 @@ MODULE_SCOPE bool TkpTextGetIndex(Tcl_Interp *interp, TkSharedText *sharedTextPt
/*
*----------------------------------------------------------------------
*
+ * TkTextIsMark --
+ *
+ * Test whether this is a mark.
+ *
+ * Results:
+ * Whether this is a mark.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+inline
+bool
+TkTextIsMark(
+ const TkTextSegment *segPtr)
+{
+ assert(segPtr);
+ return segPtr->typePtr == &tkTextLeftMarkType || segPtr->typePtr == &tkTextRightMarkType;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkTextIsSpecialMark --
*
* Test whether this is a special mark: "insert", or "current".
diff --git a/generic/tkTextTag.c b/generic/tkTextTag.c
index fa698dc..485850d 100644
--- a/generic/tkTextTag.c
+++ b/generic/tkTextTag.c
@@ -498,7 +498,7 @@ TkTextTagCmd(
Tcl_WrongNumArgs(interp, 3, objv, "tagName ?option? ?value? ?option value ...?");
return TCL_ERROR;
}
- return TkConfigureTag(interp, textPtr, Tcl_GetString(objv[3]), objc - 4, objv + 4);
+ return TkConfigureTag(interp, textPtr, Tcl_GetString(objv[3]), true, objc - 4, objv + 4);
case TAG_DELETE: {
Tcl_HashEntry *hPtr;
bool anyChanges = false;
@@ -1115,6 +1115,7 @@ TkConfigureTag(
Tcl_Interp *interp, /* Current interpreter. */
TkText *textPtr, /* Info about overall widget. */
char const *tagName, /* Name of affected tag. */
+ bool redraw, /* Redraw the affected text if required? */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Remaining argument objects. */
{
@@ -1404,7 +1405,7 @@ TkConfigureTag(
TkBTreeUpdateElideInfo(textPtr, tagPtr);
}
- if (!newTag && affectsDisplay) {
+ if (redraw && !newTag && affectsDisplay) {
/*
* This line is not necessary if this is a new tag, since it can't possibly have
* been applied to anything yet.
@@ -2023,7 +2024,7 @@ TkTextCreateTag(
* to it to the hash table entry.
*/
- tagPtr = memset(malloc(sizeof(TkTextTag)), 0, sizeof(TkTextTag));
+ tagPtr = calloc(1, sizeof(TkTextTag));
tagPtr->name = name;
tagPtr->index = index;
tagPtr->priority = textPtr->sharedTextPtr->numEnabledTags;
diff --git a/generic/tkTextUndo.c b/generic/tkTextUndo.c
index 499bd6e..a919da9 100644
--- a/generic/tkTextUndo.c
+++ b/generic/tkTextUndo.c
@@ -417,7 +417,7 @@ TkTextUndoCreateStack(
assert(undoProc);
#endif
- stack = memset(malloc(sizeof(*stack)), 0, sizeof(*stack));
+ stack = calloc(1, sizeof(*stack));
stack->undoProc = undoProc;
stack->freeProc = freeProc;
stack->contentChangedProc = contentChangedProc;
diff --git a/generic/tkTextWind.c b/generic/tkTextWind.c
index cbf44a3..5a921cf 100644
--- a/generic/tkTextWind.c
+++ b/generic/tkTextWind.c
@@ -656,7 +656,8 @@ MakeWindow(
TkTextSegment *ewPtr;
TkTextEmbWindowClient *client;
- ewPtr = memset(malloc(SEG_SIZE(TkTextEmbWindow)), 0, SEG_SIZE(TkTextEmbWindow));
+ ewPtr = calloc(1, SEG_SIZE(TkTextEmbWindow));
+ NEW_SEGMENT(ewPtr);
ewPtr->typePtr = &tkTextEmbWindowType;
ewPtr->size = 1;
ewPtr->refCount = 1;
@@ -666,7 +667,7 @@ MakeWindow(
ewPtr->body.ew.optionTable = Tk_CreateOptionTable(textPtr->interp, optionSpecs);
DEBUG_ALLOC(tkTextCountNewSegment++);
- client = memset(malloc(sizeof(TkTextEmbWindowClient)), 0, sizeof(TkTextEmbWindowClient));
+ client = calloc(1, sizeof(TkTextEmbWindowClient));
client->textPtr = textPtr;
client->parent = ewPtr;
ewPtr->body.ew.clients = client;
@@ -870,7 +871,7 @@ EmbWinConfigure(
* Have to make the new client.
*/
- client = memset(malloc(sizeof(TkTextEmbWindowClient)), 0, sizeof(TkTextEmbWindowClient));
+ client = calloc(1, sizeof(TkTextEmbWindowClient));
client->next = ewPtr->body.ew.clients;
client->textPtr = textPtr;
client->parent = ewPtr;
@@ -1486,7 +1487,7 @@ EmbWinLayoutProc(
* now need to add to our client list.
*/
- client = memset(malloc(sizeof(TkTextEmbWindowClient)), 0, sizeof(TkTextEmbWindowClient));
+ client = calloc(1, sizeof(TkTextEmbWindowClient));
client->next = ewPtr->body.ew.clients;
client->textPtr = textPtr;
client->parent = ewPtr;