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