]> git.saurik.com Git - wxWidgets.git/blame - utils/tex2rtf/src/tex2any.cpp
change in XRC format
[wxWidgets.git] / utils / tex2rtf / src / tex2any.cpp
CommitLineData
9a29912f
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: tex2any.cpp
3// Purpose: Utilities for Latex conversion.
4// Author: Julian Smart
5// Modified by:
6// Created: 01/01/99
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include "wx/wx.h"
25#endif
26
27#include <ctype.h>
28#include "tex2any.h"
29#include <stdlib.h>
30#include <time.h>
31
32/*
33 * Variables accessible from clients
34 *
35 */
36
37TexChunk * DocumentTitle = NULL;
38TexChunk * DocumentAuthor = NULL;
39TexChunk * DocumentDate = NULL;
40
41// Header/footers/pagestyle
42TexChunk * LeftHeaderEven = NULL;
43TexChunk * LeftFooterEven = NULL;
44TexChunk * CentreHeaderEven = NULL;
45TexChunk * CentreFooterEven = NULL;
46TexChunk * RightHeaderEven = NULL;
47TexChunk * RightFooterEven = NULL;
48TexChunk * LeftHeaderOdd = NULL;
49TexChunk * LeftFooterOdd = NULL;
50TexChunk * CentreHeaderOdd = NULL;
51TexChunk * CentreFooterOdd = NULL;
52TexChunk * RightHeaderOdd = NULL;
53TexChunk * RightFooterOdd = NULL;
54char * PageStyle = copystring("plain");
55
56int DocumentStyle = LATEX_REPORT;
57int MinorDocumentStyle = 0;
58wxPathList TexPathList;
59char * BibliographyStyleString = copystring("plain");
60char * DocumentStyleString = copystring("report");
61char * MinorDocumentStyleString = NULL;
62int ParSkip = 0;
63int ParIndent = 0;
64
65int normalFont = 10;
66int smallFont = 8;
67int tinyFont = 6;
68int largeFont1 = 12;
69int LargeFont2 = 14;
70int LARGEFont3 = 18;
71int hugeFont1 = 20;
72int HugeFont2 = 24;
73int HUGEFont3 = 28;
74
75/*
76 * USER-ADJUSTABLE SETTINGS
77 *
78 */
79
80// Section font sizes
81int chapterFont = 12; // LARGEFont3;
82int sectionFont = 12; // LargeFont2;
83int subsectionFont = 12; // largeFont1;
84int titleFont = LARGEFont3;
85int authorFont = LargeFont2;
86int mirrorMargins = TRUE;
87bool winHelp = FALSE; // Output in Windows Help format if TRUE, linear otherwise
88bool isInteractive = FALSE;
89bool runTwice = FALSE;
90int convertMode = TEX_RTF;
91bool headerRule = FALSE;
92bool footerRule = FALSE;
93bool compatibilityMode = FALSE; // If TRUE, maximum Latex compatibility
94 // (Quality of RTF generation deteriorate)
95bool generateHPJ; // Generate WinHelp Help Project file
96char *winHelpTitle = NULL; // Windows Help title
97int defaultTableColumnWidth = 2000;
98
99int labelIndentTab = 18; // From left indent to item label (points)
100int itemIndentTab = 40; // From left indent to item (points)
101
102bool useUpButton = TRUE;
103int htmlBrowseButtons = HTML_BUTTONS_TEXT;
104
105bool truncateFilenames = FALSE; // Truncate for DOS
106int winHelpVersion = 3; // WinHelp Version (3 for Windows 3.1, 4 for Win95)
107bool winHelpContents = FALSE; // Generate .cnt file for WinHelp 4
108bool htmlIndex = FALSE; // Generate .htx file for HTML
109bool htmlFrameContents = FALSE; // Use frames for HTML contents page
110bool useHeadingStyles = TRUE; // Insert \s1, s2 etc.
111bool useWord = TRUE; // Insert proper Word table of contents, etc etc
112int contentsDepth = 4; // Depth of Word table of contents
113bool indexSubsections = TRUE; // Index subsections in linear RTF
114// Linear RTF method of including bitmaps. Can be "includepicture", "hex"
115char *bitmapMethod = copystring("includepicture");
116bool upperCaseNames = FALSE;
117// HTML background and text colours
118char *backgroundImageString = NULL;
119char *backgroundColourString = copystring("255;255;255");
120char *textColourString = NULL;
121char *linkColourString = NULL;
122char *followedLinkColourString = NULL;
123bool combineSubSections = FALSE;
14204c7a 124bool htmlWorkshopFiles = FALSE;
9a29912f
JS
125
126/*
127 * International support
128 */
129
130// Names to help with internationalisation
131char *ContentsNameString = copystring("Contents");
132char *AbstractNameString = copystring("Abstract");
133char *GlossaryNameString = copystring("Glossary");
134char *ReferencesNameString = copystring("References");
135char *FiguresNameString = copystring("List of Figures");
136char *TablesNameString = copystring("List of Tables");
137char *FigureNameString = copystring("Figure");
138char *TableNameString = copystring("Table");
139char *IndexNameString = copystring("Index");
140char *ChapterNameString = copystring("chapter");
141char *SectionNameString = copystring("section");
142char *SubsectionNameString = copystring("subsection");
143char *SubsubsectionNameString = copystring("subsubsection");
144char *UpNameString = copystring("Up");
145
146/*
147 * Section numbering
148 *
149 */
150
151int chapterNo = 0;
152int sectionNo = 0;
153int subsectionNo = 0;
154int subsubsectionNo = 0;
155int figureNo = 0;
156int tableNo = 0;
157
158/*
159 * Other variables
160 *
161 */
162
163FILE *CurrentOutput1 = NULL;
164FILE *CurrentOutput2 = NULL;
165FILE *Inputs[15];
166int LineNumbers[15];
167char *FileNames[15];
168int CurrentInputIndex = 0;
169
170char *TexFileRoot = NULL;
171char *TexBibName = NULL; // Bibliography output file name
172char *TexTmpBibName = NULL; // Temporary bibliography output file name
173bool isSync = FALSE; // If TRUE, should not yield to other processes.
174bool stopRunning = FALSE; // If TRUE, should abort.
175
176static int currentColumn = 0;
177char *currentArgData = NULL;
178bool haveArgData = FALSE; // If TRUE, we're simulating the data.
179TexChunk *currentArgument = NULL;
180TexChunk *nextChunk = NULL;
181bool isArgOptional = FALSE;
446dd881 182int noArgs = 0;
9a29912f
JS
183
184TexChunk *TopLevel = NULL;
185// wxList MacroDefs(wxKEY_STRING);
186wxHashTable MacroDefs(wxKEY_STRING);
187wxStringList IgnorableInputFiles; // Ignorable \input files, e.g. psbox.tex
188char *BigBuffer = NULL; // For reading in large chunks of text
189TexMacroDef *SoloBlockDef = NULL;
190TexMacroDef *VerbatimMacroDef = NULL;
191
192#define IncrementLineNumber() LineNumbers[CurrentInputIndex] ++
193
194void TexOutput(char *s, bool ordinaryText)
195{
196 int len = strlen(s);
197
198 // Update current column, but only if we're guaranteed to
199 // be ordinary text (not mark-up stuff)
200 int i;
201 if (ordinaryText)
202 for (i = 0; i < len; i++)
203 {
204 if (s[i] == 13 || s[i] == 10)
205 currentColumn = 0;
206 else
207 currentColumn ++;
208 }
209
210 if (CurrentOutput1)
211 fprintf(CurrentOutput1, "%s", s);
212 if (CurrentOutput2)
213 fprintf(CurrentOutput2, "%s", s);
214}
215
216/*
217 * Try to find a Latex macro, in one of the following forms:
218 * (1) \begin{} ... \end{}
219 * (2) \macroname{arg1}...{argn}
220 * (3) {\bf arg1}
221 */
222
223void ForbidWarning(TexMacroDef *def)
224{
225 char buf[100];
226 switch (def->forbidden)
227 {
228 case FORBID_WARN:
229 {
230 sprintf(buf, "Warning: it is recommended that command %s is not used.", def->name);
231 OnInform(buf);
232 break;
233 }
234 case FORBID_ABSOLUTELY:
235 {
236 sprintf(buf, "Error: command %s cannot be used and will lead to errors.", def->name);
237 OnInform(buf);
238 break;
239 }
240 default:
241 break;
242 }
243}
244
245TexMacroDef *MatchMacro(char *buffer, int *pos, char **env, bool *parseToBrace)
246{
247 *parseToBrace = TRUE;
248 int i = (*pos);
249 TexMacroDef *def = NULL;
250 char macroBuf[40];
251
252 // First, try to find begin{thing}
253 if (strncmp(buffer+i, "begin{", 6) == 0)
254 {
255 i += 6;
256
257 int j = i;
258 while ((isalpha(buffer[j]) || buffer[j] == '*') && ((j - i) < 39))
259 {
260 macroBuf[j-i] = buffer[j];
261 j ++;
262 }
263 macroBuf[j-i] = 0;
264 def = (TexMacroDef *)MacroDefs.Get(macroBuf);
265
266 if (def)
267 {
268 *pos = j + 1; // BUGBUG Should this be + 1???
269 *env = def->name;
270 ForbidWarning(def);
271 return def;
272 }
273 else return NULL;
274 }
275
276 // Failed, so try to find macro from definition list
277 int j = i;
278
279 // First try getting a one-character macro, but ONLY
280 // if these TWO characters are not both alphabetical (could
281 // be a longer macro)
282 if (!(isalpha(buffer[i]) && isalpha(buffer[i+1])))
283 {
284 macroBuf[0] = buffer[i];
285 macroBuf[1] = 0;
286
287 def = (TexMacroDef *)MacroDefs.Get(macroBuf);
288 if (def) j ++;
289 }
290
291 if (!def)
292 {
293 while ((isalpha(buffer[j]) || buffer[j] == '*') && ((j - i) < 39))
294 {
295 macroBuf[j-i] = buffer[j];
296 j ++;
297 }
298 macroBuf[j-i] = 0;
299 def = (TexMacroDef *)MacroDefs.Get(macroBuf);
300 }
301
302 if (def)
303 {
304 i = j;
305
306 // We want to check whether this is a space-consuming macro
307 // (e.g. {\bf word})
308 // No brace, e.g. \input thing.tex instead of \input{thing};
309 // or a numeric argument, such as \parindent0pt
310 if ((def->no_args > 0) && ((buffer[i] == 32) || (buffer[i] == '=') || (isdigit(buffer[i]))))
311 {
312 if ((buffer[i] == 32) || (buffer[i] == '='))
313 i ++;
314
315 *parseToBrace = FALSE;
316 }
317 *pos = i;
318 ForbidWarning(def);
319 return def;
320 }
321 return NULL;
322}
323
324void EatWhiteSpace(char *buffer, int *pos)
325{
326 int len = strlen(buffer);
327 int j = *pos;
328 bool keepGoing = TRUE;
329 bool moreLines = TRUE;
330 while ((j < len) && keepGoing &&
331 (buffer[j] == 10 || buffer[j] == 13 || buffer[j] == ' ' || buffer[j] == 9))
332 {
333 j ++;
334 if (j >= len)
335 {
336 if (moreLines)
337 {
338 moreLines = read_a_line(buffer);
339 len = strlen(buffer);
340 j = 0;
341 }
342 else
343 keepGoing = FALSE;
344 }
345 }
346 *pos = j;
347}
348
349bool FindEndEnvironment(char *buffer, int *pos, char *env)
350{
351 int i = (*pos);
352
353 // Try to find end{thing}
354 if ((strncmp(buffer+i, "end{", 4) == 0) &&
355 (strncmp(buffer+i+4, env, strlen(env)) == 0))
356 {
357 *pos = i + 5 + strlen(env);
358 return TRUE;
359 }
360 else return FALSE;
361}
362
363bool readingVerbatim = FALSE;
364bool readInVerbatim = FALSE; // Within a verbatim, but not nec. verbatiminput
365
f6bcfd97
BP
366// Switched this off because e.g. \verb${$ causes it to fail. There is no
367// detection of \verb yet.
368#define CHECK_BRACES 0
369
370unsigned long leftCurly = 0;
371unsigned long rightCurly = 0;
372static wxString currentFileName = "";
373
9a29912f
JS
374bool read_a_line(char *buf)
375{
376 if (CurrentInputIndex < 0)
377 {
378 buf[0] = 0;
379 return FALSE;
380 }
381
382 int ch = -2;
383 int i = 0;
384 buf[0] = 0;
f6bcfd97 385
9a29912f
JS
386 while (ch != EOF && ch != 10)
387 {
388 if (((i == 14) && (strncmp(buf, "\\end{verbatim}", 14) == 0)) ||
389 ((i == 16) && (strncmp(buf, "\\end{toocomplex}", 16) == 0)))
390 readInVerbatim = FALSE;
391
392 ch = getc(Inputs[CurrentInputIndex]);
f6bcfd97
BP
393
394#if CHECK_BRACES
395 if (ch == '{' && !readInVerbatim)
396 leftCurly++;
397 if (ch == '}' && !readInVerbatim)
398 {
399 rightCurly++;
400 if (rightCurly > leftCurly)
401 {
402 wxString errBuf;
403 errBuf.Printf("An extra right Curly brace ('}') was detected at line %l inside file %s",LineNumbers[CurrentInputIndex], (const char*) currentFileName.c_str());
404 OnError((char *)errBuf.c_str());
405
406 // Reduce the count of right curly braces, so the mismatched count
407 // isn't reported on every line that has a '}' after the first mismatch
408 rightCurly--;
409 }
410 }
411#endif
412
9a29912f
JS
413 if (ch != EOF)
414 {
415 // Check for 2 consecutive newlines and replace with \par
416 if (ch == 10 && !readInVerbatim)
417 {
418 int ch1 = getc(Inputs[CurrentInputIndex]);
419 if ((ch1 == 10) || (ch1 == 13))
420 {
421 // Eliminate newline (10) following DOS linefeed
422 if (ch1 == 13) ch1 = getc(Inputs[CurrentInputIndex]);
423 buf[i] = 0;
424 IncrementLineNumber();
425// strcat(buf, "\\par\n");
426// i += 6;
427 strcat(buf, "\\par");
428 i += 5;
429 }
430 else
431 {
432 ungetc(ch1, Inputs[CurrentInputIndex]);
433 buf[i] = ch;
434 i ++;
435 }
436 }
437 else
438 {
439
440 // Convert embedded characters to RTF equivalents
441 switch(ch)
442 {
443