mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
Format generated header using clang-format
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPLv3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import subprocess
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
|
||||||
@@ -224,6 +225,13 @@ static inline void
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def write_header(text, path):
|
||||||
|
with open(path, 'w') as f:
|
||||||
|
print('#pragma once', file=f)
|
||||||
|
print(text, file=f)
|
||||||
|
subprocess.check_call(['clang-format', '-i', path])
|
||||||
|
|
||||||
|
|
||||||
def graphics_parser():
|
def graphics_parser():
|
||||||
flag = frozenset
|
flag = frozenset
|
||||||
keymap = {
|
keymap = {
|
||||||
@@ -249,10 +257,7 @@ def graphics_parser():
|
|||||||
'z': ('z_index', 'int'),
|
'z': ('z_index', 'int'),
|
||||||
}
|
}
|
||||||
text = generate('parse_graphics_code', 'screen_handle_graphics_command', 'graphics_command', keymap, 'GraphicsCommand')
|
text = generate('parse_graphics_code', 'screen_handle_graphics_command', 'graphics_command', keymap, 'GraphicsCommand')
|
||||||
|
write_header(text, 'kitty/parse-graphics-command.h')
|
||||||
with open('kitty/parse-graphics-command.h', 'w') as f:
|
|
||||||
print('#pragma once', file=f)
|
|
||||||
print(text, file=f)
|
|
||||||
|
|
||||||
|
|
||||||
graphics_parser()
|
graphics_parser()
|
||||||
|
|||||||
@@ -1,209 +1,317 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
static inline void
|
static inline void parse_graphics_code(Screen *screen,
|
||||||
parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
|
PyObject UNUSED *dump_callback) {
|
||||||
unsigned int pos = 1;
|
unsigned int pos = 1;
|
||||||
enum PARSER_STATES { KEY, EQUAL, UINT, INT, FLAG, AFTER_VALUE , PAYLOAD };
|
enum PARSER_STATES { KEY, EQUAL, UINT, INT, FLAG, AFTER_VALUE, PAYLOAD };
|
||||||
enum PARSER_STATES state = KEY, value_state = FLAG;
|
enum PARSER_STATES state = KEY, value_state = FLAG;
|
||||||
static GraphicsCommand g;
|
static GraphicsCommand g;
|
||||||
unsigned int i, code;
|
unsigned int i, code;
|
||||||
uint64_t lcode;
|
uint64_t lcode;
|
||||||
bool is_negative;
|
bool is_negative;
|
||||||
memset(&g, 0, sizeof(g));
|
memset(&g, 0, sizeof(g));
|
||||||
size_t sz;
|
size_t sz;
|
||||||
static uint8_t payload[4096];
|
static uint8_t payload[4096];
|
||||||
|
|
||||||
enum KEYS {
|
|
||||||
action='a',
|
|
||||||
delete_action='d',
|
|
||||||
transmission_type='t',
|
|
||||||
compressed='o',
|
|
||||||
format='f',
|
|
||||||
more='m',
|
|
||||||
id='i',
|
|
||||||
width='w',
|
|
||||||
height='h',
|
|
||||||
x_offset='x',
|
|
||||||
y_offset='y',
|
|
||||||
data_height='v',
|
|
||||||
data_width='s',
|
|
||||||
data_sz='S',
|
|
||||||
data_offset='O',
|
|
||||||
num_cells='c',
|
|
||||||
num_lines='r',
|
|
||||||
cell_x_offset='X',
|
|
||||||
cell_y_offset='Y',
|
|
||||||
z_index='z'
|
|
||||||
};
|
|
||||||
|
|
||||||
enum KEYS key = 'a';
|
|
||||||
|
|
||||||
while (pos < screen->parser_buf_pos) {
|
enum KEYS {
|
||||||
switch(state) {
|
action = 'a',
|
||||||
case KEY:
|
delete_action = 'd',
|
||||||
key = screen->parser_buf[pos++];
|
transmission_type = 't',
|
||||||
state = EQUAL;
|
compressed = 'o',
|
||||||
switch(key) {
|
format = 'f',
|
||||||
case action: value_state = FLAG; break;
|
more = 'm',
|
||||||
case delete_action: value_state = FLAG; break;
|
id = 'i',
|
||||||
case transmission_type: value_state = FLAG; break;
|
width = 'w',
|
||||||
case compressed: value_state = FLAG; break;
|
height = 'h',
|
||||||
case format: value_state = UINT; break;
|
x_offset = 'x',
|
||||||
case more: value_state = UINT; break;
|
y_offset = 'y',
|
||||||
case id: value_state = UINT; break;
|
data_height = 'v',
|
||||||
case width: value_state = UINT; break;
|
data_width = 's',
|
||||||
case height: value_state = UINT; break;
|
data_sz = 'S',
|
||||||
case x_offset: value_state = UINT; break;
|
data_offset = 'O',
|
||||||
case y_offset: value_state = UINT; break;
|
num_cells = 'c',
|
||||||
case data_height: value_state = UINT; break;
|
num_lines = 'r',
|
||||||
case data_width: value_state = UINT; break;
|
cell_x_offset = 'X',
|
||||||
case data_sz: value_state = UINT; break;
|
cell_y_offset = 'Y',
|
||||||
case data_offset: value_state = UINT; break;
|
z_index = 'z'
|
||||||
case num_cells: value_state = UINT; break;
|
};
|
||||||
case num_lines: value_state = UINT; break;
|
|
||||||
case cell_x_offset: value_state = UINT; break;
|
|
||||||
case cell_y_offset: value_state = UINT; break;
|
|
||||||
case z_index: value_state = INT; break;
|
|
||||||
default:
|
|
||||||
REPORT_ERROR("Malformed GraphicsCommand control block, invalid key character: 0x%x", key);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EQUAL:
|
enum KEYS key = 'a';
|
||||||
if (screen->parser_buf[pos++] != '=') {
|
|
||||||
REPORT_ERROR("Malformed GraphicsCommand control block, no = after key, found: 0x%x instead", screen->parser_buf[pos-1]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
state = value_state;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FLAG:
|
while (pos < screen->parser_buf_pos) {
|
||||||
switch(key) {
|
switch (state) {
|
||||||
|
case KEY:
|
||||||
case action: {
|
key = screen->parser_buf[pos++];
|
||||||
g.action = screen->parser_buf[pos++] & 0xff;
|
state = EQUAL;
|
||||||
if (g.action != 'q' && g.action != 't' && g.action != 'p' && g.action != 'T' && g.action != 'd') {
|
switch (key) {
|
||||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag value for action: 0x%x", g.action);
|
case action:
|
||||||
return;
|
value_state = FLAG;
|
||||||
};
|
break;
|
||||||
}
|
case delete_action:
|
||||||
break;
|
value_state = FLAG;
|
||||||
|
break;
|
||||||
|
case transmission_type:
|
||||||
|
value_state = FLAG;
|
||||||
|
break;
|
||||||
|
case compressed:
|
||||||
|
value_state = FLAG;
|
||||||
|
break;
|
||||||
|
case format:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case more:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case id:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case width:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case height:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case x_offset:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case y_offset:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case data_height:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case data_width:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case data_sz:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case data_offset:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case num_cells:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case num_lines:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case cell_x_offset:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case cell_y_offset:
|
||||||
|
value_state = UINT;
|
||||||
|
break;
|
||||||
|
case z_index:
|
||||||
|
value_state = INT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
REPORT_ERROR("Malformed GraphicsCommand control block, invalid key "
|
||||||
|
"character: 0x%x",
|
||||||
|
key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case delete_action: {
|
case EQUAL:
|
||||||
g.delete_action = screen->parser_buf[pos++] & 0xff;
|
if (screen->parser_buf[pos++] != '=') {
|
||||||
if (g.delete_action != 'A' && g.delete_action != 'q' && g.delete_action != 'x' && g.delete_action != 'Y' && g.delete_action != 'z' && g.delete_action != 'a' && g.delete_action != 'Z' && g.delete_action != 'p' && g.delete_action != 'Q' && g.delete_action != 'c' && g.delete_action != 'P' && g.delete_action != 'y' && g.delete_action != 'C' && g.delete_action != 'i' && g.delete_action != 'X' && g.delete_action != 'I') {
|
REPORT_ERROR("Malformed GraphicsCommand control block, no = after key, "
|
||||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag value for delete_action: 0x%x", g.delete_action);
|
"found: 0x%x instead",
|
||||||
return;
|
screen->parser_buf[pos - 1]);
|
||||||
};
|
return;
|
||||||
}
|
}
|
||||||
break;
|
state = value_state;
|
||||||
|
break;
|
||||||
|
|
||||||
case transmission_type: {
|
case FLAG:
|
||||||
g.transmission_type = screen->parser_buf[pos++] & 0xff;
|
switch (key) {
|
||||||
if (g.transmission_type != 't' && g.transmission_type != 'f' && g.transmission_type != 's' && g.transmission_type != 'd') {
|
|
||||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag value for transmission_type: 0x%x", g.transmission_type);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case compressed: {
|
case action: {
|
||||||
g.compressed = screen->parser_buf[pos++] & 0xff;
|
g.action = screen->parser_buf[pos++] & 0xff;
|
||||||
if (g.compressed != 'z') {
|
if (g.action != 't' && g.action != 'T' && g.action != 'q' &&
|
||||||
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag value for compressed: 0x%x", g.compressed);
|
g.action != 'd' && g.action != 'p') {
|
||||||
return;
|
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
|
||||||
};
|
"value for action: 0x%x",
|
||||||
}
|
g.action);
|
||||||
break;
|
return;
|
||||||
|
};
|
||||||
default:
|
} break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
state = AFTER_VALUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INT:
|
case delete_action: {
|
||||||
#define READ_UINT \
|
g.delete_action = screen->parser_buf[pos++] & 0xff;
|
||||||
for (i = pos; i < MIN(screen->parser_buf_pos, pos + 10); i++) { \
|
if (g.delete_action != 'A' && g.delete_action != 'I' &&
|
||||||
if (screen->parser_buf[i] < '0' || screen->parser_buf[i] > '9') break; \
|
g.delete_action != 'x' && g.delete_action != 'c' &&
|
||||||
} \
|
g.delete_action != 'i' && g.delete_action != 'z' &&
|
||||||
if (i == pos) { REPORT_ERROR("Malformed GraphicsCommand control block, expecting an integer value for key: %c", key & 0xFF); return; } \
|
g.delete_action != 'Q' && g.delete_action != 'P' &&
|
||||||
lcode = utoi(screen->parser_buf + pos, i - pos); pos = i; \
|
g.delete_action != 'a' && g.delete_action != 'C' &&
|
||||||
if (lcode > UINT32_MAX) { REPORT_ERROR("Malformed GraphicsCommand control block, number is too large"); return; } \
|
g.delete_action != 'q' && g.delete_action != 'X' &&
|
||||||
code = lcode;
|
g.delete_action != 'Y' && g.delete_action != 'Z' &&
|
||||||
|
g.delete_action != 'y' && g.delete_action != 'p') {
|
||||||
|
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
|
||||||
|
"value for delete_action: 0x%x",
|
||||||
|
g.delete_action);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} break;
|
||||||
|
|
||||||
is_negative = false;
|
case transmission_type: {
|
||||||
if(screen->parser_buf[pos] == '-') { is_negative = true; pos++; }
|
g.transmission_type = screen->parser_buf[pos++] & 0xff;
|
||||||
#define I(x) case x: g.x = is_negative ? 0 - (int32_t)code : (int32_t)code; break
|
if (g.transmission_type != 't' && g.transmission_type != 's' &&
|
||||||
READ_UINT;
|
g.transmission_type != 'd' && g.transmission_type != 'f') {
|
||||||
switch(key) {
|
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
|
||||||
I(z_index);
|
"value for transmission_type: 0x%x",
|
||||||
default: break;
|
g.transmission_type);
|
||||||
}
|
return;
|
||||||
state = AFTER_VALUE;
|
};
|
||||||
break;
|
} break;
|
||||||
|
|
||||||
|
case compressed: {
|
||||||
|
g.compressed = screen->parser_buf[pos++] & 0xff;
|
||||||
|
if (g.compressed != 'z') {
|
||||||
|
REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag "
|
||||||
|
"value for compressed: 0x%x",
|
||||||
|
g.compressed);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = AFTER_VALUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INT:
|
||||||
|
#define READ_UINT \
|
||||||
|
for (i = pos; i < MIN(screen->parser_buf_pos, pos + 10); i++) { \
|
||||||
|
if (screen->parser_buf[i] < '0' || screen->parser_buf[i] > '9') \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
if (i == pos) { \
|
||||||
|
REPORT_ERROR("Malformed GraphicsCommand control block, expecting an " \
|
||||||
|
"integer value for key: %c", \
|
||||||
|
key & 0xFF); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
lcode = utoi(screen->parser_buf + pos, i - pos); \
|
||||||
|
pos = i; \
|
||||||
|
if (lcode > UINT32_MAX) { \
|
||||||
|
REPORT_ERROR( \
|
||||||
|
"Malformed GraphicsCommand control block, number is too large"); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
code = lcode;
|
||||||
|
|
||||||
|
is_negative = false;
|
||||||
|
if (screen->parser_buf[pos] == '-') {
|
||||||
|
is_negative = true;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
#define I(x) \
|
||||||
|
case x: \
|
||||||
|
g.x = is_negative ? 0 - (int32_t)code : (int32_t)code; \
|
||||||
|
break
|
||||||
|
READ_UINT;
|
||||||
|
switch (key) {
|
||||||
|
I(z_index);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = AFTER_VALUE;
|
||||||
|
break;
|
||||||
#undef I
|
#undef I
|
||||||
case UINT:
|
case UINT:
|
||||||
READ_UINT;
|
READ_UINT;
|
||||||
#define U(x) case x: g.x = code; break
|
#define U(x) \
|
||||||
switch(key) {
|
case x: \
|
||||||
U(format); U(more); U(id); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(data_sz); U(data_offset); U(num_cells); U(num_lines); U(cell_x_offset); U(cell_y_offset);
|
g.x = code; \
|
||||||
default: break;
|
break
|
||||||
}
|
switch (key) {
|
||||||
state = AFTER_VALUE;
|
U(format);
|
||||||
break;
|
U(more);
|
||||||
|
U(id);
|
||||||
|
U(width);
|
||||||
|
U(height);
|
||||||
|
U(x_offset);
|
||||||
|
U(y_offset);
|
||||||
|
U(data_height);
|
||||||
|
U(data_width);
|
||||||
|
U(data_sz);
|
||||||
|
U(data_offset);
|
||||||
|
U(num_cells);
|
||||||
|
U(num_lines);
|
||||||
|
U(cell_x_offset);
|
||||||
|
U(cell_y_offset);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = AFTER_VALUE;
|
||||||
|
break;
|
||||||
#undef U
|
#undef U
|
||||||
#undef READ_UINT
|
#undef READ_UINT
|
||||||
|
|
||||||
case AFTER_VALUE:
|
case AFTER_VALUE:
|
||||||
switch (screen->parser_buf[pos++]) {
|
switch (screen->parser_buf[pos++]) {
|
||||||
default:
|
default:
|
||||||
REPORT_ERROR("Malformed GraphicsCommand control block, expecting a comma or semi-colon after a value, found: 0x%x",
|
REPORT_ERROR("Malformed GraphicsCommand control block, expecting a "
|
||||||
screen->parser_buf[pos - 1]);
|
"comma or semi-colon after a value, found: 0x%x",
|
||||||
return;
|
screen->parser_buf[pos - 1]);
|
||||||
case ',':
|
return;
|
||||||
state = KEY;
|
case ',':
|
||||||
break;
|
state = KEY;
|
||||||
case ';': state = PAYLOAD; break;
|
break;
|
||||||
}
|
case ';':
|
||||||
break;
|
state = PAYLOAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAYLOAD: {
|
||||||
case PAYLOAD: {
|
sz = screen->parser_buf_pos - pos;
|
||||||
sz = screen->parser_buf_pos - pos;
|
const char *err = base64_decode(screen->parser_buf + pos, sz, payload,
|
||||||
const char *err = base64_decode(screen->parser_buf + pos, sz, payload, sizeof(payload), &g.payload_sz);
|
sizeof(payload), &g.payload_sz);
|
||||||
if (err != NULL) { REPORT_ERROR("Failed to parse GraphicsCommand command payload with error: %s", err); return; }
|
if (err != NULL) {
|
||||||
pos = screen->parser_buf_pos;
|
REPORT_ERROR(
|
||||||
}
|
"Failed to parse GraphicsCommand command payload with error: %s",
|
||||||
break;
|
err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos = screen->parser_buf_pos;
|
||||||
|
} break;
|
||||||
|
|
||||||
} // end switch
|
} // end switch
|
||||||
} // end while
|
} // end while
|
||||||
|
|
||||||
switch(state) {
|
switch (state) {
|
||||||
case EQUAL:
|
case EQUAL:
|
||||||
REPORT_ERROR("Malformed GraphicsCommand control block, no = after key"); return;
|
REPORT_ERROR("Malformed GraphicsCommand control block, no = after key");
|
||||||
case INT:
|
return;
|
||||||
case UINT:
|
case INT:
|
||||||
REPORT_ERROR("Malformed GraphicsCommand control block, expecting an integer value"); return;
|
case UINT:
|
||||||
case FLAG:
|
REPORT_ERROR(
|
||||||
REPORT_ERROR("Malformed GraphicsCommand control block, expecting a flag value"); return;
|
"Malformed GraphicsCommand control block, expecting an integer value");
|
||||||
default:
|
return;
|
||||||
break;
|
case FLAG:
|
||||||
}
|
REPORT_ERROR(
|
||||||
|
"Malformed GraphicsCommand control block, expecting a flag value");
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
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",
|
REPORT_VA_COMMAND(
|
||||||
"action", g.action, "delete_action", g.delete_action, "transmission_type", g.transmission_type, "compressed", g.compressed,
|
"s {sc sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI si sI} y#",
|
||||||
"format", (unsigned int)g.format, "more", (unsigned int)g.more, "id", (unsigned int)g.id, "width", (unsigned int)g.width, "height", (unsigned int)g.height, "x_offset", (unsigned int)g.x_offset, "y_offset", (unsigned int)g.y_offset, "data_height", (unsigned int)g.data_height, "data_width", (unsigned int)g.data_width, "data_sz", (unsigned int)g.data_sz, "data_offset", (unsigned int)g.data_offset, "num_cells", (unsigned int)g.num_cells, "num_lines", (unsigned int)g.num_lines, "cell_x_offset", (unsigned int)g.cell_x_offset, "cell_y_offset", (unsigned int)g.cell_y_offset,
|
"graphics_command", "action", g.action, "delete_action", g.delete_action,
|
||||||
"z_index", (int)g.z_index
|
"transmission_type", g.transmission_type, "compressed", g.compressed,
|
||||||
, "payload_sz", g.payload_sz, payload, g.payload_sz
|
"format", (unsigned int)g.format, "more", (unsigned int)g.more, "id",
|
||||||
);
|
(unsigned int)g.id, "width", (unsigned int)g.width, "height",
|
||||||
|
(unsigned int)g.height, "x_offset", (unsigned int)g.x_offset, "y_offset",
|
||||||
|
(unsigned int)g.y_offset, "data_height", (unsigned int)g.data_height,
|
||||||
|
"data_width", (unsigned int)g.data_width, "data_sz",
|
||||||
|
(unsigned int)g.data_sz, "data_offset", (unsigned int)g.data_offset,
|
||||||
|
"num_cells", (unsigned int)g.num_cells, "num_lines",
|
||||||
|
(unsigned int)g.num_lines, "cell_x_offset", (unsigned int)g.cell_x_offset,
|
||||||
|
"cell_y_offset", (unsigned int)g.cell_y_offset, "z_index", (int)g.z_index,
|
||||||
|
"payload_sz", g.payload_sz, payload, g.payload_sz);
|
||||||
|
|
||||||
screen_handle_graphics_command(screen, &g, payload);
|
screen_handle_graphics_command(screen, &g, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user