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