KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_setup_rules.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <bitmaps.h>
25#include <confirm.h>
27#include <pcb_edit_frame.h>
28#include <pcbexpr_evaluator.h>
29#include <board.h>
31#include <project.h>
32#include <string_utils.h>
33#include <tool/tool_manager.h>
34#include <panel_setup_rules.h>
37#include <scintilla_tricks.h>
38#include <drc/drc_rule_parser.h>
39#include <tools/drc_tool.h>
40#include <pgm_base.h>
41
42PANEL_SETUP_RULES::PANEL_SETUP_RULES( wxWindow* aParentWindow, PCB_EDIT_FRAME* aFrame ) :
43 PANEL_SETUP_RULES_BASE( aParentWindow ),
44 m_frame( aFrame ),
45 m_scintillaTricks( nullptr ),
46 m_helpWindow( nullptr )
47{
48 m_scintillaTricks = new SCINTILLA_TRICKS( m_textEditor, wxT( "()" ), false,
49 [this]( wxKeyEvent& aEvent )
50 {
51 wxPostEvent( PAGED_DIALOG::GetDialog( this ),
52 wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
53 } );
54
55 m_textEditor->AutoCompSetSeparator( '|' );
56
57 m_netClassRegex.Compile( "^NetClass\\s*[!=]=\\s*$", wxRE_ADVANCED );
58 m_netNameRegex.Compile( "^NetName\\s*[!=]=\\s*$", wxRE_ADVANCED );
59 m_typeRegex.Compile( "^Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
60 m_viaTypeRegex.Compile( "^Via_Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
61 m_padTypeRegex.Compile( "^Pad_Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
62 m_pinTypeRegex.Compile( "^Pin_Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
63 m_fabPropRegex.Compile( "^Fabrication_Property\\s*[!=]=\\s*$", wxRE_ADVANCED );
64 m_shapeRegex.Compile( "^Shape\\s*[!=]=\\s*$", wxRE_ADVANCED );
65 m_zoneConnStyleRegex.Compile( "^Zone_Connection_Style\\s*[!=]=\\s*$", wxRE_ADVANCED );
66
67 m_compileButton->SetBitmap( KiBitmap( BITMAPS::drc ) );
68
69 m_textEditor->SetZoom( Pgm().GetCommonSettings()->m_Appearance.text_editor_zoom );
70
71 m_textEditor->UsePopUp( 0 );
72 m_textEditor->Bind( wxEVT_STC_CHARADDED, &PANEL_SETUP_RULES::onScintillaCharAdded, this );
73 m_textEditor->Bind( wxEVT_STC_AUTOCOMP_CHAR_DELETED, &PANEL_SETUP_RULES::onScintillaCharAdded, this );
74 m_textEditor->Bind( wxEVT_CHAR_HOOK, &PANEL_SETUP_RULES::onCharHook, this );
75}
76
77
79{
80 Pgm().GetCommonSettings()->m_Appearance.text_editor_zoom = m_textEditor->GetZoom();
81
82 delete m_scintillaTricks;
83
84 if( m_helpWindow )
85 m_helpWindow->Destroy();
86};
87
88
89void PANEL_SETUP_RULES::onCharHook( wxKeyEvent& aEvent )
90{
91 if( aEvent.GetKeyCode() == WXK_ESCAPE && !m_textEditor->AutoCompActive() )
92 {
93 if( m_originalText != m_textEditor->GetText() )
94 {
95 if( !IsOK( this, _( "Cancel Changes?" ) ) )
96 return;
97 }
98 }
99
100 aEvent.Skip();
101}
102
103
104void PANEL_SETUP_RULES::OnContextMenu(wxMouseEvent &event)
105{
106 wxMenu menu;
107
108 menu.Append( wxID_UNDO, _( "Undo" ) );
109 menu.Append( wxID_REDO, _( "Redo" ) );
110
111 menu.AppendSeparator();
112
113 menu.Append( 1, _( "Cut" ) ); // Don't use wxID_CUT, wxID_COPY, etc. On Mac (at least),
114 menu.Append( 2, _( "Copy" ) ); // wxWidgets never delivers them to us.
115 menu.Append( 3, _( "Paste" ) );
116 menu.Append( 4, _( "Delete" ) );
117
118 menu.AppendSeparator();
119
120 menu.Append( 5, _( "Select All" ) );
121
122 menu.AppendSeparator();
123
124 menu.Append( wxID_ZOOM_IN, _( "Zoom In" ) );
125 menu.Append( wxID_ZOOM_OUT, _( "Zoom Out" ) );
126
127
128 switch( GetPopupMenuSelectionFromUser( menu ) )
129 {
130 case wxID_UNDO:
131 m_textEditor->Undo();
132 break;
133 case wxID_REDO:
134 m_textEditor->Redo();
135 break;
136
137 case 1:
138 m_textEditor->Cut();
139 break;
140 case 2:
141 m_textEditor->Copy();
142 break;
143 case 3:
144 m_textEditor->Paste();
145 break;
146 case 4:
147 {
148 long from, to;
149 m_textEditor->GetSelection( &from, &to );
150
151 if( to > from )
152 m_textEditor->DeleteRange( from, to );
153
154 break;
155 }
156
157 case 5:
158 m_textEditor->SelectAll();
159 break;
160
161 case wxID_ZOOM_IN:
162 m_textEditor->ZoomIn();
163 break;
164 case wxID_ZOOM_OUT:
165 m_textEditor->ZoomOut();
166 break;
167 }
168}
169
170
171void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
172{
174 m_textEditor->SearchAnchor();
175
176 wxString rules = m_textEditor->GetText();
177 int currentPos = m_textEditor->GetCurrentPos();
178 int startPos = 0;
179
180 for( int line = m_textEditor->LineFromPosition( currentPos ); line > 0; line-- )
181 {
182 int lineStart = m_textEditor->PositionFromLine( line );
183 wxString beginning = m_textEditor->GetTextRange( lineStart, lineStart + 10 );
184
185 if( beginning.StartsWith( wxT( "(rule " ) ) )
186 {
187 startPos = lineStart;
188 break;
189 }
190 }
191
192 enum
193 {
194 NONE,
195 STRING,
196 SEXPR_OPEN,
197 SEXPR_TOKEN,
198 SEXPR_STRING,
199 STRUCT_REF
200 };
201
202 auto isDisallowToken =
203 []( const wxString& token ) -> bool
204 {
205 return token == wxT( "buried_via" )
206 || token == wxT( "graphic" )
207 || token == wxT( "hole" )
208 || token == wxT( "micro_via" )
209 || token == wxT( "pad" )
210 || token == wxT( "text" )
211 || token == wxT( "track" )
212 || token == wxT( "via" )
213 || token == wxT( "zone" );
214 };
215
216 std::stack<wxString> sexprs;
217 wxString partial;
218 wxString last;
219 int context = NONE;
220 int expr_context = NONE;
221
222 for( int i = startPos; i < currentPos; ++i )
223 {
224 wxChar c = m_textEditor->GetCharAt( i );
225
226 if( c == '\\' )
227 {
228 i++; // skip escaped char
229 }
230 else if( context == STRING )
231 {
232 if( c == '"' )
233 {
234 context = NONE;
235 }
236 else
237 {
238 if( expr_context == STRING )
239 {
240 if( c == '\'' )
241 expr_context = NONE;
242 else
243 partial += c;
244 }
245 else if( c == '\'' )
246 {
247 last = partial;
248 partial = wxEmptyString;
249 expr_context = STRING;
250 }
251 else if( c == '.' )
252 {
253 partial = wxEmptyString;
254 expr_context = STRUCT_REF;
255 }
256 else
257 {
258 partial += c;
259 }
260 }
261 }
262 else if( c == '"' )
263 {
264 last = partial;
265 partial = wxEmptyString;
266 context = STRING;
267 }
268 else if( c == '(' )
269 {
270 if( context == SEXPR_OPEN && !partial.IsEmpty() )
271 {
272 m_textEditor->AutoCompCancel();
273 sexprs.push( partial );
274 }
275
276 partial = wxEmptyString;
277 context = SEXPR_OPEN;
278 }
279 else if( c == ')' )
280 {
281 while( !sexprs.empty() && ( sexprs.top() == wxT( "assertion" )
282 || sexprs.top() == wxT( "disallow" )
283 || isDisallowToken( sexprs.top() )
284 || sexprs.top() == wxT( "min_resolved_spokes" )
285 || sexprs.top() == wxT( "zone_connection" ) ) )
286 {
287 sexprs.pop();
288 }
289
290 if( !sexprs.empty() )
291 sexprs.pop();
292
293 context = NONE;
294 }
295 else if( c == ' ' )
296 {
297 if( context == SEXPR_OPEN && ( partial == wxT( "constraint" )
298 || partial == wxT( "disallow" )
299 || partial == wxT( "layer" )
300 || partial == wxT( "severity" ) ) )
301 {
302 m_textEditor->AutoCompCancel();
303 sexprs.push( partial );
304
305 partial = wxEmptyString;
306 context = SEXPR_TOKEN;
307 continue;
308 }
309 else if( partial == wxT( "disallow" )
310 || isDisallowToken( partial )
311 || partial == wxT( "min_resolved_spokes" )
312 || partial == wxT( "zone_connection" ) )
313 {
314 m_textEditor->AutoCompCancel();
315 sexprs.push( partial );
316
317 partial = wxEmptyString;
318 context = SEXPR_TOKEN;
319 continue;
320 }
321 else if( partial == wxT( "rule" )
322 || partial == wxT( "assertion" )
323 || partial == wxT( "condition" ) )
324 {
325 m_textEditor->AutoCompCancel();
326 sexprs.push( partial );
327
328 partial = wxEmptyString;
329 context = SEXPR_STRING;
330 continue;
331 }
332
333 context = NONE;
334 }
335 else
336 {
337 partial += c;
338 }
339 }
340
341 wxString tokens;
342
343 if( context == SEXPR_OPEN )
344 {
345 if( sexprs.empty() )
346 {
347 tokens = wxT( "rule|"
348 "version" );
349 }
350 else if( sexprs.top() == wxT( "rule" ) )
351 {
352 tokens = wxT( "condition|"
353 "constraint|"
354 "layer|"
355 "severity" );
356 }
357 else if( sexprs.top() == wxT( "constraint" ) )
358 {
359 tokens = wxT( "max|min|opt" );
360 }
361 }
362 else if( context == SEXPR_TOKEN )
363 {
364 if( sexprs.empty() )
365 {
366 /* badly formed grammar */
367 }
368 else if( sexprs.top() == wxT( "constraint" ) )
369 {
370 tokens = wxT( "annular_width|"
371 "assertion|"
372 "clearance|"
373 "connection_width|"
374 "courtyard_clearance|"
375 "diff_pair_gap|"
376 "diff_pair_uncoupled|"
377 "disallow|"
378 "edge_clearance|"
379 "length|"
380 "hole_clearance|"
381 "hole_size|"
382 "hole_to_hole|"
383 "min_resolved_spokes|"
384 "physical_clearance|"
385 "physical_hole_clearance|"
386 "silk_clearance|"
387 "skew|"
388 "text_height|"
389 "text_thickness|"
390 "thermal_relief_gap|"
391 "thermal_spoke_width|"
392 "track_width|"
393 "via_count|"
394 "via_diameter|"
395 "zone_connection" );
396 }
397 else if( sexprs.top() == wxT( "disallow" ) || isDisallowToken( sexprs.top() ) )
398 {
399 tokens = wxT( "buried_via|"
400 "graphic|"
401 "hole|"
402 "micro_via|"
403 "pad|"
404 "text|"
405 "track|"
406 "via|"
407 "zone" );
408 }
409 else if( sexprs.top() == wxT( "zone_connection" ) )
410 {
411 tokens = wxT( "none|solid|thermal_reliefs" );
412 }
413 else if( sexprs.top() == wxT( "min_resolved_spokes" ) )
414 {
415 tokens = wxT( "0|1|2|3|4" );
416 }
417 else if( sexprs.top() == wxT( "layer" ) )
418 {
419 tokens = wxT( "inner|outer|\"x\"" );
420 }
421 else if( sexprs.top() == wxT( "severity" ) )
422 {
423 tokens = wxT( "warning|error|ignore|exclusion" );
424 }
425 }
426 else if( context == SEXPR_STRING && !sexprs.empty()
427 && ( sexprs.top() == wxT( "condition" ) || sexprs.top() == wxT( "assertion" ) ) )
428 {
429 m_textEditor->AddText( wxT( "\"" ) );
430 }
431 else if( context == STRING && !sexprs.empty()
432 && ( sexprs.top() == wxT( "condition" ) || sexprs.top() == wxT( "assertion" ) ) )
433 {
434 if( expr_context == STRUCT_REF )
435 {
437 std::set<wxString> propNames;
438
439 for( const PROPERTY_MANAGER::CLASS_INFO& cls : propMgr.GetAllClasses() )
440 {
441 const PROPERTY_LIST& props = propMgr.GetProperties( cls.type );
442
443 for( PROPERTY_BASE* prop : props )
444 {
445 // TODO: It would be nice to replace IsHiddenFromRulesEditor with a nickname
446 // system, so that two different properies don't need to be created. This is
447 // a bigger change than I want to make right now, though.
448 if( prop->IsHiddenFromRulesEditor() )
449 continue;
450
451 wxString ref( prop->Name() );
452 ref.Replace( wxT( " " ), wxT( "_" ) );
453 propNames.insert( ref );
454 }
455 }
456
457 for( const wxString& propName : propNames )
458 tokens += wxT( "|" ) + propName;
459
461
462 for( const wxString& funcSig : functions.GetSignatures() )
463 {
464 if( !funcSig.Contains( "DEPRECATED" ) )
465 tokens += wxT( "|" ) + funcSig;
466 }
467 }
468 else if( expr_context == STRING )
469 {
470 if( m_netClassRegex.Matches( last ) )
471 {
473 std::shared_ptr<NET_SETTINGS>& netSettings = bds.m_NetSettings;
474
475 for( const auto& [ name, netclass ] : netSettings->m_NetClasses )
476 tokens += wxT( "|" ) + name;
477 }
478 else if( m_netNameRegex.Matches( last ) )
479 {
480 BOARD* board = m_frame->GetBoard();
481
482 for( const wxString& netnameCandidate : board->GetNetClassAssignmentCandidates() )
483 tokens += wxT( "|" ) + netnameCandidate;
484 }
485 else if( m_typeRegex.Matches( last ) )
486 {
487 tokens = wxT( "Bitmap|"
488 "Dimension|"
489 "Footprint|"
490 "Graphic|"
491 "Group|"
492 "Leader|"
493 "Pad|"
494 "Target|"
495 "Text|"
496 "Text Box|"
497 "Track|"
498 "Via|"
499 "Zone" );
500 }
501 else if( m_viaTypeRegex.Matches( last ) )
502 {
503 tokens = wxT( "Through|"
504 "Blind/buried|"
505 "Micro" );
506 }
507 else if( m_padTypeRegex.Matches( last ) )
508 {
509 tokens = wxT( "Through-hole|"
510 "SMD|"
511 "Edge connector|"
512 "NPTH, mechanical" );
513 }
514 else if( m_pinTypeRegex.Matches( last ) )
515 {
516 tokens = wxT( "Input|"
517 "Output|"
518 "Bidirectional|"
519 "Tri-state|"
520 "Passive|"
521 "Free|"
522 "Unspecified|"
523 "Power input|"
524 "Power output|"
525 "Open collector|"
526 "Open emitter|"
527 "Unconnected" );
528 }
529 else if( m_fabPropRegex.Matches( last ) )
530 {
531 tokens = wxT( "None|"
532 "BGA pad|"
533 "Fiducial, global to board|"
534 "Fiducial, local to footprint|"
535 "Test point pad|"
536 "Heatsink pad|"
537 "Castellated pad" );
538 }
539 else if( m_shapeRegex.Matches( last ) )
540 {
541 tokens = wxT( "Segment|"
542 "Rectangle|"
543 "Arc|"
544 "Circle|"
545 "Polygon|"
546 "Bezier" );
547 }
548 else if( m_zoneConnStyleRegex.Matches( last ) )
549 {
550 tokens = wxT( "Inherited|"
551 "None|"
552 "Solid|"
553 "Thermal reliefs" );
554 }
555 }
556 }
557
558 if( !tokens.IsEmpty() )
559 m_scintillaTricks->DoAutocomplete( partial, wxSplit( tokens, '|' ) );
560}
561
562
563void PANEL_SETUP_RULES::OnCompile( wxCommandEvent& event )
564{
566
567 try
568 {
569 std::vector<std::shared_ptr<DRC_RULE>> dummyRules;
570
571 DRC_RULES_PARSER parser( m_textEditor->GetText(), _( "DRC rules" ) );
572
573 parser.Parse( dummyRules, m_errorsReport );
574 }
575 catch( PARSE_ERROR& pe )
576 {
577 wxString msg = wxString::Format( wxT( "%s <a href='%d:%d'>%s</a>%s" ),
578 _( "ERROR:" ),
579 pe.lineNumber,
580 pe.byteIndex,
581 pe.ParseProblem(),
582 wxEmptyString );
583
585 }
586
588}
589
590
591void PANEL_SETUP_RULES::OnErrorLinkClicked( wxHtmlLinkEvent& event )
592{
593 wxString link = event.GetLinkInfo().GetHref();
594 wxArrayString parts;
595 long line = 0, offset = 0;
596
597 wxStringSplit( link, parts, ':' );
598
599 if( parts.size() > 1 )
600 {
601 parts[0].ToLong( &line );
602 parts[1].ToLong( &offset );
603 }
604
605 int pos = m_textEditor->PositionFromLine( line - 1 ) + ( offset - 1 );
606
607 m_textEditor->GotoPos( pos );
608
609 m_textEditor->SetFocus();
610}
611
612
614{
615 wxFileName rulesFile( m_frame->GetDesignRulesPath() );
616
617 if( rulesFile.FileExists() )
618 {
619 wxTextFile file( rulesFile.GetFullPath() );
620
621 if( file.Open() )
622 {
623 for ( wxString str = file.GetFirstLine(); !file.Eof(); str = file.GetNextLine() )
624 {
626 m_textEditor->AddText( str << '\n' );
627 }
628
629 m_textEditor->EmptyUndoBuffer();
630
631 wxCommandEvent dummy;
632 OnCompile( dummy );
633 }
634 }
635
636 m_originalText = m_textEditor->GetText();
637
638 if( m_frame->Prj().IsNullProject() )
639 {
640 m_textEditor->ClearAll();
641 m_textEditor->AddText( _( "Design rules cannot be added without a project" ) );
642 m_textEditor->Disable();
643 }
644
645 return true;
646}
647
648
650{
651 if( m_originalText == m_textEditor->GetText() )
652 return true;
653
654 if( m_frame->Prj().IsNullProject() )
655 return true;
656
657 wxString rulesFilepath = m_frame->GetDesignRulesPath();
658
659 try
660 {
661 if( m_textEditor->SaveFile( rulesFilepath ) )
662 {
663 m_frame->GetBoard()->GetDesignSettings().m_DRCEngine->InitEngine( rulesFilepath );
664 return true;
665 }
666 }
667 catch( PARSE_ERROR& )
668 {
669 // Don't lock them in to the Setup dialog if they have bad rules. They've already
670 // saved them so we can allow an exit.
671 return true;
672 }
673
674 return false;
675}
676
677
678void PANEL_SETUP_RULES::OnSyntaxHelp( wxHyperlinkEvent& aEvent )
679{
680 if( m_helpWindow )
681 {
683 return;
684 }
685
686 wxString msg =
688 ;
689
690#ifdef __WXMAC__
691 msg.Replace( wxT( "Ctrl+" ), wxT( "Cmd+" ) );
692#endif
693
694 m_helpWindow = new HTML_MESSAGE_BOX( nullptr, _( "Syntax Help" ) );
695 m_helpWindow->SetDialogSizeInDU( 420, 320 );
696
697 wxString html_txt;
698 ConvertMarkdown2Html( wxGetTranslation( msg ), html_txt );
699
700 html_txt.Replace( wxS( "<td" ), wxS( "<td valign=top" ) );
701 m_helpWindow->AddHTML_Text( html_txt );
702
704}
const char * name
Definition: DXF_plotter.cpp:57
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:106
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
std::shared_ptr< DRC_ENGINE > m_DRCEngine
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:271
std::set< wxString > GetNetClassAssignmentCandidates() const
Return the set of netname candidates for netclass assignment.
Definition: board.cpp:1607
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:731
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
void SetDialogSizeInDU(int aWidth, int aHeight)
Set the dialog size, using a "logical" value.
void AddHTML_Text(const wxString &message)
Add HTML text (without any change) to message list.
void ShowModeless()
Show a modeless version of the dialog (without an OK button).
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
void SetModified()
Definition: paged_dialog.h:43
static PAGED_DIALOG * GetDialog(wxWindow *aWindow)
Class PANEL_SETUP_RULES_BASE.
wxStyledTextCtrl * m_textEditor
WX_HTML_REPORT_BOX * m_errorsReport
wxBitmapButton * m_compileButton
bool TransferDataToWindow() override
void OnErrorLinkClicked(wxHtmlLinkEvent &event) override
void onScintillaCharAdded(wxStyledTextEvent &aEvent)
PCB_EDIT_FRAME * m_frame
void OnContextMenu(wxMouseEvent &event) override
~PANEL_SETUP_RULES() override
HTML_MESSAGE_BOX * m_helpWindow
void OnCompile(wxCommandEvent &event) override
bool TransferDataFromWindow() override
void OnSyntaxHelp(wxHyperlinkEvent &aEvent) override
PANEL_SETUP_RULES(wxWindow *aParentWindow, PCB_EDIT_FRAME *aFrame)
void onCharHook(wxKeyEvent &aEvent)
SCINTILLA_TRICKS * m_scintillaTricks
const wxArrayString GetSignatures() const
static PCBEXPR_BUILTIN_FUNCTIONS & Instance()
wxString GetDesignRulesPath()
Return the absolute path to the design rules file for the currently-loaded board.
BOARD * GetBoard() const
The main frame for Pcbnew.
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition: project.cpp:161
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:74
CLASSES_INFO GetAllClasses()
const PROPERTY_LIST & GetProperties(TYPE_ID aType) const
Return all properties for a specific type.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:76
Add cut/copy/paste, dark theme, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
void DoAutocomplete(const wxString &aPartial, const wxArrayString &aTokens)
void Clear()
Delete the stored messages.
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
void Flush()
Build the HTML messages page.
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:360
This file is part of the common library.
#define _(s)
@ NONE
Definition: kibis.h:54
see class PGM_BASE
std::vector< PROPERTY_BASE * > PROPERTY_LIST
Definition: property_mgr.h:48
@ RPT_SEVERITY_ERROR
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:115
std::vector< FAB_LAYER_COLOR > dummy
bool ConvertSmartQuotesAndDashes(wxString *aString)
Convert curly quotes and em/en dashes to straight quotes and dashes.
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
void ConvertMarkdown2Html(const wxString &aMarkdownInput, wxString &aHtmlOutput)
A filename or source description, a problem input line, a line number, a byte offset,...
Definition: ki_exception.h:119
int lineNumber
at which line number, 1 based index.
Definition: ki_exception.h:120
const wxString ParseProblem()
Definition: ki_exception.h:150
int byteIndex
at which byte offset within the line, 1 based index
Definition: ki_exception.h:121