summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2021-12-05 13:08:13 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2021-12-05 13:08:13 (GMT)
commit7aeec15b8da5b1e001fa058e14ca243125b0b78d (patch)
treea7069bfe1574ddbdd8cf5187e955671cb90c3845 /generic
parent2b4da644c31f39693820f8eedef814b38dac6a06 (diff)
parent673d172ff18004c4391acdfd660952d372590ecd (diff)
downloadtk-7aeec15b8da5b1e001fa058e14ca243125b0b78d.zip
tk-7aeec15b8da5b1e001fa058e14ca243125b0b78d.tar.gz
tk-7aeec15b8da5b1e001fa058e14ca243125b0b78d.tar.bz2
Merge 8.7
Diffstat (limited to 'generic')
-rw-r--r--generic/tkCanvLine.c235
-rw-r--r--generic/tkCanvPoly.c92
-rw-r--r--generic/tkImgPPM.c6
-rw-r--r--generic/tkTextTag.c26
-rw-r--r--generic/ttk/ttkTreeview.c47
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;