diff --git a/build/bakefiles/regex.bkl b/build/bakefiles/regex.bkl
index fa9a7ce92d..b93a2fc24c 100644
--- a/build/bakefiles/regex.bkl
+++ b/build/bakefiles/regex.bkl
@@ -10,7 +10,7 @@
builtin
- wxregex$(WXDEBUGFLAG)$(HOST_SUFFIX)
+ wxregex$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(HOST_SUFFIX)
$(TOP_SRCDIR)src/regex
@@ -18,11 +18,12 @@
+ $(id)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(HOST_SUFFIX)
$(TOP_SRCDIR)include
$(SETUPHDIR)
$(UNICODE_DEFINE)
$(LIBDIRNAME)
- -w-8004 -w-8012 -w-8057 -w-8066
+ -w-8008 -w-8012 -w-8057 -w-8064 -w-8066 -w-8070
src/regex/regcomp.c
src/regex/regexec.c
diff --git a/include/wx/features.h b/include/wx/features.h
index 80d7e6b317..fec65015ba 100644
--- a/include/wx/features.h
+++ b/include/wx/features.h
@@ -56,5 +56,13 @@
#undef wxHAS_CRASH_REPORT
#endif
+/* wxRE_ADVANCED is not always available, depending on regex library used
+ * (it's unavailable only if compiling via configure against system library) */
+#ifndef WX_NO_REGEX_ADVANCED
+ #define wxHAS_REGEX_ADVANCED
+#else
+ #undef wxHAS_REGEX_ADVANCED
+#endif
+
#endif /* _WX_FEATURES_H_ */
diff --git a/include/wx/regex.h b/include/wx/regex.h
index 78224ca942..1656008c5a 100644
--- a/include/wx/regex.h
+++ b/include/wx/regex.h
@@ -29,8 +29,13 @@ class WXDLLIMPEXP_BASE wxString;
// flags for regex compilation: these can be used with Compile()
enum
{
- // use extended regex syntax (default)
+ // use extended regex syntax
wxRE_EXTENDED = 0,
+
+ // use advanced RE syntax (built-in regex only)
+#ifdef wxHAS_REGEX_ADVANCED
+ wxRE_ADVANCED = 1,
+#endif
// use basic RE syntax
wxRE_BASIC = 2,
diff --git a/src/common/regex.cpp b/src/common/regex.cpp
index 12d49ee971..2cd6afafce 100644
--- a/src/common/regex.cpp
+++ b/src/common/regex.cpp
@@ -73,7 +73,7 @@ public:
private:
// return the string containing the error message for the given err code
- wxString GetErrorMsg(int errorcode) const;
+ wxString GetErrorMsg(int errorcode, bool badconv) const;
// init the members
void Init()
@@ -131,8 +131,19 @@ wxRegExImpl::~wxRegExImpl()
Free();
}
-wxString wxRegExImpl::GetErrorMsg(int errorcode) const
+wxString wxRegExImpl::GetErrorMsg(int errorcode, bool badconv) const
{
+#if wxUSE_UNICODE && !defined(__REG_NOFRONT)
+ // currently only needed when using system library in Unicode mode
+ if ( badconv )
+ {
+ return _("conversion to 8-bit encoding failed");
+ }
+#else
+ // 'use' badconv to avoid a compiler warning
+ (void)badconv;
+#endif
+
wxString szError;
// first get the string length needed
@@ -158,14 +169,25 @@ bool wxRegExImpl::Compile(const wxString& expr, int flags)
{
Reinit();
- // translate our flags to regcomp() ones
- wxASSERT_MSG( !(flags &
- ~(wxRE_BASIC | wxRE_ICASE | wxRE_NOSUB | wxRE_NEWLINE)),
+#ifdef WX_NO_REGEX_ADVANCED
+# define FLAVORS wxRE_BASIC
+#else
+# define FLAVORS (wxRE_ADVANCED | wxRE_BASIC)
+ wxASSERT_MSG( (flags & FLAVORS) != FLAVORS,
+ _T("incompatible flags in wxRegEx::Compile") );
+#endif
+ wxASSERT_MSG( !(flags & ~(FLAVORS | wxRE_ICASE | wxRE_NOSUB | wxRE_NEWLINE)),
_T("unrecognized flags in wxRegEx::Compile") );
+ // translate our flags to regcomp() ones
int flagsRE = 0;
if ( !(flags & wxRE_BASIC) )
- flagsRE |= REG_EXTENDED;
+#ifndef WX_NO_REGEX_ADVANCED
+ if (flags & wxRE_ADVANCED)
+ flagsRE |= REG_ADVANCED;
+ else
+#endif
+ flagsRE |= REG_EXTENDED;
if ( flags & wxRE_ICASE )
flagsRE |= REG_ICASE;
if ( flags & wxRE_NOSUB )
@@ -173,14 +195,19 @@ bool wxRegExImpl::Compile(const wxString& expr, int flags)
if ( flags & wxRE_NEWLINE )
flagsRE |= REG_NEWLINE;
+ // compile it
+#ifdef __REG_NOFRONT
+ bool conv = true;
+ int errorcode = re_comp(&m_RegEx, expr, expr.length(), flagsRE);
+#else
+ const wxWX2MBbuf conv = expr.mbc_str();
+ int errorcode = conv ? regcomp(&m_RegEx, conv, flagsRE) : REG_BADPAT;
+#endif
-
- int errorcode = regcomp(&m_RegEx, expr, flagsRE);
-
- if ( errorcode )
+ if ( errorcode )
{
wxLogError(_("Invalid regular expression '%s': %s"),
- expr.c_str(), GetErrorMsg(errorcode).c_str());
+ expr.c_str(), GetErrorMsg(errorcode, !conv).c_str());
m_isCompiled = FALSE;
}
@@ -250,7 +277,13 @@ bool wxRegExImpl::Matches(const wxChar *str, int flags) const
}
// do match it
- int rc = regexec(&self->m_RegEx, str, m_nMatches, m_Matches, flagsRE);
+#ifdef __REG_NOFRONT
+ bool conv = true;
+ int rc = re_exec(&self->m_RegEx, str, wxStrlen(str), NULL, m_nMatches, m_Matches, flagsRE);
+#else
+ const wxWX2MBbuf conv = wxConvertWX2MB(str);
+ int rc = conv ? regexec(&self->m_RegEx, conv, m_nMatches, m_Matches, flagsRE) : REG_BADPAT;
+#endif
switch ( rc )
{
@@ -261,7 +294,7 @@ bool wxRegExImpl::Matches(const wxChar *str, int flags) const
default:
// an error occured
wxLogError(_("Failed to match '%s' in regular expression: %s"),
- str, GetErrorMsg(rc).c_str());
+ str, GetErrorMsg(rc, !conv).c_str());
// fall through
case REG_NOMATCH:
diff --git a/src/regex/splice.sh b/src/regex/splice.sh
new file mode 100755
index 0000000000..02fad6de19
--- /dev/null
+++ b/src/regex/splice.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+#############################################################################
+# Name: splice
+# Purpose: Splice a marked section of regcustom.h into regex.h
+# Author: Mike Wetherell
+# RCS-ID: $Id$
+# Copyright: (c) 2004 Mike Wetherell
+# Licence: wxWindows licence
+#############################################################################
+
+#
+# Works by greping for the marks then passing their line numbers to sed. Which
+# is slighly the long way round, but allows some error checking.
+#
+
+SRC=regcustom.h
+DST=regex.h
+MARK1='^/\* --- begin --- \*/$'
+MARK2='^/\* --- end --- \*/$'
+PROG=`basename $0`
+TMP=$DST.tmp
+
+# findline(pattern, file)
+# Prints the line number of the 1st line matching the pattern in the file
+#
+findline() {
+ if ! LINE=`grep -n -- "$1" "$2"`; then
+ echo "$PROG: marker '$1' not found in '$2'" >&2
+ return 1
+ fi
+ echo $LINE | sed -n '1s/[^0-9].*//p' # take just the line number
+}
+
+# findmarkers([out] line1, [out] line2, pattern1, pattern2, file)
+# Returns (via the variables named in the 1st two parameters) the line
+# numbers of the lines matching the patterns in file. Checks pattern1 comes
+# before pattern2.
+#
+findmarkers() {
+ if ! LINE1=`findline "$3" "$5"` || ! LINE2=`findline "$4" "$5"`; then
+ return 1
+ fi
+ if [ $LINE1 -ge $LINE2 ]; then
+ echo "$PROG: marker '$3' not before '$4' in '$5'" >&2
+ return 1
+ fi
+ eval $1=$LINE1
+ eval $2=$LINE2
+}
+
+# find markers
+#
+if findmarkers SRCLINE1 SRCLINE2 "$MARK1" "$MARK2" $SRC &&
+ findmarkers DSTLINE1 DSTLINE2 "$MARK1" "$MARK2" $DST
+then
+ # do splice
+ #
+ if (sed $DSTLINE1,\$d $DST &&
+ sed -n $SRCLINE1,${SRCLINE2}p $SRC &&
+ sed 1,${DSTLINE2}d $DST) > $TMP
+ then
+ mv $TMP $DST
+ exit 0
+ else
+ rm $TMP
+ fi
+fi
+
+exit 1