Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
45cdad8b
Commit
45cdad8b
authored
Oct 16, 2007
by
CHARRAS
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
changes in track connectivity computation
parent
28b17187
Changes
11
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1704 additions
and
1699 deletions
+1704
-1699
change_log.txt
change_log.txt
+18
-0
wxstruct.h
include/wxstruct.h
+63
-71
kicad.mo
internat/fr/kicad.mo
+0
-0
kicad.po
internat/fr/kicad.po
+1495
-1507
class_board_item.cpp
pcbnew/class_board_item.cpp
+2
-2
class_track.h
pcbnew/class_track.h
+77
-72
controle.cpp
pcbnew/controle.cpp
+1
-1
ioascii.cpp
pcbnew/ioascii.cpp
+6
-27
locate.cpp
pcbnew/locate.cpp
+31
-6
modedit_onclick.cpp
pcbnew/modedit_onclick.cpp
+10
-12
ratsnest.cpp
pcbnew/ratsnest.cpp
+1
-1
No files found.
change_log.txt
View file @
45cdad8b
...
@@ -4,6 +4,24 @@ Started 2007-June-11
...
@@ -4,6 +4,24 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with
Please add newer entries at the top, list the date and your name with
email address.
email address.
2007-Oct-13 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
+ pcbnew:
remove a change for Read VIA because via attributes
(TROUGH VIA, BLIND VIA or BURIED VIA) are autorisations for layer connection,
and are not a real layer indicator.
If a via connect layers from copper to component, it can have a BURIED VIA attribute.
the meaning is for this via the layer pair can be changed for other layer pair
if after editing this via connect 2 tracks which are only int internal layers,
its layer pair can be changed.
If a via has a TROUGH VIA attribute, it connects ALL layers, whenever tracks
connected to it.
Note: curenty: only TROUGH VIA are handled.
Other types (BLIND VIA and BURIED VIA) are only experimental.
A **lot** of code is needed for a full support.
enhancements in connectivity computation
2007-Oct-15 UPDATE Geoff Harland <gharlandau@yahoo.com.au>
2007-Oct-15 UPDATE Geoff Harland <gharlandau@yahoo.com.au>
================================================================================
================================================================================
...
...
include/wxstruct.h
View file @
45cdad8b
This diff is collapsed.
Click to expand it.
internat/fr/kicad.mo
View file @
45cdad8b
No preview for this file type
internat/fr/kicad.po
View file @
45cdad8b
This diff is collapsed.
Click to expand it.
pcbnew/class_board_item.cpp
View file @
45cdad8b
...
@@ -49,9 +49,9 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
...
@@ -49,9 +49,9 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
if
(
(
pad
->
m_Masque_Layer
&
ALL_CU_LAYERS
)
==
ALL_CU_LAYERS
)
if
(
(
pad
->
m_Masque_Layer
&
ALL_CU_LAYERS
)
==
ALL_CU_LAYERS
)
text
<<
_
(
"all copper layers"
);
text
<<
_
(
"all copper layers"
);
else
if
(
(
pad
->
m_Masque_Layer
&
CUIVRE_LAYER
)
==
CUIVRE_LAYER
)
else
if
(
(
pad
->
m_Masque_Layer
&
CUIVRE_LAYER
)
==
CUIVRE_LAYER
)
text
<<
_
(
"copper layer
s
"
);
text
<<
_
(
"copper layer"
);
else
if
(
(
pad
->
m_Masque_Layer
&
CMP_LAYER
)
==
CMP_LAYER
)
else
if
(
(
pad
->
m_Masque_Layer
&
CMP_LAYER
)
==
CMP_LAYER
)
text
<<
_
(
"cmp layer
s
"
);
text
<<
_
(
"cmp layer"
);
else
text
<<
_
(
"???"
);
else
text
<<
_
(
"???"
);
text
<<
_
(
") of "
)
<<
(
(
MODULE
*
)
GetParent
()
)
->
GetReference
();
text
<<
_
(
") of "
)
<<
(
(
MODULE
*
)
GetParent
()
)
->
GetReference
();
break
;
break
;
...
...
pcbnew/class_track.h
View file @
45cdad8b
...
@@ -7,15 +7,17 @@
...
@@ -7,15 +7,17 @@
#include "base_struct.h"
#include "base_struct.h"
/* Type des Vias (shape)*/
/
* Forme des Vias ( parametre .shape ) */
/
/ Via attributes (m_Shape parmeter)
#define
VIA_NORMALE 3
/* type via : traversante (throught via)
*/
#define
THROUGH_VIA 3
/* Always a through hole via
*/
#define
VIA_ENTERREE 2
/* type via : enterree ou aveugle (blind via)
*/
#define
BURIED_VIA 2
/* this via can be on internal layers
*/
#define
VIA_BORGNE 1
/* type via : borgne ou demi-traversante (buried via)
*/
#define
BLIND_VIA 1
/* this via which connect from internal layers to an external layer
*/
#define
VIA_NOT_DEFINED 0
/* reserved
*/
#define
NOT_DEFINED_VIA 0
/* reserved (unused)
*/
#define SQUARE_VIA
0x80000000
/* Flag pour forme carree */
#define SQUARE_VIA
_SHAPE 0x80000000
/* Flag pour forme carree */
#define VIA_NORMALE THROUGH_VIA
#define VIA_ENTERREE BURIED_VIA
#define VIA_BORGNE BLIND_VIA
/***/
/***/
...
@@ -80,7 +82,7 @@ public:
...
@@ -80,7 +82,7 @@ public:
TRACK
*
GetBestInsertPoint
(
BOARD
*
Pcb
);
TRACK
*
GetBestInsertPoint
(
BOARD
*
Pcb
);
/* Copie d'un Element d'une chaine de n elements
/* Copie d'un Element d'une chaine de n elements
TRACK* CopyList( int NbSegm = 1 ) const;
*
TRACK* CopyList( int NbSegm = 1 ) const;
*/
*/
/* Recherche du debut du net
/* Recherche du debut du net
...
@@ -181,11 +183,12 @@ public:
...
@@ -181,11 +183,12 @@ public:
*/
*/
wxString
GetClass
()
const
wxString
GetClass
()
const
{
{
return
wxT
(
"TRACK"
);
return
wxT
(
"TRACK"
);
}
}
#if defined(DEBUG)
#if defined (DEBUG)
/**
/**
* Function Show
* Function Show
* is used to output the object tree, currently for debugging only.
* is used to output the object tree, currently for debugging only.
...
@@ -194,6 +197,7 @@ public:
...
@@ -194,6 +197,7 @@ public:
* @param os The ostream& to output to.
* @param os The ostream& to output to.
*/
*/
void
Show
(
int
nestLevel
,
std
::
ostream
&
os
);
void
Show
(
int
nestLevel
,
std
::
ostream
&
os
);
#endif
#endif
};
};
...
@@ -210,11 +214,11 @@ public:
...
@@ -210,11 +214,11 @@ public:
*/
*/
wxString
GetClass
()
const
wxString
GetClass
()
const
{
{
return
wxT
(
"ZONE"
);
return
wxT
(
"ZONE"
);
}
}
SEGZONE
*
Next
()
const
{
return
(
SEGZONE
*
)
Pnext
;
}
SEGZONE
*
Next
()
const
{
return
(
SEGZONE
*
)
Pnext
;
}
};
};
...
@@ -249,11 +253,12 @@ public:
...
@@ -249,11 +253,12 @@ public:
*/
*/
wxString
GetClass
()
const
wxString
GetClass
()
const
{
{
return
wxT
(
"VIA"
);
return
wxT
(
"VIA"
);
}
}
#if defined(DEBUG)
#if defined (DEBUG)
/**
/**
* Function Show
* Function Show
* is used to output the object tree, currently for debugging only.
* is used to output the object tree, currently for debugging only.
...
@@ -262,8 +267,8 @@ public:
...
@@ -262,8 +267,8 @@ public:
* @param os The ostream& to output to.
* @param os The ostream& to output to.
*/
*/
void
Show
(
int
nestLevel
,
std
::
ostream
&
os
);
void
Show
(
int
nestLevel
,
std
::
ostream
&
os
);
#endif
#endif
};
};
...
...
pcbnew/controle.cpp
View file @
45cdad8b
...
@@ -413,5 +413,5 @@ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse )
...
@@ -413,5 +413,5 @@ void WinEDA_BasePcbFrame::GeneralControle( wxDC* DC, wxPoint Mouse )
}
}
SetToolbars
();
SetToolbars
();
Affiche_Status_Box
();
/*
Affichage des coord curseur
*/
Affiche_Status_Box
();
/*
Display new cursor coordinates
*/
}
}
pcbnew/ioascii.cpp
View file @
45cdad8b
...
@@ -172,32 +172,11 @@ int WinEDA_BasePcbFrame::ReadListeSegmentDescr( wxDC* DC, FILE* File,
...
@@ -172,32 +172,11 @@ int WinEDA_BasePcbFrame::ReadListeSegmentDescr( wxDC* DC, FILE* File,
PtSegm
->
m_Width
=
width
;
PtSegm
->
m_Width
=
width
;
// Before specifying the value for any new via's Shape property, check
// the values of its top_layer and bottom_layer properties, to determine
// what value should *really* be assigned to that property (as all
// versions of KiCad up until revision 335 (committed on 2007-Oct-13)
// could sometimes assign an inappropriate value to that property).
if
(
makeType
==
TYPEVIA
)
if
(
makeType
==
TYPEVIA
)
{
{
int
b_layer
=
(
layer
>>
4
)
&
15
;
// a THROUGH HOLE VIA always connects all layers
int
t_layer
=
layer
&
15
;
if
(
shape
==
THROUGH_VIA
)
if
(
(
(
b_layer
==
COPPER_LAYER_N
)
&&
(
t_layer
==
CMP_N
)
)
layer
=
(
COPPER_LAYER_N
<<
4
)
+
LAYER_CMP_N
;
||
(
(
b_layer
==
CMP_N
)
&&
(
t_layer
==
COPPER_LAYER_N
)
)
)
{
// The via is really of a "standard" (through-hole) type
shape
=
VIA_NORMALE
;
}
else
if
(
(
b_layer
==
COPPER_LAYER_N
)
||
(
t_layer
==
CMP_N
)
||
(
b_layer
==
CMP_N
)
||
(
t_layer
==
COPPER_LAYER_N
)
)
{
// The via is really of a "blind" type
shape
=
VIA_BORGNE
;
}
else
{
// The via is really of a "buried" type
shape
=
VIA_ENTERREE
;
}
}
}
PtSegm
->
m_Shape
=
shape
;
PtSegm
->
m_Shape
=
shape
;
...
@@ -221,11 +200,11 @@ int WinEDA_BasePcbFrame::ReadListeSegmentDescr( wxDC* DC, FILE* File,
...
@@ -221,11 +200,11 @@ int WinEDA_BasePcbFrame::ReadListeSegmentDescr( wxDC* DC, FILE* File,
{
{
case
TYPETRACK
:
case
TYPETRACK
:
case
TYPEVIA
:
case
TYPEVIA
:
DisplayActivity
(
PerCent
,
wxT
(
"Tracks:"
)
);
DisplayActivity
(
PerCent
,
_
(
"Tracks:"
)
);
break
;
break
;
case
TYPEZONE
:
case
TYPEZONE
:
DisplayActivity
(
PerCent
,
wxT
(
"Zones:"
)
);
DisplayActivity
(
PerCent
,
_
(
"Zones:"
)
);
break
;
break
;
}
}
#endif
#endif
...
...
pcbnew/locate.cpp
View file @
45cdad8b
...
@@ -663,6 +663,21 @@ TEXTE_MODULE* LocateTexteModule( BOARD* Pcb, MODULE** PtModule, int typeloc )
...
@@ -663,6 +663,21 @@ TEXTE_MODULE* LocateTexteModule( BOARD* Pcb, MODULE** PtModule, int typeloc )
}
}
/******************************************/
inline
int
Dist
(
wxPoint
&
p1
,
wxPoint
&
p2
)
/******************************************/
/*
return the dist min between p1 and p2
*/
{
int
dist
;
dist
=
abs
(
p1
.
x
-
p2
.
x
)
+
abs
(
p1
.
y
-
p2
.
y
);
dist
*=
7
;
dist
/=
10
;
return
dist
;
}
/**************************************************************/
/**************************************************************/
TRACK
*
Locate_Piste_Connectee
(
TRACK
*
PtRefSegm
,
TRACK
*
pt_base
,
TRACK
*
Locate_Piste_Connectee
(
TRACK
*
PtRefSegm
,
TRACK
*
pt_base
,
TRACK
*
pt_lim
,
int
extr
)
TRACK
*
pt_lim
,
int
extr
)
...
@@ -686,6 +701,7 @@ TRACK* Locate_Piste_Connectee( TRACK* PtRefSegm, TRACK* pt_base,
...
@@ -686,6 +701,7 @@ TRACK* Locate_Piste_Connectee( TRACK* PtRefSegm, TRACK* pt_base,
int
Reflayer
;
int
Reflayer
;
wxPoint
pos_ref
;
wxPoint
pos_ref
;
int
ii
;
int
ii
;
int
min_dist
;
if
(
extr
==
START
)
if
(
extr
==
START
)
pos_ref
=
PtRefSegm
->
m_Start
;
pos_ref
=
PtRefSegm
->
m_Start
;
...
@@ -708,13 +724,16 @@ TRACK* Locate_Piste_Connectee( TRACK* PtRefSegm, TRACK* pt_base,
...
@@ -708,13 +724,16 @@ TRACK* Locate_Piste_Connectee( TRACK* PtRefSegm, TRACK* pt_base,
goto
suite
;
goto
suite
;
if
(
PtSegmN
==
PtRefSegm
)
if
(
PtSegmN
==
PtRefSegm
)
goto
suite
;
goto
suite
;
if
(
pos_ref
==
PtSegmN
->
m_Start
)
min_dist
=
(
PtSegmN
->
m_Width
+
PtRefSegm
->
m_Width
)
/
2
;
if
(
Dist
(
pos_ref
,
PtSegmN
->
m_Start
)
<
min_dist
)
{
/* Test des couches */
{
/* Test des couches */
if
(
Reflayer
&
PtSegmN
->
ReturnMaskLayer
()
)
if
(
Reflayer
&
PtSegmN
->
ReturnMaskLayer
()
)
return
PtSegmN
;
return
PtSegmN
;
}
}
if
(
pos_ref
==
PtSegmN
->
m_End
)
if
(
Dist
(
pos_ref
,
PtSegmN
->
m_End
)
<
min_dist
)
{
/* Test des couches */
{
/* Test des couches */
if
(
Reflayer
&
PtSegmN
->
ReturnMaskLayer
()
)
if
(
Reflayer
&
PtSegmN
->
ReturnMaskLayer
()
)
return
PtSegmN
;
return
PtSegmN
;
...
@@ -732,13 +751,16 @@ suite:
...
@@ -732,13 +751,16 @@ suite:
goto
suite1
;
goto
suite1
;
if
(
PtSegmB
==
PtRefSegm
)
if
(
PtSegmB
==
PtRefSegm
)
goto
suite1
;
goto
suite1
;
if
(
pos_ref
==
PtSegmB
->
m_Start
)
min_dist
=
(
PtSegmB
->
m_Width
+
PtRefSegm
->
m_Width
)
/
2
;
if
(
Dist
(
pos_ref
,
PtSegmB
->
m_Start
)
<
min_dist
)
{
/* Test des couches */
{
/* Test des couches */
if
(
Reflayer
&
PtSegmB
->
ReturnMaskLayer
()
)
if
(
Reflayer
&
PtSegmB
->
ReturnMaskLayer
()
)
return
PtSegmB
;
return
PtSegmB
;
}
}
if
(
pos_ref
==
PtSegmB
->
m_End
)
if
(
Dist
(
pos_ref
,
PtSegmB
->
m_End
)
<
min_dist
)
{
/* Test des couches */
{
/* Test des couches */
if
(
Reflayer
&
PtSegmB
->
ReturnMaskLayer
()
)
if
(
Reflayer
&
PtSegmB
->
ReturnMaskLayer
()
)
return
PtSegmB
;
return
PtSegmB
;
...
@@ -769,13 +791,16 @@ suite1:
...
@@ -769,13 +791,16 @@ suite1:
continue
;
continue
;
}
}
if
(
pos_ref
==
PtSegmN
->
m_Start
)
min_dist
=
(
PtSegmN
->
m_Width
+
PtRefSegm
->
m_Width
)
/
2
;
if
(
Dist
(
pos_ref
,
PtSegmN
->
m_Start
)
<
min_dist
)
{
/* Test des couches */
{
/* Test des couches */
if
(
Reflayer
&
PtSegmN
->
ReturnMaskLayer
()
)
if
(
Reflayer
&
PtSegmN
->
ReturnMaskLayer
()
)
return
PtSegmN
;
return
PtSegmN
;
}
}
if
(
pos_ref
==
PtSegmN
->
m_End
)
if
(
Dist
(
pos_ref
,
PtSegmN
->
m_End
)
<
min_dist
)
{
/* Test des couches */
{
/* Test des couches */
if
(
Reflayer
&
PtSegmN
->
ReturnMaskLayer
()
)
if
(
Reflayer
&
PtSegmN
->
ReturnMaskLayer
()
)
return
PtSegmN
;
return
PtSegmN
;
...
...
pcbnew/modedit_onclick.cpp
View file @
45cdad8b
...
@@ -30,8 +30,7 @@
...
@@ -30,8 +30,7 @@
void
WinEDA_ModuleEditFrame
::
OnLeftClick
(
wxDC
*
DC
,
const
wxPoint
&
MousePos
)
void
WinEDA_ModuleEditFrame
::
OnLeftClick
(
wxDC
*
DC
,
const
wxPoint
&
MousePos
)
/*************************************************************************/
/*************************************************************************/
/* Traite les commandes declenche par le bouton gauche de la souris,
/* Handle the left click in footprint editor
* quand un outil est deja selectionn
*/
*/
{
{
BOARD_ITEM
*
DrawStruct
=
GetCurItem
();
BOARD_ITEM
*
DrawStruct
=
GetCurItem
();
...
@@ -39,7 +38,7 @@ void WinEDA_ModuleEditFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
...
@@ -39,7 +38,7 @@ void WinEDA_ModuleEditFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
DrawPanel
->
CursorOff
(
DC
);
DrawPanel
->
CursorOff
(
DC
);
if
(
m_ID_current_state
==
0
)
if
(
m_ID_current_state
==
0
)
{
{
if
(
DrawStruct
&&
DrawStruct
->
m_Flags
)
// Command
e "POPUP" en cour
s
if
(
DrawStruct
&&
DrawStruct
->
m_Flags
)
// Command
in progres
s
{
{
switch
(
DrawStruct
->
Type
()
)
switch
(
DrawStruct
->
Type
()
)
{
{
...
@@ -75,7 +74,7 @@ void WinEDA_ModuleEditFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
...
@@ -75,7 +74,7 @@ void WinEDA_ModuleEditFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
DrawStruct
=
GetCurItem
();
DrawStruct
=
GetCurItem
();
if
(
!
DrawStruct
||
(
DrawStruct
->
m_Flags
==
0
)
)
if
(
!
DrawStruct
||
(
DrawStruct
->
m_Flags
==
0
)
)
{
{
DrawStruct
=
(
BOARD_ITEM
*
)
ModeditLocateAndDisplay
();
DrawStruct
=
ModeditLocateAndDisplay
();
SetCurItem
(
DrawStruct
);
SetCurItem
(
DrawStruct
);
}
}
...
@@ -177,9 +176,9 @@ bool WinEDA_ModuleEditFrame::OnRightClick( const wxPoint& MousePos,
...
@@ -177,9 +176,9 @@ bool WinEDA_ModuleEditFrame::OnRightClick( const wxPoint& MousePos,
wxMenu
*
PopMenu
)
wxMenu
*
PopMenu
)
/*********************************************************************/
/*********************************************************************/
/*
Prepare le menu PullUp affich par un click sur le bouton droit
/*
Handle the right click in the footprint editor:
*
de la souris.
*
Create the pull up menu
*
Ce menu est ensuite complt par la liste des commandes de ZOOM
*
After this menu is built, the standart ZOOM menu is added
*/
*/
{
{
BOARD_ITEM
*
DrawStruct
=
GetCurItem
();
BOARD_ITEM
*
DrawStruct
=
GetCurItem
();
...
@@ -376,9 +375,8 @@ bool WinEDA_ModuleEditFrame::OnRightClick( const wxPoint& MousePos,
...
@@ -376,9 +375,8 @@ bool WinEDA_ModuleEditFrame::OnRightClick( const wxPoint& MousePos,
void
WinEDA_ModuleEditFrame
::
OnLeftDClick
(
wxDC
*
DC
,
const
wxPoint
&
MousePos
)
void
WinEDA_ModuleEditFrame
::
OnLeftDClick
(
wxDC
*
DC
,
const
wxPoint
&
MousePos
)
/****************************************************************************/
/****************************************************************************/
/* Appel sur un double click:
/* Handle the double click in the footprin editor:
* pour un lment editable (textes, composant):
* If the double clicked item is editable: call the corresponding editor.
* appel de l'editeur correspondant.
*/
*/
{
{
BOARD_ITEM
*
DrawStruct
=
GetCurItem
();
BOARD_ITEM
*
DrawStruct
=
GetCurItem
();
...
@@ -392,13 +390,13 @@ void WinEDA_ModuleEditFrame::OnLeftDClick( wxDC* DC, const wxPoint& MousePos )
...
@@ -392,13 +390,13 @@ void WinEDA_ModuleEditFrame::OnLeftDClick( wxDC* DC, const wxPoint& MousePos )
case
0
:
case
0
:
if
(
(
DrawStruct
==
NULL
)
||
(
DrawStruct
->
m_Flags
==
0
)
)
if
(
(
DrawStruct
==
NULL
)
||
(
DrawStruct
->
m_Flags
==
0
)
)
{
{
DrawStruct
=
PcbGeneral
LocateAndDisplay
();
DrawStruct
=
Modedit
LocateAndDisplay
();
}
}
if
(
(
DrawStruct
==
NULL
)
||
(
DrawStruct
->
m_Flags
!=
0
)
)
if
(
(
DrawStruct
==
NULL
)
||
(
DrawStruct
->
m_Flags
!=
0
)
)
break
;
break
;
//
Element localis
//
Item found
SetCurItem
(
DrawStruct
);
SetCurItem
(
DrawStruct
);
switch
(
DrawStruct
->
Type
()
)
switch
(
DrawStruct
->
Type
()
)
...
...
pcbnew/ratsnest.cpp
View file @
45cdad8b
...
@@ -33,7 +33,7 @@ static bool DisplayRastnestInProgress; // Enable the display of the ratsnes
...
@@ -33,7 +33,7 @@ static bool DisplayRastnestInProgress; // Enable the display of the ratsnes
* Build_Board_Ratsnest( wxDC* DC ) Create this rastnest
* Build_Board_Ratsnest( wxDC* DC ) Create this rastnest
* for each net:
* for each net:
* First:
* First:
* we create
links
(and therefore a logical block) between 2 pad. This is achieved by:
* we create
a link
(and therefore a logical block) between 2 pad. This is achieved by:
* search for a pad without link.
* search for a pad without link.
* search its nearest pad
* search its nearest pad
* link these 2 pads (i.e. create a ratsnest item)
* link these 2 pads (i.e. create a ratsnest item)
...
...
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