Fix deletion with image numbers

This commit is contained in:
Kovid Goyal 2020-12-16 18:57:46 +05:30
parent 2fd6bf7442
commit e82a6dedd9
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 37 additions and 18 deletions

View File

@ -251,7 +251,7 @@ def graphics_parser() -> None:
flag = frozenset flag = frozenset
keymap: KeymapType = { keymap: KeymapType = {
'a': ('action', flag('tTqpd')), 'a': ('action', flag('tTqpd')),
'd': ('delete_action', flag('aAiIcCpPqQxXyYzZ')), 'd': ('delete_action', flag('aAiIcCnNpPqQxXyYzZ')),
't': ('transmission_type', flag('dfts')), 't': ('transmission_type', flag('dfts')),
'o': ('compressed', flag('z')), 'o': ('compressed', flag('z')),
'f': ('format', 'uint'), 'f': ('format', 'uint'),

View File

@ -805,14 +805,14 @@ grman_clear(GraphicsManager *self, bool all, CellPixelSize cell) {
static inline bool static inline bool
id_filter_func(const ImageRef *ref, Image *img, const void *data, CellPixelSize cell UNUSED) { id_filter_func(const ImageRef *ref, Image *img, const void *data, CellPixelSize cell UNUSED) {
const GraphicsCommand *g = data; const GraphicsCommand *g = data;
if (img->client_id == g->id) return !g->placement_id || ref->client_id == g->placement_id; if (g->id && img->client_id == g->id) return !g->placement_id || ref->client_id == g->placement_id;
return false; return false;
} }
static inline bool static inline bool
number_filter_func(const ImageRef *ref, Image *img, const void *data, CellPixelSize cell UNUSED) { number_filter_func(const ImageRef *ref, Image *img, const void *data, CellPixelSize cell UNUSED) {
const GraphicsCommand *g = data; const GraphicsCommand *g = data;
if (img->client_number == g->image_number) return !g->placement_id || ref->client_id == g->placement_id; if (g->image_number && img->client_number == g->image_number) return !g->placement_id || ref->client_id == g->placement_id;
return false; return false;
} }
@ -849,7 +849,7 @@ point3d_filter_func(const ImageRef *ref, Image *img, const void *data, CellPixel
static void static void
handle_delete_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c, bool *is_dirty, CellPixelSize cell) { handle_delete_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c, bool *is_dirty, CellPixelSize cell) {
static GraphicsCommand d; GraphicsCommand d;
bool only_first_image = false; bool only_first_image = false;
switch (g->delete_action) { switch (g->delete_action) {
#define I(u, data, func) filter_refs(self, data, g->delete_action == u, func, cell, only_first_image); *is_dirty = true; break #define I(u, data, func) filter_refs(self, data, g->delete_action == u, func, cell, only_first_image); *is_dirty = true; break
@ -870,7 +870,7 @@ handle_delete_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c
case 'n': case 'n':
case 'N': case 'N':
only_first_image = true; only_first_image = true;
I('N', &g, number_filter_func); I('N', g, number_filter_func);
default: default:
REPORT_ERROR("Unknown graphics command delete action: %c", g->delete_action); REPORT_ERROR("Unknown graphics command delete action: %c", g->delete_action);
break; break;

View File

@ -144,8 +144,8 @@ static inline void parse_graphics_code(Screen *screen,
case action: { case action: {
g.action = screen->parser_buf[pos++] & 0xff; g.action = screen->parser_buf[pos++] & 0xff;
if (g.action != 'T' && g.action != 'd' && g.action != 'p' && if (g.action != 'T' && g.action != 'q' && g.action != 'd' &&
g.action != 't' && g.action != 'q') { g.action != 'p' && g.action != 't') {
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag " REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
"value for action: 0x%x", "value for action: 0x%x",
g.action); g.action);
@ -155,14 +155,15 @@ static inline void parse_graphics_code(Screen *screen,
case delete_action: { case delete_action: {
g.delete_action = screen->parser_buf[pos++] & 0xff; g.delete_action = screen->parser_buf[pos++] & 0xff;
if (g.delete_action != 'y' && g.delete_action != 'c' && if (g.delete_action != 'C' && g.delete_action != 'z' &&
g.delete_action != 'x' && g.delete_action != 'p' && g.delete_action != 'y' && g.delete_action != 'X' &&
g.delete_action != 'P' && g.delete_action != 'Q' && g.delete_action != 'a' && g.delete_action != 'P' &&
g.delete_action != 'C' && g.delete_action != 'Y' && g.delete_action != 'i' && g.delete_action != 'c' &&
g.delete_action != 'i' && g.delete_action != 'z' && g.delete_action != 'N' && g.delete_action != 'I' &&
g.delete_action != 'A' && g.delete_action != 'a' && g.delete_action != 'p' && g.delete_action != 'q' &&
g.delete_action != 'q' && g.delete_action != 'Z' && g.delete_action != 'Q' && g.delete_action != 'Z' &&
g.delete_action != 'X' && g.delete_action != 'I') { g.delete_action != 'A' && g.delete_action != 'n' &&
g.delete_action != 'x' && g.delete_action != 'Y') {
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag " REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
"value for delete_action: 0x%x", "value for delete_action: 0x%x",
g.delete_action); g.delete_action);
@ -172,8 +173,8 @@ static inline void parse_graphics_code(Screen *screen,
case transmission_type: { case transmission_type: {
g.transmission_type = screen->parser_buf[pos++] & 0xff; g.transmission_type = screen->parser_buf[pos++] & 0xff;
if (g.transmission_type != 's' && g.transmission_type != 'd' && if (g.transmission_type != 'd' && g.transmission_type != 'f' &&
g.transmission_type != 't' && g.transmission_type != 'f') { g.transmission_type != 's' && g.transmission_type != 't') {
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag " REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
"value for transmission_type: 0x%x", "value for transmission_type: 0x%x",
g.transmission_type); g.transmission_type);

View File

@ -231,7 +231,7 @@ class TestGraphics(BaseTest):
# test error handling for loading bad png data # test error handling for loading bad png data
self.assertRaisesRegex(ValueError, '[EBADPNG]', load_png_data, b'dsfsdfsfsfd') self.assertRaisesRegex(ValueError, '[EBADPNG]', load_png_data, b'dsfsdfsfsfd')
def test_load_with_numbers(self): def test_gr_operations_with_numbers(self):
s = self.create_screen() s = self.create_screen()
g = s.grman g = s.grman
@ -280,6 +280,24 @@ class TestGraphics(BaseTest):
code, idstr = put(c=2, r=2, I=94) code, idstr = put(c=2, r=2, I=94)
self.ae(code, 'ENOENT') self.ae(code, 'ENOENT')
# test delete with number
def delete(ac='N', **kw):
cmd = 'a=d'
if ac:
cmd += ',d={}'.format(ac)
if kw:
cmd += ',' + ','.join('{}={}'.format(k, v) for k, v in kw.items())
send_command(s, cmd)
count = s.grman.image_count
put(i=1), put(i=2), put(i=3), put(i=4), put(i=5)
delete(I=94)
self.ae(s.grman.image_count, count)
delete(I=93)
self.ae(s.grman.image_count, count - 1)
delete(I=1)
self.ae(s.grman.image_count, count - 2)
def test_image_put(self): def test_image_put(self):
cw, ch = 10, 20 cw, ch = 10, 20
s, dx, dy, put_image, put_ref, layers, rect_eq = put_helpers(self, cw, ch) s, dx, dy, put_image, put_ref, layers, rect_eq = put_helpers(self, cw, ch)