Thanks to visit codestin.com
Credit goes to github.com

Skip to content

selection.match() produces a selection with bad boundaries #1467

@copperwater

Description

@copperwater

I was debugging some Lua code that looks like this:

a = selection.match(some_mapfrag);
b = selection.match(another_mapfrag);
c = a + b;

Instead of being a union of all the points that match either mapfrag, the resulting selection c is empty.

This is because the initial selection has bounds of lx=COLNO, hx=0, etc. selection.match checks all points on the map, using selection_setpoint, which sets the selection's "bounds_dirty" to TRUE any time it sets a point to 0. Since it's highly likely (1, 0) or some other coordinate early in the whole-map iteration will not match the mapfrag, this happens almost immediately, and because bounds_dirty is now set, the bounds never get updated when points are added to the selection. Then when the selections are combined, l_selection_or immediately exits the for loop that iterates from lx to hx, since hx < lx.

The reason I'm not doing this as a pull request is because there are two possible solutions, and I'm not sure which is correct. Both are pretty small so I've just put the diffs below.

The broader solution is to selection_setpoint itself, so it impacts every selection creator, and basically says that we shouldn't set bounds_dirty when setting a point not in the selection, to still be not in the selection:

         if (sel->bounds.hy < y) sel->bounds.hy = y;
-    } else {
+    } else if (sel->map[sel->wid * y + x] != 0) {
+        /* only set bounds_dirty if changing a point from 1 to 0; if changing a
+         * point from 0 to 0, nothing has really changed with the bounds */
         sel->bounds_dirty = TRUE;
     }

The narrower solution views this as only a problem with selection.match, and basically just fixes up the selections produced from it:

         for (x = 1; x < sel->wid; x++)
             selection_setpoint(x, y, sel, mapfrag_match(mf, x,y) ? 1 : 0);
 
+    /* unless the (0, 1) coordinate is a match, this will wind up with a
+     * selection with lx=COLNO, hx=0, etc, so fix the boundaries */
+    selection_recalc_bounds(sel);
+
     mapfrag_free(&mf);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions