mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-21 05:18:06 +01:00
Change to the linux kernel coding style
for arq in `git ls-files *.c`; do
echo $arq;
indent -linux -l115 $arq;
done
The different line break at 115 columns is because
I use a widescreen monitor :-)
This commit is contained in:
475
src/xdnd.c
475
src/xdnd.c
@@ -18,7 +18,6 @@
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
|
||||
#define XDND_VERSION 3L
|
||||
|
||||
Atom _XA_XdndAware;
|
||||
@@ -39,37 +38,34 @@ Atom _XA_WINDOWMAKER_XDNDEXCHANGE;
|
||||
|
||||
Atom atom_support;
|
||||
|
||||
void
|
||||
wXDNDInitializeAtoms()
|
||||
void wXDNDInitializeAtoms()
|
||||
{
|
||||
|
||||
_XA_XdndAware = XInternAtom(dpy, "XdndAware", False);
|
||||
_XA_XdndEnter = XInternAtom(dpy, "XdndEnter", False);
|
||||
_XA_XdndLeave = XInternAtom(dpy, "XdndLeave", False);
|
||||
_XA_XdndDrop = XInternAtom(dpy, "XdndDrop", False);
|
||||
_XA_XdndPosition = XInternAtom(dpy, "XdndPosition", False);
|
||||
_XA_XdndStatus = XInternAtom(dpy, "XdndStatus", False);
|
||||
_XA_XdndActionCopy = XInternAtom(dpy, "XdndActionCopy", False);
|
||||
_XA_XdndSelection = XInternAtom(dpy, "XdndSelection", False);
|
||||
_XA_XdndFinished = XInternAtom(dpy, "XdndFinished", False);
|
||||
_XA_XdndAware = XInternAtom(dpy, "XdndAware", False);
|
||||
_XA_XdndEnter = XInternAtom(dpy, "XdndEnter", False);
|
||||
_XA_XdndLeave = XInternAtom(dpy, "XdndLeave", False);
|
||||
_XA_XdndDrop = XInternAtom(dpy, "XdndDrop", False);
|
||||
_XA_XdndPosition = XInternAtom(dpy, "XdndPosition", False);
|
||||
_XA_XdndStatus = XInternAtom(dpy, "XdndStatus", False);
|
||||
_XA_XdndActionCopy = XInternAtom(dpy, "XdndActionCopy", False);
|
||||
_XA_XdndSelection = XInternAtom(dpy, "XdndSelection", False);
|
||||
_XA_XdndFinished = XInternAtom(dpy, "XdndFinished", False);
|
||||
|
||||
_XA_WINDOWMAKER_XDNDEXCHANGE = XInternAtom(dpy, "_WINDOWMAKER_XDNDEXCHANGE", False);
|
||||
_XA_WINDOWMAKER_XDNDEXCHANGE = XInternAtom(dpy, "_WINDOWMAKER_XDNDEXCHANGE", False);
|
||||
|
||||
/*
|
||||
_XA_MOTIF_DRAG_RECEIVER_INFO = XInternAtom(dpy, "_MOTIF_DRAG_RECEIVER_INFO",False);
|
||||
_XA_MOTIF_DRAG_AND_DROP_MESSAGE = XInternAtom(dpy, "_MOTIF_DRAG_AND_DROP_MESSAGE", False);
|
||||
*/
|
||||
/*
|
||||
_XA_MOTIF_DRAG_RECEIVER_INFO = XInternAtom(dpy, "_MOTIF_DRAG_RECEIVER_INFO",False);
|
||||
_XA_MOTIF_DRAG_AND_DROP_MESSAGE = XInternAtom(dpy, "_MOTIF_DRAG_AND_DROP_MESSAGE", False);
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
wXDNDMakeAwareness(Window window)
|
||||
void wXDNDMakeAwareness(Window window)
|
||||
{
|
||||
long int xdnd_version = 3;
|
||||
/*
|
||||
MotifDragReceiverInfo info;
|
||||
*/
|
||||
XChangeProperty (dpy, window, _XA_XdndAware, XA_ATOM,
|
||||
32, PropModeAppend, (char *)&xdnd_version, 1);
|
||||
long int xdnd_version = 3;
|
||||
/*
|
||||
MotifDragReceiverInfo info;
|
||||
*/
|
||||
XChangeProperty(dpy, window, _XA_XdndAware, XA_ATOM, 32, PropModeAppend, (char *)&xdnd_version, 1);
|
||||
|
||||
/*** MOTIF ***
|
||||
info.byte_order = '\0';
|
||||
@@ -88,253 +84,248 @@ wXDNDMakeAwareness(Window window)
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
wXDNDClearAwareness(Window window)
|
||||
void wXDNDClearAwareness(Window window)
|
||||
{
|
||||
XDeleteProperty (dpy, window, _XA_XdndAware);
|
||||
XDeleteProperty(dpy, window, _XA_XdndAware);
|
||||
}
|
||||
|
||||
Bool
|
||||
wXDNDProcessSelection(XEvent *event)
|
||||
Bool wXDNDProcessSelection(XEvent * event)
|
||||
{
|
||||
WScreen *scr = wScreenForWindow(event->xselection.requestor);
|
||||
char *retain;
|
||||
Atom ret_type;
|
||||
int ret_format;
|
||||
unsigned long ret_item;
|
||||
unsigned long remain_byte;
|
||||
char * delme;
|
||||
XEvent xevent;
|
||||
Window selowner = XGetSelectionOwner(dpy,_XA_XdndSelection);
|
||||
WMArray *items;
|
||||
WScreen *scr = wScreenForWindow(event->xselection.requestor);
|
||||
char *retain;
|
||||
Atom ret_type;
|
||||
int ret_format;
|
||||
unsigned long ret_item;
|
||||
unsigned long remain_byte;
|
||||
char *delme;
|
||||
XEvent xevent;
|
||||
Window selowner = XGetSelectionOwner(dpy, _XA_XdndSelection);
|
||||
WMArray *items;
|
||||
|
||||
XGetWindowProperty(dpy, event->xselection.requestor,
|
||||
_XA_WINDOWMAKER_XDNDEXCHANGE,
|
||||
0, 65536, True, atom_support, &ret_type, &ret_format,
|
||||
&ret_item, &remain_byte, (unsigned char **)&delme);
|
||||
if (delme) {
|
||||
scr->xdestring = delme;
|
||||
}
|
||||
|
||||
XGetWindowProperty(dpy, event->xselection.requestor,
|
||||
_XA_WINDOWMAKER_XDNDEXCHANGE,
|
||||
0, 65536, True, atom_support, &ret_type, &ret_format,
|
||||
&ret_item, &remain_byte, (unsigned char **)&delme);
|
||||
if (delme){
|
||||
scr->xdestring=delme;
|
||||
}
|
||||
/*send finished */
|
||||
memset(&xevent, 0, sizeof(xevent));
|
||||
xevent.xany.type = ClientMessage;
|
||||
xevent.xany.display = dpy;
|
||||
xevent.xclient.window = selowner;
|
||||
xevent.xclient.message_type = _XA_XdndFinished;
|
||||
xevent.xclient.format = 32;
|
||||
XDND_FINISHED_TARGET_WIN(&xevent) = event->xselection.requestor;
|
||||
XSendEvent(dpy, selowner, 0, 0, &xevent);
|
||||
|
||||
/*send finished*/
|
||||
memset (&xevent, 0, sizeof(xevent));
|
||||
xevent.xany.type = ClientMessage;
|
||||
xevent.xany.display = dpy;
|
||||
xevent.xclient.window = selowner;
|
||||
xevent.xclient.message_type = _XA_XdndFinished;
|
||||
xevent.xclient.format = 32;
|
||||
XDND_FINISHED_TARGET_WIN(&xevent) = event->xselection.requestor;
|
||||
XSendEvent(dpy, selowner, 0, 0, &xevent);
|
||||
/*process dropping */
|
||||
if (scr->xdestring) {
|
||||
WMArrayIterator iter;
|
||||
int length, str_size;
|
||||
int total_size = 0;
|
||||
char *tmp;
|
||||
|
||||
/*process dropping*/
|
||||
if (scr->xdestring) {
|
||||
WMArrayIterator iter;
|
||||
int length, str_size;
|
||||
int total_size = 0;
|
||||
char *tmp;
|
||||
items = WMCreateArray(4);
|
||||
retain = wstrdup(scr->xdestring);
|
||||
XFree(scr->xdestring); /* since xdestring was created by Xlib */
|
||||
|
||||
items = WMCreateArray(4);
|
||||
retain = wstrdup(scr->xdestring);
|
||||
XFree(scr->xdestring); /* since xdestring was created by Xlib */
|
||||
length = strlen(retain);
|
||||
|
||||
length = strlen(retain);
|
||||
/* search in string */
|
||||
while (length--) {
|
||||
if (retain[length] == '\r') { /* useless char, nuke it */
|
||||
retain[length] = 0;
|
||||
}
|
||||
if (retain[length] == '\n') {
|
||||
str_size = strlen(&retain[length + 1]);
|
||||
if (str_size) {
|
||||
WMAddToArray(items, wstrdup(&retain[length + 1]));
|
||||
total_size += str_size + 3; /* reserve for " \"\"" */
|
||||
/* this is nonsense -- if (length)
|
||||
WMAppendArray(items, WMCreateArray(1)); */
|
||||
}
|
||||
retain[length] = 0;
|
||||
}
|
||||
}
|
||||
/* final one */
|
||||
WMAddToArray(items, wstrdup(retain));
|
||||
total_size += strlen(retain) + 3;
|
||||
wfree(retain);
|
||||
|
||||
/* search in string */
|
||||
while (length--) {
|
||||
if (retain[length] == '\r') { /* useless char, nuke it */
|
||||
retain[length] = 0;
|
||||
}
|
||||
if (retain[length] == '\n') {
|
||||
str_size = strlen(&retain[length + 1]);
|
||||
if(str_size) {
|
||||
WMAddToArray(items, wstrdup(&retain[length + 1]));
|
||||
total_size += str_size + 3; /* reserve for " \"\"" */
|
||||
/* this is nonsense -- if (length)
|
||||
WMAppendArray(items, WMCreateArray(1));*/
|
||||
}
|
||||
retain[length] = 0;
|
||||
}
|
||||
}
|
||||
/* final one */
|
||||
WMAddToArray(items, wstrdup(retain));
|
||||
total_size += strlen(retain) + 3;
|
||||
wfree(retain);
|
||||
/* now pack new string */
|
||||
scr->xdestring = wmalloc(total_size);
|
||||
scr->xdestring[0] = 0; /* empty string */
|
||||
WM_ETARETI_ARRAY(items, tmp, iter) {
|
||||
if (!strncmp(tmp, "file:", 5)) {
|
||||
/* add more 2 chars while removing 5 is harmless */
|
||||
strcat(scr->xdestring, " \"");
|
||||
strcat(scr->xdestring, &tmp[5]);
|
||||
strcat(scr->xdestring, "\"");
|
||||
} else {
|
||||
/* unsupport object, still need more " ? tell ]d */
|
||||
strcat(scr->xdestring, &tmp[5]);
|
||||
}
|
||||
wfree(tmp);
|
||||
}
|
||||
WMFreeArray(items);
|
||||
wDockReceiveDNDDrop(scr, event);
|
||||
/*
|
||||
printf("free ");
|
||||
puts(scr->xdestring);
|
||||
*/
|
||||
wfree(scr->xdestring); /* this xdestring is not from Xlib (no XFree) */
|
||||
}
|
||||
|
||||
/* now pack new string */
|
||||
scr->xdestring = wmalloc(total_size);
|
||||
scr->xdestring[0]=0; /* empty string */
|
||||
WM_ETARETI_ARRAY(items, tmp, iter) {
|
||||
if (!strncmp(tmp,"file:",5)) {
|
||||
/* add more 2 chars while removing 5 is harmless */
|
||||
strcat(scr->xdestring, " \"");
|
||||
strcat(scr->xdestring, &tmp[5]);
|
||||
strcat(scr->xdestring, "\"");
|
||||
} else {
|
||||
/* unsupport object, still need more " ? tell ]d */
|
||||
strcat(scr->xdestring, &tmp[5]);
|
||||
}
|
||||
wfree(tmp);
|
||||
}
|
||||
WMFreeArray(items);
|
||||
wDockReceiveDNDDrop(scr,event);
|
||||
/*
|
||||
printf("free ");
|
||||
puts(scr->xdestring);
|
||||
*/
|
||||
wfree(scr->xdestring); /* this xdestring is not from Xlib (no XFree) */
|
||||
}
|
||||
|
||||
/* why doesn't this function return anything ? -Dan */
|
||||
/* why doesn't this function return anything ? -Dan */
|
||||
}
|
||||
|
||||
Bool
|
||||
isAwareXDND(Window window)
|
||||
Bool isAwareXDND(Window window)
|
||||
{
|
||||
Atom actual;
|
||||
int format;
|
||||
unsigned long count, remaining;
|
||||
unsigned char *data=0;
|
||||
Atom actual;
|
||||
int format;
|
||||
unsigned long count, remaining;
|
||||
unsigned char *data = 0;
|
||||
|
||||
if (!window) return False;
|
||||
XGetWindowProperty (dpy, window, _XA_XdndAware,
|
||||
0, 0x8000000L, False, XA_ATOM,
|
||||
&actual, &format,
|
||||
&count, &remaining, &data);
|
||||
if (actual != XA_ATOM || format != 32 || count == 0 || !data) {
|
||||
if (data)
|
||||
XFree (data);
|
||||
return False;
|
||||
}
|
||||
if (data)
|
||||
XFree (data);
|
||||
return True;
|
||||
if (!window)
|
||||
return False;
|
||||
XGetWindowProperty(dpy, window, _XA_XdndAware,
|
||||
0, 0x8000000L, False, XA_ATOM, &actual, &format, &count, &remaining, &data);
|
||||
if (actual != XA_ATOM || format != 32 || count == 0 || !data) {
|
||||
if (data)
|
||||
XFree(data);
|
||||
return False;
|
||||
}
|
||||
if (data)
|
||||
XFree(data);
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool
|
||||
acceptXDND(Window window)
|
||||
Bool acceptXDND(Window window)
|
||||
{
|
||||
WScreen *scr = wScreenForWindow(window);
|
||||
WDock *dock;
|
||||
int icon_pos,i;
|
||||
WScreen *scr = wScreenForWindow(window);
|
||||
WDock *dock;
|
||||
int icon_pos, i;
|
||||
|
||||
icon_pos = -1;
|
||||
if ((dock = scr->dock)!=NULL) {
|
||||
for (i=0; i<dock->max_icons; i++) {
|
||||
if (dock->icon_array[i]
|
||||
&& dock->icon_array[i]->icon->core->window==window) {
|
||||
icon_pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (icon_pos<0 && (dock = scr->workspaces[scr->current_workspace]->clip)!=NULL) {
|
||||
for (i=0; i<dock->max_icons; i++) {
|
||||
if (dock->icon_array[i]
|
||||
&& dock->icon_array[i]->icon->core->window==window) {
|
||||
icon_pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (icon_pos<0) return False;
|
||||
if (!dock) return False;
|
||||
if (isAwareXDND(dock->icon_array[icon_pos]->icon->icon_win)) return False;
|
||||
icon_pos = -1;
|
||||
if ((dock = scr->dock) != NULL) {
|
||||
for (i = 0; i < dock->max_icons; i++) {
|
||||
if (dock->icon_array[i]
|
||||
&& dock->icon_array[i]->icon->core->window == window) {
|
||||
icon_pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (icon_pos < 0 && (dock = scr->workspaces[scr->current_workspace]->clip) != NULL) {
|
||||
for (i = 0; i < dock->max_icons; i++) {
|
||||
if (dock->icon_array[i]
|
||||
&& dock->icon_array[i]->icon->core->window == window) {
|
||||
icon_pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (icon_pos < 0)
|
||||
return False;
|
||||
if (!dock)
|
||||
return False;
|
||||
if (isAwareXDND(dock->icon_array[icon_pos]->icon->icon_win))
|
||||
return False;
|
||||
|
||||
if (dock->icon_array[icon_pos]->dnd_command!=NULL) return True;
|
||||
if (dock->icon_array[icon_pos]->dnd_command != NULL)
|
||||
return True;
|
||||
|
||||
return False;
|
||||
return False;
|
||||
}
|
||||
|
||||
Bool
|
||||
wXDNDProcessClientMessage(XClientMessageEvent *event)
|
||||
Bool wXDNDProcessClientMessage(XClientMessageEvent * event)
|
||||
{
|
||||
/* test */
|
||||
{
|
||||
char * name = XGetAtomName(dpy, event->message_type);
|
||||
/*
|
||||
printf("Get %s\n",name);
|
||||
*/
|
||||
XFree(name);
|
||||
}
|
||||
/* test */
|
||||
{
|
||||
char *name = XGetAtomName(dpy, event->message_type);
|
||||
/*
|
||||
printf("Get %s\n",name);
|
||||
*/
|
||||
XFree(name);
|
||||
}
|
||||
|
||||
/*
|
||||
if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
|
||||
printf("motif dnd msg %d\n",event->data.b[0]);
|
||||
if (event->data.b[0] == XmDROP_START){
|
||||
unsigned x_root, y_root, flags;
|
||||
unsigned char reason;
|
||||
unsigned long timestamp;
|
||||
Atom atom;
|
||||
Window source_window;
|
||||
MotifDragInitiatorInfo *initiator_info;
|
||||
Atom ret_type;
|
||||
int ret_format;
|
||||
unsigned long ret_item;
|
||||
unsigned long remain_byte;
|
||||
/*
|
||||
if (event->message_type == _XA_MOTIF_DRAG_AND_DROP_MESSAGE) {
|
||||
printf("motif dnd msg %d\n",event->data.b[0]);
|
||||
if (event->data.b[0] == XmDROP_START){
|
||||
unsigned x_root, y_root, flags;
|
||||
unsigned char reason;
|
||||
unsigned long timestamp;
|
||||
Atom atom;
|
||||
Window source_window;
|
||||
MotifDragInitiatorInfo *initiator_info;
|
||||
Atom ret_type;
|
||||
int ret_format;
|
||||
unsigned long ret_item;
|
||||
unsigned long remain_byte;
|
||||
|
||||
reason = event->data.b[0];
|
||||
flags = event->data.s[1];
|
||||
timestamp = event->data.l[1];
|
||||
x_root = event->data.s[4];
|
||||
y_root = event->data.s[5];
|
||||
atom = event->data.l[3];
|
||||
source_window = event->data.l[4];
|
||||
reason = event->data.b[0];
|
||||
flags = event->data.s[1];
|
||||
timestamp = event->data.l[1];
|
||||
x_root = event->data.s[4];
|
||||
y_root = event->data.s[5];
|
||||
atom = event->data.l[3];
|
||||
source_window = event->data.l[4];
|
||||
|
||||
XGetWindowProperty(dpy, source_window, atom,
|
||||
0, sizeof(*initiator_info), True, atom_support,
|
||||
&ret_type, &ret_format,
|
||||
&ret_item, &remain_byte, (unsigned char **)&initiator_info);
|
||||
}
|
||||
}
|
||||
else */
|
||||
if (event->message_type == _XA_XdndEnter) {
|
||||
if ((event->data.l[1] & 1) == 0){
|
||||
atom_support = event->data.l[2];
|
||||
}
|
||||
/*
|
||||
else puts("enter more than 3 types");
|
||||
*/
|
||||
return True;
|
||||
} else if (event->message_type == _XA_XdndLeave) {
|
||||
return True;
|
||||
} else if (event->message_type == _XA_XdndDrop) {
|
||||
if (event->data.l[0] == XGetSelectionOwner(dpy, _XA_XdndSelection)){
|
||||
XConvertSelection(dpy, _XA_XdndSelection, atom_support,
|
||||
_XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
|
||||
}
|
||||
else {
|
||||
puts("wierd selection owner? QT?");
|
||||
XConvertSelection(dpy, _XA_XdndSelection, atom_support,
|
||||
_XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
|
||||
}
|
||||
return True;
|
||||
} else if (event->message_type == _XA_XdndPosition) {
|
||||
XEvent xevent;
|
||||
Window srcwin = event->data.l[0];
|
||||
if (atom_support != XInternAtom(dpy, "text/uri-list", False)) {
|
||||
return True;
|
||||
}
|
||||
{
|
||||
memset (&xevent, 0, sizeof(xevent));
|
||||
xevent.xany.type = ClientMessage;
|
||||
xevent.xany.display = dpy;
|
||||
xevent.xclient.window = srcwin;
|
||||
xevent.xclient.message_type = _XA_XdndStatus;
|
||||
xevent.xclient.format = 32;
|
||||
XGetWindowProperty(dpy, source_window, atom,
|
||||
0, sizeof(*initiator_info), True, atom_support,
|
||||
&ret_type, &ret_format,
|
||||
&ret_item, &remain_byte, (unsigned char **)&initiator_info);
|
||||
}
|
||||
}
|
||||
else */
|
||||
if (event->message_type == _XA_XdndEnter) {
|
||||
if ((event->data.l[1] & 1) == 0) {
|
||||
atom_support = event->data.l[2];
|
||||
}
|
||||
/*
|
||||
else puts("enter more than 3 types");
|
||||
*/
|
||||
return True;
|
||||
} else if (event->message_type == _XA_XdndLeave) {
|
||||
return True;
|
||||
} else if (event->message_type == _XA_XdndDrop) {
|
||||
if (event->data.l[0] == XGetSelectionOwner(dpy, _XA_XdndSelection)) {
|
||||
XConvertSelection(dpy, _XA_XdndSelection, atom_support,
|
||||
_XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
|
||||
} else {
|
||||
puts("wierd selection owner? QT?");
|
||||
XConvertSelection(dpy, _XA_XdndSelection, atom_support,
|
||||
_XA_WINDOWMAKER_XDNDEXCHANGE, event->window, CurrentTime);
|
||||
}
|
||||
return True;
|
||||
} else if (event->message_type == _XA_XdndPosition) {
|
||||
XEvent xevent;
|
||||
Window srcwin = event->data.l[0];
|
||||
if (atom_support != XInternAtom(dpy, "text/uri-list", False)) {
|
||||
return True;
|
||||
}
|
||||
{
|
||||
memset(&xevent, 0, sizeof(xevent));
|
||||
xevent.xany.type = ClientMessage;
|
||||
xevent.xany.display = dpy;
|
||||
xevent.xclient.window = srcwin;
|
||||
xevent.xclient.message_type = _XA_XdndStatus;
|
||||
xevent.xclient.format = 32;
|
||||
|
||||
XDND_STATUS_TARGET_WIN (&xevent) = event->window;
|
||||
XDND_STATUS_WILL_ACCEPT_SET (&xevent, acceptXDND(event->window));
|
||||
XDND_STATUS_WANT_POSITION_SET(&xevent, True);
|
||||
XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024,768);
|
||||
XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy;
|
||||
XDND_STATUS_TARGET_WIN(&xevent) = event->window;
|
||||
XDND_STATUS_WILL_ACCEPT_SET(&xevent, acceptXDND(event->window));
|
||||
XDND_STATUS_WANT_POSITION_SET(&xevent, True);
|
||||
XDND_STATUS_RECT_SET(&xevent, 0, 0, 1024, 768);
|
||||
XDND_STATUS_ACTION(&xevent) = _XA_XdndActionCopy;
|
||||
|
||||
XSendEvent(dpy, srcwin, 0, 0, &xevent);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
XSendEvent(dpy, srcwin, 0, 0, &xevent);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user