📄 htmlutil.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Name: htmlutil.cpp
// Purpose: Converts Latex to HTML
// Author: Julian Smart
// Modified by: Wlodzimierz ABX Skiba 2003/2004 Unicode support
// Ron Lee
// Created: 7.9.93
// RCS-ID: $Id: htmlutil.cpp,v 1.33 2005/09/23 12:56:33 MR Exp $
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#endif
#include "wx/arrstr.h"
#include "tex2any.h"
#include "tex2rtf.h"
#include "table.h"
#include <stdio.h>
#define HTML_FILENAME_PATTERN _T("%s_%s.html")
#if !WXWIN_COMPATIBILITY_2_4
static inline wxChar* copystring(const wxChar* s)
{ return wxStrcpy(new wxChar[wxStrlen(s) + 1], s); }
#endif
extern wxHashTable TexReferences;
extern int passNumber;
extern void DecToHex(int, wxChar *);
void GenerateHTMLIndexFile(wxChar *fname);
bool PrimaryAnchorOfTheFile( wxChar *file, wxChar *label );
void GenerateHTMLWorkshopFiles(wxChar *fname);
void HTMLWorkshopAddToContents(int level, wxChar *s, wxChar *file);
void HTMLWorkshopStartContents();
void HTMLWorkshopEndContents();
void OutputContentsFrame(void);
#include "readshg.h" // Segmented hypergraphics parsing
wxChar *ChaptersName = NULL;
wxChar *SectionsName = NULL;
wxChar *SubsectionsName = NULL;
wxChar *SubsubsectionsName = NULL;
wxChar *TitlepageName = NULL;
wxChar *lastFileName = NULL;
wxChar *lastTopic = NULL;
wxChar *currentFileName = NULL;
wxChar *contentsFrameName = NULL;
static TexChunk *descriptionItemArg = NULL;
static TexChunk *helpRefFilename = NULL;
static TexChunk *helpRefText = NULL;
static int indentLevel = 0;
static int citeCount = 1;
extern FILE *Contents;
FILE *FrameContents = NULL;
FILE *Titlepage = NULL;
// FILE *FrameTitlepage = NULL;
int fileId = 0;
bool subsectionStarted = false;
// Which column of a row are we in? (Assumes no nested tables, of course)
int currentColumn = 0;
// Are we in verbatim mode? If so, format differently.
static bool inVerbatim = false;
// Need to know whether we're in a table or figure for benefit
// of listoffigures/listoftables
static bool inFigure = false;
static bool inTable = false;
// This is defined in the Tex2Any library.
extern wxChar *BigBuffer;
// DHS Two-column table dimensions.
static int TwoColWidthA = -1;
static int TwoColWidthB = -1;
class HyperReference: public wxObject
{
public:
wxChar *refName;
wxChar *refFile;
HyperReference(wxChar *name, wxChar *file)
{
if (name) refName = copystring(name);
if (file) refFile = copystring(file);
}
};
class TexNextPage: public wxObject
{
public:
wxChar *label;
wxChar *filename;
TexNextPage(wxChar *theLabel, wxChar *theFile)
{
label = copystring(theLabel);
filename = copystring(theFile);
}
~TexNextPage(void)
{
delete[] label;
delete[] filename;
}
};
wxHashTable TexNextPages(wxKEY_STRING);
static wxChar *CurrentChapterName = NULL;
static wxChar *CurrentChapterFile = NULL;
static wxChar *CurrentSectionName = NULL;
static wxChar *CurrentSectionFile = NULL;
static wxChar *CurrentSubsectionName = NULL;
static wxChar *CurrentSubsectionFile = NULL;
static wxChar *CurrentSubsubsectionName = NULL;
static wxChar *CurrentSubsubsectionFile = NULL;
static wxChar *CurrentTopic = NULL;
static void SetCurrentTopic(wxChar *s)
{
if (CurrentTopic) delete[] CurrentTopic;
CurrentTopic = copystring(s);
}
void SetCurrentChapterName(wxChar *s, wxChar *file)
{
if (CurrentChapterName) delete[] CurrentChapterName;
CurrentChapterName = copystring(s);
if (CurrentChapterFile) delete[] CurrentChapterFile;
CurrentChapterFile = copystring(file);
currentFileName = CurrentChapterFile;
SetCurrentTopic(s);
}
void SetCurrentSectionName(wxChar *s, wxChar *file)
{
if (CurrentSectionName) delete[] CurrentSectionName;
CurrentSectionName = copystring(s);
if (CurrentSectionFile) delete[] CurrentSectionFile;
CurrentSectionFile = copystring(file);
currentFileName = CurrentSectionFile;
SetCurrentTopic(s);
}
void SetCurrentSubsectionName(wxChar *s, wxChar *file)
{
if (CurrentSubsectionName) delete[] CurrentSubsectionName;
CurrentSubsectionName = copystring(s);
if (CurrentSubsectionFile) delete[] CurrentSubsectionFile;
CurrentSubsectionFile = copystring(file);
currentFileName = CurrentSubsectionFile;
SetCurrentTopic(s);
}
void SetCurrentSubsubsectionName(wxChar *s, wxChar *file)
{
if (CurrentSubsubsectionName) delete[] CurrentSubsubsectionName;
CurrentSubsubsectionName = copystring(s);
if (CurrentSubsubsectionFile) delete[] CurrentSubsubsectionFile;
CurrentSubsubsectionFile = copystring(file);
currentFileName = CurrentSubsubsectionFile;
SetCurrentTopic(s);
}
// mapping between fileId and filenames if truncateFilenames=false:
static wxArrayString gs_filenames;
/*
* Close former filedescriptor and reopen using another filename.
*
*/
void ReopenFile(FILE **fd, wxChar **fileName, const wxChar *label)
{
if (*fd)
{
wxFprintf(*fd, _T("\n</FONT></BODY></HTML>\n"));
fclose(*fd);
}
fileId ++;
wxChar buf[400];
if (truncateFilenames)
{
wxSnprintf(buf, sizeof(buf), _T("%s%d.htm"), FileRoot, fileId);
}
else
{
if (fileId == 1)
gs_filenames.Add(wxEmptyString);
wxSnprintf(buf, sizeof(buf), HTML_FILENAME_PATTERN, FileRoot, label);
gs_filenames.Add(buf);
}
if (*fileName) delete[] *fileName;
*fileName = copystring(wxFileNameFromPath(buf));
*fd = wxFopen(buf, _T("w"));
wxFprintf(*fd, _T("<HTML>\n"));
}
/*
* Reopen section contents file, i.e. the index appended to each section
* in subsectionCombine mode
*/
static wxChar *SectionContentsFilename = NULL;
static FILE *SectionContentsFD = NULL;
void ReopenSectionContentsFile(void)
{
if ( SectionContentsFD )
{
fclose(SectionContentsFD);
}
if ( SectionContentsFilename )
delete[] SectionContentsFilename;
SectionContentsFD = NULL;
SectionContentsFilename = NULL;
// Create the name from the current section filename
if ( CurrentSectionFile )
{
wxChar buf[256];
wxStrcpy(buf, CurrentSectionFile);
wxStripExtension(buf);
wxStrcat(buf, _T(".con"));
SectionContentsFilename = copystring(buf);
SectionContentsFD = wxFopen(SectionContentsFilename, _T("w"));
}
}
/*
* Given a TexChunk with a string value, scans through the string
* converting Latex-isms into HTML-isms, such as 2 newlines -> <P>.
*
*/
void ProcessText2HTML(TexChunk *chunk)
{
bool changed = false;
int ptr = 0;
int i = 0;
wxChar ch = 1;
int len = wxStrlen(chunk->value);
while (ch != 0)
{
ch = chunk->value[i];
// 2 newlines means \par
if (!inVerbatim && chunk->value[i] == 10 && ((len > i+1 && chunk->value[i+1] == 10) ||
((len > i+1 && chunk->value[i+1] == 13) &&
(len > i+2 && chunk->value[i+2] == 10))))
{
BigBuffer[ptr] = 0; wxStrcat(BigBuffer, _T("<P>\n\n")); ptr += 5;
i += 2;
changed = true;
}
else if (!inVerbatim && ch == _T('`') && (len >= i+1 && chunk->value[i+1] == '`'))
{
BigBuffer[ptr] = '"'; ptr ++;
i += 2;
changed = true;
}
else if (!inVerbatim && ch == _T('`')) // Change ` to '
{
BigBuffer[ptr] = 39; ptr ++;
i += 1;
changed = true;
}
else if (ch == _T('<')) // Change < to <
{
BigBuffer[ptr] = 0;
wxStrcat(BigBuffer, _T("<"));
ptr += 4;
i += 1;
changed = true;
}
else if (ch == _T('>')) // Change > to >
{
BigBuffer[ptr] = 0;
wxStrcat(BigBuffer, _T(">"));
ptr += 4;
i += 1;
changed = true;
}
else
{
BigBuffer[ptr] = ch;
i ++;
ptr ++;
}
}
BigBuffer[ptr] = 0;
if (changed)
{
delete chunk->value;
chunk->value = copystring(BigBuffer);
}
}
/*
* Scan through all chunks starting from the given one,
* calling ProcessText2HTML to convert Latex-isms to RTF-isms.
* This should be called after Tex2Any has parsed the file,
* and before TraverseDocument is called.
*
*/
void Text2HTML(TexChunk *chunk)
{
Tex2RTFYield();
if (stopRunning) return;
switch (chunk->type)
{
case CHUNK_TYPE_MACRO:
{
TexMacroDef *def = chunk->def;
if (def && def->ignore)
return;
if (def && (def->macroId == ltVERBATIM || def->macroId == ltVERB || def->macroId == ltSPECIAL))
inVerbatim = true;
wxNode *node = chunk->children.GetFirst();
while (node)
{
TexChunk *child_chunk = (TexChunk *)node->GetData();
Text2HTML(child_chunk);
node = node->GetNext();
}
if (def && (def->macroId == ltVERBATIM || def->macroId == ltVERB || def->macroId == ltSPECIAL))
inVerbatim = false;
break;
}
case CHUNK_TYPE_ARG:
{
wxNode *node = chunk->children.GetFirst();
while (node)
{
TexChunk *child_chunk = (TexChunk *)node->GetData();
Text2HTML(child_chunk);
node = node->GetNext();
}
break;
}
case CHUNK_TYPE_STRING:
{
if (chunk->value)
ProcessText2HTML(chunk);
break;
}
}
}
/*
* Add appropriate browse buttons to this page.
*
*/
void AddBrowseButtons(wxChar *upLabel, wxChar *upFilename,
wxChar *previousLabel, wxChar *previousFilename,
wxChar *thisLabel, wxChar *thisFilename)
{
wxChar contentsReferenceBuf[80];
wxChar upReferenceBuf[80];
wxChar backReferenceBuf[80];
wxChar forwardReferenceBuf[80];
if (htmlBrowseButtons == HTML_BUTTONS_NONE)
return;
wxChar *contentsReference; // no need to initialize because always assigned below
if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
contentsReference = ContentsNameString;
else
{
// contentsReference = "<img align=center src=\"contents.gif\" BORDER=0 ALT=\"Contents\">";
contentsReference = contentsReferenceBuf;
wxSnprintf(contentsReference, sizeof(contentsReferenceBuf),
_T("<img align=center src=\"%s\" BORDER=0 ALT=\"Contents\">"),
ConvertCase(_T("contents.gif")));
}
wxChar *upReference; // no need to initialize because always assigned below
if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
upReference = UpNameString;
else
{
// upReference = "<img align=center src=\"up.gif\" ALT=\"Up\">";
upReference = upReferenceBuf;
wxSnprintf(upReference, sizeof(upReferenceBuf),
_T("<img align=center src=\"%s\" BORDER=0 ALT=\"Up\">"),
ConvertCase(_T("up.gif")));
}
wxChar *backReference; // no need to initialize because always assigned below
if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
backReference = _T("<<");
else
{
// backReference = "<img align=center src=\"back.gif\" ALT=\"Previous\">";
backReference = backReferenceBuf;
wxSnprintf(backReference, sizeof(backReferenceBuf),
_T("<img align=center src=\"%s\" BORDER=0 ALT=\"Previous\">"),
ConvertCase(_T("back.gif")));
}
wxChar *forwardReference; // no need to initialize because always assigned below
if (htmlBrowseButtons == HTML_BUTTONS_TEXT)
forwardReference = _T(">>");
else
{
// forwardReference = "<img align=center src=\"forward.gif\" ALT=\"Next\">";
forwardReference = forwardReferenceBuf;
wxSnprintf(forwardReference, sizeof(forwardReferenceBuf),
_T("<img align=center src=\"%s\" BORDER=0 ALT=\"Next\">"),
ConvertCase(_T("forward.gif")));
}
TexOutput(_T("<CENTER>"));
wxChar buf[200];
/*
* Contents button
*
*/
if (truncateFilenames)
{
wxChar buf1[80];
wxStrcpy(buf1, ConvertCase(wxFileNameFromPath(FileRoot)));
wxSnprintf(buf, sizeof(buf),
_T("\n<A HREF=\"%s.%s\">%s</A> "),
buf1, ConvertCase(_T("htm")), contentsReference);
}
else
{
wxChar buf1[80];
wxStrcpy(buf1, ConvertCase(wxFileNameFromPath(FileRoot)));
wxSnprintf(buf, sizeof(buf),
_T("\n<A HREF=\"%s%s\">%s</A> "),
buf1, ConvertCase(_T("_contents.html")), contentsReference);
}
// TexOutput(_T("<NOFRAMES>"));
TexOutput(buf);
// TexOutput(_T("</NOFRAMES>"));
/*
* Up button
*
*/
if (upLabel && upFilename)
{
if ( (wxStrlen(upLabel) > 0) && !PrimaryAnchorOfTheFile(upFilename, upLabel) )
wxSnprintf(buf, sizeof(buf),
_T("<A HREF=\"%s#%s\">%s</A> "),
ConvertCase(upFilename), upLabel, upReference);
else
wxSnprintf(buf, sizeof(buf),
_T("<A HREF=\"%s\">%s</A> "),
ConvertCase(upFilename), upReference);
if (wxStrcmp(upLabel, _T("contents")) == 0)
{
// TexOutput(_T("<NOFRAMES>"));
TexOutput(buf);
// TexOutput(_T("</NOFRAMES>"));
}
else
TexOutput(buf);
}
/*
* << button
*
*/
if (previousLabel && previousFilename)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -