diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2021-12-05 13:08:13 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2021-12-05 13:08:13 (GMT) |
commit | 7aeec15b8da5b1e001fa058e14ca243125b0b78d (patch) | |
tree | a7069bfe1574ddbdd8cf5187e955671cb90c3845 /generic | |
parent | 2b4da644c31f39693820f8eedef814b38dac6a06 (diff) | |
parent | 673d172ff18004c4391acdfd660952d372590ecd (diff) | |
download | tk-7aeec15b8da5b1e001fa058e14ca243125b0b78d.zip tk-7aeec15b8da5b1e001fa058e14ca243125b0b78d.tar.gz tk-7aeec15b8da5b1e001fa058e14ca243125b0b78d.tar.bz2 |
Merge 8.7
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tkCanvLine.c | 235 | ||||
-rw-r--r-- | generic/tkCanvPoly.c | 92 | ||||
-rw-r--r-- | generic/tkImgPPM.c | 6 | ||||
-rw-r--r-- | generic/tkTextTag.c | 26 | ||||
-rw-r--r-- | generic/ttk/ttkTreeview.c | 47 |
5 files changed, 309 insertions, 97 deletions
diff --git a/generic/tkCanvLine.c b/generic/tkCanvLine.c index 07dbb70..69e5551 100644 --- a/generic/tkCanvLine.c +++ b/generic/tkCanvLine.c @@ -960,7 +960,7 @@ LineInsert( Tcl_Obj *obj) /* New coordinates to be inserted. */ { LineItem *linePtr = (LineItem *) itemPtr; - int length, objc, i; + int length, oriNumPoints, objc, nbInsPoints, i; double *newCoordPtr, *coordPtr; Tk_State state = itemPtr->state; Tcl_Obj **objv; @@ -973,13 +973,21 @@ LineInsert( || !objc || objc&1) { return; } + oriNumPoints = linePtr->numPoints; length = 2*linePtr->numPoints; + nbInsPoints = objc / 2; if (beforeThis == TCL_INDEX_NONE) { beforeThis = 0; } if (beforeThis + 1 > (TkSizeT)length + 1) { beforeThis = length; } + + /* + * With arrows, the end points of the line are adjusted so that a thick + * line doesn't stick out past the arrowheads (see ConfigureArrows). + */ + if (linePtr->firstArrowPtr != NULL) { linePtr->coordPtr[0] = linePtr->firstArrowPtr[0]; linePtr->coordPtr[1] = linePtr->firstArrowPtr[1]; @@ -1001,7 +1009,7 @@ LineInsert( } } - for (i=beforeThis; i<length; i++) { + for (i=(int)beforeThis; i<length; i++) { newCoordPtr[i+objc] = linePtr->coordPtr[i]; } if (linePtr->coordPtr) { @@ -1014,59 +1022,112 @@ LineInsert( if ((length > 3) && (state != TK_STATE_HIDDEN)) { /* * This is some optimizing code that will result that only the part of - * the polygon that changed (and the objects that are overlapping with + * the line that changed (and the objects that are overlapping with * that part) need to be redrawn. A special flag is set that instructs * the general canvas code not to redraw the whole object. If this * flag is not set, the canvas will do the redrawing, otherwise I have * to do it here. + * Rationale for the optimization code can be found in Tk ticket + * [5fb8145997]. */ itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW; - if ((int)beforeThis > 0) { - beforeThis -= 2; - objc += 2; - } - if ((int)beforeThis+objc < length) { - objc += 2; - } + /* + * Include one point at left of the left insert position, and one + * point at right of the right insert position. + */ + + beforeThis -= 2; + objc += 4; + if (linePtr->smooth) { - if ((int)beforeThis > 0) { + if (!strcmp(linePtr->smooth->name, "true")) { + /* + * Quadratic Bezier splines. A second point must be included at + * each side of the insert position. + */ + beforeThis -= 2; - objc += 2; - } - if ((int)beforeThis+objc+2 < length) { - objc += 2; + objc += 4; + + /* + * Moreover, if the insert position is the first or last point + * of the line, include a third point. + */ + + if ((int)beforeThis == -4) { + objc += 2; + } + if ((int)beforeThis + 4 == length - (objc - 8)) { + beforeThis -= 2; + objc += 2; + } + + } else if (!strcmp(linePtr->smooth->name, "raw")) { + /* + * Cubic Bezier splines. See details in ticket [5fb8145997]. + */ + + if (((oriNumPoints - 1) % 3) || (nbInsPoints % 3)) { + /* + * No optimization for "degenerate" lines or when inserting + * something else than a multiple of 3 points. + */ + + itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; + } else { + beforeThis -= (int)beforeThis % 6; + objc += 4; + } + + } else { + /* + * Custom smoothing method. No optimization is possible. + */ + + itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; } } - itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[beforeThis]; - itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[beforeThis+1]; - if ((linePtr->firstArrowPtr != NULL) && ((int)beforeThis < 1)) { - /* - * Include old first arrow. - */ - for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW; - i++, coordPtr += 2) { - TkIncludePoint(itemPtr, coordPtr); + if (itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) { + if ((int)beforeThis < 0) { + beforeThis = 0; + } + if ((int)beforeThis + objc > length) { + objc = length - (int)beforeThis; } - } - if ((linePtr->lastArrowPtr != NULL) && ((int)beforeThis+objc >= length)) { - /* - * Include old last arrow. - */ - for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW; - i++, coordPtr += 2) { + itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[beforeThis]; + itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[beforeThis+1]; + if ((linePtr->firstArrowPtr != NULL) && ((int)beforeThis < 2)) { + /* + * Include old first arrow. + */ + + for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW; + i++, coordPtr += 2) { + TkIncludePoint(itemPtr, coordPtr); + } + } + if ((linePtr->lastArrowPtr != NULL) && ((int)beforeThis+objc >= length)) { + /* + * Include old last arrow. + */ + + for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW; + i++, coordPtr += 2) { + TkIncludePoint(itemPtr, coordPtr); + } + } + coordPtr = linePtr->coordPtr + beforeThis; + for (i=0; i<objc; i+=2) { TkIncludePoint(itemPtr, coordPtr); + coordPtr += 2; } } - coordPtr = linePtr->coordPtr + beforeThis + 2; - for (i=2; i<objc; i+=2) { - TkIncludePoint(itemPtr, coordPtr); - coordPtr += 2; - } } + if (linePtr->firstArrowPtr != NULL) { ckfree(linePtr->firstArrowPtr); linePtr->firstArrowPtr = NULL; @@ -1083,7 +1144,7 @@ LineInsert( double width; int intWidth; - if ((linePtr->firstArrowPtr != NULL) && ((int)beforeThis > 2)) { + if ((linePtr->firstArrowPtr != NULL) && ((int)beforeThis < 2)) { /* * Include new first arrow. */ @@ -1093,9 +1154,9 @@ LineInsert( TkIncludePoint(itemPtr, coordPtr); } } - if ((linePtr->lastArrowPtr != NULL) && ((int)beforeThis+objc < length-2)) { + if ((linePtr->lastArrowPtr != NULL) && ((int)beforeThis+objc >= length)) { /* - * Include new right arrow. + * Include new last arrow. */ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW; @@ -1153,7 +1214,9 @@ LineDeleteCoords( TkSizeT last) /* Index of last character to delete. */ { LineItem *linePtr = (LineItem *) itemPtr; - int count, i, first1, last1; + int count, i, first1, last1, nbDelPoints; + int oriNumPoints = linePtr->numPoints; + int canOptimize = 1; int length = 2*linePtr->numPoints; double *coordPtr; Tk_State state = itemPtr->state; @@ -1162,18 +1225,24 @@ LineDeleteCoords( state = Canvas(canvas)->canvas_state; } - first &= -2; + first &= -2; /* If odd, make it even. */ last &= -2; if ((int)first < 0) { first = 0; } if ((int)last >= length) { - last = length-2; + last = length - 2; } if ((int)first > (int)last) { return; } + + /* + * With arrows, the end points of the line are adjusted so that a thick + * line doesn't stick out past the arrowheads (see ConfigureArrows). + */ + if (linePtr->firstArrowPtr != NULL) { linePtr->coordPtr[0] = linePtr->firstArrowPtr[0]; linePtr->coordPtr[1] = linePtr->firstArrowPtr[1]; @@ -1184,22 +1253,74 @@ LineDeleteCoords( } first1 = first; last1 = last; - if (first1 > 0) { - first1 -= 2; - } - if (last1 < length-2) { - last1 += 2; - } + nbDelPoints = (last - first) / 2 + 1; + + /* + * Include one point at left of the left delete position, and one + * point at right of the right delete position. + */ + + first1 -= 2; + last1 += 2; + if (linePtr->smooth) { - if (first1 > 0) { + + if (!strcmp(linePtr->smooth->name, "true")) { + /* + * Quadratic Bezier splines. A second point must be included at + * each side of the delete position. + */ + first1 -= 2; - } - if (last1 < length-2) { last1 += 2; + + /* + * If the delete position is the first or last point of the line, + * include a third point. + */ + + if (first1 == -4) { + last1 += 2; + } + if (last1 - 4 == length - 2) { + first1 -= 2; + } + + } else if (!strcmp(linePtr->smooth->name, "raw")) { + /* + * Cubic Bezier splines. See details in ticket [5fb8145997]. + */ + + if (((oriNumPoints - 1) % 3) || (nbDelPoints % 3)) { + /* + * No optimization for "degenerate" lines or when deleting + * something else than a multiple of 3 points. + */ + + canOptimize = 0; + } + else { + first1 -= first1 % 6; + last1 = last + 6 - last % 6; + } + + } else { + /* + * Custom smoothing method. No optimization is possible. + */ + + canOptimize = 0; } } - if ((first1 >= 2) || (last1 < length-2)) { + if (first1 < 0) { + first1 = 0; + } + if (last1 >= length) { + last1 = length - 2; + } + + if (canOptimize && ((first1 >= 2) || (last1 < length-2))) { /* * This is some optimizing code that will result that only the part of * the line that changed (and the objects that are overlapping with @@ -1207,6 +1328,8 @@ LineDeleteCoords( * the general canvas code not to redraw the whole object. If this * flag is set, the redrawing has to be done here, otherwise the * general Canvas code will take care of it. + * Rationale for the optimization code can be found in Tk ticket + * [5fb8145997]. */ itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW; @@ -1222,7 +1345,7 @@ LineDeleteCoords( TkIncludePoint(itemPtr, coordPtr); } } - if ((linePtr->lastArrowPtr != NULL) && (last1 >= length-2)) { + if ((linePtr->lastArrowPtr != NULL) && (last1 >= length - 2)) { /* * Include old last arrow. */ @@ -1259,7 +1382,7 @@ LineDeleteCoords( double width; int intWidth; - if ((linePtr->firstArrowPtr != NULL) && (first1 < 4)) { + if ((linePtr->firstArrowPtr != NULL) && (first1 < 2)) { /* * Include new first arrow. */ @@ -1269,9 +1392,9 @@ LineDeleteCoords( TkIncludePoint(itemPtr, coordPtr); } } - if ((linePtr->lastArrowPtr != NULL) && (last1 > length-4)) { + if ((linePtr->lastArrowPtr != NULL) && (last1 >= length - 2)) { /* - * Include new right arrow. + * Include new last arrow. */ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW; diff --git a/generic/tkCanvPoly.c b/generic/tkCanvPoly.c index 90b2896..86e21f0 100644 --- a/generic/tkCanvPoly.c +++ b/generic/tkCanvPoly.c @@ -1021,7 +1021,7 @@ PolygonInsert( Tcl_Obj *obj) /* New coordinates to be inserted. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; - int length, objc, i; + int length, oriNumPoints, objc, nbInsPoints, i; Tcl_Obj **objv; double *newCoordPtr; Tk_State state = itemPtr->state; @@ -1034,7 +1034,9 @@ PolygonInsert( || !objc || objc&1) { return; } + oriNumPoints = polyPtr->numPoints - polyPtr->autoClosed; length = 2*(polyPtr->numPoints - polyPtr->autoClosed); + nbInsPoints = objc / 2; while ((int)beforeThis > length) { beforeThis -= length; } @@ -1092,6 +1094,8 @@ PolygonInsert( * the general canvas code not to redraw the whole object. If this * flag is not set, the canvas will do the redrawing, otherwise I have * to do it here. + * Rationale for the optimization code can be found in Tk ticket + * [5fb8145997]. */ double width; @@ -1108,42 +1112,76 @@ PolygonInsert( itemPtr->x1 = itemPtr->x2 = (int) polyPtr->coordPtr[beforeThis]; itemPtr->y1 = itemPtr->y2 = (int) polyPtr->coordPtr[beforeThis+1]; + beforeThis -= 2; objc += 4; + if (polyPtr->smooth) { - beforeThis -= 2; - objc += 4; - } + if (!strcmp(polyPtr->smooth->name, "true")) { + /* + * Quadratic Bezier splines. + */ + + beforeThis -= 2; + objc += 4; + + } else if (!strcmp(polyPtr->smooth->name, "raw")) { + /* + * Cubic Bezier splines. + */ + + if ((oriNumPoints % 3) || (nbInsPoints % 3)) { + /* + * No optimization for "degenerate" polygons or when inserting + * something else than a multiple of 3 points. + */ + + itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; + } else { + beforeThis -= abs((int)beforeThis) % 6; + objc += 4; + } - /* - * Be careful; beforeThis could now be negative - */ + } else { + /* + * Custom smoothing method. No optimization is possible. + */ - for (i=beforeThis; i<(int)beforeThis+objc; i+=2) { - j = i; - if (j < 0) { - j += length; - } else if (j >= length) { - j -= length; + itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; } - TkIncludePoint(itemPtr, polyPtr->coordPtr+j); } - width = polyPtr->outline.width; - if (Canvas(canvas)->currentItemPtr == itemPtr) { - if (polyPtr->outline.activeWidth > width) { - width = polyPtr->outline.activeWidth; + + if (itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) { + /* + * Be careful; beforeThis could now be negative + */ + + for (i=(int)beforeThis; i<(int)beforeThis+objc; i+=2) { + j = i; + if (j < 0) { + j += length; + } else if (j >= length) { + j -= length; + } + TkIncludePoint(itemPtr, polyPtr->coordPtr+j); } - } else if (state == TK_STATE_DISABLED) { - if (polyPtr->outline.disabledWidth > 0.0) { - width = polyPtr->outline.disabledWidth; + width = polyPtr->outline.width; + if (Canvas(canvas)->currentItemPtr == itemPtr) { + if (polyPtr->outline.activeWidth > width) { + width = polyPtr->outline.activeWidth; + } + } else if (state == TK_STATE_DISABLED) { + if (polyPtr->outline.disabledWidth > 0.0) { + width = polyPtr->outline.disabledWidth; + } } + itemPtr->x1 -= (int) width; + itemPtr->y1 -= (int) width; + itemPtr->x2 += (int) width; + itemPtr->y2 += (int) width; + Tk_CanvasEventuallyRedraw(canvas, + itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2); } - itemPtr->x1 -= (int) width; - itemPtr->y1 -= (int) width; - itemPtr->x2 += (int) width; - itemPtr->y2 += (int) width; - Tk_CanvasEventuallyRedraw(canvas, - itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2); } ComputePolygonBbox(canvas, polyPtr); diff --git a/generic/tkImgPPM.c b/generic/tkImgPPM.c index 6a4426b..ed21927 100644 --- a/generic/tkImgPPM.c +++ b/generic/tkImgPPM.c @@ -241,7 +241,7 @@ FileReadPPM( unsigned char *p; unsigned int value; - for (p = pixelPtr; count > 0; count--, p += 2) { + for (p = pixelPtr; count > 0; count -= 2, p += 2) { value = ((unsigned int) p[0]) * 256 + ((unsigned int) p[1]); value = value * 255 / maxIntensity; p[0] = p[1] = (unsigned char) value; @@ -604,8 +604,8 @@ StringReadPPM( } else { unsigned int value; - for (p = pixelPtr,count=nBytes; count > 1; count-=2, p += 2) { - value = ((unsigned int) p[0]) * 256 + ((unsigned int) p[1]); + for (p = pixelPtr,count=nBytes; count > 1; count-=2, p += 2, dataBuffer += 2) { + value = ((unsigned int)dataBuffer[0]) * 256 + ((unsigned int)dataBuffer[1]); value = value * 255 / maxIntensity; p[0] = p[1] = (unsigned char) value; } diff --git a/generic/tkTextTag.c b/generic/tkTextTag.c index 1ffa602..8c7d6a4 100644 --- a/generic/tkTextTag.c +++ b/generic/tkTextTag.c @@ -1481,11 +1481,31 @@ TkTextBindProc( } TkTextPickCurrent(textPtr, eventPtr); } - if ((textPtr->numCurTags > 0) - && (textPtr->sharedTextPtr->bindingTable != NULL) + + if ((textPtr->sharedTextPtr->bindingTable != NULL) && (textPtr->tkwin != NULL) && !(textPtr->flags & DESTROYED)) { - TagBindEvent(textPtr, eventPtr, textPtr->numCurTags, + if (textPtr->numCurTags > 0) { + /* + * The mouse is inside the text widget, the 'current' mark was updated. + */ + + TagBindEvent(textPtr, eventPtr, textPtr->numCurTags, textPtr->curTagArrayPtr); + } else if ((eventPtr->type == KeyPress) || (eventPtr->type == KeyRelease)) { + /* + * Key events fire independently of the 'current' mark and use the + * 'insert' mark. + */ + + TkTextIndex index; + TkTextTag** tagArrayPtr; + int numTags; + + TkTextMarkNameToIndex(textPtr, "insert", &index); + tagArrayPtr = TkBTreeGetTags(&index, textPtr, &numTags); + SortTags(numTags, tagArrayPtr); + TagBindEvent(textPtr, eventPtr, numTags, tagArrayPtr); + } } if (repick) { unsigned int oldState; diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index 4e212d8..ac4a694 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -2680,7 +2680,7 @@ static int TreeviewDeleteCommand( { Treeview *tv = (Treeview *)recordPtr; TreeItem **items, *delq; - int i, selItemDeleted = 0; + int i, selChange = 0; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "items"); @@ -2708,7 +2708,7 @@ static int TreeviewDeleteCommand( delq = 0; for (i=0; items[i]; ++i) { if (items[i]->state & TTK_STATE_SELECTED) { - selItemDeleted = 1; + selChange = 1; } delq = DeleteItems(items[i], delq); } @@ -2726,7 +2726,7 @@ static int TreeviewDeleteCommand( } ckfree(items); - if (selItemDeleted) { + if (selChange) { Tk_SendVirtualEvent(tv->core.tkwin, "TreeviewSelect", NULL); } TtkRedisplayWidget(&tv->core); @@ -2953,7 +2953,7 @@ static int TreeviewSelectionCommand( }; Treeview *tv = (Treeview *)recordPtr; - int selop, i; + int selop, i, selChange = 0; TreeItem *item, **items; if (objc == 2) { @@ -2985,28 +2985,59 @@ static int TreeviewSelectionCommand( { case SELECTION_SET: for (item=tv->tree.root; item; item = NextPreorder(item)) { + int inSetList = 0; + + for (i=0; items[i]; ++i) { + if (item == items[i]) { + inSetList = 1; + if (!(item->state & TTK_STATE_SELECTED)) { + /* Item newly selected */ + selChange = 1; + } + break; + } + } + if (!inSetList && (item->state & TTK_STATE_SELECTED)) { + /* Item newly deselected */ + selChange = 1; + } + if (selChange) break; + } + for (item=tv->tree.root; item; item = NextPreorder(item)) { item->state &= ~TTK_STATE_SELECTED; } - /*FALLTHRU*/ - case SELECTION_ADD: for (i=0; items[i]; ++i) { items[i]->state |= TTK_STATE_SELECTED; } break; + case SELECTION_ADD: + for (i=0; items[i]; ++i) { + if (!(items[i]->state & TTK_STATE_SELECTED)) { + items[i]->state |= TTK_STATE_SELECTED; + selChange = 1; + } + } + break; case SELECTION_REMOVE: for (i=0; items[i]; ++i) { - items[i]->state &= ~TTK_STATE_SELECTED; + if (items[i]->state & TTK_STATE_SELECTED) { + items[i]->state &= ~TTK_STATE_SELECTED; + selChange = 1; + } } break; case SELECTION_TOGGLE: for (i=0; items[i]; ++i) { items[i]->state ^= TTK_STATE_SELECTED; + selChange = 1; } break; } ckfree(items); - Tk_SendVirtualEvent(tv->core.tkwin, "TreeviewSelect", NULL); + if (selChange) { + Tk_SendVirtualEvent(tv->core.tkwin, "TreeviewSelect", NULL); + } TtkRedisplayWidget(&tv->core); return TCL_OK; |