1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        tex2rtf.cpp
3 // Purpose:     Converts Latex to linear/WinHelp RTF, HTML, wxHelp.
4 // Author:      Julian Smart
5 // Modified by: Wlodzimiez ABX Skiba 2003/2004 Unicode support
6 //              Ron Lee
7 // Created:     7.9.93
8 // RCS-ID:      $Id: tex2rtf.cpp 44180 2007-01-09 14:35:06Z VZ $
9 // Copyright:   (c) Julian Smart
10 // Licence:     wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12 
13 // For compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
15 
16 #ifdef __BORLANDC__
17 #pragma hdrstop
18 #endif
19 
20 #if defined(__WXMSW__)
21     #include "wx/msw/wrapwin.h"
22 #endif
23 
24 #ifndef WX_PRECOMP
25     #ifndef NO_GUI
26         #include "wx/menu.h"
27         #include "wx/textctrl.h"
28         #include "wx/filedlg.h"
29         #include "wx/msgdlg.h"
30         #include "wx/icon.h"
31     #endif
32 #endif
33 
34 #include "wx/log.h"
35 
36 #ifndef NO_GUI
37     #include "wx/timer.h"
38     #include "wx/help.h"
39     #include "wx/cshelp.h"
40     #include "wx/helphtml.h"
41     #ifdef __WXMSW__
42         #include "wx/msw/helpchm.h"
43     #else
44         #include "wx/html/helpctrl.h"
45     #endif
46 #endif // !NO_GUI
47 
48 #include "wx/utils.h"
49 
50 #if wxUSE_IOSTREAMH
51 #include <iostream.h>
52 #include <fstream.h>
53 #else
54 #include <iostream>
55 #include <fstream>
56 #endif
57 
58 #include <ctype.h>
59 #include <stdlib.h>
60 #include "tex2any.h"
61 #include "tex2rtf.h"
62 #include "rtfutils.h"
63 #include "symbols.h"
64 
65 #if (defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXX11__) || defined(__WXMGL__)) && !defined(NO_GUI)
66 #include "tex2rtf.xpm"
67 #endif
68 
69 #if !WXWIN_COMPATIBILITY_2_4
copystring(const wxChar * s)70 static inline wxChar* copystring(const wxChar* s)
71     { return wxStrcpy(new wxChar[wxStrlen(s) + 1], s); }
72 #endif
73 
74 const float versionNo = float(TEX2RTF_VERSION_NUMBER);
75 
76 TexChunk *currentMember = NULL;
77 bool startedSections = false;
78 wxChar *contentsString = NULL;
79 bool suppressNameDecoration = false;
80 bool OkToClose = true;
81 int passNumber = 1;
82 unsigned long errorCount = 0;
83 
84 #ifndef NO_GUI
85 
86 extern wxChar *BigBuffer;
87 extern wxChar *TexFileRoot;
88 extern wxChar *TexBibName;         // Bibliography output file name
89 extern wxChar *TexTmpBibName;      // Temporary bibliography output file name
90 extern wxList ColourTable;
91 extern TexChunk *TopLevel;
92 
93 #if wxUSE_HELP
94 wxHelpControllerBase *HelpInstance = NULL;
95 #endif // wxUSE_HELP
96 
97 #ifdef __WXMSW__
98 static wxChar *ipc_buffer = NULL;
99 static wxChar Tex2RTFLastStatus[100];
100 Tex2RTFServer *TheTex2RTFServer = NULL;
101 #endif // __WXMSW__
102 
103 #endif // !NO_GUI
104 
105 wxChar *bulletFile = NULL;
106 
107 FILE *Contents = NULL;   // Contents page
108 FILE *Chapters = NULL;   // Chapters (WinHelp RTF) or rest of file (linear RTF)
109 FILE *Sections = NULL;
110 FILE *Subsections = NULL;
111 FILE *Subsubsections = NULL;
112 FILE *Popups = NULL;
113 FILE *WinHelpContentsFile = NULL;
114 
115 wxString InputFile;
116 wxString OutputFile;
117 wxChar *MacroFile = copystring(_T("tex2rtf.ini"));
118 
119 wxChar *FileRoot = NULL;
120 wxChar *ContentsName = NULL;    // Contents page from last time around
121 wxChar *TmpContentsName = NULL; // Current contents page
122 wxChar *TmpFrameContentsName = NULL; // Current frame contents page
123 wxChar *WinHelpContentsFileName = NULL; // WinHelp .cnt file
124 wxChar *RefFileName = NULL;         // Reference file name
125 
126 wxChar *RTFCharset = copystring(_T("ansi"));
127 
128 #ifdef __WXMSW__
129 int BufSize = 100;             // Size of buffer in K
130 #else
131 int BufSize = 500;
132 #endif
133 
134 bool Go(void);
135 void ShowOptions(void);
136 void ShowVersion(void);
137 
138 wxChar wxTex2RTFBuffer[1500];
139 
140 #ifdef NO_GUI
IMPLEMENT_APP_CONSOLE(MyApp)141     IMPLEMENT_APP_CONSOLE(MyApp)
142 #else
143     wxMenuBar *menuBar = NULL;
144     MyFrame *frame = NULL;
145     // DECLARE_APP(MyApp)
146     IMPLEMENT_APP(MyApp)
147 #endif
148 
149 // `Main program' equivalent, creating windows and returning main app frame
150 bool MyApp::OnInit()
151 {
152   // Use default list of macros defined in tex2any.cc
153   DefineDefaultMacros();
154   AddMacroDef(ltHARDY, _T("hardy"), 0);
155 
156   FileRoot = new wxChar[300];
157   ContentsName = new wxChar[300];
158   TmpContentsName = new wxChar[300];
159   TmpFrameContentsName = new wxChar[300];
160   WinHelpContentsFileName = new wxChar[300];
161   RefFileName = new wxChar[300];
162 
163   WX_CLEAR_LIST(wxList,ColourTable);
164 
165   int n = 1;
166 
167   // Read input/output files
168   if (argc > 1)
169   {
170       if (argv[1][0] != _T('-'))
171       {
172           InputFile = argv[1];
173           n ++;
174 
175           if (argc > 2)
176           {
177               if (argv[2][0] != _T('-'))
178               {
179                   OutputFile = argv[2];
180                   n ++;
181               }
182           }
183       }
184   }
185 
186   TexPathList.Add(::wxGetCwd());
187 
188   int i;
189   for (i = n; i < argc;)
190   {
191     if (wxStrcmp(argv[i], _T("-winhelp")) == 0)
192     {
193       i ++;
194       convertMode = TEX_RTF;
195       winHelp = true;
196     }
197 #ifndef NO_GUI
198     else if (wxStrcmp(argv[i], _T("-interactive")) == 0)
199     {
200       i ++;
201       isInteractive = true;
202     }
203 #endif
204     else if (wxStrcmp(argv[i], _T("-sync")) == 0)  // Don't yield
205     {
206       i ++;
207       isSync = true;
208     }
209     else if (wxStrcmp(argv[i], _T("-rtf")) == 0)
210     {
211       i ++;
212       convertMode = TEX_RTF;
213     }
214     else if (wxStrcmp(argv[i], _T("-html")) == 0)
215     {
216       i ++;
217       convertMode = TEX_HTML;
218     }
219     else if (wxStrcmp(argv[i], _T("-xlp")) == 0)
220     {
221       i ++;
222       convertMode = TEX_XLP;
223     }
224     else if (wxStrcmp(argv[i], _T("-twice")) == 0)
225     {
226       i ++;
227       runTwice = true;
228     }
229     else if (wxStrcmp(argv[i], _T("-macros")) == 0)
230     {
231       i ++;
232       if (i < argc)
233       {
234         MacroFile = copystring(argv[i]);
235         i ++;
236       }
237     }
238     else if (wxStrcmp(argv[i], _T("-bufsize")) == 0)
239     {
240       i ++;
241       if (i < argc)
242       {
243         BufSize = wxAtoi(argv[i]);
244         i ++;
245       }
246     }
247     else if (wxStrcmp(argv[i], _T("-charset")) == 0)
248     {
249       i ++;
250       if (i < argc)
251       {
252         wxChar *s = argv[i];
253         i ++;
254         if (wxStrcmp(s, _T("ansi")) == 0 || wxStrcmp(s, _T("pc")) == 0 || wxStrcmp(s, _T("mac")) == 0 ||
255             wxStrcmp(s, _T("pca")) == 0)
256           RTFCharset = copystring(s);
257         else
258         {
259           OnError(_T("Incorrect argument for -charset"));
260           return false;
261         }
262       }
263     }
264     else if (wxStrcmp(argv[i], _T("-checkcurlybraces")) == 0)
265     {
266       i ++;
267       checkCurlyBraces = true;
268     }
269     else if (wxStrcmp(argv[i], _T("-checkcurleybraces")) == 0)
270     {
271       // Support the old, incorrectly spelled version of -checkcurlybraces
272       // so that old scripts which run tex2rtf -checkcurleybraces still work.
273       i ++;
274       checkCurlyBraces = true;
275     }
276     else if (wxStrcmp(argv[i], _T("-checksyntax")) == 0)
277     {
278       i ++;
279       checkSyntax = true;
280     }
281     else if (wxStrcmp(argv[i], _T("-version")) == 0)
282     {
283       i ++;
284       ShowVersion();
285 #ifdef NO_GUI
286       exit(1);
287 #else
288       return false;
289 #endif
290     }
291     else
292     {
293       wxString buf;
294       buf.Printf(_T("Invalid switch %s.\n"), argv[i]);
295       OnError((wxChar *)buf.c_str());
296 #ifdef NO_GUI
297       ShowOptions();
298       exit(1);
299 #else
300       return false;
301 #endif
302     }
303   }
304 
305 #ifdef NO_GUI
306   if (InputFile.empty() || OutputFile.empty())
307   {
308       wxSTD cout << "Tex2RTF: input or output file is missing.\n";
309       ShowOptions();
310       exit(1);
311   }
312 #endif
313 
314   if (!InputFile.empty())
315   {
316       TexPathList.EnsureFileAccessible(InputFile);
317   }
318   if (InputFile.empty() || OutputFile.empty())
319       isInteractive = true;
320 
321 #if defined(__WXMSW__) && !defined(NO_GUI)
322   wxDDEInitialize();
323   Tex2RTFLastStatus[0] = 0; // DDE connection return value
324   TheTex2RTFServer = new Tex2RTFServer;
325   TheTex2RTFServer->Create(_T("TEX2RTF"));
326 #endif
327 
328   TexInitialize(BufSize);
329   ResetContentsLevels(0);
330 
331 #ifndef NO_GUI
332 
333   if (isInteractive)
334   {
335     // Create the main frame window
336     frame = new MyFrame(NULL, wxID_ANY, _T("Tex2RTF"), wxDefaultPosition, wxSize(400, 300));
337 #if wxUSE_STATUSBAR
338     frame->CreateStatusBar(2);
339 #endif // wxUSE_STATUSBAR
340 
341     // Give it an icon
342     // TODO: uncomment this when we have tex2rtf.xpm
343     frame->SetIcon(wxICON(tex2rtf));
344 
345     if (!InputFile.empty())
346     {
347         wxString title;
348         title.Printf( _T("Tex2RTF [%s]"), wxFileNameFromPath(InputFile).c_str());
349         frame->SetTitle(title);
350     }
351 
352     // Make a menubar
353     wxMenu *file_menu = new wxMenu;
354     file_menu->Append(TEX_GO, _T("&Go"), _T("Run converter"));
355     file_menu->Append(TEX_SET_INPUT, _T("Set &Input File"), _T("Set the LaTeX input file"));
356     file_menu->Append(TEX_SET_OUTPUT, _T("Set &Output File"), _T("Set the output file"));
357     file_menu->AppendSeparator();
358     file_menu->Append(TEX_VIEW_LATEX, _T("View &LaTeX File"), _T("View the LaTeX input file"));
359     file_menu->Append(TEX_VIEW_OUTPUT, _T("View Output &File"), _T("View output file"));
360     file_menu->Append(TEX_SAVE_FILE, _T("&Save log file"), _T("Save displayed text into file"));
361     file_menu->AppendSeparator();
362     file_menu->Append(TEX_QUIT, _T("E&xit"), _T("Exit Tex2RTF"));
363 
364     wxMenu *macro_menu = new wxMenu;
365 
366     macro_menu->Append(TEX_LOAD_CUSTOM_MACROS, _T("&Load Custom Macros"), _T("Load custom LaTeX macro file"));
367     macro_menu->Append(TEX_VIEW_CUSTOM_MACROS, _T("View &Custom Macros"), _T("View custom LaTeX macros"));
368 
369     wxMenu *mode_menu = new wxMenu;
370 
371     mode_menu->Append(TEX_MODE_RTF, _T("Output linear &RTF"), _T("Wordprocessor-compatible RTF"));
372     mode_menu->Append(TEX_MODE_WINHELP, _T("Output &WinHelp RTF"), _T("WinHelp-compatible RTF"));
373     mode_menu->Append(TEX_MODE_HTML, _T("Output &HTML"), _T("HTML World Wide Web hypertext file"));
374     mode_menu->Append(TEX_MODE_XLP, _T("Output &XLP"), _T("wxHelp hypertext help file"));
375 
376     wxMenu *options_menu = new wxMenu;
377 
378     options_menu->Append(TEX_OPTIONS_CURLY_BRACE, _T("Curly brace matching"), _T("Checks for mismatched curly braces"),true);
379     options_menu->Append(TEX_OPTIONS_SYNTAX_CHECKING, _T("Syntax checking"), _T("Syntax checking for common errors"),true);
380 
381     options_menu->Check(TEX_OPTIONS_CURLY_BRACE, checkCurlyBraces);
382     options_menu->Check(TEX_OPTIONS_SYNTAX_CHECKING, checkSyntax);
383 
384     wxMenu *help_menu = new wxMenu;
385 
386     help_menu->Append(TEX_HELP, _T("&Help"), _T("Tex2RTF Contents Page"));
387     help_menu->Append(TEX_ABOUT, _T("&About Tex2RTF"), _T("About Tex2RTF"));
388 
389     menuBar = new wxMenuBar;
390     menuBar->Append(file_menu, _T("&File"));
391     menuBar->Append(macro_menu, _T("&Macros"));
392     menuBar->Append(mode_menu, _T("&Conversion Mode"));
393     menuBar->Append(options_menu, _T("&Options"));
394     menuBar->Append(help_menu, _T("&Help"));
395 
396     frame->SetMenuBar(menuBar);
397     frame->textWindow = new wxTextCtrl(frame, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY|wxTE_MULTILINE);
398 
399     (*frame->textWindow) << _T("Welcome to Tex2RTF.\n");
400 //    ShowOptions();
401 
402 #if wxUSE_HELP
403 #if wxUSE_MS_HTML_HELP && !defined(__WXUNIVERSAL__)
404     HelpInstance = new wxCHMHelpController;
405 #else
406     HelpInstance = new wxHelpController;
407 #endif
408     HelpInstance->Initialize(_T("tex2rtf"));
409 #endif // wxUSE_HELP
410 
411     /*
412      * Read macro/initialisation file
413      *
414      */
415 
416     wxString path = TexPathList.FindValidPath(MacroFile);
417     if (!path.empty())
418         ReadCustomMacros(path);
419 
420 #if wxUSE_STATUSBAR
421     wxString inStr(_T("In "));
422     switch (convertMode)
423     {
424         case TEX_RTF:
425             if(winHelp)
426                 inStr += _T("WinHelp RTF");
427             else
428                 inStr += _T("linear RTF");
429             break;
430 
431         case TEX_HTML:
432             inStr += _T("HTML");
433             break;
434 
435         case TEX_XLP:
436             inStr += _T("XLP");
437             break;
438 
439         default:
440             inStr += _T("unknown");
441             break;
442     }
443     inStr += _T(" mode.");
444     frame->SetStatusText(inStr, 1);
445 #endif // wxUSE_STATUSBAR
446 
447     frame->Show(true);
448     return true;
449   }
450   else
451 #endif // NO_GUI
452   {
453     /*
454      * Read macro/initialisation file
455      *
456      */
457 
458     wxString path = TexPathList.FindValidPath(MacroFile);
459     if (!path.empty())
460         ReadCustomMacros(path);
461 
462     bool rc = Go();
463     if ( rc && runTwice )
464     {
465         rc = Go();
466     }
467 #ifdef NO_GUI
468     return rc;
469 #else
470     OnExit(); // Do cleanup since OnExit won't be called now
471     return false;
472 #endif
473   }
474 }
475 
476 #ifndef NO_GUI
OnExit()477 int MyApp::OnExit()
478 {
479   wxNode *node = CustomMacroList.GetFirst();
480   while (node)
481   {
482     CustomMacro *macro = (CustomMacro *)node->GetData();
483     delete macro;
484     delete node;
485     node = CustomMacroList.GetFirst();
486   }
487   MacroDefs.BeginFind();
488   wxHashTable::Node* mNode = MacroDefs.Next();
489   while (mNode)
490   {
491     TexMacroDef* def = (TexMacroDef*) mNode->GetData();
492     delete def;
493     mNode = MacroDefs.Next();
494   }
495   MacroDefs.Clear();
496 #ifdef __WXMSW__
497   delete TheTex2RTFServer;
498   wxDDECleanUp();
499 #endif
500 
501 #if wxUSE_HELP
502   delete HelpInstance;
503 #endif // wxUSE_HELP
504 
505     if (BigBuffer)
506     {
507       delete BigBuffer;
508       BigBuffer = NULL;
509     }
510     if (currentArgData)
511     {
512       delete currentArgData;
513       currentArgData = NULL;
514     }
515     if (TexFileRoot)
516     {
517       delete TexFileRoot;
518       TexFileRoot = NULL;
519     }
520     if (TexBibName)
521     {
522       delete TexBibName;
523       TexBibName = NULL;
524     }
525     if (TexTmpBibName)
526     {
527       delete TexTmpBibName;
528       TexTmpBibName = NULL;
529     }
530     if (FileRoot)
531     {
532       delete FileRoot;
533       FileRoot = NULL;
534     }
535     if (ContentsName)
536     {
537       delete ContentsName;
538       ContentsName = NULL;
539     }
540     if (TmpContentsName)
541     {
542       delete TmpContentsName;
543       TmpContentsName = NULL;
544     }
545     if (TmpFrameContentsName)
546     {
547       delete TmpFrameContentsName;
548       TmpFrameContentsName = NULL;
549     }
550     if (WinHelpContentsFileName)
551     {
552       delete WinHelpContentsFileName;
553       WinHelpContentsFileName = NULL;
554     }
555     if (RefFileName)
556     {
557       delete RefFileName;
558       RefFileName = NULL;
559     }
560     if (TopLevel)
561     {
562       delete TopLevel;
563       TopLevel = NULL;
564     }
565     if (MacroFile)
566     {
567       delete MacroFile;
568       MacroFile = NULL;
569     }
570     if (RTFCharset)
571     {
572       delete RTFCharset;
573       RTFCharset = NULL;
574     }
575 
576     delete [] PageStyle;
577     delete [] BibliographyStyleString;
578     delete [] DocumentStyleString;
579     delete [] bitmapMethod;
580     delete [] backgroundColourString;
581     delete [] ContentsNameString;
582     delete [] AbstractNameString;
583     delete [] GlossaryNameString;
584     delete [] ReferencesNameString;
585     delete [] FiguresNameString;
586     delete [] TablesNameString;
587     delete [] FigureNameString;
588     delete [] TableNameString;
589     delete [] IndexNameString;
590     delete [] ChapterNameString;
591     delete [] SectionNameString;
592     delete [] SubsectionNameString;
593     delete [] SubsubsectionNameString;
594     delete [] UpNameString;
595     if (winHelpTitle)
596       delete[] winHelpTitle;
597 
598   // TODO: this simulates zero-memory leaks!
599   // Otherwise there are just too many...
600 #ifndef __WXGTK__
601 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
602   wxDebugContext::SetCheckpoint();
603 #endif
604 #endif
605 
606   return 0;
607 }
608 #endif
609 
ShowVersion(void)610 void ShowVersion(void)
611 {
612     wxChar buf[100];
613     wxSnprintf(buf, sizeof(buf), _T("Tex2RTF version %.2f"), versionNo);
614     OnInform(buf);
615 }
616 
ShowOptions(void)617 void ShowOptions(void)
618 {
619     ShowVersion();
620     OnInform(_T("Usage: tex2rtf [input] [output] [switches]\n"));
621     OnInform(_T("where valid switches are"));
622 #ifndef NO_GUI
623     OnInform(_T("    -interactive"));
624 #endif
625     OnInform(_T("    -bufsize <size in K>"));
626     OnInform(_T("    -charset <pc | pca | ansi | mac> (default ansi)"));
627     OnInform(_T("    -twice"));
628     OnInform(_T("    -sync"));
629     OnInform(_T("    -checkcurlybraces"));
630     OnInform(_T("    -checksyntax"));
631     OnInform(_T("    -version"));
632     OnInform(_T("    -macros <filename>"));
633     OnInform(_T("    -winhelp"));
634     OnInform(_T("    -rtf"));
635     OnInform(_T("    -html"));
636     OnInform(_T("    -xlp\n"));
637 }
638 
639 #ifndef NO_GUI
640 
BEGIN_EVENT_TABLE(MyFrame,wxFrame)641 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
642     EVT_CLOSE(MyFrame::OnCloseWindow)
643     EVT_MENU(TEX_QUIT, MyFrame::OnExit)
644     EVT_MENU(TEX_GO, MyFrame::OnGo)
645     EVT_MENU(TEX_SET_INPUT, MyFrame::OnSetInput)
646     EVT_MENU(TEX_SET_OUTPUT, MyFrame::OnSetOutput)
647     EVT_MENU(TEX_SAVE_FILE, MyFrame::OnSaveFile)
648     EVT_MENU(TEX_VIEW_LATEX, MyFrame::OnViewLatex)
649     EVT_MENU(TEX_VIEW_OUTPUT, MyFrame::OnViewOutput)
650     EVT_MENU(TEX_VIEW_CUSTOM_MACROS, MyFrame::OnShowMacros)
651     EVT_MENU(TEX_LOAD_CUSTOM_MACROS, MyFrame::OnLoadMacros)
652     EVT_MENU(TEX_MODE_RTF, MyFrame::OnModeRTF)
653     EVT_MENU(TEX_MODE_WINHELP, MyFrame::OnModeWinHelp)
654     EVT_MENU(TEX_MODE_HTML, MyFrame::OnModeHTML)
655     EVT_MENU(TEX_MODE_XLP, MyFrame::OnModeXLP)
656     EVT_MENU(TEX_OPTIONS_CURLY_BRACE, MyFrame::OnOptionsCurlyBrace)
657     EVT_MENU(TEX_OPTIONS_SYNTAX_CHECKING, MyFrame::OnOptionsSyntaxChecking)
658     EVT_MENU(TEX_HELP, MyFrame::OnHelp)
659     EVT_MENU(TEX_ABOUT, MyFrame::OnAbout)
660 END_EVENT_TABLE()
661 
662 // My frame constructor
663 MyFrame::MyFrame(wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size):
664   wxFrame(frame, id, title, pos, size)
665 {}
666 
OnCloseWindow(wxCloseEvent & WXUNUSED (event))667 void MyFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
668 {
669   if (!stopRunning && !OkToClose)
670   {
671     stopRunning = true;
672     runTwice = false;
673     return;
674   }
675   else if (OkToClose)
676   {
677     this->Destroy();
678   }
679 }
680 
OnExit(wxCommandEvent & WXUNUSED (event))681 void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
682 {
683   Close();
684 //    this->Destroy();
685 }
686 
OnGo(wxCommandEvent & WXUNUSED (event))687 void MyFrame::OnGo(wxCommandEvent& WXUNUSED(event))
688 {
689       passNumber = 1;
690       errorCount = 0;
691       menuBar->EnableTop(0, false);
692       menuBar->EnableTop(1, false);
693       menuBar->EnableTop(2, false);
694       menuBar->EnableTop(3, false);
695       textWindow->Clear();
696       Tex2RTFYield(true);
697       Go();
698 
699       if (stopRunning)
700       {
701 #if wxUSE_STATUSBAR
702         SetStatusText(_T("Build aborted!"));
703 #endif // wxUSE_STATUSBAR
704         wxString errBuf;
705         errBuf.Printf(_T("\nErrors encountered during this pass: %lu\n"), errorCount);
706         OnInform((wxChar *)errBuf.c_str());
707       }
708 
709 
710       if (runTwice && !stopRunning)
711       {
712         Tex2RTFYield(true);
713         Go();
714       }
715       menuBar->EnableTop(0, true);
716       menuBar->EnableTop(1, true);
717       menuBar->EnableTop(2, true);
718       menuBar->EnableTop(3, true);
719 }
720 
OnSetInput(wxCommandEvent & WXUNUSED (event))721 void MyFrame::OnSetInput(wxCommandEvent& WXUNUSED(event))
722 {
723       ChooseInputFile(true);
724 }
725 
OnSetOutput(wxCommandEvent & WXUNUSED (event))726 void MyFrame::OnSetOutput(wxCommandEvent& WXUNUSED(event))
727 {
728       ChooseOutputFile(true);
729 }
730 
OnSaveFile(wxCommandEvent & WXUNUSED (event))731 void MyFrame::OnSaveFile(wxCommandEvent& WXUNUSED(event))
732 {
733 #if wxUSE_FILEDLG
734     wxString s = wxFileSelector(_T("Save text to file"), wxEmptyString, wxEmptyString, _T("txt"), _T("*.txt"));
735     if (!s.empty())
736     {
737         textWindow->SaveFile(s);
738 #if wxUSE_STATUSBAR
739         wxChar buf[350];
740         wxSnprintf(buf, sizeof(buf), _T("Saved text to %s"), (const wxChar*) s.c_str());
741         frame->SetStatusText(buf, 0);
742 #endif // wxUSE_STATUSBAR
743     }
744 #endif // wxUSE_FILEDLG
745 }
746 
OnViewOutput(wxCommandEvent & WXUNUSED (event))747 void MyFrame::OnViewOutput(wxCommandEvent& WXUNUSED(event))
748 {
749     ChooseOutputFile();
750     if (!OutputFile.empty() && wxFileExists(OutputFile))
751     {
752         textWindow->LoadFile(OutputFile);
753         wxChar buf[300];
754         wxString str(wxFileNameFromPath(OutputFile));
755         wxSnprintf(buf, sizeof(buf), _T("Tex2RTF [%s]"), (const wxChar*) str.c_str());
756         frame->SetTitle(buf);
757     }
758 }
759 
OnViewLatex(wxCommandEvent & WXUNUSED (event))760 void MyFrame::OnViewLatex(wxCommandEvent& WXUNUSED(event))
761 {
762     ChooseInputFile();
763     if (!InputFile.empty() && wxFileExists(InputFile))
764     {
765         textWindow->LoadFile(InputFile);
766         wxChar buf[300];
767         wxString str(wxFileNameFromPath(OutputFile));
768         wxSnprintf(buf, sizeof(buf), _T("Tex2RTF [%s]"), (const wxChar*) str.c_str());
769         frame->SetTitle(buf);
770     }
771 }
772 
OnLoadMacros(wxCommandEvent & WXUNUSED (event))773 void MyFrame::OnLoadMacros(wxCommandEvent& WXUNUSED(event))
774 {
775     textWindow->Clear();
776 #if wxUSE_FILEDLG
777     wxString s = wxFileSelector(_T("Choose custom macro file"), wxPathOnly(MacroFile), wxFileNameFromPath(MacroFile), _T("ini"), _T("*.ini"));
778     if (!s.empty() && wxFileExists(s))
779     {
780         MacroFile = copystring(s);
781         ReadCustomMacros(s);
782         ShowCustomMacros();
783     }
784 #endif // wxUSE_FILEDLG
785 }
786 
OnShowMacros(wxCommandEvent & WXUNUSED (event))787 void MyFrame::OnShowMacros(wxCommandEvent& WXUNUSED(event))
788 {
789     textWindow->Clear();
790     Tex2RTFYield(true);
791     ShowCustomMacros();
792 }
793 
OnModeRTF(wxCommandEvent & WXUNUSED (event))794 void MyFrame::OnModeRTF(wxCommandEvent& WXUNUSED(event))
795 {
796     convertMode = TEX_RTF;
797     winHelp = false;
798     InputFile = wxEmptyString;
799     OutputFile = wxEmptyString;
800 #if wxUSE_STATUSBAR
801     SetStatusText(_T("In linear RTF mode."), 1);
802 #endif // wxUSE_STATUSBAR
803 }
804 
OnModeWinHelp(wxCommandEvent & WXUNUSED (event))805 void MyFrame::OnModeWinHelp(wxCommandEvent& WXUNUSED(event))
806 {
807     convertMode = TEX_RTF;
808     winHelp = true;
809     InputFile = wxEmptyString;
810     OutputFile = wxEmptyString;
811 #if wxUSE_STATUSBAR
812     SetStatusText(_T("In WinHelp RTF mode."), 1);
813 #endif // wxUSE_STATUSBAR
814 }
815 
OnModeHTML(wxCommandEvent & WXUNUSED (event))816 void MyFrame::OnModeHTML(wxCommandEvent& WXUNUSED(event))
817 {
818     convertMode = TEX_HTML;
819     winHelp = false;
820     InputFile = wxEmptyString;
821     OutputFile = wxEmptyString;
822 #if wxUSE_STATUSBAR
823     SetStatusText(_T("In HTML mode."), 1);
824 #endif // wxUSE_STATUSBAR
825 }
826 
OnModeXLP(wxCommandEvent & WXUNUSED (event))827 void MyFrame::OnModeXLP(wxCommandEvent& WXUNUSED(event))
828 {
829     convertMode = TEX_XLP;
830     InputFile = wxEmptyString;
831     OutputFile = wxEmptyString;
832 #if wxUSE_STATUSBAR
833     SetStatusText(_T("In XLP mode."), 1);
834 #endif // wxUSE_STATUSBAR
835 }
836 
OnOptionsCurlyBrace(wxCommandEvent & WXUNUSED (event))837 void MyFrame::OnOptionsCurlyBrace(wxCommandEvent& WXUNUSED(event))
838 {
839     checkCurlyBraces = !checkCurlyBraces;
840 #if wxUSE_STATUSBAR
841     if (checkCurlyBraces)
842     {
843         SetStatusText(_T("Checking curly braces: YES"), 1);
844     }
845     else
846     {
847         SetStatusText(_T("Checking curly braces: NO"), 1);
848     }
849 #endif // wxUSE_STATUSBAR
850 }
851 
852 
OnOptionsSyntaxChecking(wxCommandEvent & WXUNUSED (event))853 void MyFrame::OnOptionsSyntaxChecking(wxCommandEvent& WXUNUSED(event))
854 {
855     checkSyntax = !checkSyntax;
856 #if wxUSE_STATUSBAR
857     if (checkSyntax)
858     {
859         SetStatusText(_T("Checking syntax: YES"), 1);
860     }
861     else
862     {
863         SetStatusText(_T("Checking syntax: NO"), 1);
864     }
865 #endif // wxUSE_STATUSBAR
866 }
867 
868 
OnHelp(wxCommandEvent & WXUNUSED (event))869 void MyFrame::OnHelp(wxCommandEvent& WXUNUSED(event))
870 {
871 #if wxUSE_HELP
872       HelpInstance->LoadFile();
873       HelpInstance->DisplayContents();
874 #endif // wxUSE_HELP
875 }
876 
OnAbout(wxCommandEvent & WXUNUSED (event))877 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
878 {
879       wxChar buf[300];
880       wxString platform = wxGetOsDescription();
881       wxSnprintf(buf, sizeof(buf), _T("Tex2RTF Version %.2f %s\nLaTeX to RTF, WinHelp, and HTML Conversion\n\n(c) Julian Smart, George Tasker and others, 1999-2005"), versionNo, platform.c_str());
882       wxMessageBox(buf, _T("About Tex2RTF"));
883 }
884 
ChooseInputFile(bool force)885 void ChooseInputFile(bool force)
886 {
887 #if wxUSE_FILEDLG
888     if (force || InputFile.empty())
889     {
890         wxString s = wxFileSelector(_T("Choose LaTeX input file"), wxPathOnly(InputFile), wxFileNameFromPath(InputFile), _T("tex"), _T("*.tex"));
891         if (!s.empty())
892         {
893             // Different file, so clear index entries.
894             ClearKeyWordTable();
895             ResetContentsLevels(0);
896             passNumber = 1;
897             errorCount = 0;
898 
899             InputFile = s;
900             wxString str = wxFileNameFromPath(InputFile);
901             wxString buf;
902             buf.Printf(_T("Tex2RTF [%s]"), str.c_str());
903             frame->SetTitle((wxChar *)buf.c_str());
904             OutputFile = wxEmptyString;
905         }
906     }
907 #else
908     wxUnusedVar(force);
909 #endif // wxUSE_FILEDLG
910 }
911 
ChooseOutputFile(bool force)912 void ChooseOutputFile(bool force)
913 {
914     wxChar extensionBuf[10];
915     wxChar wildBuf[10];
916     wxStrcpy(wildBuf, _T("*."));
917     wxString path;
918     if (!OutputFile.empty())
919         path = wxPathOnly(OutputFile);
920     else if (!InputFile.empty())
921         path = wxPathOnly(InputFile);
922 
923     switch (convertMode)
924     {
925         case TEX_RTF:
926         {
927             wxStrcpy(extensionBuf, _T("rtf"));
928             wxStrcat(wildBuf, _T("rtf"));
929             break;
930         }
931         case TEX_XLP:
932         {
933             wxStrcpy(extensionBuf, _T("xlp"));
934             wxStrcat(wildBuf, _T("xlp"));
935             break;
936         }
937         case TEX_HTML:
938         {
939             wxStrcpy(extensionBuf, _T("html"));
940             wxStrcat(wildBuf, _T("html"));
941             break;
942         }
943     }
944 #if wxUSE_FILEDLG
945     if (force || OutputFile.empty())
946     {
947         wxString s = wxFileSelector(_T("Choose output file"), path, wxFileNameFromPath(OutputFile),
948                                     extensionBuf, wildBuf);
949         if (!s.empty())
950             OutputFile = s;
951     }
952 #else
953     wxUnusedVar(force);
954 #endif // wxUSE_FILEDLG
955 }
956 #endif
957 
Go(void)958 bool Go(void)
959 {
960 #ifndef NO_GUI
961   ChooseInputFile();
962   ChooseOutputFile();
963 #endif
964 
965   if (InputFile.empty() || OutputFile.empty() || stopRunning)
966     return false;
967 
968 #ifndef NO_GUI
969   if (isInteractive)
970   {
971     wxChar buf[300];
972     wxString str = wxFileNameFromPath(InputFile);
973 
974     wxSnprintf(buf, sizeof(buf), _T("Tex2RTF [%s]"), (const wxChar*) str);
975     frame->SetTitle(buf);
976   }
977 
978   wxLongLong localTime = wxGetLocalTimeMillis();
979 #endif
980 
981   // Find extension-less filename
982   wxStrcpy(FileRoot, OutputFile.c_str());
983   StripExtension(FileRoot);
984 
985   if (truncateFilenames && convertMode == TEX_HTML)
986   {
987     // Truncate to five characters. This ensures that
988     // we can generate DOS filenames such as thing999. But 1000 files
989     // may not be enough, of course...
990     wxChar* sName = wxFileNameFromPath( FileRoot);  // this Julian's method is non-destructive reference
991 
992     if(sName)
993       if(wxStrlen( sName) > 5)
994         sName[5] = '\0';  // that should do!
995   }
996 
997   wxSnprintf(ContentsName, 300, _T("%s.con"), FileRoot);
998   wxSnprintf(TmpContentsName, 300, _T("%s.cn1"), FileRoot);
999   wxSnprintf(TmpFrameContentsName, 300, _T("%s.frc"), FileRoot);
1000   wxSnprintf(WinHelpContentsFileName, 300, _T("%s.cnt"), FileRoot);
1001   wxSnprintf(RefFileName, 300, _T("%s.ref"), FileRoot);
1002 
1003   TexPathList.EnsureFileAccessible(InputFile);
1004   if (!bulletFile)
1005   {
1006     wxString s = TexPathList.FindValidPath(_T("bullet.bmp"));
1007     if (!s.empty())
1008     {
1009       wxString str = wxFileNameFromPath(s);
1010       bulletFile = copystring(str);
1011     }
1012   }
1013 
1014   if (wxFileExists(RefFileName))
1015     ReadTexReferences(RefFileName);
1016 
1017   bool success = false;
1018 
1019   if (!InputFile.empty() && !OutputFile.empty())
1020   {
1021     if (!wxFileExists(InputFile))
1022     {
1023       OnError(_T("Cannot open input file!"));
1024       TexCleanUp();
1025       return false;
1026     }
1027 #if !defined(NO_GUI) && wxUSE_STATUSBAR
1028     if (isInteractive)
1029     {
1030       wxString buf;
1031       buf.Printf(_T("Working, pass %d...Click CLOSE to abort"), passNumber);
1032       frame->SetStatusText((wxChar *)buf.c_str());
1033     }
1034 #endif
1035     OkToClose = false;
1036     OnInform(_T("Reading LaTeX file..."));
1037     TexLoadFile(InputFile);
1038 
1039     if (stopRunning)
1040     {
1041         OkToClose = true;
1042         return false;
1043     }
1044 
1045     switch (convertMode)
1046     {
1047       case TEX_RTF:
1048       {
1049         success = RTFGo();
1050         break;
1051       }
1052       case TEX_XLP:
1053       {
1054         success = XLPGo();
1055         break;
1056       }
1057       case TEX_HTML:
1058       {
1059         success = HTMLGo();
1060         break;
1061       }
1062     }
1063   }
1064   if (stopRunning)
1065   {
1066     OnInform(_T("*** Aborted by user."));
1067     success = false;
1068     stopRunning = false;
1069     OkToClose = true;
1070   }
1071 
1072   if (success)
1073   {
1074     WriteTexReferences(RefFileName);
1075     TexCleanUp();
1076     startedSections = false;
1077 
1078     wxString buf;
1079 #ifndef NO_GUI
1080     wxLongLong elapsed = wxGetLocalTimeMillis() - localTime;
1081     buf.Printf(_T("Finished PASS #%d in %ld seconds.\n"), passNumber, (long)(elapsed.GetLo()/1000.0));
1082     OnInform((wxChar *)buf.c_str());
1083 
1084     if (errorCount)
1085     {
1086         buf.Printf(_T("Errors encountered during this pass: %lu\n"), errorCount);
1087         OnInform((wxChar *)buf.c_str());
1088     }
1089 
1090 #if wxUSE_STATUSBAR
1091     if (isInteractive)
1092     {
1093       buf.Printf(_T("Done, %d %s."), passNumber, (passNumber > 1) ? _T("passes") : _T("pass"));
1094       frame->SetStatusText((wxChar *)buf.c_str());
1095     }
1096 #endif // wxUSE_STATUSBAR
1097 #else
1098     buf.Printf(_T("Done, %d %s."), passNumber, (passNumber > 1) ? _T("passes") : _T("pass"));
1099     OnInform((wxChar *)buf.c_str());
1100     if (errorCount)
1101     {
1102         buf.Printf(_T("Errors encountered during this pass: %lu\n"), errorCount);
1103         OnInform((wxChar *)buf.c_str());
1104     }
1105 #endif
1106     passNumber ++;
1107     errorCount = 0;
1108     OkToClose = true;
1109     return true;
1110   }
1111 
1112   TexCleanUp();
1113   startedSections = false;
1114 
1115 #if !defined(NO_GUI) && wxUSE_STATUSBAR
1116   frame->SetStatusText(_T("Aborted by user."));
1117 #endif // GUI
1118 
1119   OnInform(_T("Sorry, unsuccessful."));
1120   OkToClose = true;
1121   return false;
1122 }
1123 
OnError(const wxChar * msg)1124 void OnError(const wxChar *msg)
1125 {
1126     wxString msg_string = msg;
1127     errorCount++;
1128 
1129 #ifdef NO_GUI
1130     wxSTD cerr << "Error: " << msg_string.mb_str() << "\n";
1131     wxSTD cerr.flush();
1132 #else
1133     if (isInteractive && frame)
1134     {
1135         (*frame->textWindow) << _T("Error: ") << msg << _T("\n");
1136     }
1137     else
1138     {
1139 #if defined(__UNIX__)
1140         wxSTD cerr << "Error: " << msg_string.mb_str() << "\n";
1141         wxSTD cerr.flush();
1142 #elif defined(__WXMSW__)
1143         wxLogError(msg);
1144 #endif
1145     }
1146 
1147     Tex2RTFYield(true);
1148 #endif // NO_GUI
1149 }
1150 
OnInform(const wxChar * msg)1151 void OnInform(const wxChar *msg)
1152 {
1153     wxString msg_string = msg;
1154 #ifdef NO_GUI
1155     wxSTD cout << msg_string.mb_str() << "\n";
1156     wxSTD cout.flush();
1157 #else
1158     if (isInteractive && frame)
1159     {
1160        (*frame->textWindow) << msg << _T("\n");
1161     }
1162     else
1163     {
1164 #if defined(__UNIX__)
1165         wxSTD cout << msg_string.mb_str() << "\n";
1166         wxSTD cout.flush();
1167 #elif defined(__WXMSW__)
1168         wxLogInfo(msg);
1169 #endif
1170     }
1171 
1172     if (isInteractive)
1173     {
1174         Tex2RTFYield(true);
1175     }
1176 #endif // NO_GUI
1177 }
1178 
OnMacro(int macroId,int no_args,bool start)1179 void OnMacro(int macroId, int no_args, bool start)
1180 {
1181   switch (convertMode)
1182   {
1183     case TEX_RTF:
1184     {
1185       RTFOnMacro(macroId, no_args, start);
1186       break;
1187     }
1188     case TEX_XLP:
1189     {
1190       XLPOnMacro(macroId, no_args, start);
1191       break;
1192     }
1193     case TEX_HTML:
1194     {
1195       HTMLOnMacro(macroId, no_args, start);
1196       break;
1197     }
1198   }
1199 }
1200 
OnArgument(int macroId,int arg_no,bool start)1201 bool OnArgument(int macroId, int arg_no, bool start)
1202 {
1203   switch (convertMode)
1204   {
1205     case TEX_RTF:
1206     {
1207       return RTFOnArgument(macroId, arg_no, start);
1208       // break;
1209     }
1210     case TEX_XLP:
1211     {
1212       return XLPOnArgument(macroId, arg_no, start);
1213       // break;
1214     }
1215     case TEX_HTML:
1216     {
1217       return HTMLOnArgument(macroId, arg_no, start);
1218       // break;
1219     }
1220   }
1221   return true;
1222 }
1223 
1224 /*
1225  * DDE Stuff
1226  */
1227 #if defined(__WXMSW__) && !defined(NO_GUI)
1228 
1229 /*
1230  * Server
1231  */
1232 
OnAcceptConnection(const wxString & topic)1233 wxConnectionBase *Tex2RTFServer::OnAcceptConnection(const wxString& topic)
1234 {
1235   if (topic == _T("TEX2RTF"))
1236   {
1237     if (!ipc_buffer)
1238       ipc_buffer = new wxChar[1000];
1239 
1240     return new Tex2RTFConnection(ipc_buffer, 4000);
1241   }
1242   else
1243     return NULL;
1244 }
1245 
1246  /*
1247   * Connection
1248   */
1249 
Tex2RTFConnection(wxChar * buf,int size)1250 Tex2RTFConnection::Tex2RTFConnection(wxChar *buf, int size):wxDDEConnection(buf, size)
1251 {
1252 }
1253 
SplitCommand(wxChar * data,wxChar * firstArg,wxChar * secondArg)1254 bool SplitCommand(wxChar *data, wxChar *firstArg, wxChar *secondArg)
1255 {
1256   firstArg[0] = 0;
1257   secondArg[0] = 0;
1258   int i = 0;
1259   bool stop = false;
1260   // Find first argument (command name)
1261   while (!stop)
1262   {
1263     if (data[i] == ' ' || data[i] == 0)
1264       stop = true;
1265     else
1266     {
1267       firstArg[i] = data[i];
1268       i ++;
1269     }
1270   }
1271   firstArg[i] = 0;
1272   if (data[i] == ' ')
1273   {
1274     // Find second argument
1275     i ++;
1276     int j = 0;
1277     while (data[i] != 0)
1278     {
1279       secondArg[j] = data[i];
1280       i ++;
1281       j ++;
1282     }
1283     secondArg[j] = 0;
1284   }
1285   return true;
1286 }
1287 
OnExecute(const wxString & WXUNUSED (topic),wxChar * data,int WXUNUSED (size),wxIPCFormat WXUNUSED (format))1288 bool Tex2RTFConnection::OnExecute(const wxString& WXUNUSED(topic), wxChar *data, int WXUNUSED(size), wxIPCFormat WXUNUSED(format))
1289 {
1290   wxStrcpy(Tex2RTFLastStatus, _T("OK"));
1291 
1292   wxChar firstArg[50];
1293   wxChar secondArg[300];
1294   if (SplitCommand(data, firstArg, secondArg))
1295   {
1296     bool hasArg = (wxStrlen(secondArg) > 0);
1297     if (wxStrcmp(firstArg, _T("INPUT")) == 0 && hasArg)
1298     {
1299         InputFile = secondArg;
1300         if (frame)
1301         {
1302             wxChar buf[100];
1303             wxString str = wxFileNameFromPath(InputFile);
1304             wxSnprintf(buf, sizeof(buf), _T("Tex2RTF [%s]"), (const wxChar*) str);
1305             frame->SetTitle(buf);
1306         }
1307     }
1308     else if (wxStrcmp(firstArg, _T("OUTPUT")) == 0 && hasArg)
1309     {
1310         OutputFile = secondArg;
1311     }
1312     else if (wxStrcmp(firstArg, _T("GO")) == 0)
1313     {
1314       wxStrcpy(Tex2RTFLastStatus, _T("WORKING"));
1315       if (!Go())
1316         wxStrcpy(Tex2RTFLastStatus, _T("CONVERSION ERROR"));
1317       else
1318         wxStrcpy(Tex2RTFLastStatus, _T("OK"));
1319     }
1320     else if (wxStrcmp(firstArg, _T("EXIT")) == 0)
1321     {
1322       if (frame) frame->Close();
1323     }
1324     else if (wxStrcmp(firstArg, _T("MINIMIZE")) == 0 || wxStrcmp(firstArg, _T("ICONIZE")) == 0)
1325     {
1326       if (frame)
1327         frame->Iconize(true);
1328     }
1329     else if (wxStrcmp(firstArg, _T("SHOW")) == 0 || wxStrcmp(firstArg, _T("RESTORE")) == 0)
1330     {
1331       if (frame)
1332       {
1333         frame->Iconize(false);
1334         frame->Show(true);
1335       }
1336     }
1337     else
1338     {
1339       // Try for a setting
1340       wxStrcpy(Tex2RTFLastStatus, RegisterSetting(firstArg, secondArg, false));
1341 #if !defined(NO_GUI) && wxUSE_STATUSBAR
1342       if (frame && wxStrcmp(firstArg, _T("conversionMode")) == 0)
1343       {
1344         wxChar buf[100];
1345         wxStrcpy(buf, _T("In "));
1346 
1347         if (winHelp && (convertMode == TEX_RTF))
1348           wxStrcat(buf, _T("WinHelp RTF"));
1349         else if (!winHelp && (convertMode == TEX_RTF))
1350           wxStrcat(buf, _T("linear RTF"));
1351         else if (convertMode == TEX_HTML) wxStrcat(buf, _T("HTML"));
1352         else if (convertMode == TEX_XLP) wxStrcat(buf, _T("XLP"));
1353           wxStrcat(buf, _T(" mode."));
1354         frame->SetStatusText(buf, 1);
1355       }
1356 #endif
1357     }
1358   }
1359   return true;
1360 }
1361 
OnRequest(const wxString & WXUNUSED (topic),const wxString & WXUNUSED (item),int * WXUNUSED (size),wxIPCFormat WXUNUSED (format))1362 wxChar *Tex2RTFConnection::OnRequest(const wxString& WXUNUSED(topic), const wxString& WXUNUSED(item), int *WXUNUSED(size), wxIPCFormat WXUNUSED(format))
1363 {
1364   return Tex2RTFLastStatus;
1365 }
1366 
1367 #endif
1368 
1369 #ifndef NO_GUI
1370 #ifndef __WXGTK__
1371 //void wxObject::Dump(wxSTD ostream& str)
1372 //{
1373 //  if (GetClassInfo() && GetClassInfo()->GetClassName())
1374 //    str << GetClassInfo()->GetClassName();
1375 //  else
1376 //    str << "unknown object class";
1377 //}
1378 #endif
1379 #endif
1380