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
943b0678
Commit
943b0678
authored
Nov 12, 2013
by
Dick Hollenbeck
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Completion of DIALOG_FP_PLUGIN_OPTIONS
parent
e8e6b1f7
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
338 additions
and
167 deletions
+338
-167
dialog_fp_lib_table.cpp
pcbnew/dialogs/dialog_fp_lib_table.cpp
+15
-10
dialog_fp_plugin_options.cpp
pcbnew/dialogs/dialog_fp_plugin_options.cpp
+58
-20
dialog_fp_plugin_options_base.cpp
pcbnew/dialogs/dialog_fp_plugin_options_base.cpp
+20
-34
dialog_fp_plugin_options_base.fbp
pcbnew/dialogs/dialog_fp_plugin_options_base.fbp
+202
-88
dialog_fp_plugin_options_base.h
pcbnew/dialogs/dialog_fp_plugin_options_base.h
+11
-4
github_plugin.cpp
pcbnew/github/github_plugin.cpp
+10
-6
plugin.cpp
pcbnew/plugin.cpp
+22
-5
No files found.
pcbnew/dialogs/dialog_fp_lib_table.cpp
View file @
943b0678
...
...
@@ -323,19 +323,24 @@ public:
attr
->
SetEditor
(
new
wxGridCellChoiceEditor
(
choices
)
);
m_global_grid
->
SetColAttr
(
COL_TYPE
,
attr
);
m_global_grid
->
AutoSizeColumns
(
false
);
m_project_grid
->
AutoSizeColumns
(
false
);
populateEnvironReadOnlyTable
();
/*
Connect( MYID_FIRST, MYID_LAST, wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler( DIALOG_FP_LIB_TABLE::onPopupSelection ), NULL, this );
*/
for
(
int
i
=
0
;
i
<
2
;
++
i
)
{
wxGrid
*
g
=
i
==
0
?
m_global_grid
:
m_project_grid
;
populateEnvironReadOnlyTable
();
// all but COL_OPTIONS, which is edited with Option Editor anyways.
g
->
AutoSizeColumn
(
COL_NICKNAME
,
true
);
g
->
AutoSizeColumn
(
COL_TYPE
,
false
);
g
->
AutoSizeColumn
(
COL_URI
,
false
);
g
->
AutoSizeColumn
(
COL_DESCR
,
false
);
/* This scrunches the dialog hideously
Fit();
*/
g
->
SetColSize
(
COL_OPTIONS
,
80
);
}
// This scrunches the dialog hideously, probably due to wxAUI container.
// Fit();
// We derive from DIALOG_SHIM so prior size will be used anyways.
// fire pageChangedHandler() so m_cur_grid gets set
wxAuiNotebookEvent
uneventful
;
...
...
pcbnew/dialogs/dialog_fp_plugin_options.cpp
View file @
943b0678
...
...
@@ -30,6 +30,11 @@
#include <fp_lib_table.h>
#include <grid_tricks.h>
#define INITIAL_HELP \
_( "Select an <b>Option Choice</b> in the listbox above, and then click the <b>Append Selected Option</b> button." )
using
std
::
string
;
// re-enter the dialog with the column sizes preserved from last time.
...
...
@@ -52,7 +57,8 @@ public:
const
wxString
&
aOptions
,
wxString
*
aResult
)
:
DIALOG_FP_PLUGIN_OPTIONS_BASE
(
aParent
),
m_callers_options
(
aOptions
),
m_result
(
aResult
)
m_result
(
aResult
),
m_initial_help
(
INITIAL_HELP
)
{
wxString
title
=
wxString
::
Format
(
_
(
"Options for Library '%s'"
),
GetChars
(
aNickname
)
);
...
...
@@ -62,7 +68,9 @@ public:
// add Cut, Copy, and Paste to wxGrid
m_grid
->
PushEventHandler
(
new
GRID_TRICKS
(
m_grid
)
);
// Fill the grid with aOptions
m_grid
->
SetColMinimalWidth
(
1
,
250
);
// Fill the grid with existing aOptions
string
options
=
TO_UTF8
(
aOptions
);
PROPERTIES
*
props
=
FP_LIB_TABLE
::
ParseOptions
(
options
);
...
...
@@ -86,26 +94,21 @@ public:
IO_MGR
::
PCB_FILE_T
pi_type
=
IO_MGR
::
EnumFromStr
(
aPluginType
);
PLUGIN
::
RELEASER
pi
(
IO_MGR
::
PluginFind
(
pi_type
)
);
PROPERTIES
choices
;
pi
->
FootprintLibOptions
(
&
choices
);
pi
->
FootprintLibOptions
(
&
m_
choices
);
if
(
choices
.
size
()
)
if
(
m_
choices
.
size
()
)
{
int
needed_rows
=
(
int
)
choices
.
size
()
-
m_option_choices
->
GetNumberRows
();
if
(
needed_rows
>
0
)
m_option_choices
->
AppendRows
(
needed_rows
);
int
row
=
0
;
for
(
PROPERTIES
::
const_iterator
it
=
choices
.
begin
();
it
!=
choices
.
end
();
++
it
,
++
row
)
for
(
PROPERTIES
::
const_iterator
it
=
m_choices
.
begin
();
it
!=
m_
choices
.
end
();
++
it
,
++
row
)
{
DBG
(
printf
(
"[%s]:'%s'
\n
"
,
it
->
first
.
c_str
(),
it
->
second
.
c_str
()
);)
m_option_choices
->
SetCellValue
(
row
,
0
,
FROM_UTF8
(
it
->
first
.
c_str
()
)
);
m_
option_choices
->
SetCellValue
(
row
,
1
,
FROM_UTF8
(
it
->
second
.
c_str
()
)
);
wxString
item
=
FROM_UTF8
(
it
->
first
.
c_str
()
);
m_
listbox
->
InsertItems
(
1
,
&
item
,
row
);
}
}
m_
option_choices
->
AutoSizeColumns
(
false
);
m_
html
->
SetPage
(
m_initial_help
);
if
(
!
col_width_option
)
{
...
...
@@ -117,6 +120,8 @@ public:
m_grid
->
SetColSize
(
1
,
col_width_value
);
}
Fit
();
// initial focus on the grid please.
m_grid
->
SetFocus
();
}
...
...
@@ -131,6 +136,9 @@ public:
private
:
const
wxString
&
m_callers_options
;
wxString
*
m_result
;
PROPERTIES
m_choices
;
wxString
m_initial_help
;
/// If the cursor is not on a valid cell, because there are no rows at all, return -1,
/// else return a 0 based column index.
...
...
@@ -219,14 +227,12 @@ private:
return
-
1
;
}
//-----<event handlers>------------------------------------------------------
void
onAppendOption
(
wxMouseEvent
&
event
)
void
appendOption
()
{
int
selected_row
=
m_
option_choices
->
GetCursorRow
();
if
(
selected_row
>=
0
)
int
selected_row
=
m_
listbox
->
GetSelection
();
if
(
selected_row
!=
wxNOT_FOUND
)
{
wxString
option
=
m_
option_choices
->
GetCellValue
(
selected_row
,
0
);
wxString
option
=
m_
listbox
->
GetString
(
selected_row
);
int
row_count
=
m_grid
->
GetNumberRows
();
int
row
;
...
...
@@ -247,6 +253,38 @@ private:
}
}
//-----<event handlers>------------------------------------------------------
void
onListBoxItemSelected
(
wxCommandEvent
&
event
)
{
if
(
event
.
IsSelection
()
)
{
const
char
*
option
=
TO_UTF8
(
event
.
GetString
()
);
string
help_text
;
if
(
m_choices
.
Value
(
option
,
&
help_text
)
)
{
wxString
page
(
FROM_UTF8
(
help_text
.
c_str
()
)
);
m_html
->
SetPage
(
page
);
}
else
{
m_html
->
SetPage
(
m_initial_help
);
}
}
}
void
onListBoxItemDoubleClicked
(
wxCommandEvent
&
event
)
{
appendOption
();
}
void
onAppendOption
(
wxCommandEvent
&
event
)
{
appendOption
();
}
void
onAppendRow
(
wxMouseEvent
&
event
)
{
appendRow
();
...
...
pcbnew/dialogs/dialog_fp_plugin_options_base.cpp
View file @
943b0678
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version
Apr 30
2013)
// C++ code generated with wxFormBuilder (version
Nov 5
2013)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
...
...
@@ -83,50 +83,32 @@ DIALOG_FP_PLUGIN_OPTIONS_BASE::DIALOG_FP_PLUGIN_OPTIONS_BASE( wxWindow* parent,
wxGridSizer
*
m_choose_size
;
m_choose_size
=
new
wxGridSizer
(
1
,
1
,
0
,
0
);
m_button1
=
new
wxButton
(
this
,
wxID_ANY
,
_
(
"<<"
),
wxDefaultPosition
,
wxDefaultSize
,
0
);
m_button1
->
SetMaxSize
(
wxSize
(
50
,
-
1
)
);
m_choose_size
->
Add
(
m_button1
,
0
,
wxALIGN_CENTER
|
wxALIGN_CENTER_HORIZONTAL
|
wxALIGN_CENTER_VERTICAL
|
wxLEFT
|
wxRIGHT
,
5
);
m_horizontal_sizer
->
Add
(
m_choose_size
,
0
,
wxEXPAND
,
5
);
wxStaticBoxSizer
*
m_options_sizer
;
m_options_sizer
=
new
wxStaticBoxSizer
(
new
wxStaticBox
(
this
,
wxID_ANY
,
_
(
"Option Choices:"
)
),
wx
HORIZONT
AL
);
m_options_sizer
=
new
wxStaticBoxSizer
(
new
wxStaticBox
(
this
,
wxID_ANY
,
_
(
"Option Choices:"
)
),
wx
VERTIC
AL
);
m_options_sizer
->
SetMinSize
(
wxSize
(
200
,
-
1
)
);
m_option_choices
=
new
wxGrid
(
this
,
wxID_ANY
,
wxDefaultPosition
,
wxDefaultSize
,
wxHSCROLL
|
wxVSCROLL
);
m_listbox
=
new
wxListBox
(
this
,
wxID_ANY
,
wxDefaultPosition
,
wxDefaultSize
,
0
,
NULL
,
wxLB_ALWAYS_SB
|
wxLB_SINGLE
);
m_listbox
->
SetToolTip
(
_
(
"Options supported by current plugin"
)
);
// Grid
m_option_choices
->
CreateGrid
(
0
,
2
);
m_option_choices
->
EnableEditing
(
false
);
m_option_choices
->
EnableGridLines
(
true
);
m_option_choices
->
EnableDragGridSize
(
false
);
m_option_choices
->
SetMargins
(
0
,
0
);
m_options_sizer
->
Add
(
m_listbox
,
0
,
wxALL
|
wxEXPAND
,
5
);
// Columns
m_option_choices
->
AutoSizeColumns
();
m_option_choices
->
EnableDragColMove
(
false
);
m_option_choices
->
EnableDragColSize
(
true
);
m_option_choices
->
SetColLabelSize
(
30
);
m_option_choices
->
SetColLabelValue
(
0
,
_
(
"Option"
)
);
m_option_choices
->
SetColLabelValue
(
1
,
_
(
"Description"
)
);
m_option_choices
->
SetColLabelAlignment
(
wxALIGN_CENTRE
,
wxALIGN_CENTRE
);
m_append_choice_button
=
new
wxButton
(
this
,
wxID_ANY
,
_
(
"<< Append Selected Option"
),
wxDefaultPosition
,
wxDefaultSize
,
0
);
m_options_sizer
->
Add
(
m_append_choice_button
,
0
,
wxALIGN_CENTER
|
wxALIGN_CENTER_HORIZONTAL
|
wxALIGN_CENTER_VERTICAL
|
wxBOTTOM
|
wxEXPAND
|
wxLEFT
|
wxRIGHT
,
5
);
// Rows
m_option_choices
->
AutoSizeRows
();
m_option_choices
->
EnableDragRowSize
(
true
);
m_option_choices
->
SetRowLabelSize
(
0
);
m_option_choices
->
SetRowLabelAlignment
(
wxALIGN_CENTRE
,
wxALIGN_CENTRE
);
m_staticText1
=
new
wxStaticText
(
this
,
wxID_ANY
,
_
(
"Option Specific Help:"
),
wxDefaultPosition
,
wxDefaultSize
,
0
);
m_staticText1
->
Wrap
(
-
1
);
m_options_sizer
->
Add
(
m_staticText1
,
0
,
wxLEFT
|
wxRIGHT
|
wxTOP
,
5
);
// Label Appearance
m_html
=
new
wxHtmlWindow
(
this
,
wxID_ANY
,
wxDefaultPosition
,
wxDefaultSize
,
wxHW_SCROLLBAR_AUTO
|
wxVSCROLL
);
m_html
->
SetMinSize
(
wxSize
(
300
,
300
)
);
// Cell Defaults
m_option_choices
->
SetDefaultCellAlignment
(
wxALIGN_LEFT
,
wxALIGN_TOP
);
m_options_sizer
->
Add
(
m_option_choices
,
1
,
wxEXPAND
|
wxTOP
,
5
);
m_options_sizer
->
Add
(
m_html
,
1
,
wxALL
|
wxEXPAND
,
5
);
m_horizontal_sizer
->
Add
(
m_options_sizer
,
4
,
wxEXPAND
,
5
);
m_horizontal_sizer
->
Add
(
m_options_sizer
,
2
,
wxEXPAND
,
5
);
bSizer4
->
Add
(
m_horizontal_sizer
,
1
,
wxALL
|
wxEXPAND
,
5
);
...
...
@@ -153,7 +135,9 @@ DIALOG_FP_PLUGIN_OPTIONS_BASE::DIALOG_FP_PLUGIN_OPTIONS_BASE( wxWindow* parent,
m_delete_row
->
Connect
(
wxEVT_LEFT_DOWN
,
wxMouseEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onDeleteRow
),
NULL
,
this
);
m_move_up
->
Connect
(
wxEVT_LEFT_DOWN
,
wxMouseEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onMoveUp
),
NULL
,
this
);
m_move_down
->
Connect
(
wxEVT_LEFT_DOWN
,
wxMouseEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onMoveDown
),
NULL
,
this
);
m_button1
->
Connect
(
wxEVT_LEFT_DOWN
,
wxMouseEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onAppendOption
),
NULL
,
this
);
m_listbox
->
Connect
(
wxEVT_COMMAND_LISTBOX_SELECTED
,
wxCommandEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onListBoxItemSelected
),
NULL
,
this
);
m_listbox
->
Connect
(
wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
,
wxCommandEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onListBoxItemDoubleClicked
),
NULL
,
this
);
m_append_choice_button
->
Connect
(
wxEVT_COMMAND_BUTTON_CLICKED
,
wxCommandEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onAppendOption
),
NULL
,
this
);
m_sdbSizer1Cancel
->
Connect
(
wxEVT_COMMAND_BUTTON_CLICKED
,
wxCommandEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onCancelButtonClick
),
NULL
,
this
);
m_sdbSizer1OK
->
Connect
(
wxEVT_COMMAND_BUTTON_CLICKED
,
wxCommandEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onOKButtonClick
),
NULL
,
this
);
}
...
...
@@ -166,7 +150,9 @@ DIALOG_FP_PLUGIN_OPTIONS_BASE::~DIALOG_FP_PLUGIN_OPTIONS_BASE()
m_delete_row
->
Disconnect
(
wxEVT_LEFT_DOWN
,
wxMouseEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onDeleteRow
),
NULL
,
this
);
m_move_up
->
Disconnect
(
wxEVT_LEFT_DOWN
,
wxMouseEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onMoveUp
),
NULL
,
this
);
m_move_down
->
Disconnect
(
wxEVT_LEFT_DOWN
,
wxMouseEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onMoveDown
),
NULL
,
this
);
m_button1
->
Disconnect
(
wxEVT_LEFT_DOWN
,
wxMouseEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onAppendOption
),
NULL
,
this
);
m_listbox
->
Disconnect
(
wxEVT_COMMAND_LISTBOX_SELECTED
,
wxCommandEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onListBoxItemSelected
),
NULL
,
this
);
m_listbox
->
Disconnect
(
wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
,
wxCommandEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onListBoxItemDoubleClicked
),
NULL
,
this
);
m_append_choice_button
->
Disconnect
(
wxEVT_COMMAND_BUTTON_CLICKED
,
wxCommandEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onAppendOption
),
NULL
,
this
);
m_sdbSizer1Cancel
->
Disconnect
(
wxEVT_COMMAND_BUTTON_CLICKED
,
wxCommandEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onCancelButtonClick
),
NULL
,
this
);
m_sdbSizer1OK
->
Disconnect
(
wxEVT_COMMAND_BUTTON_CLICKED
,
wxCommandEventHandler
(
DIALOG_FP_PLUGIN_OPTIONS_BASE
::
onOKButtonClick
),
NULL
,
this
);
...
...
pcbnew/dialogs/dialog_fp_plugin_options_base.fbp
View file @
943b0678
This diff is collapsed.
Click to expand it.
pcbnew/dialogs/dialog_fp_plugin_options_base.h
View file @
943b0678
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version
Apr 30
2013)
// C++ code generated with wxFormBuilder (version
Nov 5
2013)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
...
...
@@ -23,6 +23,9 @@ class DIALOG_SHIM;
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/statbox.h>
#include <wx/listbox.h>
#include <wx/stattext.h>
#include <wx/html/htmlwin.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
...
...
@@ -41,8 +44,10 @@ class DIALOG_FP_PLUGIN_OPTIONS_BASE : public DIALOG_SHIM
wxButton
*
m_delete_row
;
wxButton
*
m_move_up
;
wxButton
*
m_move_down
;
wxButton
*
m_button1
;
wxGrid
*
m_option_choices
;
wxListBox
*
m_listbox
;
wxButton
*
m_append_choice_button
;
wxStaticText
*
m_staticText1
;
wxHtmlWindow
*
m_html
;
wxStdDialogButtonSizer
*
m_sdbSizer1
;
wxButton
*
m_sdbSizer1OK
;
wxButton
*
m_sdbSizer1Cancel
;
...
...
@@ -53,7 +58,9 @@ class DIALOG_FP_PLUGIN_OPTIONS_BASE : public DIALOG_SHIM
virtual
void
onDeleteRow
(
wxMouseEvent
&
event
)
=
0
;
virtual
void
onMoveUp
(
wxMouseEvent
&
event
)
=
0
;
virtual
void
onMoveDown
(
wxMouseEvent
&
event
)
=
0
;
virtual
void
onAppendOption
(
wxMouseEvent
&
event
)
=
0
;
virtual
void
onListBoxItemSelected
(
wxCommandEvent
&
event
)
=
0
;
virtual
void
onListBoxItemDoubleClicked
(
wxCommandEvent
&
event
)
=
0
;
virtual
void
onAppendOption
(
wxCommandEvent
&
event
)
=
0
;
virtual
void
onCancelButtonClick
(
wxCommandEvent
&
event
)
=
0
;
virtual
void
onOKButtonClick
(
wxCommandEvent
&
event
)
=
0
;
...
...
pcbnew/github/github_plugin.cpp
View file @
943b0678
...
...
@@ -183,14 +183,18 @@ void GITHUB_PLUGIN::FootprintLibOptions( PROPERTIES* aListToAppendTo ) const
// inherit options supported by all PLUGINs.
PLUGIN
::
FootprintLibOptions
(
aListToAppendTo
);
(
*
aListToAppendTo
)[
"allow_pretty_writing_to_this_dir"
]
=
wxString
(
_
(
"Set this property to a directory where footprints are written to.
\n
"
"The directory should have a 'pretty' extension"
(
*
aListToAppendTo
)[
"allow_pretty_writing_to_this_dir"
]
=
wxString
(
_
(
"Set this property to a directory where footprints are to be written as pretty "
"footprints when saving to this library. Anything saved will take precedence over "
"footprints by the same name in the github repo. These saved footprints can then "
"be sent to the library maintainer as updates. "
"<p>The directory should have a <b>.pretty</b> file extension because the "
"Kicad plugin is used to do the saving.</p>"
)).
utf8_str
();
(
*
aListToAppendTo
)[
"cache_github_zip_in_this_dir"
]
=
wxString
(
_
(
"Set this property to a directory where the github *.zip file will be cached.
\n
"
"This should speed up subsequent visits to this library."
(
*
aListToAppendTo
)[
"cache_github_zip_in_this_dir"
]
=
wxString
(
_
(
"Set this property to a directory where the github *.zip file will be cached.
"
"This should speed up subsequent visits to this library."
)).
utf8_str
();
}
...
...
pcbnew/plugin.cpp
View file @
943b0678
...
...
@@ -112,10 +112,27 @@ bool PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath )
void
PLUGIN
::
FootprintLibOptions
(
PROPERTIES
*
aListToAppendTo
)
const
{
// (*aListToAppendTo)["debug_level"] = TO_UTF8( _( "Enable debug logging for Footprint*() functions in this PLUGIN." ) );
// (*aListToAppendTo)["read_filter_regex"] = TO_UTF8( _("Regular expression footprint name filter") );
// (*aListToAppendTo)["enable transaction logging"] = ""; // mere presence enables, value is moot.
#if 1
(
*
aListToAppendTo
)[
"debug_level"
]
=
wxString
(
_
(
"Enable debug logging for Footprint*() functions in this PLUGIN."
)).
utf8_str
();
(
*
aListToAppendTo
)[
"read_filter_regex"
]
=
wxString
(
_
(
"Regular expression <b>footprint name</b> filter."
)).
utf8_str
();
(
*
aListToAppendTo
)[
"enable_transaction_logging"
]
=
wxString
(
_
(
"Enable transaction logging. The mere presence of this option turns on the "
" logging, no need to set a Value."
)).
utf8_str
();
#endif
#if 1
// Suitable for a C++ to python PLUGIN::Footprint*() adapter, move it to the adapter
// if and when implemented.
(
*
aListToAppendTo
)[
"python_footprint_plugin"
]
=
wxString
(
_
(
"Enter the python module which implements the PLUGIN::Footprint*() functions."
)).
utf8_str
();
#endif
}
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