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