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