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