Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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
wine
wine-winehq
Commits
745e7c93
Commit
745e7c93
authored
Jul 30, 2013
by
Aric Stewart
Committed by
Alexandre Julliard
Aug 01, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wineps.drv: Allow for vertical text printing.
With extensive review and help from Huw Davies.
parent
75fc8845
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
206 additions
and
47 deletions
+206
-47
builtin.c
dlls/wineps.drv/builtin.c
+1
-1
download.c
dlls/wineps.drv/download.c
+15
-8
font.c
dlls/wineps.drv/font.c
+9
-5
ps.c
dlls/wineps.drv/ps.c
+1
-1
psdrv.h
dlls/wineps.drv/psdrv.h
+6
-4
text.c
dlls/wineps.drv/text.c
+174
-28
No files found.
dlls/wineps.drv/builtin.c
View file @
745e7c93
...
...
@@ -238,7 +238,7 @@ BOOL PSDRV_WriteSetBuiltinFont(PHYSDEV dev)
PSDRV_PDEVICE
*
physDev
=
get_psdrv_dev
(
dev
);
return
PSDRV_WriteSetFont
(
dev
,
physDev
->
font
.
fontinfo
.
Builtin
.
afm
->
FontName
,
physDev
->
font
.
size
,
physDev
->
font
.
escapement
,
FALSE
);
physDev
->
font
.
size
,
physDev
->
font
.
escapement
,
FALSE
,
FALSE
);
}
BOOL
PSDRV_WriteBuiltinGlyphShow
(
PHYSDEV
dev
,
LPCWSTR
str
,
INT
count
)
...
...
dlls/wineps.drv/download.c
View file @
745e7c93
...
...
@@ -47,9 +47,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
/****************************************************************************
* get_download_name
*/
static
void
get_download_name
(
PHYSDEV
dev
,
LPOUTLINETEXTMETRICA
potm
,
char
**
str
)
static
void
get_download_name
(
PHYSDEV
dev
,
LPOUTLINETEXTMETRICA
potm
,
char
**
str
,
BOOL
vertical
)
{
static
const
char
reserved_chars
[]
=
" %/(){}[]<>
\n\r\t\b\f
"
;
static
const
char
vertical_suffix
[]
=
"_vert"
;
int
len
;
char
*
p
;
DWORD
size
;
...
...
@@ -89,7 +90,7 @@ static void get_download_name(PHYSDEV dev, LPOUTLINETEXTMETRICA potm, char **str
name_record
->
language_id
==
0
&&
name_record
->
name_id
==
6
)
{
TRACE
(
"Got Mac PS name %s
\n
"
,
debugstr_an
((
char
*
)
strings
+
name_record
->
offset
,
name_record
->
length
));
*
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
name_record
->
length
+
1
);
*
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
name_record
->
length
+
sizeof
(
vertical_suffix
)
);
memcpy
(
*
str
,
strings
+
name_record
->
offset
,
name_record
->
length
);
*
(
*
str
+
name_record
->
length
)
=
'\0'
;
HeapFree
(
GetProcessHeap
(),
0
,
name
);
...
...
@@ -107,7 +108,7 @@ static void get_download_name(PHYSDEV dev, LPOUTLINETEXTMETRICA potm, char **str
unicode
[
c
]
=
0
;
TRACE
(
"Got Windows PS name %s
\n
"
,
debugstr_w
(
unicode
));
len
=
WideCharToMultiByte
(
1252
,
0
,
unicode
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
*
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
*
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
sizeof
(
vertical_suffix
)
-
1
);
WideCharToMultiByte
(
1252
,
0
,
unicode
,
-
1
,
*
str
,
len
,
NULL
,
NULL
);
HeapFree
(
GetProcessHeap
(),
0
,
unicode
);
HeapFree
(
GetProcessHeap
(),
0
,
name
);
...
...
@@ -120,11 +121,13 @@ static void get_download_name(PHYSDEV dev, LPOUTLINETEXTMETRICA potm, char **str
}
len
=
strlen
((
char
*
)
potm
+
(
ptrdiff_t
)
potm
->
otmpFaceName
)
+
1
;
*
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
*
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
sizeof
(
vertical_suffix
)
-
1
);
strcpy
(
*
str
,
(
char
*
)
potm
+
(
ptrdiff_t
)
potm
->
otmpFaceName
);
done:
for
(
p
=
*
str
;
*
p
;
p
++
)
if
(
strchr
(
reserved_chars
,
*
p
))
*
p
=
'_'
;
if
(
vertical
)
strcat
(
*
str
,
vertical_suffix
);
}
/****************************************************************************
...
...
@@ -261,7 +264,7 @@ static BOOL is_fake_italic( HDC hdc )
* Write setfont for download font.
*
*/
BOOL
PSDRV_WriteSetDownloadFont
(
PHYSDEV
dev
)
BOOL
PSDRV_WriteSetDownloadFont
(
PHYSDEV
dev
,
BOOL
vertical
)
{
PSDRV_PDEVICE
*
physDev
=
get_psdrv_dev
(
dev
);
char
*
ps_name
;
...
...
@@ -271,6 +274,7 @@ BOOL PSDRV_WriteSetDownloadFont(PHYSDEV dev)
LOGFONTW
lf
;
UINT
ppem
;
XFORM
xform
;
INT
escapement
;
assert
(
physDev
->
font
.
fontloc
==
Download
);
...
...
@@ -283,7 +287,7 @@ BOOL PSDRV_WriteSetDownloadFont(PHYSDEV dev)
GetOutlineTextMetricsA
(
dev
->
hdc
,
len
,
potm
);
get_download_name
(
dev
,
potm
,
&
ps_name
);
get_download_name
(
dev
,
potm
,
&
ps_name
,
vertical
);
physDev
->
font
.
fontinfo
.
Download
=
is_font_downloaded
(
physDev
,
ps_name
);
ppem
=
calc_ppem_for_height
(
dev
->
hdc
,
lf
.
lfHeight
);
...
...
@@ -344,9 +348,12 @@ BOOL PSDRV_WriteSetDownloadFont(PHYSDEV dev)
}
}
escapement
=
physDev
->
font
.
escapement
;
if
(
vertical
)
escapement
+=
900
;
PSDRV_WriteSetFont
(
dev
,
ps_name
,
physDev
->
font
.
size
,
physDev
->
font
.
escapement
,
is_fake_italic
(
dev
->
hdc
));
PSDRV_WriteSetFont
(
dev
,
ps_name
,
physDev
->
font
.
size
,
escapement
,
is_fake_italic
(
dev
->
hdc
),
(
lf
.
lfFaceName
[
0
]
==
'@'
));
HeapFree
(
GetProcessHeap
(),
0
,
ps_name
);
HeapFree
(
GetProcessHeap
(),
0
,
potm
);
...
...
dlls/wineps.drv/font.c
View file @
745e7c93
...
...
@@ -114,7 +114,7 @@ HFONT PSDRV_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags )
}
physDev
->
font
.
escapement
=
lf
.
lfEscapement
;
physDev
->
font
.
set
=
FALSE
;
physDev
->
font
.
set
=
UNSET
;
if
(
!
subst
&&
((
ret
=
next
->
funcs
->
pSelectFont
(
next
,
hfont
,
aa_flags
))))
{
...
...
@@ -130,25 +130,29 @@ HFONT PSDRV_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags )
/***********************************************************************
* PSDRV_SetFont
*/
BOOL
PSDRV_SetFont
(
PHYSDEV
dev
)
BOOL
PSDRV_SetFont
(
PHYSDEV
dev
,
BOOL
vertical
)
{
PSDRV_PDEVICE
*
physDev
=
get_psdrv_dev
(
dev
);
PSDRV_WriteSetColor
(
dev
,
&
physDev
->
font
.
color
);
if
(
physDev
->
font
.
set
)
return
TRUE
;
if
(
vertical
&&
(
physDev
->
font
.
set
==
VERTICAL_SET
))
return
TRUE
;
if
(
!
vertical
&&
(
physDev
->
font
.
set
==
HORIZONTAL_SET
))
return
TRUE
;
switch
(
physDev
->
font
.
fontloc
)
{
case
Builtin
:
PSDRV_WriteSetBuiltinFont
(
dev
);
break
;
case
Download
:
PSDRV_WriteSetDownloadFont
(
dev
);
PSDRV_WriteSetDownloadFont
(
dev
,
vertical
);
break
;
default:
ERR
(
"fontloc = %d
\n
"
,
physDev
->
font
.
fontloc
);
assert
(
1
);
break
;
}
physDev
->
font
.
set
=
TRUE
;
if
(
vertical
)
physDev
->
font
.
set
=
VERTICAL_SET
;
else
physDev
->
font
.
set
=
HORIZONTAL_SET
;
return
TRUE
;
}
dlls/wineps.drv/ps.c
View file @
745e7c93
...
...
@@ -571,7 +571,7 @@ BOOL PSDRV_WriteCurveTo(PHYSDEV dev, POINT pts[3])
return
PSDRV_WriteSpool
(
dev
,
buf
,
strlen
(
buf
));
}
BOOL
PSDRV_WriteSetFont
(
PHYSDEV
dev
,
const
char
*
name
,
matrix
size
,
INT
escapement
,
BOOL
fake_italic
)
BOOL
PSDRV_WriteSetFont
(
PHYSDEV
dev
,
const
char
*
name
,
matrix
size
,
INT
escapement
,
BOOL
fake_italic
,
BOOL
vertical
)
{
char
*
buf
;
...
...
dlls/wineps.drv/psdrv.h
View file @
745e7c93
...
...
@@ -302,6 +302,8 @@ typedef struct
INT
xx
,
xy
,
yx
,
yy
;
}
matrix
;
enum
fontset
{
UNSET
=
0
,
HORIZONTAL_SET
,
VERTICAL_SET
};
typedef
struct
{
enum
fontloc
fontloc
;
union
{
...
...
@@ -311,7 +313,7 @@ typedef struct {
matrix
size
;
PSCOLOR
color
;
BOOL
set
;
/* Have we done a setfont yet */
enum
fontset
set
;
/* Have we done a setfont yet */
/* These are needed by PSDRV_ExtTextOut */
int
escapement
;
...
...
@@ -475,7 +477,7 @@ extern void PSDRV_FreeAFMList( FONTFAMILY *head ) DECLSPEC_HIDDEN;
extern
INT
PSDRV_XWStoDS
(
PHYSDEV
dev
,
INT
width
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_Brush
(
PHYSDEV
dev
,
BOOL
EO
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_SetFont
(
PHYSDEV
dev
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_SetFont
(
PHYSDEV
dev
,
BOOL
vertical
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_SetPen
(
PHYSDEV
dev
)
DECLSPEC_HIDDEN
;
extern
void
PSDRV_AddClip
(
PHYSDEV
dev
,
HRGN
hrgn
)
DECLSPEC_HIDDEN
;
...
...
@@ -498,7 +500,7 @@ extern BOOL PSDRV_WriteStroke(PHYSDEV dev) DECLSPEC_HIDDEN;
extern
BOOL
PSDRV_WriteRectangle
(
PHYSDEV
dev
,
INT
x
,
INT
y
,
INT
width
,
INT
height
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_WriteRRectangle
(
PHYSDEV
dev
,
INT
x
,
INT
y
,
INT
width
,
INT
height
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_WriteSetFont
(
PHYSDEV
dev
,
const
char
*
name
,
matrix
size
,
INT
escapement
,
BOOL
fake_italic
)
DECLSPEC_HIDDEN
;
BOOL
fake_italic
,
BOOL
vertical
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_WriteGlyphShow
(
PHYSDEV
dev
,
LPCSTR
g_name
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_WriteSetPen
(
PHYSDEV
dev
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_WriteArc
(
PHYSDEV
dev
,
INT
x
,
INT
y
,
INT
w
,
INT
h
,
...
...
@@ -546,7 +548,7 @@ extern BOOL PSDRV_WriteSetBuiltinFont(PHYSDEV dev) DECLSPEC_HIDDEN;
extern
BOOL
PSDRV_WriteBuiltinGlyphShow
(
PHYSDEV
dev
,
LPCWSTR
str
,
INT
count
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_SelectDownloadFont
(
PHYSDEV
dev
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_WriteSetDownloadFont
(
PHYSDEV
dev
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_WriteSetDownloadFont
(
PHYSDEV
dev
,
BOOL
vertical
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_WriteDownloadGlyphShow
(
PHYSDEV
dev
,
const
WORD
*
glpyhs
,
UINT
count
)
DECLSPEC_HIDDEN
;
extern
BOOL
PSDRV_EmptyDownloadList
(
PHYSDEV
dev
,
BOOL
write_undef
)
DECLSPEC_HIDDEN
;
...
...
dlls/wineps.drv/text.c
View file @
745e7c93
...
...
@@ -29,10 +29,135 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
psdrv
);
typedef
struct
tagRun
{
INT
start
;
BOOL
vertical
;
INT
x
;
INT
y
;
}
Run
;
static
BOOL
PSDRV_Text
(
PHYSDEV
dev
,
INT
x
,
INT
y
,
UINT
flags
,
LPCWSTR
str
,
UINT
count
,
BOOL
bDrawBackground
,
const
INT
*
lpDx
);
static
const
struct
{
WCHAR
lower
;
WCHAR
upper
;}
unrotate_ranges
[]
=
{
{
0x0000
,
0x10FF
},
/* Hangul Jamo */
{
0x1200
,
0x17FF
},
/* Mongolian */
{
0x18B0
,
0x1FFF
},
/* General Punctuation */
{
0x2070
,
0x209F
},
/* Currency Symbols */
/* Combining Diacritical Marks for Symbols */
/* Letterlike Symbols */
{
0x2150
,
0x245F
},
/* Enclosed Alphanumerics */
{
0x2500
,
0x259F
},
/* Geometric Shapes */
/* Miscellaneous Symbols */
/* Dingbats */
/* Miscellaneous Mathematical Symbols-A */
/* Supplemental Arrows-A */
{
0x2800
,
0x2E7F
},
/* East Asian scripts and symbols */
{
0xA000
,
0xABFF
},
/* Hangul Syllables */
/* Hangul Jamo Extended-B */
{
0xD800
,
0xF8FF
},
/* CJK Compatibility Ideographs */
{
0xFB00
,
0xFE0F
},
/* Vertical Forms */
/* Combining Half Marks */
/* CJK Compatibility Forms */
{
0xFE50
,
0xFEFF
},
/* Halfwidth and Fullwidth Forms */
{
0xFFEF
,
0xFFFF
},
};
static
BOOL
check_unicode_tategaki
(
WCHAR
uchar
)
{
int
i
;
for
(
i
=
0
;;
i
++
)
{
if
(
uchar
<
unrotate_ranges
[
i
].
lower
)
return
TRUE
;
if
(
uchar
>=
unrotate_ranges
[
i
].
lower
&&
uchar
<=
unrotate_ranges
[
i
].
upper
)
return
FALSE
;
}
}
static
Run
*
build_vertical_runs
(
PHYSDEV
dev
,
UINT
flags
,
LPCWSTR
str
,
UINT
count
,
INT
*
run_count
)
{
BOOL
last_vert
=
check_unicode_tategaki
(
str
[
0
]);
INT
start
,
end
;
INT
array_size
=
5
;
Run
*
run
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
Run
)
*
array_size
);
int
index
=
0
;
LOGFONTW
lf
;
if
((
!
(
flags
&
ETO_GLYPH_INDEX
))
&&
GetObjectW
(
GetCurrentObject
(
dev
->
hdc
,
OBJ_FONT
),
sizeof
(
lf
),
&
lf
)
&&
(
lf
.
lfFaceName
[
0
]
==
'@'
))
{
start
=
end
=
0
;
while
(
start
<
count
)
{
int
offset
=
0
;
while
(
end
<
count
&&
check_unicode_tategaki
(
str
[
end
])
==
last_vert
)
end
++
;
run
[
index
].
start
=
start
;
run
[
index
].
vertical
=
last_vert
;
run
[
index
].
x
=
0
;
run
[
index
].
y
=
0
;
if
(
run
[
index
].
vertical
)
{
TEXTMETRICW
tm
;
GetTextMetricsW
(
dev
->
hdc
,
&
tm
);
offset
+=
PSDRV_XWStoDS
(
dev
,
tm
.
tmAscent
-
tm
.
tmInternalLeading
);
}
if
(
start
>
0
)
{
SIZE
size
;
GetTextExtentPointW
(
dev
->
hdc
,
str
,
start
,
&
size
);
offset
+=
PSDRV_XWStoDS
(
dev
,
size
.
cx
);
}
if
(
offset
)
{
double
angle
;
angle
=
(
lf
.
lfEscapement
/
10
.
0
)
*
M_PI
/
180
.
0
;
run
[
index
].
y
=
-
offset
*
sin
(
angle
);
run
[
index
].
x
=
-
offset
*
cos
(
angle
);
}
index
++
;
if
(
index
>=
array_size
)
{
array_size
*=
2
;
run
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
run
,
sizeof
(
Run
)
*
array_size
);
}
start
=
end
;
if
(
start
<
count
)
last_vert
=
check_unicode_tategaki
(
str
[
end
]);
}
}
else
{
run
[
0
].
start
=
0
;
run
[
0
].
vertical
=
0
;
run
[
0
].
x
=
0
;
run
[
0
].
y
=
0
;
index
=
1
;
}
*
run_count
=
index
;
return
run
;
}
/***********************************************************************
* PSDRV_ExtTextOut
*/
...
...
@@ -43,48 +168,69 @@ BOOL PSDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *lprect
BOOL
bResult
=
TRUE
;
BOOL
bClipped
=
FALSE
;
BOOL
bOpaque
=
FALSE
;
Run
*
runs
=
NULL
;
int
run_count
=
0
;
int
i
=
0
;
TRACE
(
"(x=%d, y=%d, flags=0x%08x, str=%s, count=%d, lpDx=%p)
\n
"
,
x
,
y
,
flags
,
debugstr_wn
(
str
,
count
),
count
,
lpDx
);
if
(
physDev
->
job
.
id
==
0
)
return
FALSE
;
/* write font if not already written */
PSDRV_SetFont
(
dev
);
runs
=
build_vertical_runs
(
dev
,
flags
,
str
,
count
,
&
run_count
);
PSDRV_SetClip
(
dev
);
/* set clipping and/or draw background */
if
((
flags
&
(
ETO_CLIPPED
|
ETO_OPAQUE
))
&&
(
lprect
!=
NULL
))
/* set draw background */
if
((
flags
&
ETO_OPAQUE
)
&&
(
lprect
!=
NULL
))
{
PSDRV_WriteGSave
(
dev
);
PSDRV_WriteRectangle
(
dev
,
lprect
->
left
,
lprect
->
top
,
lprect
->
right
-
lprect
->
left
,
lprect
->
bottom
-
lprect
->
top
);
if
(
flags
&
ETO_OPAQUE
)
{
bOpaque
=
TRUE
;
PSDRV_WriteGSave
(
dev
);
PSDRV_WriteSetColor
(
dev
,
&
physDev
->
bkColor
);
PSDRV_WriteFill
(
dev
);
PSDRV_WriteGRestore
(
dev
);
}
PSDRV_SetClip
(
dev
);
PSDRV_WriteGSave
(
dev
);
PSDRV_WriteRectangle
(
dev
,
lprect
->
left
,
lprect
->
top
,
lprect
->
right
-
lprect
->
left
,
lprect
->
bottom
-
lprect
->
top
);
if
(
flags
&
ETO_CLIPPED
)
{
bClipped
=
TRUE
;
PSDRV_WriteClip
(
dev
);
}
bOpaque
=
TRUE
;
PSDRV_WriteSetColor
(
dev
,
&
physDev
->
bkColor
);
PSDRV_WriteFill
(
dev
);
bResult
=
PSDRV_Text
(
dev
,
x
,
y
,
flags
,
str
,
count
,
!
(
bClipped
&&
bOpaque
),
lpDx
);
PSDRV_WriteGRestore
(
dev
);
PSDRV_WriteGRestore
(
dev
);
PSDRV_ResetClip
(
dev
);
}
else
while
(
i
<
run_count
)
{
bResult
=
PSDRV_Text
(
dev
,
x
,
y
,
flags
,
str
,
count
,
TRUE
,
lpDx
);
int
cnt
;
if
(
i
!=
run_count
-
1
)
cnt
=
runs
[
i
+
1
].
start
-
runs
[
i
].
start
;
else
cnt
=
count
-
runs
[
i
].
start
;
PSDRV_SetFont
(
dev
,
runs
[
i
].
vertical
);
PSDRV_SetClip
(
dev
);
/* set clipping */
if
((
flags
&
ETO_CLIPPED
)
&&
(
lprect
!=
NULL
))
{
PSDRV_WriteGSave
(
dev
);
PSDRV_WriteRectangle
(
dev
,
lprect
->
left
,
lprect
->
top
,
lprect
->
right
-
lprect
->
left
,
lprect
->
bottom
-
lprect
->
top
);
bClipped
=
TRUE
;
PSDRV_WriteClip
(
dev
);
bResult
=
PSDRV_Text
(
dev
,
runs
[
i
].
x
+
x
,
runs
[
i
].
y
+
y
,
flags
,
&
str
[
runs
[
i
].
start
],
cnt
,
!
(
bClipped
&&
bOpaque
),
(
lpDx
)
?&
lpDx
[
runs
[
i
].
start
]
:
NULL
);
PSDRV_WriteGRestore
(
dev
);
}
else
bResult
=
PSDRV_Text
(
dev
,
runs
[
i
].
x
+
x
,
runs
[
i
].
y
+
y
,
flags
,
&
str
[
runs
[
i
].
start
],
cnt
,
TRUE
,
(
lpDx
)
?&
lpDx
[
runs
[
i
].
start
]
:
NULL
);
i
++
;
PSDRV_ResetClip
(
dev
);
}
PSDRV_ResetClip
(
dev
);
HeapFree
(
GetProcessHeap
(),
0
,
runs
);
return
bResult
;
}
...
...
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