Implement control code for deleting images
This commit is contained in:
+73
-5
@@ -561,6 +561,7 @@ handle_put_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c, b
|
||||
}
|
||||
c->x += num_cols; c->y += num_rows - 1;
|
||||
ref->effective_num_rows = num_rows;
|
||||
ref->effective_num_cols = num_cols;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -630,7 +631,7 @@ grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float scree
|
||||
// Image lifetime/scrolling {{{
|
||||
|
||||
static inline void
|
||||
filter_refs(GraphicsManager *self, const void* data, bool (*filter_func)(ImageRef*, Image*, const void*)) {
|
||||
filter_refs(GraphicsManager *self, const void* data, bool free_images, bool (*filter_func)(ImageRef*, Image*, const void*)) {
|
||||
Image *img; ImageRef *ref;
|
||||
size_t i, j;
|
||||
|
||||
@@ -643,7 +644,7 @@ filter_refs(GraphicsManager *self, const void* data, bool (*filter_func)(ImageRe
|
||||
remove_from_array(img->refs, sizeof(ImageRef), j, img->refcnt--);
|
||||
}
|
||||
}
|
||||
if (img->refcnt == 0) {
|
||||
if (img->refcnt == 0 && (free_images || img->client_id == 0)) {
|
||||
free_image(img);
|
||||
remove_from_array(self->images, sizeof(Image), i, self->image_count--);
|
||||
}
|
||||
@@ -702,7 +703,7 @@ scroll_filter_margins_func(ImageRef* ref, Image* img, const void* data) {
|
||||
|
||||
void
|
||||
grman_scroll_images(GraphicsManager *self, const ScrollData *data) {
|
||||
filter_refs(self, data, data->has_margins ? scroll_filter_margins_func : scroll_filter_func);
|
||||
filter_refs(self, data, true, data->has_margins ? scroll_filter_margins_func : scroll_filter_func);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@@ -712,7 +713,71 @@ clear_filter_func(ImageRef *ref, Image UNUSED *img, const void UNUSED *data) {
|
||||
|
||||
void
|
||||
grman_clear(GraphicsManager *self) {
|
||||
filter_refs(self, NULL, clear_filter_func);
|
||||
filter_refs(self, NULL, true, clear_filter_func);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
id_filter_func(ImageRef UNUSED *ref, Image *img, const void *data) {
|
||||
uint32_t iid = *(uint32_t*)data;
|
||||
return img->client_id == iid;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
x_filter_func(ImageRef *ref, Image UNUSED *img, const void *data) {
|
||||
const GraphicsCommand *g = data;
|
||||
return ref->start_column <= (int32_t)g->x_offset - 1 && ((int32_t)g->x_offset - 1) < ((int32_t)(ref->start_column + ref->effective_num_cols));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
y_filter_func(ImageRef *ref, Image UNUSED *img, const void *data) {
|
||||
const GraphicsCommand *g = data;
|
||||
return ref->start_row <= (int32_t)g->y_offset - 1 && ((int32_t)(g->y_offset - 1 < ref->start_row + ref->effective_num_rows));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
z_filter_func(ImageRef *ref, Image UNUSED *img, const void *data) {
|
||||
const GraphicsCommand *g = data;
|
||||
return ref->z_index == g->z_index;
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
point_filter_func(ImageRef *ref, Image *img, const void *data) {
|
||||
return x_filter_func(ref, img, data) && y_filter_func(ref, img, data);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
point3d_filter_func(ImageRef *ref, Image *img, const void *data) {
|
||||
return z_filter_func(ref, img, data) && point_filter_func(ref, img, data);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handle_delete_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c, bool *is_dirty) {
|
||||
static GraphicsCommand d;
|
||||
switch (g->delete_action) {
|
||||
#define I(u, data, func) filter_refs(self, data, g->delete_action == u, func); *is_dirty = true; break
|
||||
#define D(l, u, data, func) case l: case u: I(u, data, func)
|
||||
#define G(l, u, func) D(l, u, g, func)
|
||||
case 0:
|
||||
D('a', 'A', NULL, clear_filter_func);
|
||||
D('i', 'I', &g->id, id_filter_func);
|
||||
G('p', 'P', point_filter_func);
|
||||
G('q', 'Q', point3d_filter_func);
|
||||
G('x', 'X', x_filter_func);
|
||||
G('y', 'Y', y_filter_func);
|
||||
G('z', 'Z', z_filter_func);
|
||||
case 'c':
|
||||
case 'C':
|
||||
d.x_offset = c->x + 1; d.y_offset = c->y + 1;
|
||||
I('C', &d, point_filter_func);
|
||||
default:
|
||||
REPORT_ERROR("Unknown graphics command delete action: %c", g->delete_action);
|
||||
break;
|
||||
#undef G
|
||||
#undef D
|
||||
#undef I
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
@@ -737,12 +802,15 @@ grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint
|
||||
break;
|
||||
case 'p':
|
||||
if (!g->id) {
|
||||
REPORT_ERROR("%s", "Put graphics command without image id");
|
||||
REPORT_ERROR("Put graphics command without image id");
|
||||
break;
|
||||
}
|
||||
handle_put_command(self, g, c, is_dirty, NULL);
|
||||
ret = create_add_response(self, true, g->id);
|
||||
break;
|
||||
case 'd':
|
||||
handle_delete_command(self, g, c, is_dirty);
|
||||
break;
|
||||
default:
|
||||
REPORT_ERROR("Unknown graphics command action: %c", g->action);
|
||||
break;
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@
|
||||
#include "data-types.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char action, transmission_type, compressed;
|
||||
unsigned char action, transmission_type, compressed, delete_action;
|
||||
uint32_t format, more, id, data_sz, data_offset;
|
||||
uint32_t width, height, x_offset, y_offset, data_height, data_width, num_cells, num_lines, cell_x_offset, cell_y_offset;
|
||||
int32_t z_index;
|
||||
@@ -34,7 +34,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
uint32_t src_width, src_height, src_x, src_y;
|
||||
uint32_t cell_x_offset, cell_y_offset, num_cols, num_rows, effective_num_rows;
|
||||
uint32_t cell_x_offset, cell_y_offset, num_cols, num_rows, effective_num_rows, effective_num_cols;
|
||||
int32_t z_index;
|
||||
int32_t start_row, start_column;
|
||||
ImageRect src_rect;
|
||||
|
||||
+5
-4
@@ -540,6 +540,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
||||
enum GR_STATES state = KEY, value_state = FLAG;
|
||||
enum KEYS {
|
||||
action='a',
|
||||
delete_action='d',
|
||||
transmission_type='t',
|
||||
compressed='o',
|
||||
format = 'f',
|
||||
@@ -577,7 +578,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
||||
switch(key) {
|
||||
#define KS(n, vs) case n: state = EQUAL; value_state = vs; break
|
||||
#define U(x) KS(x, UINT)
|
||||
KS(action, FLAG); KS(transmission_type, FLAG); KS(compressed, FLAG); KS(z_index, INT);
|
||||
KS(action, FLAG); KS(delete_action, FLAG); KS(transmission_type, FLAG); KS(compressed, FLAG); KS(z_index, INT);
|
||||
U(format); U(more); U(id); U(data_sz); U(data_offset); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines); U(cell_x_offset); U(cell_y_offset);
|
||||
#undef U
|
||||
#undef KS
|
||||
@@ -598,7 +599,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
||||
case FLAG:
|
||||
switch(key) {
|
||||
#define F(a) case a: g.a = screen->parser_buf[pos++] & 0xff; break
|
||||
F(action); F(transmission_type); F(compressed);
|
||||
F(action); F(delete_action); F(transmission_type); F(compressed);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -675,8 +676,8 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
||||
#define A(x) #x, g.x
|
||||
#define U(x) #x, (unsigned int)(g.x)
|
||||
#define I(x) #x, (int)(g.x)
|
||||
REPORT_VA_COMMAND("s {sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI si} y#", "graphics_command",
|
||||
A(action), A(transmission_type), A(compressed),
|
||||
REPORT_VA_COMMAND("s {sc sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI si} y#", "graphics_command",
|
||||
A(action), A(delete_action), A(transmission_type), A(compressed),
|
||||
U(format), U(more), U(id), U(data_sz), U(data_offset),
|
||||
U(width), U(height), U(x_offset), U(y_offset), U(data_height), U(data_width), U(num_cells), U(num_lines), U(cell_x_offset), U(cell_y_offset),
|
||||
U(payload_sz), I(z_index),
|
||||
|
||||
Reference in New Issue
Block a user