Forward port from 2.6 branch to avoid wxSTD usage crashes.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38143 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Włodzimierz Skiba
2006-03-16 13:06:39 +00:00
parent 7487919e55
commit 9c9691ba24
4 changed files with 361 additions and 247 deletions

View File

@@ -301,81 +301,84 @@ void ForbidWarning(TexMacroDef *def)
TexMacroDef *MatchMacro(wxChar *buffer, int *pos, wxChar **env, bool *parseToBrace) TexMacroDef *MatchMacro(wxChar *buffer, int *pos, wxChar **env, bool *parseToBrace)
{ {
*parseToBrace = true; *parseToBrace = true;
int i = (*pos); int i = (*pos);
TexMacroDef *def = NULL; TexMacroDef *def = NULL;
wxChar macroBuf[40]; wxChar macroBuf[40];
// First, try to find begin{thing} // First, try to find begin{thing}
if (wxStrncmp(buffer+i, _T("begin{"), 6) == 0) if (wxStrncmp(buffer+i, _T("begin{"), 6) == 0)
{
i += 6;
int j = i;
while ((isalpha(buffer[j]) || buffer[j] == '*') && ((j - i) < 39))
{ {
macroBuf[j-i] = buffer[j]; i += 6;
j ++;
int j = i;
while ((isalpha(buffer[j]) || buffer[j] == '*') && ((j - i) < 39))
{
macroBuf[j-i] = buffer[j];
j ++;
}
macroBuf[j-i] = 0;
def = (TexMacroDef *)MacroDefs.Get(macroBuf);
if (def)
{
*pos = j + 1; // BUGBUG Should this be + 1???
*env = def->name;
ForbidWarning(def);
return def;
}
else
{
return NULL;
}
}
// Failed, so try to find macro from definition list
int j = i;
// First try getting a one-character macro, but ONLY
// if these TWO characters are not both alphabetical (could
// be a longer macro)
if (!(isalpha(buffer[i]) && isalpha(buffer[i+1])))
{
macroBuf[0] = buffer[i];
macroBuf[1] = 0;
def = (TexMacroDef *)MacroDefs.Get(macroBuf);
if (def) j ++;
}
if (!def)
{
while ((isalpha(buffer[j]) || buffer[j] == '*') && ((j - i) < 39))
{
macroBuf[j-i] = buffer[j];
j ++;
}
macroBuf[j-i] = 0;
def = (TexMacroDef *)MacroDefs.Get(macroBuf);
} }
macroBuf[j-i] = 0;
def = (TexMacroDef *)MacroDefs.Get(macroBuf);
if (def) if (def)
{ {
*pos = j + 1; // BUGBUG Should this be + 1??? i = j;
*env = def->name;
ForbidWarning(def); // We want to check whether this is a space-consuming macro
return def; // (e.g. {\bf word})
// No brace, e.g. \input thing.tex instead of \input{thing};
// or a numeric argument, such as \parindent0pt
if ((def->no_args > 0) && ((buffer[i] == 32) || (buffer[i] == '=') || (isdigit(buffer[i]))))
{
if ((buffer[i] == 32) || (buffer[i] == '='))
i ++;
*parseToBrace = false;
}
*pos = i;
ForbidWarning(def);
return def;
} }
else return NULL; return NULL;
}
// Failed, so try to find macro from definition list
int j = i;
// First try getting a one-character macro, but ONLY
// if these TWO characters are not both alphabetical (could
// be a longer macro)
if (!(isalpha(buffer[i]) && isalpha(buffer[i+1])))
{
macroBuf[0] = buffer[i];
macroBuf[1] = 0;
def = (TexMacroDef *)MacroDefs.Get(macroBuf);
if (def) j ++;
}
if (!def)
{
while ((isalpha(buffer[j]) || buffer[j] == '*') && ((j - i) < 39))
{
macroBuf[j-i] = buffer[j];
j ++;
}
macroBuf[j-i] = 0;
def = (TexMacroDef *)MacroDefs.Get(macroBuf);
}
if (def)
{
i = j;
// We want to check whether this is a space-consuming macro
// (e.g. {\bf word})
// No brace, e.g. \input thing.tex instead of \input{thing};
// or a numeric argument, such as \parindent0pt
if ((def->no_args > 0) && ((buffer[i] == 32) || (buffer[i] == '=') || (isdigit(buffer[i]))))
{
if ((buffer[i] == 32) || (buffer[i] == '='))
i ++;
*parseToBrace = false;
}
*pos = i;
ForbidWarning(def);
return def;
}
return NULL;
} }
void EatWhiteSpace(wxChar *buffer, int *pos) void EatWhiteSpace(wxChar *buffer, int *pos)
@@ -1271,16 +1274,20 @@ int ParseArg(TexChunk *thisArg, wxList& children, wxChar *buffer, int pos, wxCha
children.Append((wxObject *)chunk); children.Append((wxObject *)chunk);
// Eliminate newline after a \begin{} or a \\ if possible // Eliminate newline after a \begin{} or a \\ if possible
if (env || wxStrcmp(def->name, _T("\\")) == 0) if ((env || wxStrcmp(def->name, _T("\\")) == 0) && (buffer[pos] == 13))
if (buffer[pos] == 13) {
{
pos ++; pos ++;
if (buffer[pos] == 10) if (buffer[pos] == 10)
pos ++; pos ++;
} }
pos = ParseMacroBody(def->name, chunk, chunk->no_args, pos = ParseMacroBody(def->name,
buffer, pos, env, tmpParseToBrace, customMacroArgs); chunk, chunk->no_args,
buffer,
pos,
env,
tmpParseToBrace,
customMacroArgs);
// If custom macro, parse the body substituting the above found args. // If custom macro, parse the body substituting the above found args.
if (customMacro) if (customMacro)

View File

@@ -14,6 +14,8 @@
#include "wx/list.h" #include "wx/list.h"
#include "wx/hash.h" #include "wx/hash.h"
#include "wx/tokenzr.h" #include "wx/tokenzr.h"
#include "wx/wfstream.h"
#include "wx/txtstrm.h"
#include "wxhlpblk.h" #include "wxhlpblk.h"
/* /*
@@ -176,7 +178,7 @@ extern wxPathList TexPathList; // Path list, can be used for file searching
extern bool StringMatch(const wxChar *one, const wxChar *two, bool subString = true, bool exact = false); extern bool StringMatch(const wxChar *one, const wxChar *two, bool subString = true, bool exact = false);
// Define a variable value from the .ini file // Define a variable value from the .ini file
wxChar *RegisterSetting(wxChar *settingName, wxChar *settingValue, bool interactive = true); wxChar *RegisterSetting(const wxString& settingName, const wxString& settingValue, bool interactive = true);
// Major document styles // Major document styles
#define LATEX_REPORT 1 #define LATEX_REPORT 1
@@ -500,23 +502,23 @@ extern wxList CustomMacroList;
class CustomMacro: public wxObject class CustomMacro: public wxObject
{ {
public: public:
wxChar *macroName; wxChar *macroName;
wxChar *macroBody; wxChar *macroBody;
int noArgs; int noArgs;
inline CustomMacro(wxChar *name, int args, wxChar *body) inline CustomMacro(const wxChar *name, int args, wxChar *body)
{ {
noArgs = args; noArgs = args;
macroName = wxStrcpy(new wxChar[wxStrlen(name) + 1], name); macroName = wxStrcpy(new wxChar[wxStrlen(name) + 1], name);
if (body) if (body)
macroBody = wxStrcpy(new wxChar[wxStrlen(body) + 1], body); macroBody = wxStrcpy(new wxChar[wxStrlen(body) + 1], body);
else else
macroBody = NULL; macroBody = NULL;
} }
~CustomMacro(); ~CustomMacro();
}; };
bool ReadCustomMacros(wxChar *filename); bool ReadCustomMacros(const wxString& filename);
void ShowCustomMacros(void); void ShowCustomMacros(void);
CustomMacro *FindCustomMacro(wxChar *name); CustomMacro *FindCustomMacro(wxChar *name);
wxChar *ParseMultifieldString(wxChar *s, int *pos); wxChar *ParseMultifieldString(wxChar *s, int *pos);
@@ -1066,6 +1068,3 @@ extern void InitialiseColourTable(void);
#define ltTOPLEVEL 15000 #define ltTOPLEVEL 15000
#define ltCUSTOM_MACRO 15001 #define ltCUSTOM_MACRO 15001
#define ltSOLO_BLOCK 15002 #define ltSOLO_BLOCK 15002

View File

@@ -402,7 +402,7 @@ bool MyApp::OnInit()
wxString path = TexPathList.FindValidPath(MacroFile); wxString path = TexPathList.FindValidPath(MacroFile);
if (!path.empty()) if (!path.empty())
ReadCustomMacros((wxChar *)path.c_str()); ReadCustomMacros(path);
#if wxUSE_STATUSBAR #if wxUSE_STATUSBAR
wxString inStr(_T("In ")); wxString inStr(_T("In "));
@@ -444,7 +444,7 @@ bool MyApp::OnInit()
wxString path = TexPathList.FindValidPath(MacroFile); wxString path = TexPathList.FindValidPath(MacroFile);
if (!path.empty()) if (!path.empty())
ReadCustomMacros((wxChar*)path.c_str()); ReadCustomMacros(path);
Go(); Go();
if (runTwice) if (runTwice)
@@ -758,7 +758,7 @@ void MyFrame::OnLoadMacros(wxCommandEvent& WXUNUSED(event))
if (!s.empty() && wxFileExists(s)) if (!s.empty() && wxFileExists(s))
{ {
MacroFile = copystring(s); MacroFile = copystring(s);
ReadCustomMacros((wxChar *)s.c_str()); ReadCustomMacros(s);
ShowCustomMacros(); ShowCustomMacros();
} }
#endif // wxUSE_FILEDLG #endif // wxUSE_FILEDLG

View File

@@ -483,6 +483,22 @@ void ReadTexReferences(wxChar *filename)
* *
*/ */
void BibEatWhiteSpace(wxString& line)
{
while(!line.empty() && (line[0] == _T(' ') || line[0] == _T('\t') || line[0] == (wxChar)EOF))
{
if (line[0] == 10)
BibLine ++;
line = line.substr(1);
}
// Ignore end-of-line comments
if (line[0] == _T('%') || line[0] == _T(';') || line[0] == _T('#'))
{
line = wxEmptyString;
}
}
void BibEatWhiteSpace(wxSTD istream& str) void BibEatWhiteSpace(wxSTD istream& str)
{ {
char ch = (char)str.peek(); char ch = (char)str.peek();
@@ -511,6 +527,24 @@ void BibEatWhiteSpace(wxSTD istream& str)
} }
// Read word up to { or , or space // Read word up to { or , or space
wxString BibReadWord(wxString& line)
{
wxString val;
while (!line.empty() &&
line[0] != _T('\t') &&
line[0] != _T(' ') &&
line[0] != _T('{') &&
line[0] != _T('(') &&
line[0] != _T(',') &&
line[0] != _T('='))
{
val << line[0];
line = line.substr(1);
}
return val;
}
void BibReadWord(wxSTD istream& istr, wxChar *buffer) void BibReadWord(wxSTD istream& istr, wxChar *buffer)
{ {
int i = 0; int i = 0;
@@ -528,85 +562,163 @@ void BibReadWord(wxSTD istream& istr, wxChar *buffer)
} }
// Read string (double-quoted or not) to end quote or EOL // Read string (double-quoted or not) to end quote or EOL
wxString BibReadToEOL(wxString& line)
{
if(line.empty())
return wxEmptyString;
wxString val;
bool inQuotes = false;
if (line[0] == _T('"'))
{
line = line.substr(1);
inQuotes = true;
}
// If in quotes, read white space too. If not,
// stop at white space or comment.
while (!line.empty() && line[0] != _T('"') &&
(inQuotes || ((line[0] != _T(' ')) && (line[0] != 9) &&
(line[0] != _T(';')) && (line[0] != _T('%')) && (line[0] != _T('#')))))
{
val << line[0];
line = line.substr(1);
}
if (line[0] == '"')
line = line.substr(1);
return val;
}
void BibReadToEOL(wxSTD istream& istr, wxChar *buffer) void BibReadToEOL(wxSTD istream& istr, wxChar *buffer)
{ {
int i = 0; int i = 0;
buffer[i] = 0; buffer[i] = 0;
char ch = (char)istr.peek(); char ch = (char)istr.peek();
bool inQuotes = false; bool inQuotes = false;
if (ch == '"') if (ch == '"')
{ {
istr.get(ch); istr.get(ch);
ch = (char)istr.peek(); ch = (char)istr.peek();
inQuotes = true; inQuotes = true;
} }
// If in quotes, read white space too. If not, // If in quotes, read white space too. If not,
// stop at white space or comment. // stop at white space or comment.
while (!istr.eof() && ch != 13 && ch != 10 && ch != _T('"') && while (!istr.eof() && ch != 13 && ch != 10 && ch != _T('"') &&
(inQuotes || ((ch != _T(' ')) && (ch != 9) && (inQuotes || ((ch != _T(' ')) && (ch != 9) &&
(ch != _T(';')) && (ch != _T('%')) && (ch != _T('#'))))) (ch != _T(';')) && (ch != _T('%')) && (ch != _T('#')))))
{ {
istr.get(ch); istr.get(ch);
buffer[i] = ch; buffer[i] = ch;
i ++; i ++;
ch = (char)istr.peek(); ch = (char)istr.peek();
} }
if (ch == '"') if (ch == '"')
istr.get(ch); istr.get(ch);
buffer[i] = 0; buffer[i] = 0;
} }
// Read }-terminated value, taking nested braces into account. // Read }-terminated value, taking nested braces into account.
wxString BibReadValue(wxString& line,
bool ignoreBraces = true,
bool quotesMayTerminate = true)
{
wxString val;
int braceCount = 1;
bool stopping = false;
if (line.length() >= 4000)
{
wxChar buf[100];
wxSnprintf(buf, sizeof(buf), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine);
wxLogError(buf, "Tex2RTF Fatal Error");
return wxEmptyString;
}
while (!line.empty() && !stopping)
{
wxChar ch = line[0];
line = line.substr(1);
if (ch == _T('{'))
braceCount ++;
if (ch == _T('}'))
{
braceCount --;
if (braceCount == 0)
{
stopping = true;
break;
}
}
else if (quotesMayTerminate && ch == _T('"'))
{
stopping = true;
break;
}
if (!stopping)
{
if (!ignoreBraces || (ch != _T('{') && ch != _T('}')))
{
val << ch;
}
}
}
return val;
}
void BibReadValue(wxSTD istream& istr, wxChar *buffer, bool ignoreBraces = true, void BibReadValue(wxSTD istream& istr, wxChar *buffer, bool ignoreBraces = true,
bool quotesMayTerminate = true) bool quotesMayTerminate = true)
{ {
int braceCount = 1; int braceCount = 1;
int i = 0; int i = 0;
buffer[i] = 0; buffer[i] = 0;
char ch = (char)istr.peek(); char ch = (char)istr.peek();
bool stopping = false; bool stopping = false;
while (!istr.eof() && !stopping) while (!istr.eof() && !stopping)
{
// i ++;
if (i >= 4000)
{ {
wxChar buf[100]; // i ++;
wxSnprintf(buf, sizeof(buf), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine); if (i >= 4000)
wxLogError(buf, "Tex2RTF Fatal Error"); {
return; wxChar buf[100];
} wxSnprintf(buf, sizeof(buf), _T("Sorry, value > 4000 chars in bib file at line %ld."), BibLine);
istr.get(ch); wxLogError(buf, "Tex2RTF Fatal Error");
return;
}
istr.get(ch);
if (ch == '{') if (ch == '{')
braceCount ++; braceCount ++;
if (ch == '}') if (ch == '}')
{ {
braceCount --; braceCount --;
if (braceCount == 0) if (braceCount == 0)
{ {
stopping = true; stopping = true;
break; break;
} }
}
else if (quotesMayTerminate && ch == '"')
{
stopping = true;
break;
}
if (!stopping)
{
if (!ignoreBraces || (ch != '{' && ch != '}'))
{
buffer[i] = ch;
i ++;
}
}
if (ch == 10)
BibLine ++;
} }
else if (quotesMayTerminate && ch == '"') buffer[i] = 0;
{ wxUnusedVar(stopping);
stopping = true;
break;
}
if (!stopping)
{
if (!ignoreBraces || (ch != '{' && ch != '}'))
{
buffer[i] = ch;
i ++;
}
}
if (ch == 10)
BibLine ++;
}
buffer[i] = 0;
wxUnusedVar(stopping);
} }
bool ReadBib(wxChar *filename) bool ReadBib(wxChar *filename)
@@ -1082,15 +1194,17 @@ TexRef *FindReference(wxChar *key)
* *
*/ */
bool StringTobool(wxChar *val) bool StringTobool(const wxString& val)
{ {
if (wxStrncmp(val, _T("yes"), 3) == 0 || wxStrncmp(val, _T("YES"), 3) == 0 || wxString up(val);
wxStrncmp(val, _T("on"), 2) == 0 || wxStrncmp(val, _T("ON"), 2) == 0 || up.MakeUpper();
wxStrncmp(val, _T("true"), 4) == 0 || wxStrncmp(val, _T("true"), 4) == 0 ||
wxStrncmp(val, _T("ok"), 2) == 0 || wxStrncmp(val, _T("OK"), 2) == 0 || if (up.IsSameAs(_T("YES")) ||
wxStrncmp(val, _T("1"), 1) == 0) up.IsSameAs(_T("ON")) ||
return true; up.IsSameAs(_T("OK")) |
else up.IsSameAs(_T("1")))
return true;
return false; return false;
} }
@@ -1105,7 +1219,7 @@ void RegisterIntSetting (const wxString& s, int *number)
} }
// Define a variable value from the .ini file // Define a variable value from the .ini file
wxChar *RegisterSetting(wxChar *settingName, wxChar *settingValue, bool interactive) wxChar *RegisterSetting(const wxString& settingName, const wxString& settingValue, bool interactive)
{ {
wxString settingValueStr( settingValue ); wxString settingValueStr( settingValue );
@@ -1351,7 +1465,7 @@ wxChar *RegisterSetting(wxChar *settingName, wxChar *settingValue, bool interact
else else
{ {
wxChar buf[200]; wxChar buf[200];
wxSnprintf(buf, sizeof(buf), _T("Initialisation file error: unrecognised setting %s."), settingName); wxSnprintf(buf, sizeof(buf), _T("Initialisation file error: unrecognised setting %s."), settingName.c_str());
if (interactive) if (interactive)
OnInform(buf); OnInform(buf);
wxStrcpy(errorCode, buf); wxStrcpy(errorCode, buf);
@@ -1359,87 +1473,81 @@ wxChar *RegisterSetting(wxChar *settingName, wxChar *settingValue, bool interact
return errorCode; return errorCode;
} }
bool ReadCustomMacros(wxChar *filename) bool ReadCustomMacros(const wxString& filename)
{ {
if (!wxFileExists(filename)) if (!wxFileExists(filename))
return false; return false;
wxString name = filename; wxFileInputStream input( filename );
wxSTD ifstream istr((char const *)name.fn_str(), wxSTD ios::in); if(!input.Ok()) return false;
wxTextInputStream ini( input );
if (istr.bad()) return false; CustomMacroList.Clear();
CustomMacroList.Clear(); while (!input.Eof())
char ch;
wxChar macroName[100];
wxChar macroBody[1000];
int noArgs;
while (!istr.eof())
{
BibEatWhiteSpace(istr);
istr.get(ch);
if (istr.eof())
break;
if (ch != '\\') // Not a macro definition, so must be NAME=VALUE
{ {
wxChar settingName[100]; wxString line = ini.ReadLine();
settingName[0] = ch; BibEatWhiteSpace(line);
BibReadWord(istr, (settingName+1)); if (line.empty()) continue;
BibEatWhiteSpace(istr);
istr.get(ch); if (line[0] != _T('\\')) // Not a macro definition, so must be NAME=VALUE
if (ch != '=') {
{ wxString settingName = BibReadWord(line);
OnError(_T("Expected = following name: malformed tex2rtf.ini file.")); BibEatWhiteSpace(line);
return false; if (line.empty() || line[0] != _T('='))
} {
else OnError(_T("Expected = following name: malformed tex2rtf.ini file."));
{ return false;
wxChar settingValue[200]; }
BibEatWhiteSpace(istr); else
BibReadToEOL(istr, settingValue); {
RegisterSetting(settingName, settingValue); line = line.substr(1);
} BibEatWhiteSpace(line);
} wxString settingValue = BibReadToEOL(line);
else RegisterSetting(settingName, settingValue);
{ }
BibReadWord(istr, macroName); }
BibEatWhiteSpace(istr); else
istr.get(ch); {
if (ch != '[') line = line.substr(1);
{ wxString macroName = BibReadWord(line);
OnError(_T("Expected [ followed by number of arguments: malformed tex2rtf.ini file.")); BibEatWhiteSpace(line);
return false; if (line[0] != _T('['))
} {
istr >> noArgs; OnError(_T("Expected [ followed by number of arguments: malformed tex2rtf.ini file."));
istr.get(ch); return false;
if (ch != ']') }
{ line = line.substr(1);
OnError(_T("Expected ] following number of arguments: malformed tex2rtf.ini file.")); wxString noAargStr = line.BeforeFirst(_T(']'));
return false; line = line.AfterFirst(_T(']'));
} long noArgs;
BibEatWhiteSpace(istr); if (!noAargStr.ToLong(&noArgs) || line.empty())
istr.get(ch); {
if (ch != '{') OnError(_T("Expected ] following number of arguments: malformed tex2rtf.ini file."));
{ return false;
OnError(_T("Expected { followed by macro body: malformed tex2rtf.ini file.")); }
return false; BibEatWhiteSpace(line);
} if (line[0] != _T('{'))
CustomMacro *macro = new CustomMacro(macroName, noArgs, NULL); {
BibReadValue(istr, macroBody, false, false); // Don't ignore extra braces OnError(_T("Expected { followed by macro body: malformed tex2rtf.ini file."));
if (wxStrlen(macroBody) > 0) return false;
macro->macroBody = copystring(macroBody); }
CustomMacro *macro = new CustomMacro(macroName.c_str(), noArgs, NULL);
wxString macroBody = BibReadValue(line, false, false); // Don't ignore extra braces
if (!macroBody.empty())
macro->macroBody = copystring(macroBody.c_str());
BibEatWhiteSpace(line);
CustomMacroList.Append(macroName.c_str(), macro);
AddMacroDef(ltCUSTOM_MACRO, macroName.c_str(), noArgs);
}
BibEatWhiteSpace(istr);
CustomMacroList.Append(macroName, macro);
AddMacroDef(ltCUSTOM_MACRO, macroName, noArgs);
} }
} wxChar mbuf[200];
wxChar mbuf[200]; wxSnprintf(mbuf, sizeof(mbuf), _T("Read initialization file %s."), filename.c_str());
wxSnprintf(mbuf, sizeof(mbuf), _T("Read initialization file %s."), filename); OnInform(mbuf);
OnInform(mbuf); return true;
return true;
} }
CustomMacro *FindCustomMacro(wxChar *name) CustomMacro *FindCustomMacro(wxChar *name)