Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libSDL
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PocketInsanity
libSDL
Commits
ea29eee8
Commit
ea29eee8
authored
Jun 30, 2010
by
Eli Gottlieb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finished X11 shaped-window functionality and removed ellipse+polygon rendering.
parent
2c8b1ce8
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
193 additions
and
125 deletions
+193
-125
Makefile.in
Makefile.in
+1
-1
SDL_shape.h
include/SDL_shape.h
+4
-3
SDL_video.h
include/SDL_video.h
+0
-76
SDL_shape.c
src/video/SDL_shape.c
+78
-7
SDL_sysvideo.h
src/video/SDL_sysvideo.h
+38
-4
SDL_video.c
src/video/SDL_video.c
+0
-32
SDL_x11shape.c
src/video/x11/SDL_x11shape.c
+65
-2
SDL_x11video.c
src/video/x11/SDL_x11video.c
+4
-0
SDL_x11window.c
src/video/x11/SDL_x11window.c
+3
-0
No files found.
Makefile.in
View file @
ea29eee8
...
...
@@ -44,7 +44,7 @@ EMBEDSPU = @EMBEDSPU@
DIST
=
acinclude autogen.sh Borland.html Borland.zip BUGS build-scripts configure configure.in COPYING CREDITS include INSTALL Makefile.minimal Makefile.in README
*
sdl-config.in sdl.m4 sdl.pc.in SDL.spec SDL.spec.in src
test
TODO VisualC.html VisualC VisualCE Watcom-Win32.zip WhatsNew Xcode Xcode-iPhoneOS
HDRS
=
SDL.h SDL_assert.h SDL_atomic.h SDL_audio.h SDL_compat.h SDL_cpuinfo.h SDL_e
llipse.h SDL_endian.h SDL_error.h SDL_events.h SDL_haptic.h SDL_joystick.h SDL_keyboard.h SDL_keysym.h SDL_loadso.h SDL_main.h SDL_mouse.h SDL_mutex.h SDL_name.h SDL_opengl.h SDL_opengles.h SDL_pixels.h SDL_platform.h SDL_poly
.h SDL_power.h SDL_quit.h SDL_rect.h SDL_revision.h SDL_rwops.h SDL_scancode.h SDL_shape.h SDL_stdinc.h SDL_surface.h SDL_syswm.h SDL_thread.h SDL_timer.h SDL_types.h SDL_version.h SDL_video.h begin_code.h close_code.h
HDRS
=
SDL.h SDL_assert.h SDL_atomic.h SDL_audio.h SDL_compat.h SDL_cpuinfo.h SDL_e
ndian.h SDL_error.h SDL_events.h SDL_haptic.h SDL_joystick.h SDL_keyboard.h SDL_keysym.h SDL_loadso.h SDL_main.h SDL_mouse.h SDL_mutex.h SDL_name.h SDL_opengl.h SDL_opengles.h SDL_pixels.h SDL_platform
.h SDL_power.h SDL_quit.h SDL_rect.h SDL_revision.h SDL_rwops.h SDL_scancode.h SDL_shape.h SDL_stdinc.h SDL_surface.h SDL_syswm.h SDL_thread.h SDL_timer.h SDL_types.h SDL_version.h SDL_video.h begin_code.h close_code.h
LT_AGE
=
@LT_AGE@
LT_CURRENT
=
@LT_CURRENT@
...
...
include/SDL_shape.h
View file @
ea29eee8
...
...
@@ -114,10 +114,11 @@ extern DECLSPEC int SDLCALL SDL_SetWindowShape(SDL_Window *window,SDL_Surface *s
* \brief Get the shape parameters of a shaped window.
*
* \param window The shaped window whose parameters should be retrieved.
* \param shapeMode An empty shape-
parameters structure to fill
.
* \param shapeMode An empty shape-
mode structure to fill, or NULL to check whether the window has a shape
.
*
* \return 0 on success, -1 on a null shapeMode, or -2 if the SDL_Window given is not a shaped window, or -3 if the
* SDL_Window given is a window that can be shaped but isn't.
* \return 0 if the window has a shape and, provided shapeMode was not NULL, shapeMode has been filled with the mode
* data, -1 if the SDL_Window given is not a shaped window, or -2 if the SDL_Window* given is a shapeable
* window currently lacking a shape.
*
* \sa SDL_WindowShapeMode
* \sa SDL_SetWindowShape
...
...
include/SDL_video.h
View file @
ea29eee8
...
...
@@ -1239,82 +1239,6 @@ extern DECLSPEC int SDLCALL SDL_RenderFillRect(const SDL_Rect * rect);
*/
extern
DECLSPEC
int
SDLCALL
SDL_RenderFillRects
(
const
SDL_Rect
**
rect
,
int
count
);
/**
* \brief Draw an ellipse on the current rendering target with the drawing color.
*
* \param ellipse The destination ellipse.
*
* \return 0 on success, or -1 if there is no rendering context current.
*/
extern
DECLSPEC
int
SDLCALL
SDL_RenderDrawEllipse
(
const
SDL_Ellipse
ellipse
);
/**
* \brief Draw some number of ellipses in the current rendering target with the drawing color.
*
* \param ellipse A pointer to an array of destination ellipses.
* \param count The number of ellipses.
*
* \return 0 on success, or -1 if there is no rendering context current.
*/
extern
DECLSPEC
int
SDLCALL
SDL_RenderDrawEllipses
(
const
SDL_Ellipse
*
ellipse
,
int
count
);
/**
* \brief Fill an ellipse on the current rendering target with the drawing color.
*
* \param ellipse The destination ellipse
*
* \return 0 on success, or -1 if there is no rendering context current.
*/
extern
DECLSPEC
int
SDLCALL
SDL_RenderFillEllipse
(
const
SDL_Ellipse
ellipse
);
/**
* \brief Fill some number of ellipses in the current rendering target with the drawing color.
*
* \param ellipse A pointer to an array of destination ellipses.
* \param count The number of ellipses.
*
* \return 0 on success, or -1 if there is no rendering context current.
*/
extern
DECLSPEC
int
SDLCALL
SDL_RenderFillEllipses
(
const
SDL_Ellipse
*
ellipse
,
int
count
);
/**
* \brief Draw a polygon on the current rendering target with the drawing color.
*
* \param poly The destination polygon.
*
* \return 0 on success, or -1 if there is no rendering context current.
*/
extern
DECLSPEC
int
SDLCALL
SDL_RenderDrawPoly
(
const
SDL_Poly
poly
);
/**
* \brief Draw some number of polygons in the current rendering target with the drawing color.
*
* \param poly A pointer to an array of destination polygons.
* \param count The number of polygons.
*
* \return 0 on success, or -1 if there is no rendering context current.
*/
extern
DECLSPEC
int
SDLCALL
SDL_RenderDrawPolys
(
const
SDL_Poly
*
poly
,
int
count
);
/**
* \brief Fill a polygon on the current rendering target with the drawing color.
*
* \param poly The destination polygon
*
* \return 0 on success, or -1 if there is no rendering context current.
*/
extern
DECLSPEC
int
SDLCALL
SDL_RenderFillPoly
(
const
SDL_Poly
poly
);
/**
* \brief Fill some number of polygons in the current rendering target with the drawing color.
*
* \param poly A pointer to an array of destination polygons.
* \param count The number of polygons.
*
* \return 0 on success, or -1 if there is no rendering context current.
*/
extern
DECLSPEC
int
SDLCALL
SDL_RenderFillPolys
(
const
SDL_Poly
*
poly
,
int
count
);
/**
* \brief Copy a portion of the texture to the current rendering target.
*
...
...
src/video/SDL_shape.c
View file @
ea29eee8
...
...
@@ -24,28 +24,99 @@
#include "SDL.h"
#include "SDL_video.h"
#include "SDL_sysvideo.h"
#include "SDL_pixels.h"
#include "SDL_surface.h"
#include "SDL_shape.h"
SDL_Window
*
SDL_CreateShapedWindow
(
const
char
*
title
,
unsigned
int
x
,
unsigned
int
y
,
unsigned
int
w
,
unsigned
int
h
,
Uint32
flags
)
{
return
NULL
;
SDL_Window
*
result
=
SDL_CreateWindow
(
title
,
x
,
y
,
w
,
h
,
SDL_WINDOW_BORDERLESS
|
flags
&
!
SDL_WINDOW_FULLSCREEN
&
!
SDL_WINDOW_SHOWN
);
result
->
shaper
=
result
->
display
->
device
->
shape_driver
.
CreateShaper
(
result
);
result
->
shaper
->
usershownflag
=
flags
&
SDL_WINDOW_SHOWN
;
result
->
shaper
->
alphacutoff
=
1
;
result
->
shaper
->
hasshape
=
SDL_FALSE
;
return
result
;
}
SDL_bool
SDL_IsShapedWindow
(
const
SDL_Window
*
window
)
{
return
SDL_FALSE
;
if
(
window
==
NULL
)
return
SDL_FALSE
;
else
return
window
->
shaper
!=
NULL
;
}
/* REQUIRES that bitmap point to a w-by-h bitmap with 1bpp. */
void
SDL_CalculateShapeBitmap
(
Uint8
alphacutoff
,
SDL_Surface
*
shape
,
Uint8
*
bitmap
)
{
if
(
SDL_MUSTLOCK
(
shape
))
SDL_LockSurface
(
shape
);
int
x
=
0
,
y
=
0
;
for
(
x
=
0
;
x
<
shape
->
w
;
x
++
)
for
(
y
=
0
;
y
<
shape
->
h
;
y
++
)
{
void
*
pixel
=
shape
->
pixels
+
(
y
*
shape
->
pitch
)
+
(
x
*
shape
->
format
->
BytesPerPixel
);
Uint8
alpha
=
0
;
SDL_GetRGBA
(
*
(
Uint32
*
)
pixel
,
shape
->
format
,
NULL
,
NULL
,
NULL
,
&
alpha
);
Uint32
bitmap_pixel
=
y
*
shape
->
w
+
x
;
bitmap
[
bitmap_pixel
/
8
]
|=
(
alpha
>=
alphacutoff
?
1
:
0
)
<<
(
8
-
(
bitmap_pixel
%
8
));
}
if
(
SDL_MUSTLOCK
(
shape
))
SDL_UnlockSurface
(
shape
);
}
int
SDL_SetWindowShape
(
SDL_Window
*
window
,
SDL_Surface
*
shape
,
SDL_WindowShapeMode
*
shapeMode
)
{
if
(
window
==
NULL
||
!
SDL_WindowIsShaped
(
window
))
//The window given was not a shapeable window.
return
-
2
;
if
(
shape
==
NULL
)
//Invalid shape argument.
return
-
1
;
return
-
3
;
if
(
shapeMode
!=
NULL
)
{
switch
(
shapeMode
->
mode
)
{
case
ShapeModeDefault
:
{
window
->
shaper
->
alphacutoff
=
1
;
break
;
}
case
ShapeModeBinarizeAlpha
:
{
window
->
shaper
->
alphacutoff
=
shapeMode
->
parameters
.
binarizationCutoff
;
break
;
}
}
}
//TODO: Platform-specific implementations of SetWindowShape. X11 is in-progress.
int
result
=
window
->
display
->
device
->
shape_driver
.
SetWindowShape
(
window
->
shaper
,
shape
,
shapeMode
);
window
->
shaper
->
hasshape
=
SDL_TRUE
;
if
(
window
->
shaper
->
usershownflag
&
SDL_WINDOW_SHOWN
==
SDL_WINDOW_SHOWN
)
{
SDL_ShowWindow
(
window
);
window
->
shaper
->
usershownflag
&=
!
SDL_WINDOW_SHOWN
;
}
return
result
;
}
SDL_bool
SDL_WindowHasAShape
(
SDL_Window
*
window
)
{
assert
(
window
!=
NULL
&&
SDL_IsShapedWindow
(
window
));
return
window
->
shaper
->
hasshape
;
}
int
SDL_GetShapedWindowMode
(
SDL_Window
*
window
,
SDL_WindowShapeMode
*
shapeMode
)
{
if
(
shapeMode
==
NULL
)
if
(
window
!=
NULL
&&
SDL_IsShapedWindow
(
window
))
{
if
(
shapeMode
==
NULL
)
{
if
(
SDL_WindowHasAShape
(
window
))
//The window given has a shape.
return
0
;
else
//The window given is shapeable but lacks a shape.
return
-
2
;
}
else
{
if
(
window
->
shaper
->
alphacutoff
!=
1
)
{
shapeMode
->
mode
=
ShapeModeBinarizeAlpha
;
shapeMode
->
parameters
.
binarizationCutoff
=
window
->
shaper
->
alphacutoff
;
}
else
shapeMode
->
mode
=
ShapeModeDefault
;
return
0
;
}
}
else
//The window given is not a valid shapeable window.
return
-
1
;
if
(
window
==
NULL
||
!
SDL_WindowIsShaped
(
window
))
return
-
2
;
return
-
3
;
}
src/video/SDL_sysvideo.h
View file @
ea29eee8
...
...
@@ -26,11 +26,14 @@
#include "SDL_mouse.h"
#include "SDL_keysym.h"
#include "SDL_shape.h"
/* The SDL video driver */
typedef
struct
SDL_Renderer
SDL_Renderer
;
typedef
struct
SDL_RenderDriver
SDL_RenderDriver
;
typedef
struct
SDL_WindowShaper
SDL_WindowShaper
;
typedef
struct
SDL_ShapeDriver
SDL_ShapeDriver
;
typedef
struct
SDL_VideoDisplay
SDL_VideoDisplay
;
typedef
struct
SDL_VideoDevice
SDL_VideoDevice
;
...
...
@@ -97,10 +100,6 @@ struct SDL_Renderer
int
count
);
int
(
*
RenderFillRects
)
(
SDL_Renderer
*
renderer
,
const
SDL_Rect
**
rects
,
int
count
);
int
(
*
RenderDrawEllipse
)
(
SDL_Renderer
*
renderer
,
int
x
,
int
y
,
int
w
,
int
h
);
int
(
*
RenderFillEllipse
)
(
SDL_Renderer
*
renderer
,
int
x
,
int
y
,
int
w
,
int
h
);
int
(
*
RenderCopy
)
(
SDL_Renderer
*
renderer
,
SDL_Texture
*
texture
,
const
SDL_Rect
*
srcrect
,
const
SDL_Rect
*
dstrect
);
int
(
*
RenderReadPixels
)
(
SDL_Renderer
*
renderer
,
const
SDL_Rect
*
rect
,
...
...
@@ -136,6 +135,33 @@ struct SDL_RenderDriver
SDL_RendererInfo
info
;
};
/* Define the SDL window-shaper structure */
struct
SDL_WindowShaper
{
/* The window associated with the shaper */
SDL_Window
*
window
;
/* The user's specified SDL_WINDOW_SHOWN flag, for use once the user gives the window a shape. */
Uint32
usershownflag
;
/* The cutoff value for alpha-channel binarization. When alpha is greater-than-or-equal-to this value in the shape
image, the corresponding pixel of the actual window will be considered part of the window's shape. */
Uint8
alphacutoff
;
/* Has this window been assigned a shape? */
SDL_bool
hasshape
;
void
*
driverdata
;
};
/* Define the SDL shape driver structure */
struct
SDL_ShapeDriver
{
SDL_WindowShaper
*
(
*
CreateShaper
)(
SDL_Window
*
window
);
int
(
*
SetWindowShape
)(
SDL_WindowShaper
*
shaper
,
SDL_Surface
*
shape
,
SDL_WindowShapeMode
*
shapeMode
);
int
(
*
ResizeWindowShape
)(
SDL_Window
*
window
);
};
/* Define the SDL window structure, corresponding to toplevel windows */
struct
SDL_Window
{
...
...
@@ -150,6 +176,8 @@ struct SDL_Window
SDL_Renderer
*
renderer
;
SDL_DisplayMode
fullscreen_mode
;
SDL_WindowShaper
*
shaper
;
void
*
userdata
;
void
*
driverdata
;
...
...
@@ -270,6 +298,12 @@ struct SDL_VideoDevice
void
(
*
RestoreWindow
)
(
_THIS
,
SDL_Window
*
window
);
void
(
*
SetWindowGrab
)
(
_THIS
,
SDL_Window
*
window
);
void
(
*
DestroyWindow
)
(
_THIS
,
SDL_Window
*
window
);
/* * * */
/*
* Shaped-window functions
*/
SDL_ShapeDriver
shape_driver
;
/* Get some platform dependent window information */
SDL_bool
(
*
GetWindowWMInfo
)
(
_THIS
,
SDL_Window
*
window
,
...
...
src/video/SDL_video.c
View file @
ea29eee8
...
...
@@ -2534,38 +2534,6 @@ SDL_RenderFillRects(const SDL_Rect ** rects, int count)
return
renderer
->
RenderFillRects
(
renderer
,
rects
,
count
);
}
int
SDL_RenderDrawEllipse
(
const
SDL_Ellipse
ellipse
)
{
return
SDL_RenderDrawEllipses
(
&
ellipse
,
1
);
}
int
SDL_RenderDrawEllipses
(
const
SDL_Ellipse
*
ellipse
,
int
count
)
{
return
-
1
;
}
int
SDL_RenderFillEllipse
(
const
SDL_Ellipse
ellipse
)
{
return
SDL_RenderFillEllipses
(
&
ellipse
,
1
);
}
int
SDL_RenderFillEllipses
(
const
SDL_Ellipse
*
ellipse
,
int
count
)
{
return
-
1
;
}
int
SDL_RenderDrawPoly
(
const
SDL_Poly
poly
)
{
return
SDL_RenderDrawPolys
(
&
poly
,
1
);
}
int
SDL_RenderDrawPolys
(
const
SDL_Poly
*
poly
,
int
count
)
{
return
-
1
;
}
int
SDL_RenderFillPoly
(
const
SDL_Poly
poly
)
{
return
SDL_RenderFillPolys
(
&
poly
,
1
);
}
int
SDL_RenderFillPolys
(
const
SDL_Poly
*
poly
,
int
count
)
{
return
-
1
;
}
int
SDL_RenderCopy
(
SDL_Texture
*
texture
,
const
SDL_Rect
*
srcrect
,
const
SDL_Rect
*
dstrect
)
...
...
src/video/x11/SDL_x11shape.c
View file @
ea29eee8
...
...
@@ -20,6 +20,69 @@
eligottlieb@gmail.com
*/
#include "SDL_shape.h"
#include <X11/Xos.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xmu/Converters.h>
#include <X11/extensions/shape.h>
#include "SDL_x11shape.h"
#include "SDL_x11window.h"
#include "SDL_x11video.h"
/* Functions implementing shaped-window functionality for X Window System will be implemented when the API is decided. */
SDL_WindowShaper
*
X11_CreateShaper
(
SDL_Window
*
window
)
{
SDL_WindowShaper
*
result
=
malloc
(
sizeof
(
SDL_WindowShaper
));
result
->
window
=
window
;
result
->
alphacutoff
=
0
;
result
->
usershownflag
=
0
;
result
->
driverdata
=
malloc
(
sizeof
(
SDL_ShapeData
));
window
->
shaper
=
result
;
int
resized_properly
=
X11ResizeWindowShape
(
window
);
assert
(
resized_properly
==
0
);
return
result
;
}
int
X11_ResizeWindowShape
(
SDL_Window
*
window
)
{
SDL_ShapeData
*
data
=
window
->
shaper
->
driverdata
;
assert
(
data
!=
NULL
);
unsigned
int
bitmapsize
=
window
->
w
/
8
;
if
(
window
->
w
%
8
>
0
)
bitmapsize
+=
1
;
bitmapsize
*=
window
->
h
;
if
(
data
->
bitmapsize
!=
bitmapsize
||
data
->
bitmap
==
NULL
)
{
data
->
bitmapsize
=
bitmapsize
;
if
(
data
->
bitmap
!=
NULL
)
free
(
data
->
bitmap
);
data
->
bitmap
=
malloc
(
data
->
bitmapsize
);
if
(
data
->
bitmap
==
NULL
)
{
SDL_SetError
(
"Could not allocate memory for shaped-window bitmap."
);
return
-
1
;
}
}
window
->
shaper
->
usershownflag
=
window
->
flags
&
SDL_WINDOW_SHOWN
;
return
0
;
}
int
X11_SetWindowShape
(
SDL_WindowShaper
*
shaper
,
SDL_Surface
*
shape
,
SDL_WindowShapeMode
*
shapeMode
)
{
if
(
!
SDL_ISPIXELFORMAT_ALPHA
(
SDL_MasksToPixelFormatEnum
(
shape
->
format
->
BitsPerPixel
,
shape
->
format
->
Rmask
,
shape
->
format
->
Gmask
,
shape
->
format
->
Bmask
,
shape
->
format
->
Amask
)))
return
-
2
;
if
(
shape
->
w
!=
shaper
->
window
->
w
||
shape
->
h
!=
shaper
->
window
->
h
)
return
-
3
;
SDL_ShapeData
*
data
=
shaper
->
driverdata
;
assert
(
data
!=
NULL
);
/* Assume that shaper->alphacutoff already has a value. */
SDL_CalculateShapeBitmap
(
shaper
->
alphacutoff
,
shape
,
data
->
bitmap
);
SDL_WindowData
*
windowdata
=
(
SDL_WindowData
*
)(
shaper
->
window
->
driverdata
);
Pixmap
shapemask
=
XCreateBitmapFromData
(
windowdata
->
videodata
->
display
,
windowdata
->
xwindow
,
data
->
bitmap
,
shaper
->
window
->
w
,
shaper
->
window
->
h
);
XShapeCombineMask
(
windowdata
->
videodata
->
display
,
windowdata
->
xwindow
,
ShapeBounding
,
0
,
0
,
shapemask
,
ShapeSet
);
XSync
(
windowdata
->
videodata
->
display
,
False
);
XFreePixmap
(
windowdata
->
videodata
->
display
,
shapemask
);
return
0
;
}
src/video/x11/SDL_x11video.c
View file @
ea29eee8
...
...
@@ -28,6 +28,7 @@
#include "SDL_x11video.h"
#include "SDL_x11render.h"
#include "SDL_x11shape.h"
#if SDL_VIDEO_DRIVER_PANDORA
#include "SDL_x11opengles.h"
...
...
@@ -202,6 +203,9 @@ X11_CreateDevice(int devindex)
device
->
SetWindowGrab
=
X11_SetWindowGrab
;
device
->
DestroyWindow
=
X11_DestroyWindow
;
device
->
GetWindowWMInfo
=
X11_GetWindowWMInfo
;
device
->
shape_driver
.
CreateShaper
=
X11_CreateShaper
;
device
->
shape_driver
.
SetWindowShape
=
X11_SetWindowShape
;
device
->
shape_driver
.
ResizeWindowShape
=
X11_ResizeWindowShape
;
#ifdef SDL_VIDEO_OPENGL_GLX
device
->
GL_LoadLibrary
=
X11_GL_LoadLibrary
;
device
->
GL_GetProcAddress
=
X11_GL_GetProcAddress
;
...
...
src/video/x11/SDL_x11window.c
View file @
ea29eee8
...
...
@@ -28,6 +28,7 @@
#include "SDL_x11video.h"
#include "SDL_x11mouse.h"
#include "SDL_x11gamma.h"
#include "SDL_x11shape.h"
#include "../Xext/extensions/StdCmap.h"
#ifdef SDL_VIDEO_DRIVER_PANDORA
...
...
@@ -897,6 +898,8 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
SDL_WindowData
*
data
=
(
SDL_WindowData
*
)
window
->
driverdata
;
Display
*
display
=
data
->
videodata
->
display
;
if
(
SDL_IsShapedWindow
(
window
))
X11_ResizeWindowShape
(
window
);
XResizeWindow
(
display
,
data
->
xwindow
,
window
->
w
,
window
->
h
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment