Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-fonts
Project
Project
Details
Activity
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
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Aleksandr Isakov
wine-fonts
Commits
e04fe7da
Commit
e04fe7da
authored
Feb 13, 2004
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved hGCClipRgn handling to the graphics driver.
parent
41b89ddd
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
74 additions
and
66 deletions
+74
-66
gdi_private.h
dlls/gdi/gdi_private.h
+1
-1
clipping.c
dlls/wineps/clipping.c
+1
-1
bitblt.c
dlls/x11drv/bitblt.c
+1
-2
clipping.c
dlls/x11drv/clipping.c
+4
-2
graphics.c
dlls/x11drv/graphics.c
+6
-7
init.c
dlls/x11drv/init.c
+4
-9
text.c
dlls/x11drv/text.c
+13
-3
x11drv.h
dlls/x11drv/x11drv.h
+2
-0
xrender.c
dlls/x11drv/xrender.c
+13
-4
gdi.h
include/gdi.h
+0
-1
clipping.c
objects/clipping.c
+28
-32
dc.c
objects/dc.c
+1
-4
No files found.
dlls/gdi/gdi_private.h
View file @
e04fe7da
...
...
@@ -140,7 +140,7 @@ typedef struct tagDC_FUNCS
INT
(
*
pSetDIBits
)(
PHYSDEV
,
HBITMAP
,
UINT
,
UINT
,
LPCVOID
,
const
BITMAPINFO
*
,
UINT
);
INT
(
*
pSetDIBitsToDevice
)(
PHYSDEV
,
INT
,
INT
,
DWORD
,
DWORD
,
INT
,
INT
,
UINT
,
UINT
,
LPCVOID
,
const
BITMAPINFO
*
,
UINT
);
VOID
(
*
pSetDeviceClipping
)(
PHYSDEV
,
HRGN
);
VOID
(
*
pSetDeviceClipping
)(
PHYSDEV
,
HRGN
,
HRGN
);
BOOL
(
*
pSetDeviceGammaRamp
)(
PHYSDEV
,
LPVOID
);
INT
(
*
pSetMapMode
)(
PHYSDEV
,
INT
);
DWORD
(
*
pSetMapperFlags
)(
PHYSDEV
,
DWORD
);
...
...
dlls/wineps/clipping.c
View file @
e04fe7da
...
...
@@ -27,7 +27,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
/***********************************************************************
* PSDRV_SetDeviceClipping
*/
VOID
PSDRV_SetDeviceClipping
(
PSDRV_PDEVICE
*
physDev
,
HRGN
ignored
)
void
PSDRV_SetDeviceClipping
(
PSDRV_PDEVICE
*
physDev
,
HRGN
vis_rgn
,
HRGN
clip_rgn
)
{
/* We could set a dirty flag here to speed up PSDRV_SetClip */
return
;
...
...
dlls/x11drv/bitblt.c
View file @
e04fe7da
...
...
@@ -31,7 +31,6 @@
#include "wingdi.h"
#include "winreg.h"
#include "winuser.h"
#include "gdi.h"
#include "x11drv.h"
#include "wine/debug.h"
...
...
@@ -1142,7 +1141,7 @@ static BOOL BITBLT_GetVisRectangles( X11DRV_PDEVICE *physDevDst, INT xDst, INT y
rect
.
bottom
=
yDst
+
heightDst
;
if
(
widthDst
<
0
)
SWAP_INT32
(
&
rect
.
left
,
&
rect
.
right
);
if
(
heightDst
<
0
)
SWAP_INT32
(
&
rect
.
top
,
&
rect
.
bottom
);
GetRgnBox
(
physDevDst
->
dc
->
hGCClipRg
n
,
&
clipRect
);
GetRgnBox
(
physDevDst
->
regio
n
,
&
clipRect
);
if
(
!
IntersectRect
(
visRectDst
,
&
rect
,
&
clipRect
))
return
FALSE
;
/* Get the source visible rectangle */
...
...
dlls/x11drv/clipping.c
View file @
e04fe7da
...
...
@@ -109,11 +109,13 @@ RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp )
/***********************************************************************
* X11DRV_SetDeviceClipping
*/
void
X11DRV_SetDeviceClipping
(
X11DRV_PDEVICE
*
physDev
,
HRGN
h
rgn
)
void
X11DRV_SetDeviceClipping
(
X11DRV_PDEVICE
*
physDev
,
HRGN
vis_rgn
,
HRGN
clip_
rgn
)
{
RGNDATA
*
data
;
if
(
!
(
data
=
X11DRV_GetRegionData
(
hrgn
,
0
)))
return
;
CombineRgn
(
physDev
->
region
,
vis_rgn
,
clip_rgn
,
clip_rgn
?
RGN_AND
:
RGN_COPY
);
if
(
!
(
data
=
X11DRV_GetRegionData
(
physDev
->
region
,
0
)))
return
;
wine_tsx11_lock
();
XSetClipRectangles
(
gdi_display
,
physDev
->
gc
,
physDev
->
org
.
x
,
physDev
->
org
.
y
,
(
XRectangle
*
)
data
->
Buffer
,
data
->
rdh
.
nCount
,
YXBanded
);
...
...
dlls/x11drv/graphics.c
View file @
e04fe7da
...
...
@@ -1284,12 +1284,15 @@ X11DRV_ExtFloodFill( X11DRV_PDEVICE *physDev, INT x, INT y, COLORREF color,
{
XImage
*
image
;
RECT
rect
;
POINT
pt
;
TRACE
(
"X11DRV_ExtFloodFill %d,%d %06lx %d
\n
"
,
x
,
y
,
color
,
fillType
);
if
(
!
PtVisible
(
physDev
->
hdc
,
x
,
y
))
return
FALSE
;
if
(
GetClipBox
(
physDev
->
hdc
,
&
rect
)
==
ERROR
)
return
FALSE
;
LPtoDP
(
physDev
->
hdc
,
(
LPPOINT
)
&
rect
,
2
);
pt
.
x
=
x
;
pt
.
y
=
y
;
LPtoDP
(
physDev
->
hdc
,
&
pt
,
1
);
if
(
!
PtInRegion
(
physDev
->
region
,
pt
.
x
,
pt
.
y
))
return
FALSE
;
GetRgnBox
(
physDev
->
region
,
&
rect
);
wine_tsx11_lock
();
image
=
XGetImage
(
gdi_display
,
physDev
->
drawable
,
...
...
@@ -1301,10 +1304,6 @@ X11DRV_ExtFloodFill( X11DRV_PDEVICE *physDev, INT x, INT y, COLORREF color,
if
(
X11DRV_SetupGCForBrush
(
physDev
))
{
POINT
pt
;
pt
.
x
=
x
;
pt
.
y
=
y
;
LPtoDP
(
physDev
->
hdc
,
&
pt
,
1
);
/* Update the pixmap from the DIB section */
X11DRV_LockDIBSection
(
physDev
,
DIB_Status_GdiMod
,
FALSE
);
...
...
dlls/x11drv/init.c
View file @
e04fe7da
...
...
@@ -95,10 +95,8 @@ BOOL X11DRV_CreateDC( DC *dc, X11DRV_PDEVICE **pdev, LPCWSTR driver, LPCWSTR dev
if
(
!
X11DRV_DC_Funcs
)
X11DRV_DC_Funcs
=
dc
->
funcs
;
/* hack */
physDev
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
*
physDev
)
);
if
(
!
physDev
)
{
ERR
(
"Can't allocate physDev
\n
"
);
return
FALSE
;
}
if
(
!
physDev
)
return
FALSE
;
*
pdev
=
physDev
;
physDev
->
hdc
=
dc
->
hSelf
;
physDev
->
dc
=
dc
;
/* FIXME */
...
...
@@ -113,11 +111,7 @@ BOOL X11DRV_CreateDC( DC *dc, X11DRV_PDEVICE **pdev, LPCWSTR driver, LPCWSTR dev
physDev
->
drawable
=
root_window
;
physDev
->
depth
=
screen_depth
;
}
physDev
->
org
.
x
=
physDev
->
org
.
y
=
0
;
physDev
->
drawable_org
.
x
=
physDev
->
drawable_org
.
y
=
0
;
physDev
->
current_pf
=
0
;
physDev
->
used_visuals
=
0
;
physDev
->
region
=
CreateRectRgn
(
0
,
0
,
0
,
0
);
wine_tsx11_lock
();
physDev
->
gc
=
XCreateGC
(
gdi_display
,
physDev
->
drawable
,
0
,
NULL
);
...
...
@@ -136,6 +130,7 @@ BOOL X11DRV_DeleteDC( X11DRV_PDEVICE *physDev )
{
if
(
physDev
->
xrender
)
X11DRV_XRender_DeleteDC
(
physDev
);
DeleteObject
(
physDev
->
region
);
wine_tsx11_lock
();
XFreeGC
(
gdi_display
,
physDev
->
gc
);
while
(
physDev
->
used_visuals
--
>
0
)
...
...
dlls/x11drv/text.c
View file @
e04fe7da
...
...
@@ -56,6 +56,7 @@ X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
XChar2b
*
str2b
=
NULL
;
BOOL
dibUpdateFlag
=
FALSE
;
BOOL
result
=
TRUE
;
HRGN
saved_region
=
0
;
POINT
pt
;
DC
*
dc
=
physDev
->
dc
;
UINT
align
=
GetTextAlign
(
physDev
->
hdc
);
...
...
@@ -218,8 +219,12 @@ X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
if
(
flags
&
ETO_CLIPPED
)
{
SaveVisRgn16
(
HDC_16
(
physDev
->
hdc
)
);
IntersectVisRect16
(
HDC_16
(
physDev
->
hdc
),
lprect
->
left
,
lprect
->
top
,
lprect
->
right
,
lprect
->
bottom
);
HRGN
clip_region
=
CreateRectRgn
(
lprect
->
left
,
lprect
->
top
,
lprect
->
right
,
lprect
->
bottom
);
/* make a copy of the current device region */
saved_region
=
CreateRectRgn
(
0
,
0
,
0
,
0
);
CombineRgn
(
saved_region
,
physDev
->
region
,
0
,
RGN_COPY
);
X11DRV_SetDeviceClipping
(
physDev
,
saved_region
,
clip_region
);
DeleteObject
(
clip_region
);
}
/* Draw the text background if necessary */
...
...
@@ -411,7 +416,12 @@ X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
}
wine_tsx11_unlock
();
if
(
flags
&
ETO_CLIPPED
)
RestoreVisRgn16
(
HDC_16
(
physDev
->
hdc
)
);
if
(
flags
&
ETO_CLIPPED
)
{
/* restore the device region */
X11DRV_SetDeviceClipping
(
physDev
,
saved_region
,
0
);
DeleteObject
(
saved_region
);
}
goto
END
;
FAIL:
...
...
dlls/x11drv/x11drv.h
View file @
e04fe7da
...
...
@@ -91,6 +91,7 @@ typedef struct
Drawable
drawable
;
POINT
org
;
/* DC origin relative to drawable */
POINT
drawable_org
;
/* Origin of drawable relative to screen */
HRGN
region
;
/* Device region (visible region & clip region) */
X_PHYSFONT
font
;
X_PHYSPEN
pen
;
X_PHYSBRUSH
brush
;
...
...
@@ -170,6 +171,7 @@ extern BOOL X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y,
UINT
flags
,
const
RECT
*
lprect
,
LPCWSTR
str
,
UINT
count
,
const
INT
*
lpDx
);
extern
LONG
X11DRV_SetBitmapBits
(
HBITMAP
hbitmap
,
const
void
*
bits
,
LONG
count
);
extern
void
X11DRV_SetDeviceClipping
(
X11DRV_PDEVICE
*
physDev
,
HRGN
vis_rgn
,
HRGN
clip_rgn
);
extern
INT
X11DRV_SetDIBitsToDevice
(
X11DRV_PDEVICE
*
physDev
,
INT
xDest
,
INT
yDest
,
DWORD
cx
,
DWORD
cy
,
INT
xSrc
,
INT
ySrc
,
...
...
dlls/x11drv/xrender.c
View file @
e04fe7da
...
...
@@ -952,6 +952,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
int
textPixel
,
backgroundPixel
;
INT
*
deltas
=
NULL
;
INT
char_extra
;
HRGN
saved_region
=
0
;
UINT
align
=
GetTextAlign
(
hdc
);
COLORREF
textColor
=
GetTextColor
(
hdc
);
...
...
@@ -1127,8 +1128,12 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
if
(
flags
&
ETO_CLIPPED
)
{
SaveVisRgn16
(
HDC_16
(
hdc
)
);
IntersectVisRect16
(
HDC_16
(
hdc
),
lprect
->
left
,
lprect
->
top
,
lprect
->
right
,
lprect
->
bottom
);
HRGN
clip_region
=
CreateRectRgn
(
lprect
->
left
,
lprect
->
top
,
lprect
->
right
,
lprect
->
bottom
);
/* make a copy of the current device region */
saved_region
=
CreateRectRgn
(
0
,
0
,
0
,
0
);
CombineRgn
(
saved_region
,
physDev
->
region
,
0
,
RGN_COPY
);
X11DRV_SetDeviceClipping
(
physDev
,
saved_region
,
clip_region
);
DeleteObject
(
clip_region
);
}
if
(
X11DRV_XRender_Installed
)
{
...
...
@@ -1151,7 +1156,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
physDev
->
xrender
->
pict
,
hdc
,
physDev
->
drawable
);
}
if
((
data
=
X11DRV_GetRegionData
(
physDev
->
dc
->
hGCClipRg
n
,
0
)))
if
((
data
=
X11DRV_GetRegionData
(
physDev
->
regio
n
,
0
)))
{
wine_tsx11_lock
();
pXRenderSetPictureClipRectangles
(
gdi_display
,
physDev
->
xrender
->
pict
,
...
...
@@ -1465,7 +1470,11 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
HeapFree
(
GetProcessHeap
(),
0
,
deltas
);
if
(
flags
&
ETO_CLIPPED
)
RestoreVisRgn16
(
HDC_16
(
hdc
)
);
{
/* restore the device region */
X11DRV_SetDeviceClipping
(
physDev
,
saved_region
,
0
);
DeleteObject
(
saved_region
);
}
retv
=
TRUE
;
...
...
include/gdi.h
View file @
e04fe7da
...
...
@@ -115,7 +115,6 @@ typedef struct tagDC
int
flags
;
HRGN
hClipRgn
;
/* Clip region (may be 0) */
HRGN
hVisRgn
;
/* Visible region (must never be 0) */
HRGN
hGCClipRgn
;
/* GC clip region (ClipRgn AND VisRgn) */
HPEN
hPen
;
HBRUSH
hBrush
;
HFONT
hFont
;
...
...
objects/clipping.c
View file @
e04fe7da
...
...
@@ -39,8 +39,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(clipping);
*/
void
CLIPPING_UpdateGCRegion
(
DC
*
dc
)
{
if
(
!
dc
->
hGCClipRgn
)
dc
->
hGCClipRgn
=
CreateRectRgn
(
0
,
0
,
0
,
0
);
if
(
!
dc
->
hVisRgn
)
{
ERR
(
"hVisRgn is zero. Please report this.
\n
"
);
...
...
@@ -49,12 +47,8 @@ void CLIPPING_UpdateGCRegion( DC * dc )
if
(
dc
->
flags
&
DC_DIRTY
)
ERR
(
"DC is dirty. Please report this.
\n
"
);
if
(
!
dc
->
hClipRgn
)
CombineRgn
(
dc
->
hGCClipRgn
,
dc
->
hVisRgn
,
0
,
RGN_COPY
);
else
CombineRgn
(
dc
->
hGCClipRgn
,
dc
->
hClipRgn
,
dc
->
hVisRgn
,
RGN_AND
);
if
(
dc
->
funcs
->
pSetDeviceClipping
)
dc
->
funcs
->
pSetDeviceClipping
(
dc
->
physDev
,
dc
->
h
GC
ClipRgn
);
dc
->
funcs
->
pSetDeviceClipping
(
dc
->
physDev
,
dc
->
h
VisRgn
,
dc
->
h
ClipRgn
);
}
...
...
@@ -345,20 +339,18 @@ INT16 WINAPI IntersectVisRect16( HDC16 hdc16, INT16 left, INT16 top, INT16 right
*/
BOOL
WINAPI
PtVisible
(
HDC
hdc
,
INT
x
,
INT
y
)
{
BOOL
ret
=
FALSE
;
POINT
pt
;
BOOL
ret
;
DC
*
dc
=
DC_GetDCUpdate
(
hdc
);
TRACE
(
"%p %d,%d
\n
"
,
hdc
,
x
,
y
);
if
(
!
dc
)
return
FALSE
;
if
(
dc
->
hGCClipRgn
)
{
POINT
pt
;
pt
.
x
=
x
;
pt
.
y
=
y
;
LPtoDP
(
hdc
,
&
pt
,
1
);
ret
=
PtInRegion
(
dc
->
hGCClip
Rgn
,
pt
.
x
,
pt
.
y
);
}
pt
.
x
=
x
;
pt
.
y
=
y
;
LPtoDP
(
hdc
,
&
pt
,
1
);
ret
=
PtInRegion
(
dc
->
hVis
Rgn
,
pt
.
x
,
pt
.
y
);
if
(
ret
&&
dc
->
hClipRgn
)
ret
=
PtInRegion
(
dc
->
hClipRgn
,
pt
.
x
,
pt
.
y
);
GDI_ReleaseObj
(
hdc
);
return
ret
;
}
...
...
@@ -369,26 +361,23 @@ BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
*/
BOOL
WINAPI
RectVisible
(
HDC
hdc
,
const
RECT
*
rect
)
{
BOOL
ret
=
FALSE
;
RECT
tmpRect
;
BOOL
ret
;
DC
*
dc
=
DC_GetDCUpdate
(
hdc
);
if
(
!
dc
)
return
FALSE
;
TRACE
(
"%p %ld,%ldx%ld,%ld
\n
"
,
hdc
,
rect
->
left
,
rect
->
top
,
rect
->
right
,
rect
->
bottom
);
if
(
dc
->
hGCClipRgn
)
{
POINT
pt
[
2
];
RECT
tmpRect
;
pt
[
0
].
x
=
rect
->
left
;
pt
[
0
].
y
=
rect
->
top
;
pt
[
1
].
x
=
rect
->
right
;
pt
[
1
].
y
=
rect
->
bottom
;
LPtoDP
(
hdc
,
pt
,
2
);
tmpRect
.
left
=
pt
[
0
].
x
;
tmpRect
.
top
=
pt
[
0
].
y
;
tmpRect
.
right
=
pt
[
1
].
x
;
tmpRect
.
bottom
=
pt
[
1
].
y
;
ret
=
RectInRegion
(
dc
->
hGCClipRgn
,
&
tmpRect
);
tmpRect
=
*
rect
;
LPtoDP
(
hdc
,
(
POINT
*
)
&
tmpRect
,
2
);
if
(
dc
->
hClipRgn
)
{
HRGN
hrgn
=
CreateRectRgn
(
0
,
0
,
0
,
0
);
CombineRgn
(
hrgn
,
dc
->
hVisRgn
,
dc
->
hClipRgn
,
RGN_AND
);
ret
=
RectInRegion
(
hrgn
,
&
tmpRect
);
DeleteObject
(
hrgn
);
}
else
ret
=
RectInRegion
(
dc
->
hVisRgn
,
&
tmpRect
);
GDI_ReleaseObj
(
hdc
);
return
ret
;
}
...
...
@@ -402,7 +391,14 @@ INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
INT
ret
;
DC
*
dc
=
DC_GetDCUpdate
(
hdc
);
if
(
!
dc
)
return
ERROR
;
ret
=
GetRgnBox
(
dc
->
hGCClipRgn
,
rect
);
if
(
dc
->
hClipRgn
)
{
HRGN
hrgn
=
CreateRectRgn
(
0
,
0
,
0
,
0
);
CombineRgn
(
hrgn
,
dc
->
hVisRgn
,
dc
->
hClipRgn
,
RGN_AND
);
ret
=
GetRgnBox
(
hrgn
,
rect
);
DeleteObject
(
hrgn
);
}
else
ret
=
GetRgnBox
(
dc
->
hVisRgn
,
rect
);
DPtoLP
(
hdc
,
(
LPPOINT
)
rect
,
2
);
GDI_ReleaseObj
(
hdc
);
return
ret
;
...
...
objects/dc.c
View file @
e04fe7da
...
...
@@ -78,7 +78,6 @@ DC *DC_AllocDC( const DC_FUNCTIONS *funcs, WORD magic )
dc
->
flags
=
0
;
dc
->
hClipRgn
=
0
;
dc
->
hVisRgn
=
0
;
dc
->
hGCClipRgn
=
0
;
dc
->
hPen
=
GetStockObject
(
BLACK_PEN
);
dc
->
hBrush
=
GetStockObject
(
WHITE_BRUSH
);
dc
->
hFont
=
GetStockObject
(
SYSTEM_FONT
);
...
...
@@ -335,7 +334,7 @@ HDC WINAPI GetDCState( HDC hdc )
/* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
newdc
->
h
GCClipRgn
=
newdc
->
h
VisRgn
=
0
;
newdc
->
hVisRgn
=
0
;
if
(
dc
->
hClipRgn
)
{
newdc
->
hClipRgn
=
CreateRectRgn
(
0
,
0
,
0
,
0
);
...
...
@@ -764,7 +763,6 @@ BOOL WINAPI DeleteDC( HDC hdc )
dc
->
saveLevel
--
;
if
(
dcs
->
hClipRgn
)
DeleteObject
(
dcs
->
hClipRgn
);
if
(
dcs
->
hVisRgn
)
DeleteObject
(
dcs
->
hVisRgn
);
if
(
dcs
->
hGCClipRgn
)
DeleteObject
(
dcs
->
hGCClipRgn
);
PATH_DestroyGdiPath
(
&
dcs
->
path
);
GDI_FreeObject
(
hdcs
,
dcs
);
}
...
...
@@ -782,7 +780,6 @@ BOOL WINAPI DeleteDC( HDC hdc )
if
(
dc
->
hClipRgn
)
DeleteObject
(
dc
->
hClipRgn
);
if
(
dc
->
hVisRgn
)
DeleteObject
(
dc
->
hVisRgn
);
if
(
dc
->
hGCClipRgn
)
DeleteObject
(
dc
->
hGCClipRgn
);
PATH_DestroyGdiPath
(
&
dc
->
path
);
GDI_FreeObject
(
hdc
,
dc
);
...
...
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