diff options
author | gcramer <remarcg@gmx.net> | 2017-06-10 11:57:27 (GMT) |
---|---|---|
committer | gcramer <remarcg@gmx.net> | 2017-06-10 11:57:27 (GMT) |
commit | 0cc579edbf11ac3855bc857fc2fc44cfd2f489fc (patch) | |
tree | 9b2cfbcb17e26514076f35dfde8aebf378b9a1d0 /generic | |
parent | 388d5cda26e21bca70ecfbab1def0ff634341dfa (diff) | |
download | tk-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.h | 4 | ||||
-rw-r--r-- | generic/tkText.c | 7 | ||||
-rw-r--r-- | generic/tkText.h | 9 | ||||
-rw-r--r-- | generic/tkTextBTree.c | 35 | ||||
-rw-r--r-- | generic/tkTextDisp.c | 2 | ||||
-rw-r--r-- | generic/tkTextImage.c | 3 | ||||
-rw-r--r-- | generic/tkTextMark.c | 6 | ||||
-rw-r--r-- | generic/tkTextPriv.h | 25 | ||||
-rw-r--r-- | generic/tkTextTag.c | 7 | ||||
-rw-r--r-- | generic/tkTextUndo.c | 2 | ||||
-rw-r--r-- | generic/tkTextWind.c | 9 |
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; |