KiCad PCB EDA Suite
string.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) 2004-2019 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 
29 #include <clocale>
30 #include <macros.h>
31 #include <richio.h> // StrPrintf
32 #include <kicad_string.h>
33 
34 
40 static const char illegalFileNameChars[] = "\\/:\"<>|";
41 
42 
43 bool ConvertSmartQuotesAndDashes( wxString* aString )
44 {
45  bool retVal = false;
46 
47  for( wxString::iterator ii = aString->begin(); ii != aString->end(); ++ii )
48  {
49  if( *ii == L'\u00B4' || *ii == L'\u2018' || *ii == L'\u2019' )
50  {
51  *ii = '\'';
52  retVal = true;
53  }
54  if( *ii == L'\u201C' || *ii == L'\u201D' )
55  {
56  *ii = '"';
57  retVal = true;
58  }
59  if( *ii == L'\u2013' || *ii == L'\u2014' )
60  {
61  *ii = '-';
62  retVal = true;
63  }
64  }
65 
66  return retVal;
67 }
68 
69 
77 wxString EscapeString( const wxString& aSource, ESCAPE_CONTEXT aContext )
78 {
79  wxString converted;
80 
81  for( wxUniChar c: aSource )
82  {
83  if( aContext == CTX_NETNAME )
84  {
85  if( c == '/' )
86  converted += "{slash}";
87  else if( c == '\n' || c == '\r' )
88  converted += ""; // drop
89  else
90  converted += c;
91  }
92  else if( aContext == CTX_LIBID )
93  {
94  if( c == '{' )
95  converted += "{brace}";
96  else if( c == ':' )
97  converted += "{colon}";
98  else if( c == '\n' || c == '\r' )
99  converted += ""; // drop
100  else
101  converted += c;
102  }
103  else if( aContext == CTX_QUOTED_STR )
104  {
105  if( c == '\"' )
106  converted += "{dblquote}";
107  else
108  converted += c;
109  }
110  else if( aContext == CTX_LINE )
111  {
112  if( c == '\n' || c == '\r' )
113  converted += "{return}";
114  else
115  converted += c;
116  }
117  else if( aContext == CTX_FILENAME )
118  {
119  if( c == '{' )
120  converted += "{brace}";
121  else if( c == '/' )
122  converted += "{slash}";
123  else if( c == '\\' )
124  converted += "{backslash}";
125  else if( c == '\"' )
126  converted += "{dblquote}";
127  else if( c == '<' )
128  converted += "{lt}";
129  else if( c == '>' )
130  converted += "{gt}";
131  else if( c == '|' )
132  converted += "{bar}";
133  else if( c == ':' )
134  converted += "{colon}";
135  else if( c == '\t' )
136  converted += "{tab}";
137  else if( c == '\n' || c == '\r' )
138  converted += "{return}";
139  else
140  converted += c;
141  }
142  else
143  converted += c;
144  }
145 
146  return converted;
147 }
148 
149 
150 wxString UnescapeString( const wxString& aSource )
151 {
152  wxString newbuf;
153  size_t sourceLen = aSource.length();
154 
155  for( size_t i = 0; i < sourceLen; ++i )
156  {
157  if( ( aSource[i] == '$' || aSource[i] == '^' || aSource[i] == '_' )
158  && i + 1 < sourceLen && aSource[i+1] == '{' )
159  {
160  for( ; i < sourceLen; ++i )
161  {
162  newbuf += aSource[i];
163 
164  if( aSource[i] == '}' )
165  break;
166  }
167  }
168  else if( aSource[i] == '{' )
169  {
170  wxString token;
171  int depth = 1;
172 
173  for( i = i + 1; i < sourceLen; ++i )
174  {
175  if( aSource[i] == '{' )
176  depth++;
177  else if( aSource[i] == '}' )
178  depth--;
179 
180  if( depth <= 0 )
181  break;
182  else
183  token.append( aSource[i] );
184  }
185 
186  if( token == wxS( "dblquote" ) ) newbuf.append( wxS( "\"" ) );
187  else if( token == wxS( "quote" ) ) newbuf.append( wxS( "'" ) );
188  else if( token == wxS( "lt" ) ) newbuf.append( wxS( "<" ) );
189  else if( token == wxS( "gt" ) ) newbuf.append( wxS( ">" ) );
190  else if( token == wxS( "backslash" ) ) newbuf.append( wxS( "\\" ) );
191  else if( token == wxS( "slash" ) ) newbuf.append( wxS( "/" ) );
192  else if( token == wxS( "bar" ) ) newbuf.append( wxS( "|" ) );
193  else if( token == wxS( "colon" ) ) newbuf.append( wxS( ":" ) );
194  else if( token == wxS( "space" ) ) newbuf.append( wxS( " " ) );
195  else if( token == wxS( "dollar" ) ) newbuf.append( wxS( "$" ) );
196  else if( token == wxS( "tab" ) ) newbuf.append( wxS( "\t" ) );
197  else if( token == wxS( "return" ) ) newbuf.append( wxS( "\n" ) );
198  else if( token == wxS( "brace" ) ) newbuf.append( wxS( "{" ) );
199  else if( token.IsEmpty() ) newbuf.append( wxS( "{" ) );
200  else
201  {
202  newbuf.append( "{" + UnescapeString( token ) + "}" );
203  }
204  }
205  else
206  {
207  newbuf.append( aSource[i] );
208  }
209  }
210 
211  return newbuf;
212 }
213 
214 
215 int ReadDelimitedText( wxString* aDest, const char* aSource )
216 {
217  std::string utf8; // utf8 but without escapes and quotes.
218  bool inside = false;
219  const char* start = aSource;
220  char cc;
221 
222  while( (cc = *aSource++) != 0 )
223  {
224  if( cc == '"' )
225  {
226  if( inside )
227  break; // 2nd double quote is end of delimited text
228 
229  inside = true; // first delimiter found, make note, do not copy
230  }
231 
232  else if( inside )
233  {
234  if( cc == '\\' )
235  {
236  cc = *aSource++;
237 
238  if( !cc )
239  break;
240 
241  // do no copy the escape byte if it is followed by \ or "
242  if( cc != '"' && cc != '\\' )
243  utf8 += '\\';
244 
245  utf8 += cc;
246  }
247  else
248  {
249  utf8 += cc;
250  }
251  }
252  }
253 
254  *aDest = FROM_UTF8( utf8.c_str() );
255 
256  return aSource - start;
257 }
258 
259 
260 int ReadDelimitedText( char* aDest, const char* aSource, int aDestSize )
261 {
262  if( aDestSize <= 0 )
263  return 0;
264 
265  bool inside = false;
266  const char* start = aSource;
267  char* limit = aDest + aDestSize - 1;
268  char cc;
269 
270  while( (cc = *aSource++) != 0 && aDest < limit )
271  {
272  if( cc == '"' )
273  {
274  if( inside )
275  break; // 2nd double quote is end of delimited text
276 
277  inside = true; // first delimiter found, make note, do not copy
278  }
279 
280  else if( inside )
281  {
282  if( cc == '\\' )
283  {
284  cc = *aSource++;
285 
286  if( !cc )
287  break;
288 
289  // do no copy the escape byte if it is followed by \ or "
290  if( cc != '"' && cc != '\\' )
291  *aDest++ = '\\';
292 
293  if( aDest < limit )
294  *aDest++ = cc;
295  }
296  else
297  {
298  *aDest++ = cc;
299  }
300  }
301  }
302 
303  *aDest = 0;
304 
305  return aSource - start;
306 }
307 
308 
309 std::string EscapedUTF8( wxString aString )
310 {
311  // No new-lines allowed in quoted strings
312  aString.Replace( "\r\n", "\r" );
313  aString.Replace( "\n", "\r" );
314 
315  std::string utf8 = TO_UTF8( aString );
316 
317  std::string ret;
318 
319  ret += '"';
320 
321  for( std::string::const_iterator it = utf8.begin(); it!=utf8.end(); ++it )
322  {
323  // this escaping strategy is designed to be compatible with ReadDelimitedText():
324  if( *it == '"' )
325  {
326  ret += '\\';
327  ret += '"';
328  }
329  else if( *it == '\\' )
330  {
331  ret += '\\'; // double it up
332  ret += '\\';
333  }
334  else
335  {
336  ret += *it;
337  }
338  }
339 
340  ret += '"';
341 
342  return ret;
343 }
344 
345 
346 wxString EscapeHTML( const wxString& aString )
347 {
348  wxString converted;
349 
350  for( wxUniChar c: aString )
351  {
352  if( c == '\"' )
353  converted += "&quot;";
354  else if( c == '\'' )
355  converted += "&apos;";
356  else if( c == '&' )
357  converted += "&amp;";
358  else if( c == '<' )
359  converted += "&lt;";
360  else if( c == '>' )
361  converted += "&gt;";
362  else
363  converted += c;
364  }
365 
366  return converted;
367 }
368 
369 
370 bool NoPrintableChars( wxString aString )
371 {
372  return aString.Trim( true ).Trim( false ).IsEmpty();
373 }
374 
375 
376 char* StrPurge( char* text )
377 {
378  static const char whitespace[] = " \t\n\r\f\v";
379 
380  if( text )
381  {
382  while( *text && strchr( whitespace, *text ) )
383  ++text;
384 
385  char* cp = text + strlen( text ) - 1;
386 
387  while( cp >= text && strchr( whitespace, *cp ) )
388  *cp-- = '\0';
389  }
390 
391  return text;
392 }
393 
394 
395 char* GetLine( FILE* File, char* Line, int* LineNum, int SizeLine )
396 {
397  do {
398  if( fgets( Line, SizeLine, File ) == NULL )
399  return NULL;
400 
401  if( LineNum )
402  *LineNum += 1;
403 
404  } while( Line[0] == '#' || Line[0] == '\n' || Line[0] == '\r' || Line[0] == 0 );
405 
406  strtok( Line, "\n\r" );
407  return Line;
408 }
409 
410 
411 wxString DateAndTime()
412 {
413  wxDateTime datetime = wxDateTime::Now();
414 
415  datetime.SetCountry( wxDateTime::Country_Default );
416  return datetime.Format( wxDefaultDateTimeFormat, wxDateTime::Local );
417 }
418 
419 
420 int StrNumCmp( const wxString& aString1, const wxString& aString2, bool aIgnoreCase )
421 {
422  int nb1 = 0, nb2 = 0;
423 
424  auto str1 = aString1.begin();
425  auto str2 = aString2.begin();
426 
427  while( str1 != aString1.end() && str2 != aString2.end() )
428  {
429  wxUniChar c1 = *str1;
430  wxUniChar c2 = *str2;
431 
432  if( wxIsdigit( c1 ) && wxIsdigit( c2 ) ) // Both characters are digits, do numeric compare.
433  {
434  nb1 = 0;
435  nb2 = 0;
436 
437  do
438  {
439  c1 = *str1;
440  nb1 = nb1 * 10 + (int) c1 - '0';
441  ++str1;
442  } while( str1 != aString1.end() && wxIsdigit( *str1 ) );
443 
444  do
445  {
446  c2 = *str2;
447  nb2 = nb2 * 10 + (int) c2 - '0';
448  ++str2;
449  } while( str2 != aString2.end() && wxIsdigit( *str2 ) );
450 
451  if( nb1 < nb2 )
452  return -1;
453 
454  if( nb1 > nb2 )
455  return 1;
456 
457  c1 = ( str1 != aString1.end() ) ? *str1 : wxUniChar( 0 );
458  c2 = ( str2 != aString2.end() ) ? *str2 : wxUniChar( 0 );
459  }
460 
461  // Any numerical comparisons to here are identical.
462  if( aIgnoreCase )
463  {
464  if( wxToupper( c1 ) < wxToupper( c2 ) )
465  return -1;
466 
467  if( wxToupper( c1 ) > wxToupper( c2 ) )
468  return 1;
469  }
470  else
471  {
472  if( c1 < c2 )
473  return -1;
474 
475  if( c1 > c2 )
476  return 1;
477  }
478 
479  if( str1 != aString1.end() )
480  ++str1;
481 
482  if( str2 != aString2.end() )
483  ++str2;
484  }
485 
486  if( str1 == aString1.end() && str2 != aString2.end() )
487  {
488  return -1; // Identical to here but aString1 is longer.
489  }
490  else if( str1 != aString1.end() && str2 == aString2.end() )
491  {
492  return 1; // Identical to here but aString2 is longer.
493  }
494 
495  return 0;
496 }
497 
498 
499 bool WildCompareString( const wxString& pattern, const wxString& string_to_tst,
500  bool case_sensitive )
501 {
502  const wxChar* cp = NULL, * mp = NULL;
503  const wxChar* wild, * string;
504  wxString _pattern, _string_to_tst;
505 
506  if( case_sensitive )
507  {
508  wild = pattern.GetData();
509  string = string_to_tst.GetData();
510  }
511  else
512  {
513  _pattern = pattern;
514  _pattern.MakeUpper();
515  _string_to_tst = string_to_tst;
516  _string_to_tst.MakeUpper();
517  wild = _pattern.GetData();
518  string = _string_to_tst.GetData();
519  }
520 
521  while( ( *string ) && ( *wild != '*' ) )
522  {
523  if( ( *wild != *string ) && ( *wild != '?' ) )
524  return false;
525 
526  wild++; string++;
527  }
528 
529  while( *string )
530  {
531  if( *wild == '*' )
532  {
533  if( !*++wild )
534  return 1;
535  mp = wild;
536  cp = string + 1;
537  }
538  else if( ( *wild == *string ) || ( *wild == '?' ) )
539  {
540  wild++;
541  string++;
542  }
543  else
544  {
545  wild = mp;
546  string = cp++;
547  }
548  }
549 
550  while( *wild == '*' )
551  {
552  wild++;
553  }
554 
555  return !*wild;
556 }
557 
558 
559 bool ApplyModifier( double& value, const wxString& aString )
560 {
561  static const wxString modifiers( wxT( "pnumkKM" ) );
562 
563  if( !aString.length() )
564  return false;
565 
566  wxChar modifier;
567  wxString units;
568 
569  if( modifiers.Find( aString[ 0 ] ) >= 0 )
570  {
571  modifier = aString[ 0 ];
572  units = aString.Mid( 1 ).Trim();
573  }
574  else
575  {
576  modifier = ' ';
577  units = aString.Mid( 0 ).Trim();
578  }
579 
580  if( units.length()
581  && !units.CmpNoCase( wxT( "F" ) )
582  && !units.CmpNoCase( wxT( "hz" ) )
583  && !units.CmpNoCase( wxT( "W" ) )
584  && !units.CmpNoCase( wxT( "V" ) )
585  && !units.CmpNoCase( wxT( "H" ) ) )
586  return false;
587 
588  if( modifier == 'p' )
589  value *= 1.0e-12;
590  if( modifier == 'n' )
591  value *= 1.0e-9;
592  else if( modifier == 'u' )
593  value *= 1.0e-6;
594  else if( modifier == 'm' )
595  value *= 1.0e-3;
596  else if( modifier == 'k' || modifier == 'K' )
597  value *= 1.0e3;
598  else if( modifier == 'M' )
599  value *= 1.0e6;
600  else if( modifier == 'G' )
601  value *= 1.0e9;
602 
603  return true;
604 }
605 
606 
607 int ValueStringCompare( wxString strFWord, wxString strSWord )
608 {
609  // Compare unescaped text
610  strFWord = UnescapeString( strFWord );
611  strSWord = UnescapeString( strSWord );
612 
613  // The different sections of the two strings
614  wxString strFWordBeg, strFWordMid, strFWordEnd;
615  wxString strSWordBeg, strSWordMid, strSWordEnd;
616 
617  // Split the two strings into separate parts
618  SplitString( strFWord, &strFWordBeg, &strFWordMid, &strFWordEnd );
619  SplitString( strSWord, &strSWordBeg, &strSWordMid, &strSWordEnd );
620 
621  // Compare the Beginning section of the strings
622  int isEqual = strFWordBeg.CmpNoCase( strSWordBeg );
623 
624  if( isEqual > 0 )
625  return 1;
626  else if( isEqual < 0 )
627  return -1;
628  else
629  {
630  // If the first sections are equal compare their digits
631  double lFirstNumber = 0;
632  double lSecondNumber = 0;
633  bool endingIsModifier = false;
634 
635  strFWordMid.ToDouble( &lFirstNumber );
636  strSWordMid.ToDouble( &lSecondNumber );
637 
638  endingIsModifier |= ApplyModifier( lFirstNumber, strFWordEnd );
639  endingIsModifier |= ApplyModifier( lSecondNumber, strSWordEnd );
640 
641  if( lFirstNumber > lSecondNumber )
642  return 1;
643  else if( lFirstNumber < lSecondNumber )
644  return -1;
645  // If the first two sections are equal and the endings are modifiers then compare them
646  else if( !endingIsModifier )
647  return strFWordEnd.CmpNoCase( strSWordEnd );
648  // Ran out of things to compare; they must match
649  else
650  return 0;
651  }
652 }
653 
654 
655 int SplitString( wxString strToSplit,
656  wxString* strBeginning,
657  wxString* strDigits,
658  wxString* strEnd )
659 {
660  static const wxString separators( wxT( ".," ) );
661 
662  // Clear all the return strings
663  strBeginning->Empty();
664  strDigits->Empty();
665  strEnd->Empty();
666 
667  // There no need to do anything if the string is empty
668  if( strToSplit.length() == 0 )
669  return 0;
670 
671  // Starting at the end of the string look for the first digit
672  int ii;
673 
674  for( ii = (strToSplit.length() - 1); ii >= 0; ii-- )
675  {
676  if( wxIsdigit( strToSplit[ii] ) )
677  break;
678  }
679 
680  // If there were no digits then just set the single string
681  if( ii < 0 )
682  {
683  *strBeginning = strToSplit;
684  }
685  else
686  {
687  // Since there is at least one digit this is the trailing string
688  *strEnd = strToSplit.substr( ii + 1 );
689 
690  // Go to the end of the digits
691  int position = ii + 1;
692 
693  for( ; ii >= 0; ii-- )
694  {
695  if( !wxIsdigit( strToSplit[ii] ) && separators.Find( strToSplit[ii] ) < 0 )
696  break;
697  }
698 
699  // If all that was left was digits, then just set the digits string
700  if( ii < 0 )
701  *strDigits = strToSplit.substr( 0, position );
702 
703  /* We were only looking for the last set of digits everything else is
704  * part of the preamble */
705  else
706  {
707  *strDigits = strToSplit.substr( ii + 1, position - ii - 1 );
708  *strBeginning = strToSplit.substr( 0, ii + 1 );
709  }
710  }
711 
712  return 0;
713 }
714 
715 
716 int GetTrailingInt( const wxString& aStr )
717 {
718  int number = 0;
719  int base = 1;
720 
721  // Trim and extract the trailing numeric part
722  int index = aStr.Len() - 1;
723 
724  while( index >= 0 )
725  {
726  const char chr = aStr.GetChar( index );
727 
728  if( chr < '0' || chr > '9' )
729  break;
730 
731  number += ( chr - '0' ) * base;
732  base *= 10;
733  index--;
734  }
735 
736  return number;
737 }
738 
739 
741 {
743 }
744 
745 
746 bool ReplaceIllegalFileNameChars( std::string* aName, int aReplaceChar )
747 {
748  bool changed = false;
749  std::string result;
750  result.reserve( aName->length() );
751 
752  for( std::string::iterator it = aName->begin(); it != aName->end(); ++it )
753  {
754  if( strchr( illegalFileNameChars, *it ) )
755  {
756  if( aReplaceChar )
757  StrPrintf( &result, "%c", aReplaceChar );
758  else
759  StrPrintf( &result, "%%%02x", *it );
760 
761  changed = true;
762  }
763  else
764  {
765  result += *it;
766  }
767  }
768 
769  if( changed )
770  *aName = result;
771 
772  return changed;
773 }
774 
775 
776 bool ReplaceIllegalFileNameChars( wxString& aName, int aReplaceChar )
777 {
778  bool changed = false;
779  wxString result;
780  result.reserve( aName.Length() );
781  wxString illWChars = GetIllegalFileNameWxChars();
782 
783  for( wxString::iterator it = aName.begin(); it != aName.end(); ++it )
784  {
785  if( illWChars.Find( *it ) != wxNOT_FOUND )
786  {
787  if( aReplaceChar )
788  result += aReplaceChar;
789  else
790  result += wxString::Format( "%%%02x", *it );
791 
792  changed = true;
793  }
794  else
795  {
796  result += *it;
797  }
798  }
799 
800  if( changed )
801  aName = result;
802 
803  return changed;
804 }
805 
806 
807 void wxStringSplit( const wxString& aText, wxArrayString& aStrings, wxChar aSplitter )
808 {
809  wxString tmp;
810 
811  for( unsigned ii = 0; ii < aText.Length(); ii++ )
812  {
813  if( aText[ii] == aSplitter )
814  {
815  aStrings.Add( tmp );
816  tmp.Clear();
817  }
818 
819  else
820  tmp << aText[ii];
821  }
822 
823  if( !tmp.IsEmpty() )
824  {
825  aStrings.Add( tmp );
826  }
827 }
828 
829 
830 void StripTrailingZeros( wxString& aStringValue, unsigned aTrailingZeroAllowed )
831 {
832  struct lconv* lc = localeconv();
833  char sep = lc->decimal_point[0];
834  unsigned sep_pos = aStringValue.Find( sep );
835 
836  if( sep_pos > 0 )
837  {
838  // We want to keep at least aTrailingZeroAllowed digits after the separator
839  unsigned min_len = sep_pos + aTrailingZeroAllowed + 1;
840 
841  while( aStringValue.Len() > min_len )
842  {
843  if( aStringValue.Last() == '0' )
844  aStringValue.RemoveLast();
845  else
846  break;
847  }
848  }
849 }
static const char illegalFileNameChars[]
Illegal file name characters used to insure file names will be valid on all supported platforms.
Definition: string.cpp:40
ESCAPE_CONTEXT
Escape/Unescape routines to safely encode reserved-characters in various contexts.
Definition: kicad_string.h:51
int SplitString(wxString strToSplit, wxString *strBeginning, wxString *strDigits, wxString *strEnd)
Breaks a string into three parts: he alphabetic preamble, the numeric part, and any alphabetic ending...
Definition: string.cpp:655
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
Definition: string.cpp:420
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:110
char * StrPurge(char *text)
Remove leading and training spaces, tabs and end of line chars in text.
Definition: string.cpp:376
bool ReplaceIllegalFileNameChars(std::string *aName, int aReplaceChar)
Checks aName for illegal file name characters.
Definition: string.cpp:746
void StripTrailingZeros(wxString &aStringValue, unsigned aTrailingZeroAllowed)
Remove trailing zeros from a string containing a converted float number.
Definition: string.cpp:830
This file contains miscellaneous commonly used macros and functions.
std::string EscapedUTF8(wxString aString)
Return an 8 bit UTF8 string given aString in Unicode form.
Definition: string.cpp:309
int StrPrintf(std::string *result, const char *format,...)
This is like sprintf() but the output is appended to a std::string instead of to a character array.
Definition: richio.cpp:78
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
#define NULL
int ValueStringCompare(wxString strFWord, wxString strSWord)
Compare strings like the strcmp function but handle numbers and modifiers within the string text corr...
Definition: string.cpp:607
bool WildCompareString(const wxString &pattern, const wxString &string_to_tst, bool case_sensitive)
Compare a string against wild card (* and ?) pattern using the usual rules.
Definition: string.cpp:499
wxString GetIllegalFileNameWxChars()
Definition: string.cpp:740
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
Definition: string.cpp:807
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
char * GetLine(FILE *File, char *Line, int *LineNum, int SizeLine)
Read one line line from aFile.
Definition: string.cpp:395
wxString UnescapeString(const wxString &aSource)
Definition: string.cpp:150
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
These Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which ar...
Definition: string.cpp:77
int GetTrailingInt(const wxString &aStr)
Gets the trailing int, if any, from a string.
Definition: string.cpp:716
int ReadDelimitedText(wxString *aDest, const char *aSource)
Copy bytes from aSource delimited string segment to aDest wxString.
Definition: string.cpp:215
bool NoPrintableChars(wxString aString)
Return true if the string is empty or contains only whitespace.
Definition: string.cpp:370
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
Definition: string.cpp:346
bool ApplyModifier(double &value, const wxString &aString)
Definition: string.cpp:559
bool ConvertSmartQuotesAndDashes(wxString *aString)
Converts curly quotes and em/en dashes to straight quotes and dashes.
Definition: string.cpp:43
wxString DateAndTime()
Definition: string.cpp:411