mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-13 10:18:40 +12:00
This commit is contained in:
parent
de070bf485
commit
a90b5cf37a
1998 changed files with 1034301 additions and 0 deletions
914
wxWidgets/src/html/chm.cpp
Normal file
914
wxWidgets/src/html/chm.cpp
Normal file
|
@ -0,0 +1,914 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/chm.cpp
|
||||
// Purpose: CHM (Help) support for wxHTML
|
||||
// Author: Markus Sinner
|
||||
// Copyright: (c) 2003 Herd Software Development
|
||||
// CVS-ID: $Id: chm.cpp 65784 2010-10-08 11:16:54Z MW $
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_LIBMSPACK
|
||||
|
||||
#include <mspack.h>
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/module.h"
|
||||
#endif
|
||||
|
||||
#include "wx/filesys.h"
|
||||
#include "wx/mstream.h"
|
||||
#include "wx/wfstream.h"
|
||||
|
||||
#include "wx/html/forcelnk.h"
|
||||
FORCE_LINK_ME(wxhtml_chm_support)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/// wxChmTools
|
||||
/// <p>
|
||||
/// this class is used to abstract access to CHM-Archives
|
||||
/// with library mspack written by Stuart Caie
|
||||
/// http://www.kyz.uklinux.net/libmspack/
|
||||
// ----------------------------------------------------------------------------
|
||||
class wxChmTools
|
||||
{
|
||||
public:
|
||||
/// constructor
|
||||
wxChmTools(const wxFileName &archive);
|
||||
/// destructor
|
||||
~wxChmTools();
|
||||
|
||||
/// Generate error-string for error-code
|
||||
static const wxString ChmErrorMsg(int error);
|
||||
|
||||
/// get an array of archive-member-filenames
|
||||
const wxArrayString *GetFileNames()
|
||||
{
|
||||
return m_fileNames;
|
||||
};
|
||||
|
||||
/// get the name of the archive representated by this class
|
||||
const wxString GetArchiveName()
|
||||
{
|
||||
return m_chmFileName;
|
||||
};
|
||||
|
||||
/// Find a file in the archive
|
||||
const wxString Find(const wxString& pattern,
|
||||
const wxString& startfrom = wxEmptyString);
|
||||
|
||||
/// Extract a file in the archive into a file
|
||||
size_t Extract(const wxString& pattern, const wxString& filename);
|
||||
|
||||
/// check archive for a file
|
||||
bool Contains(const wxString& pattern);
|
||||
|
||||
/// get a string for the last error which occurred
|
||||
const wxString GetLastErrorMessage();
|
||||
|
||||
/// Last Error
|
||||
int m_lasterror;
|
||||
|
||||
private:
|
||||
// these vars are used by FindFirst/Next:
|
||||
wxString m_chmFileName;
|
||||
char *m_chmFileNameANSI;
|
||||
|
||||
/// mspack-pointer to mschmd_header
|
||||
struct mschmd_header *m_archive;
|
||||
/// mspack-pointer to mschm_decompressor
|
||||
struct mschm_decompressor *m_decompressor;
|
||||
|
||||
/// Array of filenames in archive
|
||||
wxArrayString * m_fileNames;
|
||||
|
||||
/// Internal function to get filepointer
|
||||
struct mschmd_file *GetMschmdFile(const wxString& pattern);
|
||||
};
|
||||
|
||||
|
||||
/***
|
||||
* constructor
|
||||
*
|
||||
* @param archive The filename of the archive to open
|
||||
*/
|
||||
wxChmTools::wxChmTools(const wxFileName &archive)
|
||||
{
|
||||
m_chmFileName = archive.GetFullPath();
|
||||
|
||||
wxASSERT_MSG( !m_chmFileName.empty(), _T("empty archive name") );
|
||||
|
||||
m_archive = NULL;
|
||||
m_decompressor = NULL;
|
||||
m_fileNames = NULL;
|
||||
m_lasterror = 0;
|
||||
|
||||
struct mschmd_header *chmh;
|
||||
struct mschm_decompressor *chmd;
|
||||
struct mschmd_file *file;
|
||||
|
||||
// Create decompressor
|
||||
chmd = mspack_create_chm_decompressor(NULL);
|
||||
m_decompressor = (struct mschm_decompressor *) chmd;
|
||||
|
||||
// NB: we must make a copy of the string because chmd->open won't call
|
||||
// strdup() [libmspack-20030726], which would cause crashes in
|
||||
// Unicode build when mb_str() returns temporary buffer
|
||||
m_chmFileNameANSI = strdup((const char*)m_chmFileName.mb_str(wxConvFile));
|
||||
|
||||
// Open the archive and store it in class:
|
||||
if ( (chmh = chmd->open(chmd, (char*)m_chmFileNameANSI)) )
|
||||
{
|
||||
m_archive = chmh;
|
||||
|
||||
// Create Filenamearray
|
||||
m_fileNames = new wxArrayString;
|
||||
|
||||
// Store Filenames in array
|
||||
for (file = chmh->files; file; file = file->next)
|
||||
{
|
||||
m_fileNames->Add(wxString::FromAscii(file->filename));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogError(_("Failed to open CHM archive '%s'."),
|
||||
archive.GetFullPath().c_str());
|
||||
m_lasterror = (chmd->last_error(chmd));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Destructor
|
||||
*/
|
||||
wxChmTools::~wxChmTools()
|
||||
{
|
||||
struct mschm_decompressor *chmd = m_decompressor;
|
||||
struct mschmd_header *chmh = m_archive;
|
||||
|
||||
delete m_fileNames;
|
||||
|
||||
// Close Archive
|
||||
if (chmh && chmd)
|
||||
chmd->close(chmd, chmh);
|
||||
|
||||
free(m_chmFileNameANSI);
|
||||
|
||||
// Destroy Decompressor
|
||||
if (chmd)
|
||||
mspack_destroy_chm_decompressor(chmd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the given pattern matches to any
|
||||
* filename stored in archive
|
||||
*
|
||||
* @param pattern The filename pattern, may include '*' and/or '?'
|
||||
* @return true, if any file matching pattern has been found,
|
||||
* false if not
|
||||
*/
|
||||
bool wxChmTools::Contains(const wxString& pattern)
|
||||
{
|
||||
int count;
|
||||
wxString pattern_tmp = wxString(pattern).MakeLower();
|
||||
|
||||
// loop through filearay
|
||||
if ( m_fileNames && (count = m_fileNames->GetCount()) > 0 )
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
wxString tmp = m_fileNames->Item(i).MakeLower();
|
||||
if ( tmp.Matches(pattern_tmp) || tmp.Mid(1).Matches(pattern_tmp))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find()
|
||||
*
|
||||
* Finds the next file descibed by a pattern in the archive, starting
|
||||
* the file given by second parameter
|
||||
*
|
||||
* @param pattern The file-pattern to search for. May contain '*' and/or '?'
|
||||
* @param startfrom The filename which the search should start after
|
||||
* @returns The full pathname of the found file
|
||||
*/
|
||||
const wxString wxChmTools::Find(const wxString& pattern,
|
||||
const wxString& startfrom)
|
||||
{
|
||||
int count;
|
||||
wxString tmp;
|
||||
wxString pattern_tmp(pattern);
|
||||
wxString startfrom_tmp(startfrom);
|
||||
pattern_tmp.MakeLower();
|
||||
startfrom_tmp.MakeLower();
|
||||
|
||||
if ( m_fileNames && (count = m_fileNames->GetCount()) > 0 )
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
tmp = m_fileNames->Item(i).MakeLower();
|
||||
// if we find the string where the search should began
|
||||
if ( tmp.Matches(startfrom_tmp) ||
|
||||
tmp.Mid(1).Matches(startfrom_tmp) )
|
||||
continue;
|
||||
if ( tmp.Matches(pattern_tmp) ||
|
||||
tmp.Mid(1).Matches(pattern_tmp) )
|
||||
{
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract ()
|
||||
*
|
||||
* extracts the first hit of pattern to the given position
|
||||
*
|
||||
* @param pattern A filename pattern (may contain * and ? chars)
|
||||
* @param filename The FileName where to temporary extract the file to
|
||||
* @return 0 at no file extracted<br>
|
||||
* number of bytes extracted else
|
||||
*/
|
||||
size_t wxChmTools::Extract(const wxString& pattern, const wxString& filename)
|
||||
{
|
||||
struct mschm_decompressor *d = m_decompressor;
|
||||
struct mschmd_header *h = m_archive;
|
||||
struct mschmd_file *f;
|
||||
|
||||
wxString tmp;
|
||||
wxString pattern_tmp = (wxString(pattern)).MakeLower();
|
||||
|
||||
for (f = h->files; f; f = f->next)
|
||||
{
|
||||
tmp = wxString::FromAscii(f->filename).MakeLower();
|
||||
if ( tmp.Matches(pattern_tmp) ||
|
||||
tmp.Mid(1).Matches(pattern_tmp) )
|
||||
{
|
||||
// ignore leading '/'
|
||||
if (d->extract(d, f,
|
||||
(char*)(const char*)filename.mb_str(wxConvFile)))
|
||||
{
|
||||
// Error
|
||||
m_lasterror = d->last_error(d);
|
||||
wxLogError(_("Could not extract %s into %s: %s"),
|
||||
wxString::FromAscii(f->filename).c_str(),
|
||||
filename.c_str(),
|
||||
ChmErrorMsg(m_lasterror).c_str());
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (size_t) f->length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find a file by pattern
|
||||
*
|
||||
* @param pattern A filename pattern (may contain * and ? chars)
|
||||
* @return A pointer to the file (mschmd_file*)
|
||||
*/
|
||||
struct mschmd_file *wxChmTools::GetMschmdFile(const wxString& pattern_orig)
|
||||
{
|
||||
struct mschmd_file *f;
|
||||
struct mschmd_header *h = (struct mschmd_header *) m_archive;
|
||||
wxString tmp;
|
||||
wxString pattern = wxString(pattern_orig).MakeLower();
|
||||
|
||||
for (f = h->files; f; f = f->next)
|
||||
{
|
||||
tmp = wxString::FromAscii(f->filename).MakeLower();
|
||||
if ( tmp.Matches(pattern) || tmp.Mid(1).Matches(pattern) )
|
||||
{
|
||||
// ignore leading '/'
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const wxString wxChmTools::GetLastErrorMessage()
|
||||
{
|
||||
return ChmErrorMsg(m_lasterror);
|
||||
}
|
||||
|
||||
const wxString wxChmTools::ChmErrorMsg(int error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case MSPACK_ERR_OK:
|
||||
return _("no error");
|
||||
case MSPACK_ERR_ARGS:
|
||||
return _("bad arguments to library function");
|
||||
case MSPACK_ERR_OPEN:
|
||||
return _("error opening file");
|
||||
case MSPACK_ERR_READ:
|
||||
return _("read error");
|
||||
case MSPACK_ERR_WRITE:
|
||||
return _("write error");
|
||||
case MSPACK_ERR_SEEK:
|
||||
return _("seek error");
|
||||
case MSPACK_ERR_NOMEMORY:
|
||||
return _("out of memory");
|
||||
case MSPACK_ERR_SIGNATURE:
|
||||
return _("bad signature");
|
||||
case MSPACK_ERR_DATAFORMAT:
|
||||
return _("error in data format");
|
||||
case MSPACK_ERR_CHECKSUM:
|
||||
return _("checksum error");
|
||||
case MSPACK_ERR_CRUNCH:
|
||||
return _("compression error");
|
||||
case MSPACK_ERR_DECRUNCH:
|
||||
return _("decompression error");
|
||||
}
|
||||
return _("unknown error");
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/// wxChmInputStream
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class wxChmInputStream : public wxInputStream
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
wxChmInputStream(const wxString& archive,
|
||||
const wxString& file, bool simulate = false);
|
||||
/// Destructor
|
||||
virtual ~wxChmInputStream();
|
||||
|
||||
/// Return the size of the accessed file in archive
|
||||
virtual size_t GetSize() const { return m_size; }
|
||||
/// End of Stream?
|
||||
virtual bool Eof() const;
|
||||
/// Set simulation-mode of HHP-File (if non is found)
|
||||
void SimulateHHP(bool sim) { m_simulateHHP = sim; }
|
||||
|
||||
protected:
|
||||
/// See wxInputStream
|
||||
virtual size_t OnSysRead(void *buffer, size_t bufsize);
|
||||
/// See wxInputStream
|
||||
virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode);
|
||||
/// See wxInputStream
|
||||
virtual wxFileOffset OnSysTell() const { return m_pos; }
|
||||
|
||||
private:
|
||||
size_t m_size;
|
||||
wxFileOffset m_pos;
|
||||
bool m_simulateHHP;
|
||||
|
||||
char * m_content;
|
||||
wxInputStream * m_contentStream;
|
||||
|
||||
void CreateHHPStream();
|
||||
bool CreateFileStream(const wxString& pattern);
|
||||
// this void* is handle of archive . I'm sorry it is void and not proper
|
||||
// type but I don't want to make unzip.h header public.
|
||||
|
||||
|
||||
// locates the file and returns a mspack_file *
|
||||
mspack_file *LocateFile(wxString filename);
|
||||
|
||||
// should store pointer to current file
|
||||
mspack_file *m_file;
|
||||
|
||||
// The Chm-Class for extracting the data
|
||||
wxChmTools *m_chm;
|
||||
|
||||
wxString m_fileName;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param archive The name of the .chm archive. Remember that archive must
|
||||
* be local file accesible via fopen, fread functions!
|
||||
* @param filename The Name of the file to be extracted from archive
|
||||
* @param simulate if true than class should simulate .HHP-File based on #SYSTEM
|
||||
* if false than class does nothing if it doesnt find .hhp
|
||||
*/
|
||||
wxChmInputStream::wxChmInputStream(const wxString& archive,
|
||||
const wxString& filename, bool simulate)
|
||||
: wxInputStream()
|
||||
{
|
||||
m_pos = 0;
|
||||
m_size = 0;
|
||||
m_content = NULL;
|
||||
m_contentStream = NULL;
|
||||
m_lasterror = wxSTREAM_NO_ERROR;
|
||||
m_chm = new wxChmTools (wxFileName(archive));
|
||||
m_file = NULL;
|
||||
m_fileName = wxString(filename).MakeLower();
|
||||
m_simulateHHP = simulate;
|
||||
|
||||
if ( !m_chm->Contains(m_fileName) )
|
||||
{
|
||||
// if the file could not be located, but was *.hhp, than we create
|
||||
// the content of the hhp-file on the fly and store it for reading
|
||||
// by the application
|
||||
if ( m_fileName.Find(_T(".hhp")) != wxNOT_FOUND && m_simulateHHP )
|
||||
{
|
||||
// now we open an hhp-file
|
||||
CreateHHPStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogError(_("Could not locate file '%s'."), filename.c_str());
|
||||
m_lasterror = wxSTREAM_READ_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // file found
|
||||
CreateFileStream(m_fileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxChmInputStream::~wxChmInputStream()
|
||||
{
|
||||
delete m_chm;
|
||||
|
||||
delete m_contentStream;
|
||||
|
||||
if (m_content)
|
||||
{
|
||||
free (m_content);
|
||||
m_content=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool wxChmInputStream::Eof() const
|
||||
{
|
||||
return (m_content==NULL ||
|
||||
m_contentStream==NULL ||
|
||||
m_contentStream->Eof() ||
|
||||
m_pos>m_size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t wxChmInputStream::OnSysRead(void *buffer, size_t bufsize)
|
||||
{
|
||||
if ( m_pos >= m_size )
|
||||
{
|
||||
m_lasterror = wxSTREAM_EOF;
|
||||
return 0;
|
||||
}
|
||||
m_lasterror = wxSTREAM_NO_ERROR;
|
||||
|
||||
// If the rest to read from the stream is less
|
||||
// than the buffer size, than only read the rest
|
||||
if ( m_pos + bufsize > m_size )
|
||||
bufsize = m_size - m_pos;
|
||||
|
||||
m_contentStream->SeekI(m_pos);
|
||||
m_contentStream->Read(buffer, bufsize);
|
||||
m_pos +=bufsize;
|
||||
m_contentStream->SeekI(m_pos);
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
wxFileOffset wxChmInputStream::OnSysSeek(wxFileOffset seek, wxSeekMode mode)
|
||||
{
|
||||
wxString mode_str = wxEmptyString;
|
||||
|
||||
if ( !m_contentStream || m_contentStream->Eof() )
|
||||
{
|
||||
m_lasterror = wxSTREAM_EOF;
|
||||
return 0;
|
||||
}
|
||||
m_lasterror = wxSTREAM_NO_ERROR;
|
||||
|
||||
wxFileOffset nextpos;
|
||||
|
||||
switch ( mode )
|
||||
{
|
||||
case wxFromCurrent:
|
||||
nextpos = seek + m_pos;
|
||||
break;
|
||||
case wxFromStart:
|
||||
nextpos = seek;
|
||||
break;
|
||||
case wxFromEnd:
|
||||
nextpos = m_size - 1 + seek;
|
||||
break;
|
||||
default:
|
||||
nextpos = m_pos;
|
||||
break; /* just to fool compiler, never happens */
|
||||
}
|
||||
m_pos=nextpos;
|
||||
|
||||
// Set current position on stream
|
||||
m_contentStream->SeekI(m_pos);
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Help Browser tries to read the contents of the
|
||||
* file by interpreting a .hhp file in the Archiv.
|
||||
* For .chm doesnt include such a file, we need
|
||||
* to rebuild the information based on stored
|
||||
* system-files.
|
||||
*/
|
||||
void
|
||||
wxChmInputStream::CreateHHPStream()
|
||||
{
|
||||
wxFileName file;
|
||||
bool topic = false;
|
||||
bool hhc = false;
|
||||
bool hhk = false;
|
||||
wxInputStream *i;
|
||||
wxMemoryOutputStream *out;
|
||||
const char *tmp;
|
||||
|
||||
// Try to open the #SYSTEM-File and create the HHP File out of it
|
||||
// see http://bonedaddy.net/pabs3/chmspec/0.1.2/Internal.html#SYSTEM
|
||||
if ( ! m_chm->Contains(_T("/#SYSTEM")) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
wxLogDebug(_("Archive doesnt contain #SYSTEM file"));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
file = wxFileName(_T("/#SYSTEM"));
|
||||
}
|
||||
|
||||
if ( CreateFileStream(_T("/#SYSTEM")) )
|
||||
{
|
||||
// New stream for writing a memory area to simulate the
|
||||
// .hhp-file
|
||||
out = new wxMemoryOutputStream();
|
||||
|
||||
tmp = "[OPTIONS]\r\n";
|
||||
out->Write((const void *) tmp, strlen(tmp));
|
||||
|
||||
wxUint16 code;
|
||||
wxUint16 len;
|
||||
void *buf;
|
||||
|
||||
// use the actual stream for reading
|
||||
i = m_contentStream;
|
||||
|
||||
/* Now read the contents, and try to get the needed information */
|
||||
|
||||
// First 4 Bytes are Version information, skip
|
||||
i->SeekI(4);
|
||||
|
||||
while (!i->Eof())
|
||||
{
|
||||
// Read #SYSTEM-Code and length
|
||||
i->Read(&code, 2);
|
||||
code = wxUINT16_SWAP_ON_BE( code ) ;
|
||||
i->Read(&len, 2);
|
||||
len = wxUINT16_SWAP_ON_BE( len ) ;
|
||||
// data
|
||||
buf = malloc(len);
|
||||
i->Read(buf, len);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 0: // CONTENTS_FILE
|
||||
if (len)
|
||||
{
|
||||
tmp = "Contents file=";
|
||||
hhc=true;
|
||||
}
|
||||
break;
|
||||
case 1: // INDEX_FILE
|
||||
tmp = "Index file=";
|
||||
hhk = true;
|
||||
break;
|
||||
case 2: // DEFAULT_TOPIC
|
||||
tmp = "Default Topic=";
|
||||
topic = true;
|
||||
break;
|
||||
case 3: // TITLE
|
||||
tmp = "Title=";
|
||||
break;
|
||||
// case 6: // COMPILED_FILE
|
||||
// tmp = "Compiled File=";
|
||||
// break;
|
||||
case 7: // COMPILED_FILE
|
||||
tmp = "Binary Index=YES\r\n";
|
||||
out->Write( (const void *) tmp, strlen(tmp));
|
||||
tmp = NULL;
|
||||
break;
|
||||
case 4: // STRUCT SYSTEM INFO
|
||||
tmp = NULL ;
|
||||
if ( len >= 28 )
|
||||
{
|
||||
char *structptr = (char*) buf ;
|
||||
// LCID at position 0
|
||||
wxUint32 dummy = *((wxUint32 *)(structptr+0)) ;
|
||||
wxUint32 lcid = wxUINT32_SWAP_ON_BE( dummy ) ;
|
||||
char msg[64];
|
||||
int len = sprintf(msg, "Language=0x%X\r\n", lcid) ;
|
||||
if (len > 0)
|
||||
out->Write(msg, len) ;
|
||||
}
|
||||
break ;
|
||||
default:
|
||||
tmp=NULL;
|
||||
}
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
out->Write((const void *) tmp, strlen(tmp));
|
||||
out->Write(buf, strlen((char*)buf));
|
||||
out->Write("\r\n", 2);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
buf=NULL;
|
||||
}
|
||||
|
||||
|
||||
// Free the old data which wont be used any more
|
||||
delete m_contentStream;
|
||||
if (m_content)
|
||||
free (m_content);
|
||||
|
||||
// Now add entries which are missing
|
||||
if ( !hhc && m_chm->Contains(_T("*.hhc")) )
|
||||
{
|
||||
tmp = "Contents File=*.hhc\r\n";
|
||||
out->Write((const void *) tmp, strlen(tmp));
|
||||
}
|
||||
|
||||
if ( !hhk && m_chm->Contains(_T("*.hhk")) )
|
||||
{
|
||||
tmp = "Index File=*.hhk\r\n";
|
||||
out->Write((const void *) tmp, strlen(tmp));
|
||||
}
|
||||
|
||||
// Now copy the Data from the memory
|
||||
out->SeekO(0, wxFromEnd);
|
||||
m_size = out->TellO();
|
||||
out->SeekO(0, wxFromStart);
|
||||
m_content = (char *) malloc (m_size+1);
|
||||
out->CopyTo(m_content, m_size);
|
||||
m_content[m_size]='\0';
|
||||
m_size++;
|
||||
m_contentStream = new wxMemoryInputStream(m_content, m_size);
|
||||
|
||||
delete out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Stream pointing to a virtual file in
|
||||
* the current archive
|
||||
*/
|
||||
bool wxChmInputStream::CreateFileStream(const wxString& pattern)
|
||||
{
|
||||
wxFileInputStream * fin;
|
||||
wxString tmpfile = wxFileName::CreateTempFileName(_T("chmstrm"));
|
||||
|
||||
if ( tmpfile.empty() )
|
||||
{
|
||||
wxLogError(_("Could not create temporary file '%s'"), tmpfile.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// try to extract the file
|
||||
if ( m_chm->Extract(pattern, tmpfile) <= 0 )
|
||||
{
|
||||
wxLogError(_("Extraction of '%s' into '%s' failed."),
|
||||
pattern.c_str(), tmpfile.c_str());
|
||||
if ( wxFileExists(tmpfile) )
|
||||
wxRemoveFile(tmpfile);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open a filestream to extracted file
|
||||
fin = new wxFileInputStream(tmpfile);
|
||||
m_size = fin->GetSize();
|
||||
m_content = (char *) malloc(m_size+1);
|
||||
fin->Read(m_content, m_size);
|
||||
m_content[m_size]='\0';
|
||||
|
||||
wxRemoveFile(tmpfile);
|
||||
|
||||
delete fin;
|
||||
|
||||
m_contentStream = new wxMemoryInputStream (m_content, m_size);
|
||||
|
||||
return m_contentStream->IsOk();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxChmFSHandler
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxChmFSHandler : public wxFileSystemHandler
|
||||
{
|
||||
public:
|
||||
/// Constructor and Destructor
|
||||
wxChmFSHandler();
|
||||
virtual ~wxChmFSHandler();
|
||||
|
||||
/// Is able to open location?
|
||||
virtual bool CanOpen(const wxString& location);
|
||||
/// Open a file
|
||||
virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location);
|
||||
/// Find first occurrence of spec
|
||||
virtual wxString FindFirst(const wxString& spec, int flags = 0);
|
||||
/// Find next occurrence of spec
|
||||
virtual wxString FindNext();
|
||||
|
||||
private:
|
||||
int m_lasterror;
|
||||
wxString m_pattern;
|
||||
wxString m_found;
|
||||
wxChmTools * m_chm;
|
||||
};
|
||||
|
||||
wxChmFSHandler::wxChmFSHandler() : wxFileSystemHandler()
|
||||
{
|
||||
m_lasterror=0;
|
||||
m_pattern=wxEmptyString;
|
||||
m_found=wxEmptyString;
|
||||
m_chm=NULL;
|
||||
}
|
||||
|
||||
wxChmFSHandler::~wxChmFSHandler()
|
||||
{
|
||||
if (m_chm)
|
||||
delete m_chm;
|
||||
}
|
||||
|
||||
bool wxChmFSHandler::CanOpen(const wxString& location)
|
||||
{
|
||||
wxString p = GetProtocol(location);
|
||||
return (p == _T("chm")) &&
|
||||
(GetProtocol(GetLeftLocation(location)) == _T("file"));
|
||||
}
|
||||
|
||||
wxFSFile* wxChmFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs),
|
||||
const wxString& location)
|
||||
{
|
||||
wxString right = GetRightLocation(location);
|
||||
wxString left = GetLeftLocation(location);
|
||||
|
||||
wxInputStream *s;
|
||||
|
||||
int index;
|
||||
|
||||
if ( GetProtocol(left) != _T("file") )
|
||||
{
|
||||
wxLogError(_("CHM handler currently supports only local files!"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Work around javascript
|
||||
wxString tmp = wxString(right);
|
||||
if ( tmp.MakeLower().Contains(_T("javascipt")) && tmp.Contains(_T("\'")) )
|
||||
{
|
||||
right = right.AfterFirst(_T('\'')).BeforeLast(_T('\''));
|
||||
}
|
||||
|
||||
// now work on the right location
|
||||
if (right.Contains(_T("..")))
|
||||
{
|
||||
wxFileName abs(right);
|
||||
abs.MakeAbsolute(_T("/"));
|
||||
right = abs.GetFullPath();
|
||||
}
|
||||
|
||||
// a workaround for absolute links to root
|
||||
if ( (index=right.Index(_T("//"))) != wxNOT_FOUND )
|
||||
{
|
||||
right=wxString(right.Mid(index+1));
|
||||
wxLogWarning(_("Link contained '//', converted to absolute link."));
|
||||
}
|
||||
|
||||
wxFileName leftFilename = wxFileSystem::URLToFileName(left);
|
||||
if (!leftFilename.FileExists())
|
||||
return NULL;
|
||||
|
||||
// Open a stream to read the content of the chm-file
|
||||
s = new wxChmInputStream(leftFilename.GetFullPath(), right, true);
|
||||
|
||||
wxString mime = GetMimeTypeFromExt(location);
|
||||
|
||||
if ( s )
|
||||
{
|
||||
return new wxFSFile(s,
|
||||
left + _T("#chm:") + right,
|
||||
mime,
|
||||
GetAnchor(location),
|
||||
wxDateTime(leftFilename.GetModificationTime()));
|
||||
}
|
||||
|
||||
delete s;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Doku see wxFileSystemHandler
|
||||
*/
|
||||
wxString wxChmFSHandler::FindFirst(const wxString& spec, int flags)
|
||||
{
|
||||
wxString right = GetRightLocation(spec);
|
||||
wxString left = GetLeftLocation(spec);
|
||||
wxString nativename = wxFileSystem::URLToFileName(left).GetFullPath();
|
||||
|
||||
if ( GetProtocol(left) != _T("file") )
|
||||
{
|
||||
wxLogError(_("CHM handler currently supports only local files!"));
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
m_chm = new wxChmTools(wxFileName(nativename));
|
||||
m_pattern = right.AfterLast(_T('/'));
|
||||
|
||||
wxString m_found = m_chm->Find(m_pattern);
|
||||
|
||||
// now fake around hhp-files which are not existing in projects...
|
||||
if (m_found.empty() &&
|
||||
m_pattern.Contains(_T(".hhp")) &&
|
||||
!m_pattern.Contains(_T(".hhp.cached")))
|
||||
{
|
||||
m_found.Printf(_T("%s#chm:%s.hhp"),
|
||||
left.c_str(), m_pattern.BeforeLast(_T('.')).c_str());
|
||||
}
|
||||
|
||||
return m_found;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxString wxChmFSHandler::FindNext()
|
||||
{
|
||||
if (m_pattern.empty())
|
||||
return wxEmptyString;
|
||||
else
|
||||
return m_chm->Find(m_pattern, m_found);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// wxModule to register CHM handler
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class wxChmSupportModule : public wxModule
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS(wxChmSupportModule)
|
||||
|
||||
public:
|
||||
virtual bool OnInit()
|
||||
{
|
||||
wxFileSystem::AddHandler(new wxChmFSHandler);
|
||||
return true;
|
||||
}
|
||||
virtual void OnExit() {}
|
||||
}
|
||||
;
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxChmSupportModule, wxModule)
|
||||
|
||||
#endif // wxUSE_LIBMSPACK
|
96
wxWidgets/src/html/descrip.mms
Normal file
96
wxWidgets/src/html/descrip.mms
Normal file
|
@ -0,0 +1,96 @@
|
|||
#*****************************************************************************
|
||||
# *
|
||||
# Make file for VMS *
|
||||
# Author : J.Jansen (joukj@hrem.nano.tudelft.nl) *
|
||||
# Date : 13 February 2006 *
|
||||
# *
|
||||
#*****************************************************************************
|
||||
.first
|
||||
define wx [--.include.wx]
|
||||
|
||||
.ifdef __WXMOTIF__
|
||||
CXX_DEFINE = /define=(__WXMOTIF__=1)/name=(as_is,short)\
|
||||
/assume=(nostdnew,noglobal_array_new)
|
||||
CC_DEFINE = /define=(__WXMOTIF__=1)/name=(as_is,short)
|
||||
.else
|
||||
.ifdef __WXGTK__
|
||||
CXX_DEFINE = /define=(__WXGTK__=1)/float=ieee/name=(as_is,short)/ieee=denorm\
|
||||
/assume=(nostdnew,noglobal_array_new)
|
||||
CC_DEFINE = /define=(__WXGTK__=1)/float=ieee/name=(as_is,short)/ieee=denorm
|
||||
.else
|
||||
.ifdef __WXGTK2__
|
||||
CXX_DEFINE = /define=(__WXGTK__=1,VMS_GTK2=1)/float=ieee/name=(as_is,short)/ieee=denorm\
|
||||
/assume=(nostdnew,noglobal_array_new)
|
||||
CC_DEFINE = /define=(__WXGTK__=1,VMS_GTK2=1)/float=ieee/name=(as_is,short)/ieee=denorm
|
||||
.else
|
||||
.ifdef __WXX11__
|
||||
CXX_DEFINE = /define=(__WXX11__=1,__WXUNIVERSAL__==1)/float=ieee\
|
||||
/name=(as_is,short)/assume=(nostdnew,noglobal_array_new)
|
||||
CC_DEFINE = /define=(__WXX11__=1,__WXUNIVERSAL__==1)/float=ieee\
|
||||
/name=(as_is,short)
|
||||
.else
|
||||
CXX_DEFINE =
|
||||
CC_DEFINE =
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.suffixes : .cpp
|
||||
|
||||
.cpp.obj :
|
||||
cxx $(CXXFLAGS)$(CXX_DEFINE) $(MMS$TARGET_NAME).cpp
|
||||
.c.obj :
|
||||
cc $(CFLAGS)$(CC_DEFINE) $(MMS$TARGET_NAME).c
|
||||
|
||||
OBJECTS = \
|
||||
helpctrl.obj,helpdata.obj,helpfrm.obj,htmlcell.obj,htmlfilt.obj,\
|
||||
htmlpars.obj,htmltag.obj,htmlwin.obj,htmprint.obj,m_dflist.obj,\
|
||||
m_fonts.obj,m_hline.obj,m_image.obj,m_layout.obj,m_links.obj,\
|
||||
m_list.obj,m_pre.obj,m_tables.obj,winpars.obj,chm.obj,m_style.obj
|
||||
|
||||
SOURCES = \
|
||||
helpctrl.cpp,helpdata.cpp,helpfrm.cpp,htmlcell.cpp,htmlfilt.cpp,\
|
||||
htmlpars.cpp,htmltag.cpp,htmlwin.cpp,htmprint.cpp,m_dflist.cpp,\
|
||||
m_fonts.cpp,m_hline.cpp,m_image.cpp,m_layout.cpp,m_links.cpp,\
|
||||
m_list.cpp,m_pre.cpp,m_tables.cpp,winpars.cpp,chm.cpp,m_style.cpp
|
||||
|
||||
all : $(SOURCES)
|
||||
$(MMS)$(MMSQUALIFIERS) $(OBJECTS)
|
||||
.ifdef __WXMOTIF__
|
||||
library [--.lib]libwx_motif.olb $(OBJECTS)
|
||||
.else
|
||||
.ifdef __WXGTK__
|
||||
library [--.lib]libwx_gtk.olb $(OBJECTS)
|
||||
.else
|
||||
.ifdef __WXGTK2__
|
||||
library [--.lib]libwx_gtk2.olb $(OBJECTS)
|
||||
.else
|
||||
.ifdef __WXX11__
|
||||
library [--.lib]libwx_x11_univ.olb $(OBJECTS)
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
|
||||
helpctrl.obj : helpctrl.cpp
|
||||
helpdata.obj : helpdata.cpp
|
||||
helpfrm.obj : helpfrm.cpp
|
||||
htmlcell.obj : htmlcell.cpp
|
||||
htmlfilt.obj : htmlfilt.cpp
|
||||
htmlpars.obj : htmlpars.cpp
|
||||
htmltag.obj : htmltag.cpp
|
||||
htmlwin.obj : htmlwin.cpp
|
||||
htmprint.obj : htmprint.cpp
|
||||
m_dflist.obj : m_dflist.cpp
|
||||
m_fonts.obj : m_fonts.cpp
|
||||
m_hline.obj : m_hline.cpp
|
||||
m_image.obj : m_image.cpp
|
||||
m_layout.obj : m_layout.cpp
|
||||
m_links.obj : m_links.cpp
|
||||
m_list.obj : m_list.cpp
|
||||
m_pre.obj : m_pre.cpp
|
||||
m_tables.obj : m_tables.cpp
|
||||
winpars.obj : winpars.cpp
|
||||
chm.obj : chm.cpp
|
||||
m_style.obj : m_style.cpp
|
442
wxWidgets/src/html/helpctrl.cpp
Normal file
442
wxWidgets/src/html/helpctrl.cpp
Normal file
|
@ -0,0 +1,442 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: helpctrl.cpp
|
||||
// Purpose: wxHtmlHelpController
|
||||
// Notes: Based on htmlhelp.cpp, implementing a monolithic
|
||||
// HTML Help controller class, by Vaclav Slavik
|
||||
// Author: Harm van der Heijden and Vaclav Slavik
|
||||
// RCS-ID: $Id: helpctrl.cpp 52470 2008-03-13 23:29:27Z VS $
|
||||
// Copyright: (c) Harm van der Heijden and Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_WXHTML_HELP
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/app.h"
|
||||
#include "wx/intl.h"
|
||||
#endif // WX_PRECOMP
|
||||
|
||||
#include "wx/busyinfo.h"
|
||||
#include "wx/html/helpctrl.h"
|
||||
#include "wx/html/helpwnd.h"
|
||||
#include "wx/html/helpfrm.h"
|
||||
#include "wx/html/helpdlg.h"
|
||||
|
||||
#if wxUSE_HELP
|
||||
#include "wx/tipwin.h"
|
||||
#endif
|
||||
|
||||
#if wxUSE_LIBMSPACK
|
||||
#include "wx/html/forcelnk.h"
|
||||
FORCE_LINK(wxhtml_chm_support)
|
||||
#endif
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpController, wxHelpControllerBase)
|
||||
|
||||
wxHtmlHelpController::wxHtmlHelpController(int style, wxWindow* parentWindow):
|
||||
wxHelpControllerBase(parentWindow)
|
||||
{
|
||||
m_helpWindow = NULL;
|
||||
m_helpFrame = NULL;
|
||||
m_helpDialog = NULL;
|
||||
m_Config = NULL;
|
||||
m_ConfigRoot = wxEmptyString;
|
||||
m_titleFormat = _("Help: %s");
|
||||
m_FrameStyle = style;
|
||||
}
|
||||
|
||||
wxHtmlHelpController::~wxHtmlHelpController()
|
||||
{
|
||||
if (m_Config)
|
||||
WriteCustomization(m_Config, m_ConfigRoot);
|
||||
if (m_helpWindow)
|
||||
DestroyHelpWindow();
|
||||
}
|
||||
|
||||
|
||||
void wxHtmlHelpController::DestroyHelpWindow()
|
||||
{
|
||||
if (m_FrameStyle & wxHF_EMBEDDED)
|
||||
return;
|
||||
|
||||
// Find top-most parent window
|
||||
// If a modal dialog
|
||||
wxWindow* parent = FindTopLevelWindow();
|
||||
if (parent)
|
||||
{
|
||||
wxDialog* dialog = wxDynamicCast(parent, wxDialog);
|
||||
if (dialog && dialog->IsModal())
|
||||
{
|
||||
dialog->EndModal(wxID_OK);
|
||||
}
|
||||
parent->Destroy();
|
||||
m_helpWindow = NULL;
|
||||
}
|
||||
m_helpDialog = NULL;
|
||||
m_helpFrame = NULL;
|
||||
}
|
||||
|
||||
void wxHtmlHelpController::OnCloseFrame(wxCloseEvent& evt)
|
||||
{
|
||||
if (m_Config)
|
||||
WriteCustomization(m_Config, m_ConfigRoot);
|
||||
|
||||
evt.Skip();
|
||||
|
||||
OnQuit();
|
||||
|
||||
if ( m_helpWindow )
|
||||
m_helpWindow->SetController(NULL);
|
||||
m_helpWindow = NULL;
|
||||
m_helpDialog = NULL;
|
||||
m_helpFrame = NULL;
|
||||
}
|
||||
|
||||
void wxHtmlHelpController::SetTitleFormat(const wxString& title)
|
||||
{
|
||||
m_titleFormat = title;
|
||||
wxHtmlHelpFrame* frame = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpFrame);
|
||||
wxHtmlHelpDialog* dialog = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpDialog);
|
||||
if (frame)
|
||||
{
|
||||
frame->SetTitleFormat(title);
|
||||
}
|
||||
else if (dialog)
|
||||
dialog->SetTitleFormat(title);
|
||||
}
|
||||
|
||||
// Find the top-most parent window
|
||||
wxWindow* wxHtmlHelpController::FindTopLevelWindow()
|
||||
{
|
||||
wxWindow* parent = m_helpWindow;
|
||||
while (parent && !parent->IsTopLevel())
|
||||
{
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
bool wxHtmlHelpController::AddBook(const wxFileName& book_file, bool show_wait_msg)
|
||||
{
|
||||
return AddBook(wxFileSystem::FileNameToURL(book_file), show_wait_msg);
|
||||
}
|
||||
|
||||
bool wxHtmlHelpController::AddBook(const wxString& book, bool show_wait_msg)
|
||||
{
|
||||
wxBusyCursor cur;
|
||||
#if wxUSE_BUSYINFO
|
||||
wxBusyInfo* busy = NULL;
|
||||
wxString info;
|
||||
if (show_wait_msg)
|
||||
{
|
||||
info.Printf(_("Adding book %s"), book.c_str());
|
||||
busy = new wxBusyInfo(info);
|
||||
}
|
||||
#endif
|
||||
bool retval = m_helpData.AddBook(book);
|
||||
#if wxUSE_BUSYINFO
|
||||
if (show_wait_msg)
|
||||
delete busy;
|
||||
#else
|
||||
wxUnusedVar(show_wait_msg);
|
||||
#endif
|
||||
if (m_helpWindow)
|
||||
m_helpWindow->RefreshLists();
|
||||
return retval;
|
||||
}
|
||||
|
||||
wxHtmlHelpFrame* wxHtmlHelpController::CreateHelpFrame(wxHtmlHelpData *data)
|
||||
{
|
||||
wxHtmlHelpFrame* frame = new wxHtmlHelpFrame(data);
|
||||
frame->SetController(this);
|
||||
frame->Create(m_parentWindow, -1, wxEmptyString, m_FrameStyle, m_Config, m_ConfigRoot);
|
||||
frame->SetTitleFormat(m_titleFormat);
|
||||
m_helpFrame = frame;
|
||||
return frame;
|
||||
}
|
||||
|
||||
wxHtmlHelpDialog* wxHtmlHelpController::CreateHelpDialog(wxHtmlHelpData *data)
|
||||
{
|
||||
wxHtmlHelpDialog* dialog = new wxHtmlHelpDialog(data);
|
||||
dialog->SetController(this);
|
||||
dialog->SetTitleFormat(m_titleFormat);
|
||||
dialog->Create(m_parentWindow, -1, wxEmptyString, m_FrameStyle);
|
||||
m_helpDialog = dialog;
|
||||
return dialog;
|
||||
}
|
||||
|
||||
wxWindow* wxHtmlHelpController::CreateHelpWindow()
|
||||
{
|
||||
if (m_helpWindow)
|
||||
{
|
||||
if (m_FrameStyle & wxHF_EMBEDDED)
|
||||
return m_helpWindow;
|
||||
|
||||
wxWindow* topLevelWindow = FindTopLevelWindow();
|
||||
if (topLevelWindow)
|
||||
topLevelWindow->Raise();
|
||||
return m_helpWindow;
|
||||
}
|
||||
|
||||
if (m_Config == NULL)
|
||||
{
|
||||
m_Config = wxConfigBase::Get(false);
|
||||
if (m_Config != NULL)
|
||||
m_ConfigRoot = _T("wxWindows/wxHtmlHelpController");
|
||||
}
|
||||
|
||||
if (m_FrameStyle & wxHF_DIALOG)
|
||||
{
|
||||
wxHtmlHelpDialog* dialog = CreateHelpDialog(&m_helpData);
|
||||
m_helpWindow = dialog->GetHelpWindow();
|
||||
}
|
||||
else if ((m_FrameStyle & wxHF_EMBEDDED) && m_parentWindow)
|
||||
{
|
||||
m_helpWindow = new wxHtmlHelpWindow(m_parentWindow, -1, wxDefaultPosition, wxDefaultSize,
|
||||
wxTAB_TRAVERSAL|wxNO_BORDER, m_FrameStyle, &m_helpData);
|
||||
}
|
||||
else // wxHF_FRAME
|
||||
{
|
||||
wxHtmlHelpFrame* frame = CreateHelpFrame(&m_helpData);
|
||||
m_helpWindow = frame->GetHelpWindow();
|
||||
frame->Show(true);
|
||||
}
|
||||
|
||||
return m_helpWindow;
|
||||
}
|
||||
|
||||
void wxHtmlHelpController::ReadCustomization(wxConfigBase* cfg, const wxString& path)
|
||||
{
|
||||
/* should not be called by the user; call UseConfig, and the controller
|
||||
* will do the rest */
|
||||
if (m_helpWindow && cfg)
|
||||
m_helpWindow->ReadCustomization(cfg, path);
|
||||
}
|
||||
|
||||
void wxHtmlHelpController::WriteCustomization(wxConfigBase* cfg, const wxString& path)
|
||||
{
|
||||
/* typically called by the controllers OnCloseFrame handler */
|
||||
if (m_helpWindow && cfg)
|
||||
m_helpWindow->WriteCustomization(cfg, path);
|
||||
}
|
||||
|
||||
void wxHtmlHelpController::UseConfig(wxConfigBase *config, const wxString& rootpath)
|
||||
{
|
||||
m_Config = config;
|
||||
m_ConfigRoot = rootpath;
|
||||
if (m_helpWindow) m_helpWindow->UseConfig(config, rootpath);
|
||||
ReadCustomization(config, rootpath);
|
||||
}
|
||||
|
||||
//// Backward compatibility with wxHelpController API
|
||||
|
||||
bool wxHtmlHelpController::Initialize(const wxString& file)
|
||||
{
|
||||
wxString dir, filename, ext;
|
||||
wxSplitPath(file, & dir, & filename, & ext);
|
||||
|
||||
if (!dir.empty())
|
||||
dir = dir + wxFILE_SEP_PATH;
|
||||
|
||||
// Try to find a suitable file
|
||||
wxString actualFilename = dir + filename + wxString(wxT(".zip"));
|
||||
if (!wxFileExists(actualFilename))
|
||||
{
|
||||
actualFilename = dir + filename + wxString(wxT(".htb"));
|
||||
if (!wxFileExists(actualFilename))
|
||||
{
|
||||
actualFilename = dir + filename + wxString(wxT(".hhp"));
|
||||
if (!wxFileExists(actualFilename))
|
||||
{
|
||||
#if wxUSE_LIBMSPACK
|
||||
actualFilename = dir + filename + wxString(wxT(".chm"));
|
||||
if (!wxFileExists(actualFilename))
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return AddBook(wxFileName(actualFilename));
|
||||
}
|
||||
|
||||
bool wxHtmlHelpController::LoadFile(const wxString& WXUNUSED(file))
|
||||
{
|
||||
// Don't reload the file or we'll have it appear again, presumably.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxHtmlHelpController::DisplaySection(int sectionNo)
|
||||
{
|
||||
return Display(sectionNo);
|
||||
}
|
||||
|
||||
bool wxHtmlHelpController::DisplayTextPopup(const wxString& text, const wxPoint& WXUNUSED(pos))
|
||||
{
|
||||
#if wxUSE_TIPWINDOW
|
||||
static wxTipWindow* s_tipWindow = NULL;
|
||||
|
||||
if (s_tipWindow)
|
||||
{
|
||||
// Prevent s_tipWindow being nulled in OnIdle,
|
||||
// thereby removing the chance for the window to be closed by ShowHelp
|
||||
s_tipWindow->SetTipWindowPtr(NULL);
|
||||
s_tipWindow->Close();
|
||||
}
|
||||
s_tipWindow = NULL;
|
||||
|
||||
if ( !text.empty() )
|
||||
{
|
||||
s_tipWindow = new wxTipWindow(wxTheApp->GetTopWindow(), text, 100, & s_tipWindow);
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
wxUnusedVar(text);
|
||||
#endif // wxUSE_TIPWINDOW
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxHtmlHelpController::SetHelpWindow(wxHtmlHelpWindow* helpWindow)
|
||||
{
|
||||
m_helpWindow = helpWindow;
|
||||
if (helpWindow)
|
||||
helpWindow->SetController(this);
|
||||
}
|
||||
|
||||
void wxHtmlHelpController::SetFrameParameters(const wxString& title,
|
||||
const wxSize& size,
|
||||
const wxPoint& pos,
|
||||
bool WXUNUSED(newFrameEachTime))
|
||||
{
|
||||
SetTitleFormat(title);
|
||||
wxHtmlHelpFrame* frame = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpFrame);
|
||||
wxHtmlHelpDialog* dialog = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpDialog);
|
||||
if (frame)
|
||||
frame->SetSize(pos.x, pos.y, size.x, size.y);
|
||||
else if (dialog)
|
||||
dialog->SetSize(pos.x, pos.y, size.x, size.y);
|
||||
}
|
||||
|
||||
wxFrame* wxHtmlHelpController::GetFrameParameters(wxSize *size,
|
||||
wxPoint *pos,
|
||||
bool *newFrameEachTime)
|
||||
{
|
||||
if (newFrameEachTime)
|
||||
(* newFrameEachTime) = false;
|
||||
|
||||
wxHtmlHelpFrame* frame = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpFrame);
|
||||
wxHtmlHelpDialog* dialog = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpDialog);
|
||||
if (frame)
|
||||
{
|
||||
if (size)
|
||||
(* size) = frame->GetSize();
|
||||
if (pos)
|
||||
(* pos) = frame->GetPosition();
|
||||
return frame;
|
||||
}
|
||||
else if (dialog)
|
||||
{
|
||||
if (size)
|
||||
(* size) = dialog->GetSize();
|
||||
if (pos)
|
||||
(* pos) = dialog->GetPosition();
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool wxHtmlHelpController::Quit()
|
||||
{
|
||||
DestroyHelpWindow();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Make the help controller's frame 'modal' if
|
||||
// needed
|
||||
void wxHtmlHelpController::MakeModalIfNeeded()
|
||||
{
|
||||
if ((m_FrameStyle & wxHF_EMBEDDED) == 0)
|
||||
{
|
||||
wxHtmlHelpFrame* frame = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpFrame);
|
||||
wxHtmlHelpDialog* dialog = wxDynamicCast(FindTopLevelWindow(), wxHtmlHelpDialog);
|
||||
if (frame)
|
||||
frame->AddGrabIfNeeded();
|
||||
else if (dialog && (m_FrameStyle & wxHF_MODAL))
|
||||
{
|
||||
dialog->ShowModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool wxHtmlHelpController::Display(const wxString& x)
|
||||
{
|
||||
CreateHelpWindow();
|
||||
bool success = m_helpWindow->Display(x);
|
||||
MakeModalIfNeeded();
|
||||
return success;
|
||||
}
|
||||
|
||||
bool wxHtmlHelpController::Display(int id)
|
||||
{
|
||||
CreateHelpWindow();
|
||||
bool success = m_helpWindow->Display(id);
|
||||
MakeModalIfNeeded();
|
||||
return success;
|
||||
}
|
||||
|
||||
bool wxHtmlHelpController::DisplayContents()
|
||||
{
|
||||
CreateHelpWindow();
|
||||
bool success = m_helpWindow->DisplayContents();
|
||||
MakeModalIfNeeded();
|
||||
return success;
|
||||
}
|
||||
|
||||
bool wxHtmlHelpController::DisplayIndex()
|
||||
{
|
||||
CreateHelpWindow();
|
||||
bool success = m_helpWindow->DisplayIndex();
|
||||
MakeModalIfNeeded();
|
||||
return success;
|
||||
}
|
||||
|
||||
bool wxHtmlHelpController::KeywordSearch(const wxString& keyword,
|
||||
wxHelpSearchMode mode)
|
||||
{
|
||||
CreateHelpWindow();
|
||||
bool success = m_helpWindow->KeywordSearch(keyword, mode);
|
||||
MakeModalIfNeeded();
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* wxHtmlModalHelp
|
||||
* A convenience class, to use like this:
|
||||
*
|
||||
* wxHtmlModalHelp help(parent, helpFile, topic);
|
||||
*/
|
||||
|
||||
wxHtmlModalHelp::wxHtmlModalHelp(wxWindow* parent, const wxString& helpFile, const wxString& topic, int style)
|
||||
{
|
||||
// Force some mandatory styles
|
||||
style |= wxHF_DIALOG | wxHF_MODAL;
|
||||
|
||||
wxHtmlHelpController controller(style, parent);
|
||||
controller.Initialize(helpFile);
|
||||
|
||||
if (topic.IsEmpty())
|
||||
controller.DisplayContents();
|
||||
else
|
||||
controller.DisplaySection(topic);
|
||||
}
|
||||
|
||||
#endif // wxUSE_WXHTML_HELP
|
||||
|
1077
wxWidgets/src/html/helpdata.cpp
Normal file
1077
wxWidgets/src/html/helpdata.cpp
Normal file
File diff suppressed because it is too large
Load diff
132
wxWidgets/src/html/helpdlg.cpp
Normal file
132
wxWidgets/src/html/helpdlg.cpp
Normal file
|
@ -0,0 +1,132 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/helpdlg.cpp
|
||||
// Purpose: wxHtmlHelpDialog
|
||||
// Notes: Based on htmlhelp.cpp, implementing a monolithic
|
||||
// HTML Help controller class, by Vaclav Slavik
|
||||
// Author: Harm van der Heijden, Vaclav Slavik and Julian Smart
|
||||
// RCS-ID: $Id: helpdlg.cpp 50074 2007-11-19 09:12:08Z JS $
|
||||
// Copyright: (c) Harm van der Heijden, Vaclav Slavik and Julian Smart
|
||||
// Licence: wxWidgets licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h"
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_WXHTML_HELP
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#include "wx/object.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
|
||||
#include "wx/sizer.h"
|
||||
|
||||
#include "wx/bmpbuttn.h"
|
||||
#include "wx/statbox.h"
|
||||
#include "wx/radiobox.h"
|
||||
#include "wx/menu.h"
|
||||
#include "wx/msgdlg.h"
|
||||
#endif // WXPRECOMP
|
||||
|
||||
#include "wx/html/htmlwin.h"
|
||||
#include "wx/html/helpdlg.h"
|
||||
#include "wx/html/helpctrl.h"
|
||||
#include "wx/artprov.h"
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpDialog, wxDialog)
|
||||
|
||||
BEGIN_EVENT_TABLE(wxHtmlHelpDialog, wxDialog)
|
||||
EVT_CLOSE(wxHtmlHelpDialog::OnCloseWindow)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
wxHtmlHelpDialog::wxHtmlHelpDialog(wxWindow* parent, wxWindowID id, const wxString& title,
|
||||
int style, wxHtmlHelpData* data)
|
||||
{
|
||||
Init(data);
|
||||
Create(parent, id, title, style);
|
||||
}
|
||||
|
||||
void wxHtmlHelpDialog::Init(wxHtmlHelpData* data)
|
||||
{
|
||||
// Simply pass the pointer on to the help window
|
||||
m_Data = data;
|
||||
m_HtmlHelpWin = NULL;
|
||||
m_helpController = NULL;
|
||||
}
|
||||
|
||||
// Create: builds the GUI components.
|
||||
bool wxHtmlHelpDialog::Create(wxWindow* parent, wxWindowID id,
|
||||
const wxString& WXUNUSED(title), int style)
|
||||
{
|
||||
m_HtmlHelpWin = new wxHtmlHelpWindow(m_Data);
|
||||
|
||||
wxDialog::Create(parent, id, _("Help"),
|
||||
wxPoint(m_HtmlHelpWin->GetCfgData().x, m_HtmlHelpWin->GetCfgData().y),
|
||||
wxSize(m_HtmlHelpWin->GetCfgData().w, m_HtmlHelpWin->GetCfgData().h),
|
||||
wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER, wxT("wxHtmlHelp"));
|
||||
m_HtmlHelpWin->Create(this, wxID_ANY, wxDefaultPosition, GetClientSize(),
|
||||
wxTAB_TRAVERSAL|wxNO_BORDER, style);
|
||||
|
||||
GetPosition(& (m_HtmlHelpWin->GetCfgData().x), & (m_HtmlHelpWin->GetCfgData()).y);
|
||||
|
||||
SetIcon(wxArtProvider::GetIcon(wxART_HELP, wxART_HELP_BROWSER));
|
||||
|
||||
wxWindow* item1 = this;
|
||||
wxBoxSizer* item2 = new wxBoxSizer(wxVERTICAL);
|
||||
item1->SetSizer(item2);
|
||||
item1->SetAutoLayout(true);
|
||||
|
||||
wxWindow* item3 = m_HtmlHelpWin;
|
||||
item2->Add(item3, 1, wxGROW|wxALL, 5);
|
||||
|
||||
wxBoxSizer* item4 = new wxBoxSizer(wxHORIZONTAL);
|
||||
item2->Add(item4, 0, wxGROW, 5);
|
||||
|
||||
item4->Add(5, 5, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
wxButton* item6 = new wxButton(item1, wxID_OK, _("Close"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
item4->Add(item6, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10);
|
||||
#ifdef __WXMAC__
|
||||
// Add some space for the resize handle
|
||||
item4->Add(5, 5, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
#endif
|
||||
|
||||
Layout();
|
||||
Centre();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wxHtmlHelpDialog::~wxHtmlHelpDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void wxHtmlHelpDialog::SetTitleFormat(const wxString& format)
|
||||
{
|
||||
m_TitleFormat = format;
|
||||
}
|
||||
|
||||
void wxHtmlHelpDialog::OnCloseWindow(wxCloseEvent& evt)
|
||||
{
|
||||
if (!IsIconized())
|
||||
{
|
||||
GetSize(& (m_HtmlHelpWin->GetCfgData().w), &(m_HtmlHelpWin->GetCfgData().h));
|
||||
GetPosition(& (m_HtmlHelpWin->GetCfgData().x), & (m_HtmlHelpWin->GetCfgData().y));
|
||||
}
|
||||
|
||||
if (m_HtmlHelpWin->GetSplitterWindow() && m_HtmlHelpWin->GetCfgData().navig_on)
|
||||
m_HtmlHelpWin->GetCfgData().sashpos = m_HtmlHelpWin->GetSplitterWindow()->GetSashPosition();
|
||||
|
||||
if (m_helpController)
|
||||
{
|
||||
m_helpController->OnCloseFrame(evt);
|
||||
}
|
||||
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
#endif // wxUSE_WXHTML_HELP
|
241
wxWidgets/src/html/helpfrm.cpp
Normal file
241
wxWidgets/src/html/helpfrm.cpp
Normal file
|
@ -0,0 +1,241 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/helpfrm.cpp
|
||||
// Purpose: wxHtmlHelpFrame
|
||||
// Notes: Based on htmlhelp.cpp, implementing a monolithic
|
||||
// HTML Help controller class, by Vaclav Slavik
|
||||
// Author: Harm van der Heijden and Vaclav Slavik
|
||||
// RCS-ID: $Id: helpfrm.cpp 56234 2008-10-11 20:18:19Z VS $
|
||||
// Copyright: (c) Harm van der Heijden and Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h"
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_WXHTML_HELP
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#include "wx/object.h"
|
||||
#include "wx/dynarray.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
#if wxUSE_STREAMS
|
||||
#include "wx/stream.h"
|
||||
#endif
|
||||
|
||||
#include "wx/sizer.h"
|
||||
|
||||
#include "wx/bmpbuttn.h"
|
||||
#include "wx/statbox.h"
|
||||
#include "wx/radiobox.h"
|
||||
#include "wx/menu.h"
|
||||
#include "wx/settings.h"
|
||||
#include "wx/msgdlg.h"
|
||||
#include "wx/textctrl.h"
|
||||
#include "wx/toolbar.h"
|
||||
#include "wx/choicdlg.h"
|
||||
#include "wx/filedlg.h"
|
||||
#endif // WXPRECOMP
|
||||
|
||||
#include "wx/html/helpfrm.h"
|
||||
#include "wx/html/helpctrl.h"
|
||||
#include "wx/notebook.h"
|
||||
#include "wx/imaglist.h"
|
||||
#include "wx/treectrl.h"
|
||||
#include "wx/tokenzr.h"
|
||||
#include "wx/wfstream.h"
|
||||
#include "wx/html/htmlwin.h"
|
||||
#include "wx/busyinfo.h"
|
||||
#include "wx/progdlg.h"
|
||||
#include "wx/fontenum.h"
|
||||
#include "wx/artprov.h"
|
||||
#include "wx/spinctrl.h"
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpFrame, wxFrame)
|
||||
|
||||
BEGIN_EVENT_TABLE(wxHtmlHelpFrame, wxFrame)
|
||||
EVT_ACTIVATE(wxHtmlHelpFrame::OnActivate)
|
||||
EVT_CLOSE(wxHtmlHelpFrame::OnCloseWindow)
|
||||
#ifdef __WXMAC__
|
||||
EVT_MENU(wxID_CLOSE, wxHtmlHelpFrame::OnClose)
|
||||
EVT_MENU(wxID_ABOUT, wxHtmlHelpFrame::OnAbout)
|
||||
EVT_MENU(wxID_HELP_CONTENTS, wxHtmlHelpFrame::OnAbout)
|
||||
#endif
|
||||
END_EVENT_TABLE()
|
||||
|
||||
wxHtmlHelpFrame::wxHtmlHelpFrame(wxWindow* parent, wxWindowID id, const wxString& title,
|
||||
int style, wxHtmlHelpData* data,
|
||||
wxConfigBase *config, const wxString& rootpath)
|
||||
{
|
||||
Init(data);
|
||||
Create(parent, id, title, style, config, rootpath);
|
||||
}
|
||||
|
||||
void wxHtmlHelpFrame::Init(wxHtmlHelpData* data)
|
||||
{
|
||||
// Simply pass the pointer on to the help window
|
||||
m_Data = data;
|
||||
m_HtmlHelpWin = NULL;
|
||||
m_helpController = (wxHtmlHelpController*) NULL;
|
||||
}
|
||||
|
||||
// Create: builds the GUI components.
|
||||
bool wxHtmlHelpFrame::Create(wxWindow* parent, wxWindowID id,
|
||||
const wxString& WXUNUSED(title), int style,
|
||||
wxConfigBase *config, const wxString& rootpath)
|
||||
{
|
||||
m_HtmlHelpWin = new wxHtmlHelpWindow(m_Data);
|
||||
m_HtmlHelpWin->SetController(m_helpController);
|
||||
if ( config)
|
||||
m_HtmlHelpWin->UseConfig(config, rootpath);
|
||||
|
||||
wxFrame::Create(parent, id, _("Help"),
|
||||
wxPoint(m_HtmlHelpWin->GetCfgData().x, m_HtmlHelpWin->GetCfgData().y),
|
||||
wxSize(m_HtmlHelpWin->GetCfgData().w, m_HtmlHelpWin->GetCfgData().h),
|
||||
wxDEFAULT_FRAME_STYLE, wxT("wxHtmlHelp"));
|
||||
#if wxUSE_STATUSBAR
|
||||
CreateStatusBar();
|
||||
#endif
|
||||
m_HtmlHelpWin->Create(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
wxTAB_TRAVERSAL|wxNO_BORDER, style);
|
||||
|
||||
GetPosition(& (m_HtmlHelpWin->GetCfgData().x), & (m_HtmlHelpWin->GetCfgData()).y);
|
||||
|
||||
SetIcon(wxArtProvider::GetIcon(wxART_HELP, wxART_FRAME_ICON));
|
||||
|
||||
// On the Mac, each modeless frame must have a menubar.
|
||||
// TODO: add more menu items, and perhaps add a style to show
|
||||
// the menubar: compulsory on the Mac, optional elsewhere.
|
||||
#ifdef __WXMAC__
|
||||
wxMenuBar* menuBar = new wxMenuBar;
|
||||
|
||||
wxMenu* fileMenu = new wxMenu;
|
||||
fileMenu->Append(wxID_HTML_OPENFILE, _("&Open..."));
|
||||
fileMenu->AppendSeparator();
|
||||
fileMenu->Append(wxID_CLOSE, _("&Close"));
|
||||
|
||||
wxMenu* helpMenu = new wxMenu;
|
||||
helpMenu->Append(wxID_ABOUT, _("&About..."));
|
||||
// Ensures we don't get an empty help menu
|
||||
helpMenu->Append(wxID_HELP_CONTENTS, _("&About..."));
|
||||
|
||||
menuBar->Append(fileMenu,_("&File"));
|
||||
menuBar->Append(helpMenu,_("&Help"));
|
||||
SetMenuBar(menuBar);
|
||||
#endif
|
||||
|
||||
m_HtmlHelpWin->GetHtmlWindow()->SetRelatedFrame(this, m_TitleFormat);
|
||||
#if wxUSE_STATUSBAR
|
||||
m_HtmlHelpWin->GetHtmlWindow()->SetRelatedStatusBar(0);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
wxHtmlHelpFrame::~wxHtmlHelpFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void wxHtmlHelpFrame::SetTitleFormat(const wxString& format)
|
||||
{
|
||||
if (GetHelpWindow() && GetHelpWindow()->GetHtmlWindow())
|
||||
GetHelpWindow()->GetHtmlWindow()->SetRelatedFrame(this, format);
|
||||
m_TitleFormat = format;
|
||||
}
|
||||
|
||||
/*
|
||||
EVENT HANDLING :
|
||||
*/
|
||||
|
||||
|
||||
void wxHtmlHelpFrame::OnActivate(wxActivateEvent& event)
|
||||
{
|
||||
// This saves one mouse click when using the
|
||||
// wxHTML for context sensitive help systems
|
||||
#ifndef __WXGTK__
|
||||
// NB: wxActivateEvent is a bit broken in wxGTK
|
||||
// and is sometimes sent when it should not be
|
||||
if (event.GetActive() && m_HtmlHelpWin)
|
||||
m_HtmlHelpWin->GetHtmlWindow()->SetFocus();
|
||||
#endif
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void wxHtmlHelpFrame::OnCloseWindow(wxCloseEvent& evt)
|
||||
{
|
||||
if (!IsIconized())
|
||||
{
|
||||
GetSize(& (m_HtmlHelpWin->GetCfgData().w), &(m_HtmlHelpWin->GetCfgData().h));
|
||||
GetPosition(& (m_HtmlHelpWin->GetCfgData().x), & (m_HtmlHelpWin->GetCfgData().y));
|
||||
}
|
||||
|
||||
#ifdef __WXGTK__
|
||||
if (IsGrabbed())
|
||||
{
|
||||
RemoveGrab();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_HtmlHelpWin->GetSplitterWindow() && m_HtmlHelpWin->GetCfgData().navig_on)
|
||||
m_HtmlHelpWin->GetCfgData().sashpos = m_HtmlHelpWin->GetSplitterWindow()->GetSashPosition();
|
||||
|
||||
if (m_helpController && m_helpController->IsKindOf(CLASSINFO(wxHtmlHelpController)))
|
||||
{
|
||||
((wxHtmlHelpController*) m_helpController)->OnCloseFrame(evt);
|
||||
}
|
||||
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
// Make the help controller's frame 'modal' if
|
||||
// needed
|
||||
void wxHtmlHelpFrame::AddGrabIfNeeded()
|
||||
{
|
||||
// So far, wxGTK only
|
||||
#ifdef __WXGTK__
|
||||
bool needGrab = false;
|
||||
|
||||
// Check if there are any modal windows present,
|
||||
// in which case we need to add a grab.
|
||||
for ( wxWindowList::iterator it = wxTopLevelWindows.begin();
|
||||
it != wxTopLevelWindows.end();
|
||||
++it )
|
||||
{
|
||||
wxWindow *win = *it;
|
||||
wxDialog *dialog = wxDynamicCast(win, wxDialog);
|
||||
|
||||
if (dialog && dialog->IsModal())
|
||||
needGrab = true;
|
||||
}
|
||||
|
||||
if (needGrab)
|
||||
AddGrab();
|
||||
#endif // __WXGTK__
|
||||
}
|
||||
|
||||
// For compatibility
|
||||
void wxHtmlHelpFrame::UseConfig(wxConfigBase *config, const wxString& rootPath)
|
||||
{
|
||||
if (m_HtmlHelpWin)
|
||||
m_HtmlHelpWin->UseConfig(config, rootPath);
|
||||
}
|
||||
|
||||
#ifdef __WXMAC__
|
||||
void wxHtmlHelpFrame::OnClose(wxCommandEvent& event)
|
||||
{
|
||||
Close(true);
|
||||
}
|
||||
|
||||
void wxHtmlHelpFrame::OnAbout(wxCommandEvent& event)
|
||||
{
|
||||
wxMessageBox(wxT("wxWidgets HTML Help Viewer (c) 1998-2006, Vaclav Slavik et al"), wxT("HelpView"),
|
||||
wxICON_INFORMATION|wxOK, this);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // wxUSE_WXHTML_HELP
|
1774
wxWidgets/src/html/helpwnd.cpp
Normal file
1774
wxWidgets/src/html/helpwnd.cpp
Normal file
File diff suppressed because it is too large
Load diff
1609
wxWidgets/src/html/htmlcell.cpp
Normal file
1609
wxWidgets/src/html/htmlcell.cpp
Normal file
File diff suppressed because it is too large
Load diff
892
wxWidgets/src/html/htmlctrl/webkit/webkit.mm
Normal file
892
wxWidgets/src/html/htmlctrl/webkit/webkit.mm
Normal file
|
@ -0,0 +1,892 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: webkit.mm
|
||||
// Purpose: wxWebKitCtrl - embeddable web kit control
|
||||
// Author: Jethro Grassie / Kevin Ollivier
|
||||
// Modified by:
|
||||
// Created: 2004-4-16
|
||||
// RCS-ID: $Id: webkit.mm 56767 2008-11-14 23:02:15Z KO $
|
||||
// Copyright: (c) Jethro Grassie / Kevin Ollivier
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
|
||||
#pragma implementation "webkit.h"
|
||||
#endif
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
#include "wx/splitter.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#if wxUSE_WEBKIT
|
||||
|
||||
#ifdef __WXCOCOA__
|
||||
#include "wx/cocoa/autorelease.h"
|
||||
#else
|
||||
#include "wx/mac/uma.h"
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <WebKit/WebKit.h>
|
||||
#include <WebKit/HIWebView.h>
|
||||
#include <WebKit/CarbonUtils.h>
|
||||
#endif
|
||||
|
||||
#include "wx/html/webkit.h"
|
||||
|
||||
#define DEBUG_WEBKIT_SIZING 0
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// macros
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxWebKitCtrl, wxControl)
|
||||
|
||||
BEGIN_EVENT_TABLE(wxWebKitCtrl, wxControl)
|
||||
EVT_SIZE(wxWebKitCtrl::OnSize)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Carbon Events handlers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// prototype for function in src/mac/carbon/toplevel.cpp
|
||||
void SetupMouseEvent( wxMouseEvent &wxevent , wxMacCarbonEvent &cEvent );
|
||||
|
||||
static const EventTypeSpec eventList[] =
|
||||
{
|
||||
//{ kEventClassControl, kEventControlTrack } ,
|
||||
{ kEventClassMouse, kEventMouseUp },
|
||||
{ kEventClassMouse, kEventMouseDown },
|
||||
{ kEventClassMouse, kEventMouseMoved },
|
||||
{ kEventClassMouse, kEventMouseDragged },
|
||||
|
||||
{ kEventClassKeyboard, kEventRawKeyDown } ,
|
||||
{ kEventClassKeyboard, kEventRawKeyRepeat } ,
|
||||
{ kEventClassKeyboard, kEventRawKeyUp } ,
|
||||
{ kEventClassKeyboard, kEventRawKeyModifiersChanged } ,
|
||||
|
||||
{ kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } ,
|
||||
{ kEventClassTextInput, kEventTextInputUpdateActiveInputArea } ,
|
||||
|
||||
#if DEBUG_WEBKIT_SIZING == 1
|
||||
{ kEventClassControl, kEventControlBoundsChanged } ,
|
||||
#endif
|
||||
};
|
||||
|
||||
// mix this in from window.cpp
|
||||
pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) ;
|
||||
|
||||
// NOTE: This is mostly taken from KeyboardEventHandler in toplevel.cpp, but
|
||||
// that expects the data pointer is a top-level window, so I needed to change
|
||||
// that in this case. However, once 2.8 is out, we should factor out the common logic
|
||||
// among the two functions and merge them.
|
||||
static pascal OSStatus wxWebKitKeyEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
|
||||
{
|
||||
OSStatus result = eventNotHandledErr ;
|
||||
wxMacCarbonEvent cEvent( event ) ;
|
||||
|
||||
wxWebKitCtrl* thisWindow = (wxWebKitCtrl*) data ;
|
||||
wxWindow* focus = thisWindow ;
|
||||
|
||||
unsigned char charCode ;
|
||||
wxChar uniChar[2] ;
|
||||
uniChar[0] = 0;
|
||||
uniChar[1] = 0;
|
||||
|
||||
UInt32 keyCode ;
|
||||
UInt32 modifiers ;
|
||||
Point point ;
|
||||
UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ;
|
||||
|
||||
#if wxUSE_UNICODE
|
||||
ByteCount dataSize = 0 ;
|
||||
if ( GetEventParameter( event, kEventParamKeyUnicodes, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr )
|
||||
{
|
||||
UniChar buf[2] ;
|
||||
int numChars = dataSize / sizeof( UniChar) + 1;
|
||||
|
||||
UniChar* charBuf = buf ;
|
||||
|
||||
if ( numChars * 2 > 4 )
|
||||
charBuf = new UniChar[ numChars ] ;
|
||||
GetEventParameter( event, kEventParamKeyUnicodes, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ;
|
||||
charBuf[ numChars - 1 ] = 0;
|
||||
|
||||
#if SIZEOF_WCHAR_T == 2
|
||||
uniChar = charBuf[0] ;
|
||||
#else
|
||||
wxMBConvUTF16 converter ;
|
||||
converter.MB2WC( uniChar , (const char*)charBuf , 2 ) ;
|
||||
#endif
|
||||
|
||||
if ( numChars * 2 > 4 )
|
||||
delete[] charBuf ;
|
||||
}
|
||||
#endif
|
||||
|
||||
GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode );
|
||||
GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
|
||||
GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers );
|
||||
GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point );
|
||||
|
||||
UInt32 message = (keyCode << 8) + charCode;
|
||||
switch ( GetEventKind( event ) )
|
||||
{
|
||||
case kEventRawKeyRepeat :
|
||||
case kEventRawKeyDown :
|
||||
{
|
||||
WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ;
|
||||
WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ;
|
||||
wxTheApp->MacSetCurrentEvent( event , handler ) ;
|
||||
if ( /* focus && */ wxTheApp->MacSendKeyDownEvent(
|
||||
focus , message , modifiers , when , point.h , point.v , uniChar[0] ) )
|
||||
{
|
||||
result = noErr ;
|
||||
}
|
||||
wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ;
|
||||
}
|
||||
break ;
|
||||
|
||||
case kEventRawKeyUp :
|
||||
if ( /* focus && */ wxTheApp->MacSendKeyUpEvent(
|
||||
focus , message , modifiers , when , point.h , point.v , uniChar[0] ) )
|
||||
{
|
||||
result = noErr ;
|
||||
}
|
||||
break ;
|
||||
|
||||
case kEventRawKeyModifiersChanged :
|
||||
{
|
||||
wxKeyEvent event(wxEVT_KEY_DOWN);
|
||||
|
||||
event.m_shiftDown = modifiers & shiftKey;
|
||||
event.m_controlDown = modifiers & controlKey;
|
||||
event.m_altDown = modifiers & optionKey;
|
||||
event.m_metaDown = modifiers & cmdKey;
|
||||
event.m_x = point.h;
|
||||
event.m_y = point.v;
|
||||
|
||||
#if wxUSE_UNICODE
|
||||
event.m_uniChar = uniChar[0] ;
|
||||
#endif
|
||||
|
||||
event.SetTimestamp(when);
|
||||
event.SetEventObject(focus);
|
||||
|
||||
if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & controlKey )
|
||||
{
|
||||
event.m_keyCode = WXK_CONTROL ;
|
||||
event.SetEventType( ( modifiers & controlKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
|
||||
focus->GetEventHandler()->ProcessEvent( event ) ;
|
||||
}
|
||||
if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & shiftKey )
|
||||
{
|
||||
event.m_keyCode = WXK_SHIFT ;
|
||||
event.SetEventType( ( modifiers & shiftKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
|
||||
focus->GetEventHandler()->ProcessEvent( event ) ;
|
||||
}
|
||||
if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & optionKey )
|
||||
{
|
||||
event.m_keyCode = WXK_ALT ;
|
||||
event.SetEventType( ( modifiers & optionKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
|
||||
focus->GetEventHandler()->ProcessEvent( event ) ;
|
||||
}
|
||||
if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & cmdKey )
|
||||
{
|
||||
event.m_keyCode = WXK_COMMAND ;
|
||||
event.SetEventType( ( modifiers & cmdKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ;
|
||||
focus->GetEventHandler()->ProcessEvent( event ) ;
|
||||
}
|
||||
|
||||
wxApp::s_lastModifiers = modifiers ;
|
||||
}
|
||||
break ;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
static pascal OSStatus wxWebKitCtrlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
|
||||
{
|
||||
OSStatus result = eventNotHandledErr ;
|
||||
|
||||
wxMacCarbonEvent cEvent( event ) ;
|
||||
|
||||
ControlRef controlRef ;
|
||||
wxWebKitCtrl* thisWindow = (wxWebKitCtrl*) data ;
|
||||
wxTopLevelWindowMac* tlw = NULL;
|
||||
if (thisWindow)
|
||||
tlw = thisWindow->MacGetTopLevelWindow();
|
||||
|
||||
cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
|
||||
|
||||
wxWindow* currentMouseWindow = thisWindow ;
|
||||
|
||||
if ( wxApp::s_captureWindow )
|
||||
currentMouseWindow = wxApp::s_captureWindow;
|
||||
|
||||
switch ( GetEventClass( event ) )
|
||||
{
|
||||
case kEventClassKeyboard:
|
||||
{
|
||||
result = wxWebKitKeyEventHandler(handler, event, data);
|
||||
break;
|
||||
}
|
||||
|
||||
case kEventClassTextInput:
|
||||
{
|
||||
result = wxMacUnicodeTextEventHandler(handler, event, data);
|
||||
break;
|
||||
}
|
||||
|
||||
case kEventClassMouse:
|
||||
{
|
||||
switch ( GetEventKind( event ) )
|
||||
{
|
||||
case kEventMouseDragged :
|
||||
case kEventMouseMoved :
|
||||
case kEventMouseDown :
|
||||
case kEventMouseUp :
|
||||
{
|
||||
wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
|
||||
SetupMouseEvent( wxevent , cEvent ) ;
|
||||
|
||||
currentMouseWindow->ScreenToClient( &wxevent.m_x , &wxevent.m_y ) ;
|
||||
wxevent.SetEventObject( currentMouseWindow ) ;
|
||||
wxevent.SetId( currentMouseWindow->GetId() ) ;
|
||||
|
||||
if ( currentMouseWindow->GetEventHandler()->ProcessEvent(wxevent) )
|
||||
{
|
||||
result = noErr;
|
||||
}
|
||||
|
||||
break; // this should enable WebKit to fire mouse dragged and mouse up events...
|
||||
}
|
||||
default :
|
||||
break ;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
result = CallNextEventHandler(handler, event);
|
||||
return result ;
|
||||
}
|
||||
|
||||
DEFINE_ONE_SHOT_HANDLER_GETTER( wxWebKitCtrlEventHandler )
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxWebKit Events
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( wxWebKitStateChangedEvent, wxCommandEvent )
|
||||
|
||||
DEFINE_EVENT_TYPE( wxEVT_WEBKIT_STATE_CHANGED )
|
||||
|
||||
wxWebKitStateChangedEvent::wxWebKitStateChangedEvent( wxWindow* win )
|
||||
{
|
||||
SetEventType( wxEVT_WEBKIT_STATE_CHANGED);
|
||||
SetEventObject( win );
|
||||
SetId(win->GetId());
|
||||
}
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( wxWebKitBeforeLoadEvent, wxCommandEvent )
|
||||
|
||||
DEFINE_EVENT_TYPE( wxEVT_WEBKIT_BEFORE_LOAD )
|
||||
|
||||
wxWebKitBeforeLoadEvent::wxWebKitBeforeLoadEvent( wxWindow* win )
|
||||
{
|
||||
m_cancelled = false;
|
||||
SetEventType( wxEVT_WEBKIT_BEFORE_LOAD);
|
||||
SetEventObject( win );
|
||||
SetId(win->GetId());
|
||||
}
|
||||
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( wxWebKitNewWindowEvent, wxCommandEvent )
|
||||
|
||||
DEFINE_EVENT_TYPE( wxEVT_WEBKIT_NEW_WINDOW )
|
||||
|
||||
wxWebKitNewWindowEvent::wxWebKitNewWindowEvent( wxWindow* win )
|
||||
{
|
||||
SetEventType( wxEVT_WEBKIT_NEW_WINDOW);
|
||||
SetEventObject( win );
|
||||
SetId(win->GetId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
// helper functions for NSString<->wxString conversion
|
||||
//---------------------------------------------------------
|
||||
|
||||
inline wxString wxStringWithNSString(NSString *nsstring)
|
||||
{
|
||||
#if wxUSE_UNICODE
|
||||
return wxString([nsstring UTF8String], wxConvUTF8);
|
||||
#else
|
||||
return wxString([nsstring lossyCString]);
|
||||
#endif // wxUSE_UNICODE
|
||||
}
|
||||
|
||||
inline NSString* wxNSStringWithWxString(const wxString &wxstring)
|
||||
{
|
||||
#if wxUSE_UNICODE
|
||||
return [NSString stringWithUTF8String: wxstring.mb_str(wxConvUTF8)];
|
||||
#else
|
||||
return [NSString stringWithCString: wxstring.c_str() length:wxstring.Len()];
|
||||
#endif // wxUSE_UNICODE
|
||||
}
|
||||
|
||||
inline int wxNavTypeFromWebNavType(int type){
|
||||
if (type == WebNavigationTypeLinkClicked)
|
||||
return wxWEBKIT_NAV_LINK_CLICKED;
|
||||
|
||||
if (type == WebNavigationTypeFormSubmitted)
|
||||
return wxWEBKIT_NAV_FORM_SUBMITTED;
|
||||
|
||||
if (type == WebNavigationTypeBackForward)
|
||||
return wxWEBKIT_NAV_BACK_NEXT;
|
||||
|
||||
if (type == WebNavigationTypeReload)
|
||||
return wxWEBKIT_NAV_RELOAD;
|
||||
|
||||
if (type == WebNavigationTypeFormResubmitted)
|
||||
return wxWEBKIT_NAV_FORM_RESUBMITTED;
|
||||
|
||||
return wxWEBKIT_NAV_OTHER;
|
||||
}
|
||||
|
||||
@interface MyFrameLoadMonitor : NSObject
|
||||
{
|
||||
wxWebKitCtrl* webKitWindow;
|
||||
}
|
||||
|
||||
- initWithWxWindow: (wxWebKitCtrl*)inWindow;
|
||||
|
||||
@end
|
||||
|
||||
@interface MyPolicyDelegate : NSObject
|
||||
{
|
||||
wxWebKitCtrl* webKitWindow;
|
||||
}
|
||||
|
||||
- initWithWxWindow: (wxWebKitCtrl*)inWindow;
|
||||
|
||||
@end
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// creation/destruction
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool wxWebKitCtrl::Create(wxWindow *parent,
|
||||
wxWindowID winID,
|
||||
const wxString& strURL,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size, long style,
|
||||
const wxValidator& validator,
|
||||
const wxString& name)
|
||||
{
|
||||
|
||||
m_currentURL = strURL;
|
||||
//m_pageTitle = _("Untitled Page");
|
||||
|
||||
//still needed for wxCocoa??
|
||||
/*
|
||||
int width, height;
|
||||
wxSize sizeInstance;
|
||||
if (size.x == wxDefaultCoord || size.y == wxDefaultCoord)
|
||||
{
|
||||
m_parent->GetClientSize(&width, &height);
|
||||
sizeInstance.x = width;
|
||||
sizeInstance.y = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
sizeInstance.x = size.x;
|
||||
sizeInstance.y = size.y;
|
||||
}
|
||||
*/
|
||||
// now create and attach WebKit view...
|
||||
#ifdef __WXCOCOA__
|
||||
wxControl::Create(parent, m_windowID, pos, sizeInstance, style , validator , name);
|
||||
SetSize(pos.x, pos.y, sizeInstance.x, sizeInstance.y);
|
||||
|
||||
wxTopLevelWindowCocoa *topWin = wxDynamicCast(this, wxTopLevelWindowCocoa);
|
||||
NSWindow* nsWin = topWin->GetNSWindow();
|
||||
NSRect rect;
|
||||
rect.origin.x = pos.x;
|
||||
rect.origin.y = pos.y;
|
||||
rect.size.width = sizeInstance.x;
|
||||
rect.size.height = sizeInstance.y;
|
||||
m_webView = (WebView*)[[WebView alloc] initWithFrame:rect frameName:@"webkitFrame" groupName:@"webkitGroup"];
|
||||
SetNSView(m_webView);
|
||||
[m_cocoaNSView release];
|
||||
|
||||
if(m_parent) m_parent->CocoaAddChild(this);
|
||||
SetInitialFrameRect(pos,sizeInstance);
|
||||
#else
|
||||
m_macIsUserPane = false;
|
||||
wxControl::Create(parent, winID, pos, size, style , validator , name);
|
||||
m_peer = new wxMacControl(this);
|
||||
WebInitForCarbon();
|
||||
HIWebViewCreate( m_peer->GetControlRefAddr() );
|
||||
|
||||
m_webView = (WebView*) HIWebViewGetWebView( m_peer->GetControlRef() );
|
||||
|
||||
MacPostControlCreate(pos, size);
|
||||
HIViewSetVisible( m_peer->GetControlRef(), true );
|
||||
[m_webView setHidden:false];
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
|
||||
if ( UMAGetSystemVersion() >= 0x1030 )
|
||||
HIViewChangeFeatures( m_peer->GetControlRef() , kHIViewIsOpaque , 0 ) ;
|
||||
#endif
|
||||
InstallControlEventHandler( m_peer->GetControlRef() , GetwxWebKitCtrlEventHandlerUPP(),
|
||||
GetEventTypeCount(eventList), eventList, this,
|
||||
(EventHandlerRef *)&m_webKitCtrlEventHandler);
|
||||
|
||||
#endif
|
||||
|
||||
// Register event listener interfaces
|
||||
MyFrameLoadMonitor* myFrameLoadMonitor = [[MyFrameLoadMonitor alloc] initWithWxWindow: this];
|
||||
[m_webView setFrameLoadDelegate:myFrameLoadMonitor];
|
||||
|
||||
// this is used to veto page loads, etc.
|
||||
MyPolicyDelegate* myPolicyDelegate = [[MyPolicyDelegate alloc] initWithWxWindow: this];
|
||||
[m_webView setPolicyDelegate:myPolicyDelegate];
|
||||
|
||||
LoadURL(m_currentURL);
|
||||
return true;
|
||||
}
|
||||
|
||||
wxWebKitCtrl::~wxWebKitCtrl()
|
||||
{
|
||||
MyFrameLoadMonitor* myFrameLoadMonitor = [m_webView frameLoadDelegate];
|
||||
MyPolicyDelegate* myPolicyDelegate = [m_webView policyDelegate];
|
||||
[m_webView setFrameLoadDelegate: nil];
|
||||
[m_webView setPolicyDelegate: nil];
|
||||
|
||||
if (myFrameLoadMonitor)
|
||||
[myFrameLoadMonitor release];
|
||||
|
||||
if (myPolicyDelegate)
|
||||
[myPolicyDelegate release];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// public methods
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxWebKitCtrl::LoadURL(const wxString &url)
|
||||
{
|
||||
if( !m_webView )
|
||||
return;
|
||||
|
||||
[[m_webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:wxNSStringWithWxString(url)]]];
|
||||
|
||||
m_currentURL = url;
|
||||
}
|
||||
|
||||
bool wxWebKitCtrl::CanGoBack(){
|
||||
if ( !m_webView )
|
||||
return false;
|
||||
|
||||
return [m_webView canGoBack];
|
||||
}
|
||||
|
||||
bool wxWebKitCtrl::CanGoForward(){
|
||||
if ( !m_webView )
|
||||
return false;
|
||||
|
||||
return [m_webView canGoForward];
|
||||
}
|
||||
|
||||
bool wxWebKitCtrl::GoBack(){
|
||||
if ( !m_webView )
|
||||
return false;
|
||||
|
||||
bool result = [(WebView*)m_webView goBack];
|
||||
return result;
|
||||
}
|
||||
|
||||
bool wxWebKitCtrl::GoForward(){
|
||||
if ( !m_webView )
|
||||
return false;
|
||||
|
||||
bool result = [(WebView*)m_webView goForward];
|
||||
return result;
|
||||
}
|
||||
|
||||
void wxWebKitCtrl::Reload(){
|
||||
if ( !m_webView )
|
||||
return;
|
||||
|
||||
[[m_webView mainFrame] reload];
|
||||
}
|
||||
|
||||
void wxWebKitCtrl::Stop(){
|
||||
if ( !m_webView )
|
||||
return;
|
||||
|
||||
[[m_webView mainFrame] stopLoading];
|
||||
}
|
||||
|
||||
bool wxWebKitCtrl::CanGetPageSource(){
|
||||
if ( !m_webView )
|
||||
return false;
|
||||
|
||||
WebDataSource* dataSource = [[m_webView mainFrame] dataSource];
|
||||
return ( [[dataSource representation] canProvideDocumentSource] );
|
||||
}
|
||||
|
||||
wxString wxWebKitCtrl::GetPageSource(){
|
||||
|
||||
if (CanGetPageSource()){
|
||||
WebDataSource* dataSource = [[m_webView mainFrame] dataSource];
|
||||
return wxStringWithNSString( [[dataSource representation] documentSource] );
|
||||
}
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
wxString wxWebKitCtrl::GetSelection(){
|
||||
if ( !m_webView )
|
||||
return wxEmptyString;
|
||||
|
||||
NSString* selectedText = [[m_webView selectedDOMRange] toString];
|
||||
return wxStringWithNSString( selectedText );
|
||||
}
|
||||
|
||||
bool wxWebKitCtrl::CanIncreaseTextSize(){
|
||||
if ( !m_webView )
|
||||
return false;
|
||||
|
||||
if ([m_webView canMakeTextLarger])
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxWebKitCtrl::IncreaseTextSize(){
|
||||
if ( !m_webView )
|
||||
return;
|
||||
|
||||
if (CanIncreaseTextSize())
|
||||
[m_webView makeTextLarger:(WebView*)m_webView];
|
||||
}
|
||||
|
||||
bool wxWebKitCtrl::CanDecreaseTextSize(){
|
||||
if ( !m_webView )
|
||||
return false;
|
||||
|
||||
if ([m_webView canMakeTextSmaller])
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxWebKitCtrl::DecreaseTextSize(){
|
||||
if ( !m_webView )
|
||||
return;
|
||||
|
||||
if (CanDecreaseTextSize())
|
||||
[m_webView makeTextSmaller:(WebView*)m_webView];
|
||||
}
|
||||
|
||||
void wxWebKitCtrl::SetPageSource(const wxString& source, const wxString& baseUrl){
|
||||
if ( !m_webView )
|
||||
return;
|
||||
|
||||
[[m_webView mainFrame] loadHTMLString:(NSString*)wxNSStringWithWxString( source ) baseURL:[NSURL URLWithString:wxNSStringWithWxString( baseUrl )]];
|
||||
|
||||
}
|
||||
|
||||
void wxWebKitCtrl::Print(bool showPrompt){
|
||||
if ( !m_webView )
|
||||
return;
|
||||
|
||||
id view = [[[m_webView mainFrame] frameView] documentView];
|
||||
NSPrintOperation *op = [NSPrintOperation printOperationWithView:view printInfo: [NSPrintInfo sharedPrintInfo]];
|
||||
if (showPrompt){
|
||||
[op setShowsPrintPanel: showPrompt];
|
||||
// in my tests, the progress bar always freezes and it stops the whole print operation.
|
||||
// do not turn this to true unless there is a workaround for the bug.
|
||||
[op setShowsProgressPanel: false];
|
||||
}
|
||||
// Print it.
|
||||
[op runOperation];
|
||||
}
|
||||
|
||||
void wxWebKitCtrl::MakeEditable(bool enable){
|
||||
if ( !m_webView )
|
||||
return;
|
||||
|
||||
[m_webView setEditable:enable ];
|
||||
}
|
||||
|
||||
bool wxWebKitCtrl::IsEditable(){
|
||||
if ( !m_webView )
|
||||
return false;
|
||||
|
||||
return [m_webView isEditable];
|
||||
}
|
||||
|
||||
int wxWebKitCtrl::GetScrollPos(){
|
||||
id result = [[m_webView windowScriptObject] evaluateWebScript:@"document.body.scrollTop"];
|
||||
return [result intValue];
|
||||
}
|
||||
|
||||
void wxWebKitCtrl::SetScrollPos(int pos){
|
||||
if ( !m_webView )
|
||||
return;
|
||||
|
||||
wxString javascript;
|
||||
javascript.Printf(wxT("document.body.scrollTop = %d;"), pos);
|
||||
[[m_webView windowScriptObject] evaluateWebScript:(NSString*)wxNSStringWithWxString( javascript )];
|
||||
}
|
||||
|
||||
wxString wxWebKitCtrl::RunScript(const wxString& javascript){
|
||||
if ( !m_webView )
|
||||
return wxEmptyString;
|
||||
|
||||
id result = [[m_webView windowScriptObject] evaluateWebScript:(NSString*)wxNSStringWithWxString( javascript )];
|
||||
|
||||
NSString* resultAsString;
|
||||
wxString resultAsWxString = wxEmptyString;
|
||||
NSString* className = NSStringFromClass([result class]);
|
||||
if ([className isEqualToString:@"NSCFNumber"])
|
||||
resultAsString = [NSString stringWithFormat:@"%@", result];
|
||||
else if ([className isEqualToString:@"NSCFString"])
|
||||
resultAsString = result;
|
||||
else if ([className isEqualToString:@"NSCFBoolean"]){
|
||||
if ([result boolValue])
|
||||
resultAsString = @"true";
|
||||
else
|
||||
resultAsString = @"false";
|
||||
}
|
||||
else if ([className isEqualToString:@"WebScriptObject"])
|
||||
resultAsString = [result stringRepresentation];
|
||||
else
|
||||
fprintf(stderr, "wxWebKitCtrl::RunScript - Unexpected return type: %s!\n", [className UTF8String]);
|
||||
|
||||
resultAsWxString = wxStringWithNSString( resultAsString );
|
||||
return resultAsWxString;
|
||||
}
|
||||
|
||||
void wxWebKitCtrl::OnSize(wxSizeEvent &event){
|
||||
// This is a nasty hack because WebKit seems to lose its position when it is embedded
|
||||
// in a control that is not itself the content view for a TLW.
|
||||
// I put it in OnSize because these calcs are not perfect, and in fact are basically
|
||||
// guesses based on reverse engineering, so it's best to give people the option of
|
||||
// overriding OnSize with their own calcs if need be.
|
||||
// I also left some test debugging print statements as a convenience if a(nother)
|
||||
// problem crops up.
|
||||
|
||||
wxWindow* tlw = MacGetTopLevelWindow();
|
||||
|
||||
NSRect frame = [m_webView frame];
|
||||
NSRect bounds = [m_webView bounds];
|
||||
|
||||
#if DEBUG_WEBKIT_SIZING
|
||||
fprintf(stderr,"Carbon window x=%d, y=%d, width=%d, height=%d\n", GetPosition().x, GetPosition().y, GetSize().x, GetSize().y);
|
||||
fprintf(stderr, "Cocoa window frame x=%G, y=%G, width=%G, height=%G\n", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
|
||||
fprintf(stderr, "Cocoa window bounds x=%G, y=%G, width=%G, height=%G\n", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
|
||||
#endif
|
||||
|
||||
// This must be the case that Apple tested with, because well, in this one case
|
||||
// we don't need to do anything! It just works. ;)
|
||||
if (GetParent() == tlw){
|
||||
return;
|
||||
}
|
||||
|
||||
// since we no longer use parent coordinates, we always want 0,0.
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
HIRect rect;
|
||||
rect.origin.x = x;
|
||||
rect.origin.y = y;
|
||||
|
||||
#if DEBUG_WEBKIT_SIZING
|
||||
printf("Before conversion, origin is: x = %d, y = %d\n", x, y);
|
||||
#endif
|
||||
|
||||
// NB: In most cases, when calling HIViewConvertRect, what people want is to use GetRootControl(),
|
||||
// and this tripped me up at first. But in fact, what we want is the root view, because we need to
|
||||
// make the y origin relative to the very top of the window, not its contents, since we later flip
|
||||
// the y coordinate for Cocoa.
|
||||
HIViewConvertRect (&rect, m_peer->GetControlRef(),
|
||||
HIViewGetRoot( (WindowRef) MacGetTopLevelWindowRef() ) );
|
||||
|
||||
x = (int)rect.origin.x;
|
||||
y = (int)rect.origin.y;
|
||||
|
||||
#if DEBUG_WEBKIT_SIZING
|
||||
printf("Moving Cocoa frame origin to: x = %d, y = %d\n", x, y);
|
||||
#endif
|
||||
|
||||
if (tlw){
|
||||
//flip the y coordinate to convert to Cocoa coordinates
|
||||
y = tlw->GetSize().y - ((GetSize().y) + y);
|
||||
}
|
||||
|
||||
#if DEBUG_WEBKIT_SIZING
|
||||
printf("y = %d after flipping value\n", y);
|
||||
#endif
|
||||
|
||||
frame.origin.x = x;
|
||||
frame.origin.y = y;
|
||||
[m_webView setFrame:frame];
|
||||
|
||||
if (IsShown())
|
||||
[(WebView*)m_webView display];
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void wxWebKitCtrl::MacVisibilityChanged(){
|
||||
bool isHidden = !IsControlVisible( m_peer->GetControlRef());
|
||||
if (!isHidden)
|
||||
[(WebView*)m_webView display];
|
||||
|
||||
[m_webView setHidden:isHidden];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Listener interfaces
|
||||
//------------------------------------------------------------
|
||||
|
||||
// NB: I'm still tracking this down, but it appears the Cocoa window
|
||||
// still has these events fired on it while the Carbon control is being
|
||||
// destroyed. Therefore, we must be careful to check both the existence
|
||||
// of the Carbon control and the event handler before firing events.
|
||||
|
||||
@implementation MyFrameLoadMonitor
|
||||
|
||||
- initWithWxWindow: (wxWebKitCtrl*)inWindow
|
||||
{
|
||||
[super init];
|
||||
webKitWindow = inWindow; // non retained
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame
|
||||
{
|
||||
if (webKitWindow && frame == [sender mainFrame]){
|
||||
NSString *url = [[[[frame provisionalDataSource] request] URL] absoluteString];
|
||||
wxWebKitStateChangedEvent thisEvent(webKitWindow);
|
||||
thisEvent.SetState(wxWEBKIT_STATE_NEGOTIATING);
|
||||
thisEvent.SetURL( wxStringWithNSString( url ) );
|
||||
if (webKitWindow->GetEventHandler())
|
||||
webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame
|
||||
{
|
||||
if (webKitWindow && frame == [sender mainFrame]){
|
||||
NSString *url = [[[[frame dataSource] request] URL] absoluteString];
|
||||
wxWebKitStateChangedEvent thisEvent(webKitWindow);
|
||||
thisEvent.SetState(wxWEBKIT_STATE_TRANSFERRING);
|
||||
thisEvent.SetURL( wxStringWithNSString( url ) );
|
||||
if (webKitWindow->GetEventHandler())
|
||||
webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
|
||||
{
|
||||
if (webKitWindow && frame == [sender mainFrame]){
|
||||
NSString *url = [[[[frame dataSource] request] URL] absoluteString];
|
||||
wxWebKitStateChangedEvent thisEvent(webKitWindow);
|
||||
thisEvent.SetState(wxWEBKIT_STATE_STOP);
|
||||
thisEvent.SetURL( wxStringWithNSString( url ) );
|
||||
if (webKitWindow->GetEventHandler())
|
||||
webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webView:(WebView *)sender didFailLoadWithError:(NSError*) error forFrame:(WebFrame *)frame
|
||||
{
|
||||
if (webKitWindow && frame == [sender mainFrame]){
|
||||
NSString *url = [[[[frame dataSource] request] URL] absoluteString];
|
||||
wxWebKitStateChangedEvent thisEvent(webKitWindow);
|
||||
thisEvent.SetState(wxWEBKIT_STATE_FAILED);
|
||||
thisEvent.SetURL( wxStringWithNSString( url ) );
|
||||
if (webKitWindow->GetEventHandler())
|
||||
webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError*) error forFrame:(WebFrame *)frame
|
||||
{
|
||||
if (webKitWindow && frame == [sender mainFrame]){
|
||||
NSString *url = [[[[frame provisionalDataSource] request] URL] absoluteString];
|
||||
wxWebKitStateChangedEvent thisEvent(webKitWindow);
|
||||
thisEvent.SetState(wxWEBKIT_STATE_FAILED);
|
||||
thisEvent.SetURL( wxStringWithNSString( url ) );
|
||||
if (webKitWindow->GetEventHandler())
|
||||
webKitWindow->GetEventHandler()->ProcessEvent( thisEvent );
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame
|
||||
{
|
||||
if (webKitWindow && frame == [sender mainFrame]){
|
||||
webKitWindow->SetPageTitle(wxStringWithNSString( title ));
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MyPolicyDelegate
|
||||
|
||||
- initWithWxWindow: (wxWebKitCtrl*)inWindow
|
||||
{
|
||||
[super init];
|
||||
webKitWindow = inWindow; // non retained
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener
|
||||
{
|
||||
wxWebKitBeforeLoadEvent thisEvent(webKitWindow);
|
||||
|
||||
// Get the navigation type.
|
||||
NSNumber *n = [actionInformation objectForKey:WebActionNavigationTypeKey];
|
||||
int actionType = [n intValue];
|
||||
thisEvent.SetNavigationType( wxNavTypeFromWebNavType(actionType) );
|
||||
|
||||
NSString *url = [[request URL] absoluteString];
|
||||
thisEvent.SetURL( wxStringWithNSString( url ) );
|
||||
|
||||
if (webKitWindow && webKitWindow->GetEventHandler())
|
||||
webKitWindow->GetEventHandler()->ProcessEvent(thisEvent);
|
||||
|
||||
if (thisEvent.IsCancelled())
|
||||
[listener ignore];
|
||||
else
|
||||
[listener use];
|
||||
}
|
||||
|
||||
- (void)webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id < WebPolicyDecisionListener >)listener
|
||||
{
|
||||
wxWebKitNewWindowEvent thisEvent(webKitWindow);
|
||||
|
||||
NSString *url = [[request URL] absoluteString];
|
||||
thisEvent.SetURL( wxStringWithNSString( url ) );
|
||||
thisEvent.SetTargetName( wxStringWithNSString( frameName ) );
|
||||
|
||||
if (webKitWindow && webKitWindow->GetEventHandler())
|
||||
webKitWindow->GetEventHandler()->ProcessEvent(thisEvent);
|
||||
|
||||
[listener use];
|
||||
}
|
||||
@end
|
||||
|
||||
#endif //wxUSE_WEBKIT
|
223
wxWidgets/src/html/htmlfilt.cpp
Normal file
223
wxWidgets/src/html/htmlfilt.cpp
Normal file
|
@ -0,0 +1,223 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/htmlfilt.cpp
|
||||
// Purpose: wxHtmlFilter - input filter for translating into HTML format
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: htmlfilt.cpp 38788 2006-04-18 08:11:26Z ABX $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#include "wx/log.h"
|
||||
#include "wx/intl.h"
|
||||
#endif
|
||||
|
||||
#include "wx/strconv.h"
|
||||
#include "wx/html/htmlfilt.h"
|
||||
#include "wx/html/htmlwin.h"
|
||||
|
||||
// utility function: read a wxString from a wxInputStream
|
||||
static void ReadString(wxString& str, wxInputStream* s, wxMBConv& conv)
|
||||
{
|
||||
size_t streamSize = s->GetSize();
|
||||
|
||||
if (streamSize == ~(size_t)0)
|
||||
{
|
||||
const size_t bufSize = 4095;
|
||||
char buffer[bufSize+1];
|
||||
size_t lastRead;
|
||||
|
||||
do
|
||||
{
|
||||
s->Read(buffer, bufSize);
|
||||
lastRead = s->LastRead();
|
||||
buffer[lastRead] = 0;
|
||||
str.Append(wxString(buffer, conv));
|
||||
}
|
||||
while (lastRead == bufSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
char* src = new char[streamSize+1];
|
||||
s->Read(src, streamSize);
|
||||
src[streamSize] = 0;
|
||||
str = wxString(src, conv);
|
||||
delete[] src;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
There is code for several default filters:
|
||||
|
||||
*/
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(wxHtmlFilter, wxObject)
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// wxHtmlFilterPlainText
|
||||
// filter for text/plain or uknown
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxHtmlFilterPlainText, wxHtmlFilter)
|
||||
|
||||
bool wxHtmlFilterPlainText::CanRead(const wxFSFile& WXUNUSED(file)) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxString wxHtmlFilterPlainText::ReadFile(const wxFSFile& file) const
|
||||
{
|
||||
wxInputStream *s = file.GetStream();
|
||||
wxString doc, doc2;
|
||||
|
||||
if (s == NULL) return wxEmptyString;
|
||||
ReadString(doc, s, wxConvISO8859_1);
|
||||
|
||||
doc.Replace(wxT("&"), wxT("&"), true);
|
||||
doc.Replace(wxT("<"), wxT("<"), true);
|
||||
doc.Replace(wxT(">"), wxT(">"), true);
|
||||
doc2 = wxT("<HTML><BODY><PRE>\n") + doc + wxT("\n</PRE></BODY></HTML>");
|
||||
return doc2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// wxHtmlFilterImage
|
||||
// filter for image/*
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
class wxHtmlFilterImage : public wxHtmlFilter
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS(wxHtmlFilterImage)
|
||||
|
||||
public:
|
||||
virtual bool CanRead(const wxFSFile& file) const;
|
||||
virtual wxString ReadFile(const wxFSFile& file) const;
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxHtmlFilterImage, wxHtmlFilter)
|
||||
|
||||
|
||||
|
||||
bool wxHtmlFilterImage::CanRead(const wxFSFile& file) const
|
||||
{
|
||||
return (file.GetMimeType().Left(6) == wxT("image/"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxString wxHtmlFilterImage::ReadFile(const wxFSFile& file) const
|
||||
{
|
||||
wxString res = wxT("<HTML><BODY><IMG SRC=\"") + file.GetLocation() + wxT("\"></BODY></HTML>");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// wxHtmlFilterHTML
|
||||
// filter for text/html
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxHtmlFilterHTML, wxHtmlFilter)
|
||||
|
||||
bool wxHtmlFilterHTML::CanRead(const wxFSFile& file) const
|
||||
{
|
||||
// return (file.GetMimeType() == "text/html");
|
||||
// This is true in most case but some page can return:
|
||||
// "text/html; char-encoding=...."
|
||||
// So we use Find instead
|
||||
return (file.GetMimeType().Find(wxT("text/html")) == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxString wxHtmlFilterHTML::ReadFile(const wxFSFile& file) const
|
||||
{
|
||||
wxInputStream *s = file.GetStream();
|
||||
wxString doc;
|
||||
|
||||
if (s == NULL)
|
||||
{
|
||||
wxLogError(_("Cannot open HTML document: %s"), file.GetLocation().c_str());
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
// NB: We convert input file to wchar_t here in Unicode mode, based on
|
||||
// either Content-Type header or <meta> tags. In ANSI mode, we don't
|
||||
// do it as it is done by wxHtmlParser (for this reason, we add <meta>
|
||||
// tag if we used Content-Type header).
|
||||
#if wxUSE_UNICODE
|
||||
int charsetPos;
|
||||
if ((charsetPos = file.GetMimeType().Find(_T("; charset="))) != wxNOT_FOUND)
|
||||
{
|
||||
wxString charset = file.GetMimeType().Mid(charsetPos + 10);
|
||||
wxCSConv conv(charset);
|
||||
ReadString(doc, s, conv);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString tmpdoc;
|
||||
ReadString(tmpdoc, s, wxConvISO8859_1);
|
||||
wxString charset = wxHtmlParser::ExtractCharsetInformation(tmpdoc);
|
||||
if (charset.empty())
|
||||
doc = tmpdoc;
|
||||
else
|
||||
{
|
||||
wxCSConv conv(charset);
|
||||
doc = wxString(tmpdoc.mb_str(wxConvISO8859_1), conv);
|
||||
}
|
||||
}
|
||||
#else // !wxUSE_UNICODE
|
||||
ReadString(doc, s, wxConvLibc);
|
||||
// add meta tag if we obtained this through http:
|
||||
if (!file.GetMimeType().empty())
|
||||
{
|
||||
wxString hdr;
|
||||
wxString mime = file.GetMimeType();
|
||||
hdr.Printf(_T("<meta http-equiv=\"Content-Type\" content=\"%s\">"), mime.c_str());
|
||||
return hdr+doc;
|
||||
}
|
||||
#endif
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
///// Module:
|
||||
|
||||
class wxHtmlFilterModule : public wxModule
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS(wxHtmlFilterModule)
|
||||
|
||||
public:
|
||||
virtual bool OnInit()
|
||||
{
|
||||
wxHtmlWindow::AddFilter(new wxHtmlFilterHTML);
|
||||
wxHtmlWindow::AddFilter(new wxHtmlFilterImage);
|
||||
return true;
|
||||
}
|
||||
virtual void OnExit() {}
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxHtmlFilterModule, wxModule)
|
||||
|
||||
#endif
|
961
wxWidgets/src/html/htmlpars.cpp
Normal file
961
wxWidgets/src/html/htmlpars.cpp
Normal file
|
@ -0,0 +1,961 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/htmlpars.cpp
|
||||
// Purpose: wxHtmlParser class (generic parser)
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: htmlpars.cpp 66413 2010-12-20 17:40:05Z JS $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#include "wx/dynarray.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/app.h"
|
||||
#endif
|
||||
|
||||
#include "wx/tokenzr.h"
|
||||
#include "wx/wfstream.h"
|
||||
#include "wx/url.h"
|
||||
#include "wx/fontmap.h"
|
||||
#include "wx/html/htmldefs.h"
|
||||
#include "wx/html/htmlpars.h"
|
||||
#include "wx/arrimpl.cpp"
|
||||
|
||||
#ifdef __WXWINCE__
|
||||
#include "wx/msw/wince/missing.h" // for bsearch()
|
||||
#endif
|
||||
|
||||
// DLL options compatibility check:
|
||||
WX_CHECK_BUILD_OPTIONS("wxHTML")
|
||||
|
||||
const wxChar *wxTRACE_HTML_DEBUG = _T("htmldebug");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlParser helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class wxHtmlTextPiece
|
||||
{
|
||||
public:
|
||||
wxHtmlTextPiece(int pos, int lng) : m_pos(pos), m_lng(lng) {}
|
||||
int m_pos, m_lng;
|
||||
};
|
||||
|
||||
WX_DECLARE_OBJARRAY(wxHtmlTextPiece, wxHtmlTextPieces);
|
||||
WX_DEFINE_OBJARRAY(wxHtmlTextPieces)
|
||||
|
||||
class wxHtmlParserState
|
||||
{
|
||||
public:
|
||||
wxHtmlTag *m_curTag;
|
||||
wxHtmlTag *m_tags;
|
||||
wxHtmlTextPieces *m_textPieces;
|
||||
int m_curTextPiece;
|
||||
wxString m_source;
|
||||
wxHtmlParserState *m_nextState;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlParser
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(wxHtmlParser,wxObject)
|
||||
|
||||
wxHtmlParser::wxHtmlParser()
|
||||
: wxObject(), m_HandlersHash(wxKEY_STRING),
|
||||
m_FS(NULL), m_HandlersStack(NULL)
|
||||
{
|
||||
m_entitiesParser = new wxHtmlEntitiesParser;
|
||||
m_Tags = NULL;
|
||||
m_CurTag = NULL;
|
||||
m_TextPieces = NULL;
|
||||
m_CurTextPiece = 0;
|
||||
m_SavedStates = NULL;
|
||||
}
|
||||
|
||||
wxHtmlParser::~wxHtmlParser()
|
||||
{
|
||||
while (RestoreState()) {}
|
||||
DestroyDOMTree();
|
||||
|
||||
if (m_HandlersStack)
|
||||
{
|
||||
wxList& tmp = *m_HandlersStack;
|
||||
wxList::iterator it, en;
|
||||
for( it = tmp.begin(), en = tmp.end(); it != en; ++it )
|
||||
delete (wxHashTable*)*it;
|
||||
tmp.clear();
|
||||
}
|
||||
delete m_HandlersStack;
|
||||
m_HandlersHash.Clear();
|
||||
WX_CLEAR_LIST(wxList, m_HandlersList);
|
||||
delete m_entitiesParser;
|
||||
}
|
||||
|
||||
wxObject* wxHtmlParser::Parse(const wxString& source)
|
||||
{
|
||||
InitParser(source);
|
||||
DoParsing();
|
||||
wxObject *result = GetProduct();
|
||||
DoneParser();
|
||||
return result;
|
||||
}
|
||||
|
||||
void wxHtmlParser::InitParser(const wxString& source)
|
||||
{
|
||||
SetSource(source);
|
||||
m_stopParsing = false;
|
||||
}
|
||||
|
||||
void wxHtmlParser::DoneParser()
|
||||
{
|
||||
DestroyDOMTree();
|
||||
}
|
||||
|
||||
void wxHtmlParser::SetSource(const wxString& src)
|
||||
{
|
||||
DestroyDOMTree();
|
||||
m_Source = src;
|
||||
CreateDOMTree();
|
||||
m_CurTag = NULL;
|
||||
m_CurTextPiece = 0;
|
||||
}
|
||||
|
||||
void wxHtmlParser::CreateDOMTree()
|
||||
{
|
||||
wxHtmlTagsCache cache(m_Source);
|
||||
m_TextPieces = new wxHtmlTextPieces;
|
||||
CreateDOMSubTree(NULL, 0, m_Source.length(), &cache);
|
||||
m_CurTextPiece = 0;
|
||||
}
|
||||
|
||||
extern bool wxIsCDATAElement(const wxChar *tag);
|
||||
|
||||
void wxHtmlParser::CreateDOMSubTree(wxHtmlTag *cur,
|
||||
int begin_pos, int end_pos,
|
||||
wxHtmlTagsCache *cache)
|
||||
{
|
||||
if (end_pos <= begin_pos) return;
|
||||
|
||||
wxChar c;
|
||||
int i = begin_pos;
|
||||
int textBeginning = begin_pos;
|
||||
|
||||
// If the tag contains CDATA text, we include the text between beginning
|
||||
// and ending tag verbosely. Setting i=end_pos will skip to the very
|
||||
// end of this function where text piece is added, bypassing any child
|
||||
// tags parsing (CDATA element can't have child elements by definition):
|
||||
if (cur != NULL && wxIsCDATAElement(cur->GetName().c_str()))
|
||||
{
|
||||
i = end_pos;
|
||||
}
|
||||
|
||||
while (i < end_pos)
|
||||
{
|
||||
c = m_Source.GetChar(i);
|
||||
|
||||
if (c == wxT('<'))
|
||||
{
|
||||
// add text to m_TextPieces:
|
||||
if (i - textBeginning > 0)
|
||||
m_TextPieces->Add(
|
||||
wxHtmlTextPiece(textBeginning, i - textBeginning));
|
||||
|
||||
// if it is a comment, skip it:
|
||||
if (i < end_pos-6 && m_Source.GetChar(i+1) == wxT('!') &&
|
||||
m_Source.GetChar(i+2) == wxT('-') &&
|
||||
m_Source.GetChar(i+3) == wxT('-'))
|
||||
{
|
||||
// Comments begin with "<!--" and end with "--[ \t\r\n]*>"
|
||||
// according to HTML 4.0
|
||||
int dashes = 0;
|
||||
i += 4;
|
||||
while (i < end_pos)
|
||||
{
|
||||
c = m_Source.GetChar(i++);
|
||||
if ((c == wxT(' ') || c == wxT('\n') ||
|
||||
c == wxT('\r') || c == wxT('\t')) && dashes >= 2) {}
|
||||
else if (c == wxT('>') && dashes >= 2)
|
||||
{
|
||||
textBeginning = i;
|
||||
break;
|
||||
}
|
||||
else if (c == wxT('-'))
|
||||
dashes++;
|
||||
else
|
||||
dashes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// add another tag to the tree:
|
||||
else if (i < end_pos-1 && m_Source.GetChar(i+1) != wxT('/'))
|
||||
{
|
||||
wxHtmlTag *chd;
|
||||
if (cur)
|
||||
chd = new wxHtmlTag(cur, m_Source,
|
||||
i, end_pos, cache, m_entitiesParser);
|
||||
else
|
||||
{
|
||||
chd = new wxHtmlTag(NULL, m_Source,
|
||||
i, end_pos, cache, m_entitiesParser);
|
||||
if (!m_Tags)
|
||||
{
|
||||
// if this is the first tag to be created make the root
|
||||
// m_Tags point to it:
|
||||
m_Tags = chd;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if there is already a root tag add this tag as
|
||||
// the last sibling:
|
||||
chd->m_Prev = m_Tags->GetLastSibling();
|
||||
chd->m_Prev->m_Next = chd;
|
||||
}
|
||||
}
|
||||
|
||||
if (chd->HasEnding())
|
||||
{
|
||||
CreateDOMSubTree(chd,
|
||||
chd->GetBeginPos(), chd->GetEndPos1(),
|
||||
cache);
|
||||
i = chd->GetEndPos2();
|
||||
}
|
||||
else
|
||||
i = chd->GetBeginPos();
|
||||
|
||||
textBeginning = i;
|
||||
}
|
||||
|
||||
// ... or skip ending tag:
|
||||
else
|
||||
{
|
||||
while (i < end_pos && m_Source.GetChar(i) != wxT('>')) i++;
|
||||
textBeginning = i+1;
|
||||
}
|
||||
}
|
||||
else i++;
|
||||
}
|
||||
|
||||
// add remaining text to m_TextPieces:
|
||||
if (end_pos - textBeginning > 0)
|
||||
m_TextPieces->Add(
|
||||
wxHtmlTextPiece(textBeginning, end_pos - textBeginning));
|
||||
}
|
||||
|
||||
void wxHtmlParser::DestroyDOMTree()
|
||||
{
|
||||
wxHtmlTag *t1, *t2;
|
||||
t1 = m_Tags;
|
||||
while (t1)
|
||||
{
|
||||
t2 = t1->GetNextSibling();
|
||||
delete t1;
|
||||
t1 = t2;
|
||||
}
|
||||
m_Tags = m_CurTag = NULL;
|
||||
|
||||
delete m_TextPieces;
|
||||
m_TextPieces = NULL;
|
||||
}
|
||||
|
||||
void wxHtmlParser::DoParsing()
|
||||
{
|
||||
m_CurTag = m_Tags;
|
||||
m_CurTextPiece = 0;
|
||||
DoParsing(0, m_Source.length());
|
||||
}
|
||||
|
||||
void wxHtmlParser::DoParsing(int begin_pos, int end_pos)
|
||||
{
|
||||
if (end_pos <= begin_pos) return;
|
||||
|
||||
wxHtmlTextPieces& pieces = *m_TextPieces;
|
||||
size_t piecesCnt = pieces.GetCount();
|
||||
|
||||
while (begin_pos < end_pos)
|
||||
{
|
||||
while (m_CurTag && m_CurTag->GetBeginPos() < begin_pos)
|
||||
m_CurTag = m_CurTag->GetNextTag();
|
||||
while (m_CurTextPiece < piecesCnt &&
|
||||
pieces[m_CurTextPiece].m_pos < begin_pos)
|
||||
m_CurTextPiece++;
|
||||
|
||||
if (m_CurTextPiece < piecesCnt &&
|
||||
(!m_CurTag ||
|
||||
pieces[m_CurTextPiece].m_pos < m_CurTag->GetBeginPos()))
|
||||
{
|
||||
// Add text:
|
||||
AddText(GetEntitiesParser()->Parse(
|
||||
m_Source.Mid(pieces[m_CurTextPiece].m_pos,
|
||||
pieces[m_CurTextPiece].m_lng)));
|
||||
begin_pos = pieces[m_CurTextPiece].m_pos +
|
||||
pieces[m_CurTextPiece].m_lng;
|
||||
m_CurTextPiece++;
|
||||
}
|
||||
else if (m_CurTag)
|
||||
{
|
||||
if (m_CurTag->HasEnding())
|
||||
begin_pos = m_CurTag->GetEndPos2();
|
||||
else
|
||||
begin_pos = m_CurTag->GetBeginPos();
|
||||
wxHtmlTag *t = m_CurTag;
|
||||
m_CurTag = m_CurTag->GetNextTag();
|
||||
AddTag(*t);
|
||||
if (m_stopParsing)
|
||||
return;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
void wxHtmlParser::AddTag(const wxHtmlTag& tag)
|
||||
{
|
||||
wxHtmlTagHandler *h;
|
||||
bool inner = false;
|
||||
|
||||
h = (wxHtmlTagHandler*) m_HandlersHash.Get(tag.GetName());
|
||||
if (h)
|
||||
{
|
||||
inner = h->HandleTag(tag);
|
||||
if (m_stopParsing)
|
||||
return;
|
||||
}
|
||||
if (!inner)
|
||||
{
|
||||
if (tag.HasEnding())
|
||||
DoParsing(tag.GetBeginPos(), tag.GetEndPos1());
|
||||
}
|
||||
}
|
||||
|
||||
void wxHtmlParser::AddTagHandler(wxHtmlTagHandler *handler)
|
||||
{
|
||||
wxString s(handler->GetSupportedTags());
|
||||
wxStringTokenizer tokenizer(s, wxT(", "));
|
||||
|
||||
while (tokenizer.HasMoreTokens())
|
||||
m_HandlersHash.Put(tokenizer.GetNextToken(), handler);
|
||||
|
||||
if (m_HandlersList.IndexOf(handler) == wxNOT_FOUND)
|
||||
m_HandlersList.Append(handler);
|
||||
|
||||
handler->SetParser(this);
|
||||
}
|
||||
|
||||
void wxHtmlParser::PushTagHandler(wxHtmlTagHandler *handler, const wxString& tags)
|
||||
{
|
||||
wxStringTokenizer tokenizer(tags, wxT(", "));
|
||||
wxString key;
|
||||
|
||||
if (m_HandlersStack == NULL)
|
||||
{
|
||||
m_HandlersStack = new wxList;
|
||||
}
|
||||
|
||||
m_HandlersStack->Insert((wxObject*)new wxHashTable(m_HandlersHash));
|
||||
|
||||
while (tokenizer.HasMoreTokens())
|
||||
{
|
||||
key = tokenizer.GetNextToken();
|
||||
m_HandlersHash.Delete(key);
|
||||
m_HandlersHash.Put(key, handler);
|
||||
}
|
||||
}
|
||||
|
||||
void wxHtmlParser::PopTagHandler()
|
||||
{
|
||||
wxList::compatibility_iterator first;
|
||||
|
||||
if ( !m_HandlersStack ||
|
||||
#if wxUSE_STL
|
||||
!(first = m_HandlersStack->GetFirst())
|
||||
#else // !wxUSE_STL
|
||||
((first = m_HandlersStack->GetFirst()) == NULL)
|
||||
#endif // wxUSE_STL/!wxUSE_STL
|
||||
)
|
||||
{
|
||||
wxLogWarning(_("Warning: attempt to remove HTML tag handler from empty stack."));
|
||||
return;
|
||||
}
|
||||
m_HandlersHash = *((wxHashTable*) first->GetData());
|
||||
delete (wxHashTable*) first->GetData();
|
||||
m_HandlersStack->Erase(first);
|
||||
}
|
||||
|
||||
void wxHtmlParser::SetSourceAndSaveState(const wxString& src)
|
||||
{
|
||||
wxHtmlParserState *s = new wxHtmlParserState;
|
||||
|
||||
s->m_curTag = m_CurTag;
|
||||
s->m_tags = m_Tags;
|
||||
s->m_textPieces = m_TextPieces;
|
||||
s->m_curTextPiece = m_CurTextPiece;
|
||||
s->m_source = m_Source;
|
||||
|
||||
s->m_nextState = m_SavedStates;
|
||||
m_SavedStates = s;
|
||||
|
||||
m_CurTag = NULL;
|
||||
m_Tags = NULL;
|
||||
m_TextPieces = NULL;
|
||||
m_CurTextPiece = 0;
|
||||
m_Source = wxEmptyString;
|
||||
|
||||
SetSource(src);
|
||||
}
|
||||
|
||||
bool wxHtmlParser::RestoreState()
|
||||
{
|
||||
if (!m_SavedStates) return false;
|
||||
|
||||
DestroyDOMTree();
|
||||
|
||||
wxHtmlParserState *s = m_SavedStates;
|
||||
m_SavedStates = s->m_nextState;
|
||||
|
||||
m_CurTag = s->m_curTag;
|
||||
m_Tags = s->m_tags;
|
||||
m_TextPieces = s->m_textPieces;
|
||||
m_CurTextPiece = s->m_curTextPiece;
|
||||
m_Source = s->m_source;
|
||||
|
||||
delete s;
|
||||
return true;
|
||||
}
|
||||
|
||||
wxString wxHtmlParser::GetInnerSource(const wxHtmlTag& tag)
|
||||
{
|
||||
return GetSource()->Mid(tag.GetBeginPos(),
|
||||
tag.GetEndPos1() - tag.GetBeginPos());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlTagHandler
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(wxHtmlTagHandler,wxObject)
|
||||
|
||||
void wxHtmlTagHandler::ParseInnerSource(const wxString& source)
|
||||
{
|
||||
// It is safe to temporarily change the source being parsed,
|
||||
// provided we restore the state back after parsing
|
||||
m_Parser->SetSourceAndSaveState(source);
|
||||
m_Parser->DoParsing();
|
||||
m_Parser->RestoreState();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlEntitiesParser
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxHtmlEntitiesParser,wxObject)
|
||||
|
||||
wxHtmlEntitiesParser::wxHtmlEntitiesParser()
|
||||
#if wxUSE_WCHAR_T && !wxUSE_UNICODE
|
||||
: m_conv(NULL), m_encoding(wxFONTENCODING_SYSTEM)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
wxHtmlEntitiesParser::~wxHtmlEntitiesParser()
|
||||
{
|
||||
#if wxUSE_WCHAR_T && !wxUSE_UNICODE
|
||||
delete m_conv;
|
||||
#endif
|
||||
}
|
||||
|
||||
void wxHtmlEntitiesParser::SetEncoding(wxFontEncoding encoding)
|
||||
{
|
||||
#if wxUSE_WCHAR_T && !wxUSE_UNICODE
|
||||
if (encoding == m_encoding)
|
||||
return;
|
||||
|
||||
delete m_conv;
|
||||
|
||||
m_encoding = encoding;
|
||||
if (m_encoding == wxFONTENCODING_SYSTEM)
|
||||
m_conv = NULL;
|
||||
else
|
||||
m_conv = new wxCSConv(wxFontMapper::GetEncodingName(m_encoding));
|
||||
#else
|
||||
(void) encoding;
|
||||
#endif
|
||||
}
|
||||
|
||||
wxString wxHtmlEntitiesParser::Parse(const wxString& input)
|
||||
{
|
||||
const wxChar *c, *last;
|
||||
const wxChar *in_str = input.c_str();
|
||||
wxString output;
|
||||
|
||||
for (c = in_str, last = in_str; *c != wxT('\0'); c++)
|
||||
{
|
||||
if (*c == wxT('&'))
|
||||
{
|
||||
if ( output.empty() )
|
||||
output.reserve(input.length());
|
||||
|
||||
if (c - last > 0)
|
||||
output.append(last, c - last);
|
||||
if ( *++c == wxT('\0') )
|
||||
break;
|
||||
|
||||
wxString entity;
|
||||
const wxChar *ent_s = c;
|
||||
wxChar entity_char;
|
||||
|
||||
for (; (*c >= wxT('a') && *c <= wxT('z')) ||
|
||||
(*c >= wxT('A') && *c <= wxT('Z')) ||
|
||||
(*c >= wxT('0') && *c <= wxT('9')) ||
|
||||
*c == wxT('_') || *c == wxT('#'); c++) {}
|
||||
entity.append(ent_s, c - ent_s);
|
||||
if (*c != wxT(';')) c--;
|
||||
last = c+1;
|
||||
entity_char = GetEntityChar(entity);
|
||||
if (entity_char)
|
||||
output << entity_char;
|
||||
else
|
||||
{
|
||||
output.append(ent_s-1, c-ent_s+2);
|
||||
wxLogTrace(wxTRACE_HTML_DEBUG,
|
||||
wxT("Unrecognized HTML entity: '%s'"),
|
||||
entity.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last == in_str) // common case: no entity
|
||||
return input;
|
||||
if (*last != wxT('\0'))
|
||||
output.append(last);
|
||||
return output;
|
||||
}
|
||||
|
||||
struct wxHtmlEntityInfo
|
||||
{
|
||||
const wxChar *name;
|
||||
unsigned code;
|
||||
};
|
||||
|
||||
extern "C" int LINKAGEMODE wxHtmlEntityCompare(const void *key, const void *item)
|
||||
{
|
||||
return wxStrcmp((wxChar*)key, ((wxHtmlEntityInfo*)item)->name);
|
||||
}
|
||||
|
||||
#if !wxUSE_UNICODE
|
||||
wxChar wxHtmlEntitiesParser::GetCharForCode(unsigned code)
|
||||
{
|
||||
#if wxUSE_WCHAR_T
|
||||
char buf[2];
|
||||
wchar_t wbuf[2];
|
||||
wbuf[0] = (wchar_t)code;
|
||||
wbuf[1] = 0;
|
||||
wxMBConv *conv = m_conv ? m_conv : &wxConvLocal;
|
||||
if (conv->WC2MB(buf, wbuf, 2) == (size_t)-1)
|
||||
return '?';
|
||||
return buf[0];
|
||||
#else
|
||||
return (code < 256) ? (wxChar)code : '?';
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
wxChar wxHtmlEntitiesParser::GetEntityChar(const wxString& entity)
|
||||
{
|
||||
unsigned code = 0;
|
||||
|
||||
if (entity.empty())
|
||||
return 0; // invalid entity reference
|
||||
|
||||
if (entity[0] == wxT('#'))
|
||||
{
|
||||
const wxChar *ent_s = entity.c_str();
|
||||
const wxChar *format;
|
||||
|
||||
if (ent_s[1] == wxT('x') || ent_s[1] == wxT('X'))
|
||||
{
|
||||
format = wxT("%x");
|
||||
ent_s++;
|
||||
}
|
||||
else
|
||||
format = wxT("%u");
|
||||
ent_s++;
|
||||
|
||||
if (wxSscanf(ent_s, format, &code) != 1)
|
||||
code = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
static wxHtmlEntityInfo substitutions[] = {
|
||||
{ wxT("AElig"),198 },
|
||||
{ wxT("Aacute"),193 },
|
||||
{ wxT("Acirc"),194 },
|
||||
{ wxT("Agrave"),192 },
|
||||
{ wxT("Alpha"),913 },
|
||||
{ wxT("Aring"),197 },
|
||||
{ wxT("Atilde"),195 },
|
||||
{ wxT("Auml"),196 },
|
||||
{ wxT("Beta"),914 },
|
||||
{ wxT("Ccedil"),199 },
|
||||
{ wxT("Chi"),935 },
|
||||
{ wxT("Dagger"),8225 },
|
||||
{ wxT("Delta"),916 },
|
||||
{ wxT("ETH"),208 },
|
||||
{ wxT("Eacute"),201 },
|
||||
{ wxT("Ecirc"),202 },
|
||||
{ wxT("Egrave"),200 },
|
||||
{ wxT("Epsilon"),917 },
|
||||
{ wxT("Eta"),919 },
|
||||
{ wxT("Euml"),203 },
|
||||
{ wxT("Gamma"),915 },
|
||||
{ wxT("Iacute"),205 },
|
||||
{ wxT("Icirc"),206 },
|
||||
{ wxT("Igrave"),204 },
|
||||
{ wxT("Iota"),921 },
|
||||
{ wxT("Iuml"),207 },
|
||||
{ wxT("Kappa"),922 },
|
||||
{ wxT("Lambda"),923 },
|
||||
{ wxT("Mu"),924 },
|
||||
{ wxT("Ntilde"),209 },
|
||||
{ wxT("Nu"),925 },
|
||||
{ wxT("OElig"),338 },
|
||||
{ wxT("Oacute"),211 },
|
||||
{ wxT("Ocirc"),212 },
|
||||
{ wxT("Ograve"),210 },
|
||||
{ wxT("Omega"),937 },
|
||||
{ wxT("Omicron"),927 },
|
||||
{ wxT("Oslash"),216 },
|
||||
{ wxT("Otilde"),213 },
|
||||
{ wxT("Ouml"),214 },
|
||||
{ wxT("Phi"),934 },
|
||||
{ wxT("Pi"),928 },
|
||||
{ wxT("Prime"),8243 },
|
||||
{ wxT("Psi"),936 },
|
||||
{ wxT("Rho"),929 },
|
||||
{ wxT("Scaron"),352 },
|
||||
{ wxT("Sigma"),931 },
|
||||
{ wxT("THORN"),222 },
|
||||
{ wxT("Tau"),932 },
|
||||
{ wxT("Theta"),920 },
|
||||
{ wxT("Uacute"),218 },
|
||||
{ wxT("Ucirc"),219 },
|
||||
{ wxT("Ugrave"),217 },
|
||||
{ wxT("Upsilon"),933 },
|
||||
{ wxT("Uuml"),220 },
|
||||
{ wxT("Xi"),926 },
|
||||
{ wxT("Yacute"),221 },
|
||||
{ wxT("Yuml"),376 },
|
||||
{ wxT("Zeta"),918 },
|
||||
{ wxT("aacute"),225 },
|
||||
{ wxT("acirc"),226 },
|
||||
{ wxT("acute"),180 },
|
||||
{ wxT("aelig"),230 },
|
||||
{ wxT("agrave"),224 },
|
||||
{ wxT("alefsym"),8501 },
|
||||
{ wxT("alpha"),945 },
|
||||
{ wxT("amp"),38 },
|
||||
{ wxT("and"),8743 },
|
||||
{ wxT("ang"),8736 },
|
||||
{ wxT("apos"),39 },
|
||||
{ wxT("aring"),229 },
|
||||
{ wxT("asymp"),8776 },
|
||||
{ wxT("atilde"),227 },
|
||||
{ wxT("auml"),228 },
|
||||
{ wxT("bdquo"),8222 },
|
||||
{ wxT("beta"),946 },
|
||||
{ wxT("brvbar"),166 },
|
||||
{ wxT("bull"),8226 },
|
||||
{ wxT("cap"),8745 },
|
||||
{ wxT("ccedil"),231 },
|
||||
{ wxT("cedil"),184 },
|
||||
{ wxT("cent"),162 },
|
||||
{ wxT("chi"),967 },
|
||||
{ wxT("circ"),710 },
|
||||
{ wxT("clubs"),9827 },
|
||||
{ wxT("cong"),8773 },
|
||||
{ wxT("copy"),169 },
|
||||
{ wxT("crarr"),8629 },
|
||||
{ wxT("cup"),8746 },
|
||||
{ wxT("curren"),164 },
|
||||
{ wxT("dArr"),8659 },
|
||||
{ wxT("dagger"),8224 },
|
||||
{ wxT("darr"),8595 },
|
||||
{ wxT("deg"),176 },
|
||||
{ wxT("delta"),948 },
|
||||
{ wxT("diams"),9830 },
|
||||
{ wxT("divide"),247 },
|
||||
{ wxT("eacute"),233 },
|
||||
{ wxT("ecirc"),234 },
|
||||
{ wxT("egrave"),232 },
|
||||
{ wxT("empty"),8709 },
|
||||
{ wxT("emsp"),8195 },
|
||||
{ wxT("ensp"),8194 },
|
||||
{ wxT("epsilon"),949 },
|
||||
{ wxT("equiv"),8801 },
|
||||
{ wxT("eta"),951 },
|
||||
{ wxT("eth"),240 },
|
||||
{ wxT("euml"),235 },
|
||||
{ wxT("euro"),8364 },
|
||||
{ wxT("exist"),8707 },
|
||||
{ wxT("fnof"),402 },
|
||||
{ wxT("forall"),8704 },
|
||||
{ wxT("frac12"),189 },
|
||||
{ wxT("frac14"),188 },
|
||||
{ wxT("frac34"),190 },
|
||||
{ wxT("frasl"),8260 },
|
||||
{ wxT("gamma"),947 },
|
||||
{ wxT("ge"),8805 },
|
||||
{ wxT("gt"),62 },
|
||||
{ wxT("hArr"),8660 },
|
||||
{ wxT("harr"),8596 },
|
||||
{ wxT("hearts"),9829 },
|
||||
{ wxT("hellip"),8230 },
|
||||
{ wxT("iacute"),237 },
|
||||
{ wxT("icirc"),238 },
|
||||
{ wxT("iexcl"),161 },
|
||||
{ wxT("igrave"),236 },
|
||||
{ wxT("image"),8465 },
|
||||
{ wxT("infin"),8734 },
|
||||
{ wxT("int"),8747 },
|
||||
{ wxT("iota"),953 },
|
||||
{ wxT("iquest"),191 },
|
||||
{ wxT("isin"),8712 },
|
||||
{ wxT("iuml"),239 },
|
||||
{ wxT("kappa"),954 },
|
||||
{ wxT("lArr"),8656 },
|
||||
{ wxT("lambda"),955 },
|
||||
{ wxT("lang"),9001 },
|
||||
{ wxT("laquo"),171 },
|
||||
{ wxT("larr"),8592 },
|
||||
{ wxT("lceil"),8968 },
|
||||
{ wxT("ldquo"),8220 },
|
||||
{ wxT("le"),8804 },
|
||||
{ wxT("lfloor"),8970 },
|
||||
{ wxT("lowast"),8727 },
|
||||
{ wxT("loz"),9674 },
|
||||
{ wxT("lrm"),8206 },
|
||||
{ wxT("lsaquo"),8249 },
|
||||
{ wxT("lsquo"),8216 },
|
||||
{ wxT("lt"),60 },
|
||||
{ wxT("macr"),175 },
|
||||
{ wxT("mdash"),8212 },
|
||||
{ wxT("micro"),181 },
|
||||
{ wxT("middot"),183 },
|
||||
{ wxT("minus"),8722 },
|
||||
{ wxT("mu"),956 },
|
||||
{ wxT("nabla"),8711 },
|
||||
{ wxT("nbsp"),160 },
|
||||
{ wxT("ndash"),8211 },
|
||||
{ wxT("ne"),8800 },
|
||||
{ wxT("ni"),8715 },
|
||||
{ wxT("not"),172 },
|
||||
{ wxT("notin"),8713 },
|
||||
{ wxT("nsub"),8836 },
|
||||
{ wxT("ntilde"),241 },
|
||||
{ wxT("nu"),957 },
|
||||
{ wxT("oacute"),243 },
|
||||
{ wxT("ocirc"),244 },
|
||||
{ wxT("oelig"),339 },
|
||||
{ wxT("ograve"),242 },
|
||||
{ wxT("oline"),8254 },
|
||||
{ wxT("omega"),969 },
|
||||
{ wxT("omicron"),959 },
|
||||
{ wxT("oplus"),8853 },
|
||||
{ wxT("or"),8744 },
|
||||
{ wxT("ordf"),170 },
|
||||
{ wxT("ordm"),186 },
|
||||
{ wxT("oslash"),248 },
|
||||
{ wxT("otilde"),245 },
|
||||
{ wxT("otimes"),8855 },
|
||||
{ wxT("ouml"),246 },
|
||||
{ wxT("para"),182 },
|
||||
{ wxT("part"),8706 },
|
||||
{ wxT("permil"),8240 },
|
||||
{ wxT("perp"),8869 },
|
||||
{ wxT("phi"),966 },
|
||||
{ wxT("pi"),960 },
|
||||
{ wxT("piv"),982 },
|
||||
{ wxT("plusmn"),177 },
|
||||
{ wxT("pound"),163 },
|
||||
{ wxT("prime"),8242 },
|
||||
{ wxT("prod"),8719 },
|
||||
{ wxT("prop"),8733 },
|
||||
{ wxT("psi"),968 },
|
||||
{ wxT("quot"),34 },
|
||||
{ wxT("rArr"),8658 },
|
||||
{ wxT("radic"),8730 },
|
||||
{ wxT("rang"),9002 },
|
||||
{ wxT("raquo"),187 },
|
||||
{ wxT("rarr"),8594 },
|
||||
{ wxT("rceil"),8969 },
|
||||
{ wxT("rdquo"),8221 },
|
||||
{ wxT("real"),8476 },
|
||||
{ wxT("reg"),174 },
|
||||
{ wxT("rfloor"),8971 },
|
||||
{ wxT("rho"),961 },
|
||||
{ wxT("rlm"),8207 },
|
||||
{ wxT("rsaquo"),8250 },
|
||||
{ wxT("rsquo"),8217 },
|
||||
{ wxT("sbquo"),8218 },
|
||||
{ wxT("scaron"),353 },
|
||||
{ wxT("sdot"),8901 },
|
||||
{ wxT("sect"),167 },
|
||||
{ wxT("shy"),173 },
|
||||
{ wxT("sigma"),963 },
|
||||
{ wxT("sigmaf"),962 },
|
||||
{ wxT("sim"),8764 },
|
||||
{ wxT("spades"),9824 },
|
||||
{ wxT("sub"),8834 },
|
||||
{ wxT("sube"),8838 },
|
||||
{ wxT("sum"),8721 },
|
||||
{ wxT("sup"),8835 },
|
||||
{ wxT("sup1"),185 },
|
||||
{ wxT("sup2"),178 },
|
||||
{ wxT("sup3"),179 },
|
||||
{ wxT("supe"),8839 },
|
||||
{ wxT("szlig"),223 },
|
||||
{ wxT("tau"),964 },
|
||||
{ wxT("there4"),8756 },
|
||||
{ wxT("theta"),952 },
|
||||
{ wxT("thetasym"),977 },
|
||||
{ wxT("thinsp"),8201 },
|
||||
{ wxT("thorn"),254 },
|
||||
{ wxT("tilde"),732 },
|
||||
{ wxT("times"),215 },
|
||||
{ wxT("trade"),8482 },
|
||||
{ wxT("uArr"),8657 },
|
||||
{ wxT("uacute"),250 },
|
||||
{ wxT("uarr"),8593 },
|
||||
{ wxT("ucirc"),251 },
|
||||
{ wxT("ugrave"),249 },
|
||||
{ wxT("uml"),168 },
|
||||
{ wxT("upsih"),978 },
|
||||
{ wxT("upsilon"),965 },
|
||||
{ wxT("uuml"),252 },
|
||||
{ wxT("weierp"),8472 },
|
||||
{ wxT("xi"),958 },
|
||||
{ wxT("yacute"),253 },
|
||||
{ wxT("yen"),165 },
|
||||
{ wxT("yuml"),255 },
|
||||
{ wxT("zeta"),950 },
|
||||
{ wxT("zwj"),8205 },
|
||||
{ wxT("zwnj"),8204 },
|
||||
{NULL, 0}};
|
||||
static size_t substitutions_cnt = 0;
|
||||
|
||||
if (substitutions_cnt == 0)
|
||||
while (substitutions[substitutions_cnt].code != 0)
|
||||
substitutions_cnt++;
|
||||
|
||||
wxHtmlEntityInfo *info = NULL;
|
||||
#ifdef __WXWINCE__
|
||||
// bsearch crashes under WinCE for some reason
|
||||
size_t i;
|
||||
for (i = 0; i < substitutions_cnt; i++)
|
||||
{
|
||||
if (entity == substitutions[i].name)
|
||||
{
|
||||
info = & substitutions[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
info = (wxHtmlEntityInfo*) bsearch(entity.c_str(), substitutions,
|
||||
substitutions_cnt,
|
||||
sizeof(wxHtmlEntityInfo),
|
||||
wxHtmlEntityCompare);
|
||||
#endif
|
||||
if (info)
|
||||
code = info->code;
|
||||
}
|
||||
|
||||
if (code == 0)
|
||||
return 0;
|
||||
else
|
||||
return GetCharForCode(code);
|
||||
}
|
||||
|
||||
wxFSFile *wxHtmlParser::OpenURL(wxHtmlURLType WXUNUSED(type),
|
||||
const wxString& url) const
|
||||
{
|
||||
return m_FS ? m_FS->OpenFile(url) : NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlParser::ExtractCharsetInformation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class wxMetaTagParser : public wxHtmlParser
|
||||
{
|
||||
public:
|
||||
wxMetaTagParser() { }
|
||||
|
||||
wxObject* GetProduct() { return NULL; }
|
||||
|
||||
protected:
|
||||
virtual void AddText(const wxChar* WXUNUSED(txt)) {}
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxMetaTagParser)
|
||||
};
|
||||
|
||||
class wxMetaTagHandler : public wxHtmlTagHandler
|
||||
{
|
||||
public:
|
||||
wxMetaTagHandler(wxString *retval) : wxHtmlTagHandler(), m_retval(retval) {}
|
||||
wxString GetSupportedTags() { return wxT("META,BODY"); }
|
||||
bool HandleTag(const wxHtmlTag& tag);
|
||||
|
||||
private:
|
||||
wxString *m_retval;
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxMetaTagHandler)
|
||||
};
|
||||
|
||||
bool wxMetaTagHandler::HandleTag(const wxHtmlTag& tag)
|
||||
{
|
||||
if (tag.GetName() == _T("BODY"))
|
||||
{
|
||||
m_Parser->StopParsing();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tag.HasParam(_T("HTTP-EQUIV")) &&
|
||||
tag.GetParam(_T("HTTP-EQUIV")).IsSameAs(_T("Content-Type"), false) &&
|
||||
tag.HasParam(_T("CONTENT")))
|
||||
{
|
||||
wxString content = tag.GetParam(_T("CONTENT")).Lower();
|
||||
if (content.Left(19) == _T("text/html; charset="))
|
||||
{
|
||||
*m_retval = content.Mid(19);
|
||||
m_Parser->StopParsing();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*static*/
|
||||
wxString wxHtmlParser::ExtractCharsetInformation(const wxString& markup)
|
||||
{
|
||||
wxString charset;
|
||||
wxMetaTagParser *parser = new wxMetaTagParser();
|
||||
if(parser)
|
||||
{
|
||||
parser->AddTagHandler(new wxMetaTagHandler(&charset));
|
||||
parser->Parse(markup);
|
||||
delete parser;
|
||||
}
|
||||
return charset;
|
||||
}
|
||||
|
||||
#endif
|
521
wxWidgets/src/html/htmltag.cpp
Normal file
521
wxWidgets/src/html/htmltag.cpp
Normal file
|
@ -0,0 +1,521 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/htmltag.cpp
|
||||
// Purpose: wxHtmlTag class (represents single tag)
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: htmltag.cpp 53433 2008-05-03 00:40:29Z VZ $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML
|
||||
|
||||
#include "wx/html/htmltag.h"
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#include "wx/colour.h"
|
||||
#endif
|
||||
|
||||
#include "wx/html/htmlpars.h"
|
||||
#include <stdio.h> // for vsscanf
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlTagsCache
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct wxHtmlCacheItem
|
||||
{
|
||||
// this is "pos" value passed to wxHtmlTag's constructor.
|
||||
// it is position of '<' character of the tag
|
||||
int Key;
|
||||
|
||||
// end positions for the tag:
|
||||
// end1 is '<' of ending tag,
|
||||
// end2 is '>' or both are
|
||||
// -1 if there is no ending tag for this one...
|
||||
// or -2 if this is ending tag </...>
|
||||
int End1, End2;
|
||||
|
||||
// name of this tag
|
||||
wxChar *Name;
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_CLASS(wxHtmlTagsCache,wxObject)
|
||||
|
||||
#define CACHE_INCREMENT 64
|
||||
|
||||
bool wxIsCDATAElement(const wxChar *tag)
|
||||
{
|
||||
return (wxStrcmp(tag, _T("SCRIPT")) == 0) ||
|
||||
(wxStrcmp(tag, _T("STYLE")) == 0);
|
||||
}
|
||||
|
||||
wxHtmlTagsCache::wxHtmlTagsCache(const wxString& source)
|
||||
{
|
||||
const wxChar *src = source.c_str();
|
||||
int lng = source.length();
|
||||
wxChar tagBuffer[256];
|
||||
|
||||
m_Cache = NULL;
|
||||
m_CacheSize = 0;
|
||||
m_CachePos = 0;
|
||||
|
||||
int pos = 0;
|
||||
while (pos < lng)
|
||||
{
|
||||
if (src[pos] == wxT('<')) // tag found:
|
||||
{
|
||||
if (m_CacheSize % CACHE_INCREMENT == 0)
|
||||
m_Cache = (wxHtmlCacheItem*) realloc(m_Cache, (m_CacheSize + CACHE_INCREMENT) * sizeof(wxHtmlCacheItem));
|
||||
int tg = m_CacheSize++;
|
||||
int stpos = pos++;
|
||||
m_Cache[tg].Key = stpos;
|
||||
|
||||
int i;
|
||||
for ( i = 0;
|
||||
pos < lng && i < (int)WXSIZEOF(tagBuffer) - 1 &&
|
||||
src[pos] != wxT('>') && !wxIsspace(src[pos]);
|
||||
i++, pos++ )
|
||||
{
|
||||
tagBuffer[i] = (wxChar)wxToupper(src[pos]);
|
||||
}
|
||||
tagBuffer[i] = _T('\0');
|
||||
|
||||
m_Cache[tg].Name = new wxChar[i+1];
|
||||
memcpy(m_Cache[tg].Name, tagBuffer, (i+1)*sizeof(wxChar));
|
||||
|
||||
while (pos < lng && src[pos] != wxT('>')) pos++;
|
||||
|
||||
if (src[stpos+1] == wxT('/')) // ending tag:
|
||||
{
|
||||
m_Cache[tg].End1 = m_Cache[tg].End2 = -2;
|
||||
// find matching begin tag:
|
||||
for (i = tg; i >= 0; i--)
|
||||
if ((m_Cache[i].End1 == -1) && (wxStrcmp(m_Cache[i].Name, tagBuffer+1) == 0))
|
||||
{
|
||||
m_Cache[i].End1 = stpos;
|
||||
m_Cache[i].End2 = pos + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Cache[tg].End1 = m_Cache[tg].End2 = -1;
|
||||
|
||||
if (wxIsCDATAElement(tagBuffer))
|
||||
{
|
||||
// store the orig pos in case we are missing the closing
|
||||
// tag (see below)
|
||||
wxInt32 old_pos = pos;
|
||||
bool foundCloseTag = false;
|
||||
|
||||
// find next matching tag
|
||||
int tag_len = wxStrlen(tagBuffer);
|
||||
while (pos < lng)
|
||||
{
|
||||
// find the ending tag
|
||||
while (pos + 1 < lng &&
|
||||
(src[pos] != '<' || src[pos+1] != '/'))
|
||||
++pos;
|
||||
if (src[pos] == '<')
|
||||
++pos;
|
||||
|
||||
// see if it matches
|
||||
int match_pos = 0;
|
||||
while (pos < lng && match_pos < tag_len && src[pos] != '>' && src[pos] != '<') {
|
||||
// cast to wxChar needed to suppress warning in
|
||||
// Unicode build
|
||||
if ((wxChar)wxToupper(src[pos]) == tagBuffer[match_pos]) {
|
||||
++match_pos;
|
||||
}
|
||||
else if (src[pos] == wxT(' ') || src[pos] == wxT('\n') ||
|
||||
src[pos] == wxT('\r') || src[pos] == wxT('\t')) {
|
||||
// need to skip over these
|
||||
}
|
||||
else {
|
||||
match_pos = 0;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
|
||||
// found a match
|
||||
if (match_pos == tag_len)
|
||||
{
|
||||
pos = pos - tag_len - 3;
|
||||
foundCloseTag = true;
|
||||
break;
|
||||
}
|
||||
else // keep looking for the closing tag
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
if (!foundCloseTag)
|
||||
{
|
||||
// we didn't find closing tag; this means the markup
|
||||
// is incorrect and the best thing we can do is to
|
||||
// ignore the unclosed tag and continue parsing as if
|
||||
// it didn't exist:
|
||||
pos = old_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
// ok, we're done, now we'll free .Name members of cache - we don't need it anymore:
|
||||
for (int i = 0; i < m_CacheSize; i++)
|
||||
{
|
||||
delete[] m_Cache[i].Name;
|
||||
m_Cache[i].Name = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void wxHtmlTagsCache::QueryTag(int at, int* end1, int* end2)
|
||||
{
|
||||
if (m_Cache == NULL) return;
|
||||
if (m_Cache[m_CachePos].Key != at)
|
||||
{
|
||||
int delta = (at < m_Cache[m_CachePos].Key) ? -1 : 1;
|
||||
do
|
||||
{
|
||||
if ( m_CachePos < 0 || m_CachePos == m_CacheSize )
|
||||
{
|
||||
// something is very wrong with HTML, give up by returning an
|
||||
// impossibly large value which is going to be ignored by the
|
||||
// caller
|
||||
*end1 =
|
||||
*end2 = INT_MAX;
|
||||
return;
|
||||
}
|
||||
|
||||
m_CachePos += delta;
|
||||
}
|
||||
while (m_Cache[m_CachePos].Key != at);
|
||||
}
|
||||
*end1 = m_Cache[m_CachePos].End1;
|
||||
*end2 = m_Cache[m_CachePos].End2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlTag
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CLASS(wxHtmlTag,wxObject)
|
||||
|
||||
wxHtmlTag::wxHtmlTag(wxHtmlTag *parent,
|
||||
const wxString& source, int pos, int end_pos,
|
||||
wxHtmlTagsCache *cache,
|
||||
wxHtmlEntitiesParser *entParser) : wxObject()
|
||||
{
|
||||
/* Setup DOM relations */
|
||||
|
||||
m_Next = NULL;
|
||||
m_FirstChild = m_LastChild = NULL;
|
||||
m_Parent = parent;
|
||||
if (parent)
|
||||
{
|
||||
m_Prev = m_Parent->m_LastChild;
|
||||
if (m_Prev == NULL)
|
||||
m_Parent->m_FirstChild = this;
|
||||
else
|
||||
m_Prev->m_Next = this;
|
||||
m_Parent->m_LastChild = this;
|
||||
}
|
||||
else
|
||||
m_Prev = NULL;
|
||||
|
||||
/* Find parameters and their values: */
|
||||
|
||||
int i;
|
||||
wxChar c;
|
||||
|
||||
// fill-in name, params and begin pos:
|
||||
i = pos+1;
|
||||
|
||||
// find tag's name and convert it to uppercase:
|
||||
while ((i < end_pos) &&
|
||||
((c = source[i++]) != wxT(' ') && c != wxT('\r') &&
|
||||
c != wxT('\n') && c != wxT('\t') &&
|
||||
c != wxT('>')))
|
||||
{
|
||||
if ((c >= wxT('a')) && (c <= wxT('z')))
|
||||
c -= (wxT('a') - wxT('A'));
|
||||
m_Name << c;
|
||||
}
|
||||
|
||||
// if the tag has parameters, read them and "normalize" them,
|
||||
// i.e. convert to uppercase, replace whitespaces by spaces and
|
||||
// remove whitespaces around '=':
|
||||
if (source[i-1] != wxT('>'))
|
||||
{
|
||||
#define IS_WHITE(c) (c == wxT(' ') || c == wxT('\r') || \
|
||||
c == wxT('\n') || c == wxT('\t'))
|
||||
wxString pname, pvalue;
|
||||
wxChar quote;
|
||||
enum
|
||||
{
|
||||
ST_BEFORE_NAME = 1,
|
||||
ST_NAME,
|
||||
ST_BEFORE_EQ,
|
||||
ST_BEFORE_VALUE,
|
||||
ST_VALUE
|
||||
} state;
|
||||
|
||||
quote = 0;
|
||||
state = ST_BEFORE_NAME;
|
||||
while (i < end_pos)
|
||||
{
|
||||
c = source[i++];
|
||||
|
||||
if (c == wxT('>') && !(state == ST_VALUE && quote != 0))
|
||||
{
|
||||
if (state == ST_BEFORE_EQ || state == ST_NAME)
|
||||
{
|
||||
m_ParamNames.Add(pname);
|
||||
m_ParamValues.Add(wxEmptyString);
|
||||
}
|
||||
else if (state == ST_VALUE && quote == 0)
|
||||
{
|
||||
m_ParamNames.Add(pname);
|
||||
if (entParser)
|
||||
m_ParamValues.Add(entParser->Parse(pvalue));
|
||||
else
|
||||
m_ParamValues.Add(pvalue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch (state)
|
||||
{
|
||||
case ST_BEFORE_NAME:
|
||||
if (!IS_WHITE(c))
|
||||
{
|
||||
pname = c;
|
||||
state = ST_NAME;
|
||||
}
|
||||
break;
|
||||
case ST_NAME:
|
||||
if (IS_WHITE(c))
|
||||
state = ST_BEFORE_EQ;
|
||||
else if (c == wxT('='))
|
||||
state = ST_BEFORE_VALUE;
|
||||
else
|
||||
pname << c;
|
||||
break;
|
||||
case ST_BEFORE_EQ:
|
||||
if (c == wxT('='))
|
||||
state = ST_BEFORE_VALUE;
|
||||
else if (!IS_WHITE(c))
|
||||
{
|
||||
m_ParamNames.Add(pname);
|
||||
m_ParamValues.Add(wxEmptyString);
|
||||
pname = c;
|
||||
state = ST_NAME;
|
||||
}
|
||||
break;
|
||||
case ST_BEFORE_VALUE:
|
||||
if (!IS_WHITE(c))
|
||||
{
|
||||
if (c == wxT('"') || c == wxT('\''))
|
||||
quote = c, pvalue = wxEmptyString;
|
||||
else
|
||||
quote = 0, pvalue = c;
|
||||
state = ST_VALUE;
|
||||
}
|
||||
break;
|
||||
case ST_VALUE:
|
||||
if ((quote != 0 && c == quote) ||
|
||||
(quote == 0 && IS_WHITE(c)))
|
||||
{
|
||||
m_ParamNames.Add(pname);
|
||||
if (quote == 0)
|
||||
{
|
||||
// VS: backward compatibility, no real reason,
|
||||
// but wxHTML code relies on this... :(
|
||||
pvalue.MakeUpper();
|
||||
}
|
||||
if (entParser)
|
||||
m_ParamValues.Add(entParser->Parse(pvalue));
|
||||
else
|
||||
m_ParamValues.Add(pvalue);
|
||||
state = ST_BEFORE_NAME;
|
||||
}
|
||||
else
|
||||
pvalue << c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#undef IS_WHITE
|
||||
}
|
||||
m_Begin = i;
|
||||
|
||||
cache->QueryTag(pos, &m_End1, &m_End2);
|
||||
if (m_End1 > end_pos) m_End1 = end_pos;
|
||||
if (m_End2 > end_pos) m_End2 = end_pos;
|
||||
}
|
||||
|
||||
wxHtmlTag::~wxHtmlTag()
|
||||
{
|
||||
wxHtmlTag *t1, *t2;
|
||||
t1 = m_FirstChild;
|
||||
while (t1)
|
||||
{
|
||||
t2 = t1->GetNextSibling();
|
||||
delete t1;
|
||||
t1 = t2;
|
||||
}
|
||||
}
|
||||
|
||||
bool wxHtmlTag::HasParam(const wxString& par) const
|
||||
{
|
||||
return (m_ParamNames.Index(par, false) != wxNOT_FOUND);
|
||||
}
|
||||
|
||||
wxString wxHtmlTag::GetParam(const wxString& par, bool with_commas) const
|
||||
{
|
||||
int index = m_ParamNames.Index(par, false);
|
||||
if (index == wxNOT_FOUND)
|
||||
return wxEmptyString;
|
||||
if (with_commas)
|
||||
{
|
||||
// VS: backward compatibility, seems to be never used by wxHTML...
|
||||
wxString s;
|
||||
s << wxT('"') << m_ParamValues[index] << wxT('"');
|
||||
return s;
|
||||
}
|
||||
else
|
||||
return m_ParamValues[index];
|
||||
}
|
||||
|
||||
int wxHtmlTag::ScanParam(const wxString& par,
|
||||
const wxChar *format,
|
||||
void *param) const
|
||||
{
|
||||
wxString parval = GetParam(par);
|
||||
return wxSscanf(parval, format, param);
|
||||
}
|
||||
|
||||
bool wxHtmlTag::GetParamAsColour(const wxString& par, wxColour *clr) const
|
||||
{
|
||||
wxCHECK_MSG( clr, false, _T("invalid colour argument") );
|
||||
|
||||
wxString str = GetParam(par);
|
||||
|
||||
// handle colours defined in HTML 4.0 first:
|
||||
if (str.length() > 1 && str[0] != _T('#'))
|
||||
{
|
||||
#define HTML_COLOUR(name, r, g, b) \
|
||||
if (str.IsSameAs(wxT(name), false)) \
|
||||
{ clr->Set(r, g, b); return true; }
|
||||
HTML_COLOUR("black", 0x00,0x00,0x00)
|
||||
HTML_COLOUR("silver", 0xC0,0xC0,0xC0)
|
||||
HTML_COLOUR("gray", 0x80,0x80,0x80)
|
||||
HTML_COLOUR("white", 0xFF,0xFF,0xFF)
|
||||
HTML_COLOUR("maroon", 0x80,0x00,0x00)
|
||||
HTML_COLOUR("red", 0xFF,0x00,0x00)
|
||||
HTML_COLOUR("purple", 0x80,0x00,0x80)
|
||||
HTML_COLOUR("fuchsia", 0xFF,0x00,0xFF)
|
||||
HTML_COLOUR("green", 0x00,0x80,0x00)
|
||||
HTML_COLOUR("lime", 0x00,0xFF,0x00)
|
||||
HTML_COLOUR("olive", 0x80,0x80,0x00)
|
||||
HTML_COLOUR("yellow", 0xFF,0xFF,0x00)
|
||||
HTML_COLOUR("navy", 0x00,0x00,0x80)
|
||||
HTML_COLOUR("blue", 0x00,0x00,0xFF)
|
||||
HTML_COLOUR("teal", 0x00,0x80,0x80)
|
||||
HTML_COLOUR("aqua", 0x00,0xFF,0xFF)
|
||||
#undef HTML_COLOUR
|
||||
}
|
||||
|
||||
// then try to parse #rrggbb representations or set from other well
|
||||
// known names (note that this doesn't strictly conform to HTML spec,
|
||||
// but it doesn't do real harm -- but it *must* be done after the standard
|
||||
// colors are handled above):
|
||||
if (clr->Set(str))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxHtmlTag::GetParamAsInt(const wxString& par, int *clr) const
|
||||
{
|
||||
if ( !HasParam(par) )
|
||||
return false;
|
||||
|
||||
long i;
|
||||
if ( !GetParam(par).ToLong(&i) )
|
||||
return false;
|
||||
|
||||
*clr = (int)i;
|
||||
return true;
|
||||
}
|
||||
|
||||
wxString wxHtmlTag::GetAllParams() const
|
||||
{
|
||||
// VS: this function is for backward compatibility only,
|
||||
// never used by wxHTML
|
||||
wxString s;
|
||||
size_t cnt = m_ParamNames.GetCount();
|
||||
for (size_t i = 0; i < cnt; i++)
|
||||
{
|
||||
s << m_ParamNames[i];
|
||||
s << wxT('=');
|
||||
if (m_ParamValues[i].Find(wxT('"')) != wxNOT_FOUND)
|
||||
s << wxT('\'') << m_ParamValues[i] << wxT('\'');
|
||||
else
|
||||
s << wxT('"') << m_ParamValues[i] << wxT('"');
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
wxHtmlTag *wxHtmlTag::GetFirstSibling() const
|
||||
{
|
||||
if (m_Parent)
|
||||
return m_Parent->m_FirstChild;
|
||||
else
|
||||
{
|
||||
wxHtmlTag *cur = (wxHtmlTag*)this;
|
||||
while (cur->m_Prev)
|
||||
cur = cur->m_Prev;
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
|
||||
wxHtmlTag *wxHtmlTag::GetLastSibling() const
|
||||
{
|
||||
if (m_Parent)
|
||||
return m_Parent->m_LastChild;
|
||||
else
|
||||
{
|
||||
wxHtmlTag *cur = (wxHtmlTag*)this;
|
||||
while (cur->m_Next)
|
||||
cur = cur->m_Next;
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
|
||||
wxHtmlTag *wxHtmlTag::GetNextTag() const
|
||||
{
|
||||
if (m_FirstChild) return m_FirstChild;
|
||||
if (m_Next) return m_Next;
|
||||
wxHtmlTag *cur = m_Parent;
|
||||
if (!cur) return NULL;
|
||||
while (cur->m_Parent && !cur->m_Next)
|
||||
cur = cur->m_Parent;
|
||||
return cur->m_Next;
|
||||
}
|
||||
|
||||
#endif
|
1683
wxWidgets/src/html/htmlwin.cpp
Normal file
1683
wxWidgets/src/html/htmlwin.cpp
Normal file
File diff suppressed because it is too large
Load diff
728
wxWidgets/src/html/htmprint.cpp
Normal file
728
wxWidgets/src/html/htmprint.cpp
Normal file
|
@ -0,0 +1,728 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/htmprint.cpp
|
||||
// Purpose: html printing classes
|
||||
// Author: Vaclav Slavik
|
||||
// Created: 25/09/99
|
||||
// RCS-ID: $Id: htmprint.cpp 55069 2008-08-12 16:02:31Z VS $
|
||||
// Copyright: (c) Vaclav Slavik, 1999
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_PRINTING_ARCHITECTURE && wxUSE_STREAMS
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/log.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/dc.h"
|
||||
#include "wx/settings.h"
|
||||
#include "wx/msgdlg.h"
|
||||
#include "wx/module.h"
|
||||
#endif
|
||||
|
||||
#include "wx/print.h"
|
||||
#include "wx/printdlg.h"
|
||||
#include "wx/html/htmprint.h"
|
||||
#include "wx/wxhtml.h"
|
||||
#include "wx/wfstream.h"
|
||||
|
||||
|
||||
// default font size of normal text (HTML font size 0) for printing, in points:
|
||||
#define DEFAULT_PRINT_FONT_SIZE 12
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// wxHtmlDCRenderer
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
wxHtmlDCRenderer::wxHtmlDCRenderer() : wxObject()
|
||||
{
|
||||
m_DC = NULL;
|
||||
m_Width = m_Height = 0;
|
||||
m_Cells = NULL;
|
||||
m_Parser = new wxHtmlWinParser();
|
||||
m_FS = new wxFileSystem();
|
||||
m_Parser->SetFS(m_FS);
|
||||
SetStandardFonts(DEFAULT_PRINT_FONT_SIZE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxHtmlDCRenderer::~wxHtmlDCRenderer()
|
||||
{
|
||||
if (m_Cells) delete m_Cells;
|
||||
if (m_Parser) delete m_Parser;
|
||||
if (m_FS) delete m_FS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlDCRenderer::SetDC(wxDC *dc, double pixel_scale)
|
||||
{
|
||||
m_DC = dc;
|
||||
m_Parser->SetDC(m_DC, pixel_scale);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlDCRenderer::SetSize(int width, int height)
|
||||
{
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
}
|
||||
|
||||
|
||||
void wxHtmlDCRenderer::SetHtmlText(const wxString& html, const wxString& basepath, bool isdir)
|
||||
{
|
||||
if (m_DC == NULL) return;
|
||||
|
||||
if (m_Cells != NULL) delete m_Cells;
|
||||
|
||||
m_FS->ChangePathTo(basepath, isdir);
|
||||
m_Cells = (wxHtmlContainerCell*) m_Parser->Parse(html);
|
||||
m_Cells->SetIndent(0, wxHTML_INDENT_ALL, wxHTML_UNITS_PIXELS);
|
||||
m_Cells->Layout(m_Width);
|
||||
}
|
||||
|
||||
|
||||
void wxHtmlDCRenderer::SetFonts(const wxString& normal_face, const wxString& fixed_face,
|
||||
const int *sizes)
|
||||
{
|
||||
m_Parser->SetFonts(normal_face, fixed_face, sizes);
|
||||
if (m_DC == NULL && m_Cells != NULL)
|
||||
m_Cells->Layout(m_Width);
|
||||
}
|
||||
|
||||
void wxHtmlDCRenderer::SetStandardFonts(int size,
|
||||
const wxString& normal_face,
|
||||
const wxString& fixed_face)
|
||||
{
|
||||
m_Parser->SetStandardFonts(size, normal_face, fixed_face);
|
||||
if (m_DC == NULL && m_Cells != NULL)
|
||||
m_Cells->Layout(m_Width);
|
||||
}
|
||||
|
||||
int wxHtmlDCRenderer::Render(int x, int y,
|
||||
wxArrayInt& known_pagebreaks,
|
||||
int from, int dont_render, int to)
|
||||
{
|
||||
int pbreak, hght;
|
||||
|
||||
if (m_Cells == NULL || m_DC == NULL) return 0;
|
||||
|
||||
pbreak = (int)(from + m_Height);
|
||||
while (m_Cells->AdjustPagebreak(&pbreak, known_pagebreaks)) {}
|
||||
hght = pbreak - from;
|
||||
if(to < hght)
|
||||
hght = to;
|
||||
|
||||
if (!dont_render)
|
||||
{
|
||||
wxHtmlRenderingInfo rinfo;
|
||||
wxDefaultHtmlRenderingStyle rstyle;
|
||||
rinfo.SetStyle(&rstyle);
|
||||
m_DC->SetBrush(*wxWHITE_BRUSH);
|
||||
m_DC->SetClippingRegion(x, y, m_Width, hght);
|
||||
m_Cells->Draw(*m_DC,
|
||||
x, (y - from),
|
||||
y, y + hght,
|
||||
rinfo);
|
||||
m_DC->DestroyClippingRegion();
|
||||
}
|
||||
|
||||
if (pbreak < m_Cells->GetHeight()) return pbreak;
|
||||
else return GetTotalHeight();
|
||||
}
|
||||
|
||||
|
||||
int wxHtmlDCRenderer::GetTotalHeight()
|
||||
{
|
||||
if (m_Cells) return m_Cells->GetHeight();
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// wxHtmlPrintout
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
wxList wxHtmlPrintout::m_Filters;
|
||||
|
||||
wxHtmlPrintout::wxHtmlPrintout(const wxString& title) : wxPrintout(title)
|
||||
{
|
||||
m_Renderer = new wxHtmlDCRenderer;
|
||||
m_RendererHdr = new wxHtmlDCRenderer;
|
||||
m_NumPages = wxHTML_PRINT_MAX_PAGES;
|
||||
m_Document = m_BasePath = wxEmptyString; m_BasePathIsDir = true;
|
||||
m_Headers[0] = m_Headers[1] = wxEmptyString;
|
||||
m_Footers[0] = m_Footers[1] = wxEmptyString;
|
||||
m_HeaderHeight = m_FooterHeight = 0;
|
||||
SetMargins(); // to default values
|
||||
SetStandardFonts(DEFAULT_PRINT_FONT_SIZE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxHtmlPrintout::~wxHtmlPrintout()
|
||||
{
|
||||
delete m_Renderer;
|
||||
delete m_RendererHdr;
|
||||
}
|
||||
|
||||
void wxHtmlPrintout::CleanUpStatics()
|
||||
{
|
||||
WX_CLEAR_LIST(wxList, m_Filters);
|
||||
}
|
||||
|
||||
// Adds input filter
|
||||
void wxHtmlPrintout::AddFilter(wxHtmlFilter *filter)
|
||||
{
|
||||
m_Filters.Append(filter);
|
||||
}
|
||||
|
||||
void wxHtmlPrintout::OnPreparePrinting()
|
||||
{
|
||||
int pageWidth, pageHeight, mm_w, mm_h, scr_w, scr_h, dc_w, dc_h;
|
||||
float ppmm_h, ppmm_v;
|
||||
|
||||
GetPageSizePixels(&pageWidth, &pageHeight);
|
||||
GetPageSizeMM(&mm_w, &mm_h);
|
||||
ppmm_h = (float)pageWidth / mm_w;
|
||||
ppmm_v = (float)pageHeight / mm_h;
|
||||
|
||||
int ppiPrinterX, ppiPrinterY;
|
||||
GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
|
||||
int ppiScreenX, ppiScreenY;
|
||||
GetPPIScreen(&ppiScreenX, &ppiScreenY);
|
||||
|
||||
wxDisplaySize(&scr_w, &scr_h);
|
||||
GetDC()->GetSize(&dc_w, &dc_h);
|
||||
|
||||
GetDC()->SetUserScale((double)dc_w / (double)pageWidth,
|
||||
(double)dc_h / (double)pageHeight);
|
||||
|
||||
/* prepare headers/footers renderer: */
|
||||
|
||||
m_RendererHdr->SetDC(GetDC(), (double)ppiPrinterY / (double)ppiScreenY);
|
||||
m_RendererHdr->SetSize((int) (ppmm_h * (mm_w - m_MarginLeft - m_MarginRight)),
|
||||
(int) (ppmm_v * (mm_h - m_MarginTop - m_MarginBottom)));
|
||||
if (m_Headers[0] != wxEmptyString)
|
||||
{
|
||||
m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[0], 1));
|
||||
m_HeaderHeight = m_RendererHdr->GetTotalHeight();
|
||||
}
|
||||
else if (m_Headers[1] != wxEmptyString)
|
||||
{
|
||||
m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[1], 1));
|
||||
m_HeaderHeight = m_RendererHdr->GetTotalHeight();
|
||||
}
|
||||
if (m_Footers[0] != wxEmptyString)
|
||||
{
|
||||
m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[0], 1));
|
||||
m_FooterHeight = m_RendererHdr->GetTotalHeight();
|
||||
}
|
||||
else if (m_Footers[1] != wxEmptyString)
|
||||
{
|
||||
m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[1], 1));
|
||||
m_FooterHeight = m_RendererHdr->GetTotalHeight();
|
||||
}
|
||||
|
||||
/* prepare main renderer: */
|
||||
m_Renderer->SetDC(GetDC(), (double)ppiPrinterY / (double)ppiScreenY);
|
||||
m_Renderer->SetSize((int) (ppmm_h * (mm_w - m_MarginLeft - m_MarginRight)),
|
||||
(int) (ppmm_v * (mm_h - m_MarginTop - m_MarginBottom) -
|
||||
m_FooterHeight - m_HeaderHeight -
|
||||
((m_HeaderHeight == 0) ? 0 : m_MarginSpace * ppmm_v) -
|
||||
((m_FooterHeight == 0) ? 0 : m_MarginSpace * ppmm_v)
|
||||
));
|
||||
m_Renderer->SetHtmlText(m_Document, m_BasePath, m_BasePathIsDir);
|
||||
CountPages();
|
||||
}
|
||||
|
||||
bool wxHtmlPrintout::OnBeginDocument(int startPage, int endPage)
|
||||
{
|
||||
if (!wxPrintout::OnBeginDocument(startPage, endPage)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool wxHtmlPrintout::OnPrintPage(int page)
|
||||
{
|
||||
wxDC *dc = GetDC();
|
||||
if (dc && dc->Ok())
|
||||
{
|
||||
if (HasPage(page))
|
||||
RenderPage(dc, page);
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
|
||||
void wxHtmlPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
|
||||
{
|
||||
*minPage = 1;
|
||||
if ( m_NumPages >= (signed)m_PageBreaks.Count()-1)
|
||||
*maxPage = m_NumPages;
|
||||
else
|
||||
*maxPage = (signed)m_PageBreaks.Count()-1;
|
||||
*selPageFrom = 1;
|
||||
*selPageTo = (signed)m_PageBreaks.Count()-1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool wxHtmlPrintout::HasPage(int pageNum)
|
||||
{
|
||||
return pageNum > 0 && (unsigned)pageNum < m_PageBreaks.Count();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlPrintout::SetHtmlText(const wxString& html, const wxString &basepath, bool isdir)
|
||||
{
|
||||
m_Document = html;
|
||||
m_BasePath = basepath;
|
||||
m_BasePathIsDir = isdir;
|
||||
}
|
||||
|
||||
void wxHtmlPrintout::SetHtmlFile(const wxString& htmlfile)
|
||||
{
|
||||
wxFileSystem fs;
|
||||
wxFSFile *ff;
|
||||
|
||||
if (wxFileExists(htmlfile))
|
||||
ff = fs.OpenFile(wxFileSystem::FileNameToURL(htmlfile));
|
||||
else
|
||||
ff = fs.OpenFile(htmlfile);
|
||||
|
||||
if (ff == NULL)
|
||||
{
|
||||
wxLogError(htmlfile + _(": file does not exist!"));
|
||||
return;
|
||||
}
|
||||
|
||||
bool done = false;
|
||||
wxHtmlFilterHTML defaultFilter;
|
||||
wxString doc;
|
||||
|
||||
wxList::compatibility_iterator node = m_Filters.GetFirst();
|
||||
while (node)
|
||||
{
|
||||
wxHtmlFilter *h = (wxHtmlFilter*) node->GetData();
|
||||
if (h->CanRead(*ff))
|
||||
{
|
||||
doc = h->ReadFile(*ff);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
node = node->GetNext();
|
||||
}
|
||||
|
||||
if (!done)
|
||||
doc = defaultFilter.ReadFile(*ff);
|
||||
|
||||
SetHtmlText(doc, htmlfile, false);
|
||||
delete ff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlPrintout::SetHeader(const wxString& header, int pg)
|
||||
{
|
||||
if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
|
||||
m_Headers[0] = header;
|
||||
if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
|
||||
m_Headers[1] = header;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlPrintout::SetFooter(const wxString& footer, int pg)
|
||||
{
|
||||
if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
|
||||
m_Footers[0] = footer;
|
||||
if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
|
||||
m_Footers[1] = footer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlPrintout::CountPages()
|
||||
{
|
||||
wxBusyCursor wait;
|
||||
int pageWidth, pageHeight, mm_w, mm_h;
|
||||
float ppmm_h, ppmm_v;
|
||||
|
||||
GetPageSizePixels(&pageWidth, &pageHeight);
|
||||
GetPageSizeMM(&mm_w, &mm_h);
|
||||
ppmm_h = (float)pageWidth / mm_w;
|
||||
ppmm_v = (float)pageHeight / mm_h;
|
||||
|
||||
int pos = 0;
|
||||
m_NumPages = 0;
|
||||
// m_PageBreaks[0] = 0;
|
||||
|
||||
m_PageBreaks.Clear();
|
||||
m_PageBreaks.Add( 0);
|
||||
do
|
||||
{
|
||||
pos = m_Renderer->Render((int)( ppmm_h * m_MarginLeft),
|
||||
(int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight),
|
||||
m_PageBreaks,
|
||||
pos, true, INT_MAX);
|
||||
m_PageBreaks.Add( pos);
|
||||
if( m_PageBreaks.Count() > wxHTML_PRINT_MAX_PAGES)
|
||||
{
|
||||
wxMessageBox( _("HTML pagination algorithm generated more than the allowed maximum number of pages and it can't continue any longer!"),
|
||||
_("Warning"), wxCANCEL | wxICON_ERROR );
|
||||
break;
|
||||
}
|
||||
} while (pos < m_Renderer->GetTotalHeight());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlPrintout::RenderPage(wxDC *dc, int page)
|
||||
{
|
||||
wxBusyCursor wait;
|
||||
|
||||
int pageWidth, pageHeight, mm_w, mm_h, scr_w, scr_h, dc_w, dc_h;
|
||||
float ppmm_h, ppmm_v;
|
||||
|
||||
GetPageSizePixels(&pageWidth, &pageHeight);
|
||||
GetPageSizeMM(&mm_w, &mm_h);
|
||||
ppmm_h = (float)pageWidth / mm_w;
|
||||
ppmm_v = (float)pageHeight / mm_h;
|
||||
wxDisplaySize(&scr_w, &scr_h);
|
||||
dc->GetSize(&dc_w, &dc_h);
|
||||
|
||||
int ppiPrinterX, ppiPrinterY;
|
||||
GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
|
||||
wxUnusedVar(ppiPrinterX);
|
||||
int ppiScreenX, ppiScreenY;
|
||||
GetPPIScreen(&ppiScreenX, &ppiScreenY);
|
||||
wxUnusedVar(ppiScreenX);
|
||||
|
||||
dc->SetUserScale((double)dc_w / (double)pageWidth,
|
||||
(double)dc_h / (double)pageHeight);
|
||||
|
||||
m_Renderer->SetDC(dc, (double)ppiPrinterY / (double)ppiScreenY);
|
||||
|
||||
dc->SetBackgroundMode(wxTRANSPARENT);
|
||||
|
||||
m_Renderer->Render((int) (ppmm_h * m_MarginLeft),
|
||||
(int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight), m_PageBreaks,
|
||||
m_PageBreaks[page-1], false, m_PageBreaks[page]-m_PageBreaks[page-1]);
|
||||
|
||||
|
||||
m_RendererHdr->SetDC(dc, (double)ppiPrinterY / (double)ppiScreenY);
|
||||
if (m_Headers[page % 2] != wxEmptyString)
|
||||
{
|
||||
m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[page % 2], page));
|
||||
m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (ppmm_v * m_MarginTop), m_PageBreaks);
|
||||
}
|
||||
if (m_Footers[page % 2] != wxEmptyString)
|
||||
{
|
||||
m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[page % 2], page));
|
||||
m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (pageHeight - ppmm_v * m_MarginBottom - m_FooterHeight), m_PageBreaks);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxString wxHtmlPrintout::TranslateHeader(const wxString& instr, int page)
|
||||
{
|
||||
wxString r = instr;
|
||||
wxString num;
|
||||
|
||||
num.Printf(wxT("%i"), page);
|
||||
r.Replace(wxT("@PAGENUM@"), num);
|
||||
|
||||
num.Printf(wxT("%lu"), (unsigned long)(m_PageBreaks.Count() - 1));
|
||||
r.Replace(wxT("@PAGESCNT@"), num);
|
||||
|
||||
const wxDateTime now = wxDateTime::Now();
|
||||
r.Replace(wxT("@DATE@"), now.FormatDate());
|
||||
r.Replace(wxT("@TIME@"), now.FormatTime());
|
||||
|
||||
r.Replace(wxT("@TITLE@"), GetTitle());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlPrintout::SetMargins(float top, float bottom, float left, float right, float spaces)
|
||||
{
|
||||
m_MarginTop = top;
|
||||
m_MarginBottom = bottom;
|
||||
m_MarginLeft = left;
|
||||
m_MarginRight = right;
|
||||
m_MarginSpace = spaces;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void wxHtmlPrintout::SetFonts(const wxString& normal_face, const wxString& fixed_face,
|
||||
const int *sizes)
|
||||
{
|
||||
m_Renderer->SetFonts(normal_face, fixed_face, sizes);
|
||||
m_RendererHdr->SetFonts(normal_face, fixed_face, sizes);
|
||||
}
|
||||
|
||||
void wxHtmlPrintout::SetStandardFonts(int size,
|
||||
const wxString& normal_face,
|
||||
const wxString& fixed_face)
|
||||
{
|
||||
m_Renderer->SetStandardFonts(size, normal_face, fixed_face);
|
||||
m_RendererHdr->SetStandardFonts(size, normal_face, fixed_face);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// wxHtmlEasyPrinting
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
wxHtmlEasyPrinting::wxHtmlEasyPrinting(const wxString& name, wxWindow *parentWindow)
|
||||
{
|
||||
m_ParentWindow = parentWindow;
|
||||
m_Name = name;
|
||||
m_PrintData = NULL;
|
||||
m_PageSetupData = new wxPageSetupDialogData;
|
||||
m_Headers[0] = m_Headers[1] = m_Footers[0] = m_Footers[1] = wxEmptyString;
|
||||
|
||||
m_PageSetupData->EnableMargins(true);
|
||||
m_PageSetupData->SetMarginTopLeft(wxPoint(25, 25));
|
||||
m_PageSetupData->SetMarginBottomRight(wxPoint(25, 25));
|
||||
|
||||
SetStandardFonts(DEFAULT_PRINT_FONT_SIZE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxHtmlEasyPrinting::~wxHtmlEasyPrinting()
|
||||
{
|
||||
delete m_PrintData;
|
||||
delete m_PageSetupData;
|
||||
}
|
||||
|
||||
|
||||
wxPrintData *wxHtmlEasyPrinting::GetPrintData()
|
||||
{
|
||||
if (m_PrintData == NULL)
|
||||
m_PrintData = new wxPrintData();
|
||||
return m_PrintData;
|
||||
}
|
||||
|
||||
|
||||
bool wxHtmlEasyPrinting::PreviewFile(const wxString &htmlfile)
|
||||
{
|
||||
wxHtmlPrintout *p1 = CreatePrintout();
|
||||
p1->SetHtmlFile(htmlfile);
|
||||
wxHtmlPrintout *p2 = CreatePrintout();
|
||||
p2->SetHtmlFile(htmlfile);
|
||||
return DoPreview(p1, p2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool wxHtmlEasyPrinting::PreviewText(const wxString &htmltext, const wxString &basepath)
|
||||
{
|
||||
wxHtmlPrintout *p1 = CreatePrintout();
|
||||
p1->SetHtmlText(htmltext, basepath, true);
|
||||
wxHtmlPrintout *p2 = CreatePrintout();
|
||||
p2->SetHtmlText(htmltext, basepath, true);
|
||||
return DoPreview(p1, p2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool wxHtmlEasyPrinting::PrintFile(const wxString &htmlfile)
|
||||
{
|
||||
wxHtmlPrintout *p = CreatePrintout();
|
||||
p->SetHtmlFile(htmlfile);
|
||||
bool ret = DoPrint(p);
|
||||
delete p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool wxHtmlEasyPrinting::PrintText(const wxString &htmltext, const wxString &basepath)
|
||||
{
|
||||
wxHtmlPrintout *p = CreatePrintout();
|
||||
p->SetHtmlText(htmltext, basepath, true);
|
||||
bool ret = DoPrint(p);
|
||||
delete p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool wxHtmlEasyPrinting::DoPreview(wxHtmlPrintout *printout1, wxHtmlPrintout *printout2)
|
||||
{
|
||||
// Pass two printout objects: for preview, and possible printing.
|
||||
wxPrintDialogData printDialogData(*GetPrintData());
|
||||
wxPrintPreview *preview = new wxPrintPreview(printout1, printout2, &printDialogData);
|
||||
if (!preview->Ok())
|
||||
{
|
||||
delete preview;
|
||||
return false;
|
||||
}
|
||||
|
||||
wxPreviewFrame *frame = new wxPreviewFrame(preview, m_ParentWindow,
|
||||
m_Name + _(" Preview"),
|
||||
wxPoint(100, 100), wxSize(650, 500));
|
||||
frame->Centre(wxBOTH);
|
||||
frame->Initialize();
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool wxHtmlEasyPrinting::DoPrint(wxHtmlPrintout *printout)
|
||||
{
|
||||
wxPrintDialogData printDialogData(*GetPrintData());
|
||||
wxPrinter printer(&printDialogData);
|
||||
|
||||
if (!printer.Print(m_ParentWindow, printout, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
(*GetPrintData()) = printer.GetPrintDialogData().GetPrintData();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void wxHtmlEasyPrinting::PageSetup()
|
||||
{
|
||||
if (!GetPrintData()->Ok())
|
||||
{
|
||||
wxLogError(_("There was a problem during page setup: you may need to set a default printer."));
|
||||
return;
|
||||
}
|
||||
|
||||
m_PageSetupData->SetPrintData(*GetPrintData());
|
||||
wxPageSetupDialog pageSetupDialog(m_ParentWindow, m_PageSetupData);
|
||||
|
||||
if (pageSetupDialog.ShowModal() == wxID_OK)
|
||||
{
|
||||
(*GetPrintData()) = pageSetupDialog.GetPageSetupData().GetPrintData();
|
||||
(*m_PageSetupData) = pageSetupDialog.GetPageSetupData();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlEasyPrinting::SetHeader(const wxString& header, int pg)
|
||||
{
|
||||
if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
|
||||
m_Headers[0] = header;
|
||||
if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
|
||||
m_Headers[1] = header;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlEasyPrinting::SetFooter(const wxString& footer, int pg)
|
||||
{
|
||||
if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
|
||||
m_Footers[0] = footer;
|
||||
if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
|
||||
m_Footers[1] = footer;
|
||||
}
|
||||
|
||||
|
||||
void wxHtmlEasyPrinting::SetFonts(const wxString& normal_face, const wxString& fixed_face,
|
||||
const int *sizes)
|
||||
{
|
||||
m_fontMode = FontMode_Explicit;
|
||||
m_FontFaceNormal = normal_face;
|
||||
m_FontFaceFixed = fixed_face;
|
||||
|
||||
if (sizes)
|
||||
{
|
||||
m_FontsSizes = m_FontsSizesArr;
|
||||
for (int i = 0; i < 7; i++) m_FontsSizes[i] = sizes[i];
|
||||
}
|
||||
else
|
||||
m_FontsSizes = NULL;
|
||||
}
|
||||
|
||||
void wxHtmlEasyPrinting::SetStandardFonts(int size,
|
||||
const wxString& normal_face,
|
||||
const wxString& fixed_face)
|
||||
{
|
||||
m_fontMode = FontMode_Standard;
|
||||
m_FontFaceNormal = normal_face;
|
||||
m_FontFaceFixed = fixed_face;
|
||||
m_FontsSizesArr[0] = size;
|
||||
}
|
||||
|
||||
|
||||
wxHtmlPrintout *wxHtmlEasyPrinting::CreatePrintout()
|
||||
{
|
||||
wxHtmlPrintout *p = new wxHtmlPrintout(m_Name);
|
||||
|
||||
if (m_fontMode == FontMode_Explicit)
|
||||
{
|
||||
p->SetFonts(m_FontFaceNormal, m_FontFaceFixed, m_FontsSizes);
|
||||
}
|
||||
else // FontMode_Standard
|
||||
{
|
||||
p->SetStandardFonts(m_FontsSizesArr[0],
|
||||
m_FontFaceNormal, m_FontFaceFixed);
|
||||
}
|
||||
|
||||
p->SetHeader(m_Headers[0], wxPAGE_EVEN);
|
||||
p->SetHeader(m_Headers[1], wxPAGE_ODD);
|
||||
p->SetFooter(m_Footers[0], wxPAGE_EVEN);
|
||||
p->SetFooter(m_Footers[1], wxPAGE_ODD);
|
||||
|
||||
p->SetMargins(m_PageSetupData->GetMarginTopLeft().y,
|
||||
m_PageSetupData->GetMarginBottomRight().y,
|
||||
m_PageSetupData->GetMarginTopLeft().x,
|
||||
m_PageSetupData->GetMarginBottomRight().x);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// A module to allow initialization/cleanup
|
||||
// without calling these functions from app.cpp or from
|
||||
// the user's application.
|
||||
|
||||
class wxHtmlPrintingModule: public wxModule
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS(wxHtmlPrintingModule)
|
||||
public:
|
||||
wxHtmlPrintingModule() : wxModule() {}
|
||||
bool OnInit() { return true; }
|
||||
void OnExit() { wxHtmlPrintout::CleanUpStatics(); }
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxHtmlPrintingModule, wxModule)
|
||||
|
||||
|
||||
// This hack forces the linker to always link in m_* files
|
||||
// (wxHTML doesn't work without handlers from these files)
|
||||
#include "wx/html/forcelnk.h"
|
||||
FORCE_WXHTML_MODULES()
|
||||
|
||||
#endif // wxUSE_HTML & wxUSE_PRINTING_ARCHITECTURE
|
86
wxWidgets/src/html/m_dflist.cpp
Normal file
86
wxWidgets/src/html/m_dflist.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/m_dflist.cpp
|
||||
// Purpose: wxHtml module for definition lists (DL,DT,DD)
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: m_dflist.cpp 38788 2006-04-18 08:11:26Z ABX $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#endif
|
||||
|
||||
#include "wx/html/forcelnk.h"
|
||||
#include "wx/html/m_templ.h"
|
||||
|
||||
#include "wx/html/htmlcell.h"
|
||||
|
||||
FORCE_LINK_ME(m_dflist)
|
||||
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(DEFLIST, "DL,DT,DD" )
|
||||
|
||||
TAG_HANDLER_CONSTR(DEFLIST) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
wxHtmlContainerCell *c;
|
||||
|
||||
|
||||
if (tag.GetName() == wxT("DL"))
|
||||
{
|
||||
if (m_WParser->GetContainer()->GetFirstChild() != NULL)
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
}
|
||||
m_WParser->GetContainer()->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_TOP);
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
if (m_WParser->GetContainer()->GetFirstChild() != NULL)
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
}
|
||||
m_WParser->GetContainer()->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_TOP);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (tag.GetName() == wxT("DT"))
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
c = m_WParser->OpenContainer();
|
||||
c->SetAlignHor(wxHTML_ALIGN_LEFT);
|
||||
c->SetMinHeight(m_WParser->GetCharHeight());
|
||||
return false;
|
||||
}
|
||||
else // "DD"
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
c = m_WParser->OpenContainer();
|
||||
c->SetIndent(5 * m_WParser->GetCharWidth(), wxHTML_INDENT_LEFT);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(DEFLIST)
|
||||
|
||||
|
||||
TAGS_MODULE_BEGIN(DefinitionList)
|
||||
|
||||
TAGS_MODULE_ADD(DEFLIST)
|
||||
|
||||
TAGS_MODULE_END(DefinitionList)
|
||||
|
||||
#endif
|
322
wxWidgets/src/html/m_fonts.cpp
Normal file
322
wxWidgets/src/html/m_fonts.cpp
Normal file
|
@ -0,0 +1,322 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/m_fonts.cpp
|
||||
// Purpose: wxHtml module for fonts & colors of fonts
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: m_fonts.cpp 39371 2006-05-28 13:51:34Z VZ $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#endif
|
||||
|
||||
#include "wx/html/forcelnk.h"
|
||||
#include "wx/html/m_templ.h"
|
||||
#include "wx/fontenum.h"
|
||||
#include "wx/tokenzr.h"
|
||||
|
||||
FORCE_LINK_ME(m_fonts)
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(FONT, "FONT" )
|
||||
|
||||
TAG_HANDLER_VARS
|
||||
wxArrayString m_Faces;
|
||||
|
||||
TAG_HANDLER_CONSTR(FONT) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
wxColour oldclr = m_WParser->GetActualColor();
|
||||
int oldsize = m_WParser->GetFontSize();
|
||||
wxString oldface = m_WParser->GetFontFace();
|
||||
|
||||
if (tag.HasParam(wxT("COLOR")))
|
||||
{
|
||||
wxColour clr;
|
||||
if (tag.GetParamAsColour(wxT("COLOR"), &clr))
|
||||
{
|
||||
m_WParser->SetActualColor(clr);
|
||||
m_WParser->GetContainer()->InsertCell(new wxHtmlColourCell(clr));
|
||||
}
|
||||
}
|
||||
|
||||
if (tag.HasParam(wxT("SIZE")))
|
||||
{
|
||||
int tmp = 0;
|
||||
wxChar c = tag.GetParam(wxT("SIZE")).GetChar(0);
|
||||
if (tag.GetParamAsInt(wxT("SIZE"), &tmp))
|
||||
{
|
||||
if (c == wxT('+') || c == wxT('-'))
|
||||
m_WParser->SetFontSize(oldsize+tmp);
|
||||
else
|
||||
m_WParser->SetFontSize(tmp);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
}
|
||||
}
|
||||
|
||||
if (tag.HasParam(wxT("FACE")))
|
||||
{
|
||||
if (m_Faces.GetCount() == 0)
|
||||
m_Faces = wxFontEnumerator::GetFacenames();
|
||||
|
||||
wxStringTokenizer tk(tag.GetParam(wxT("FACE")), wxT(","));
|
||||
int index;
|
||||
|
||||
while (tk.HasMoreTokens())
|
||||
{
|
||||
if ((index = m_Faces.Index(tk.GetNextToken(), false)) != wxNOT_FOUND)
|
||||
{
|
||||
m_WParser->SetFontFace(m_Faces[index]);
|
||||
m_WParser->GetContainer()->InsertCell(new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
if (oldface != m_WParser->GetFontFace())
|
||||
{
|
||||
m_WParser->SetFontFace(oldface);
|
||||
m_WParser->GetContainer()->InsertCell(new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
}
|
||||
if (oldsize != m_WParser->GetFontSize())
|
||||
{
|
||||
m_WParser->SetFontSize(oldsize);
|
||||
m_WParser->GetContainer()->InsertCell(new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
}
|
||||
if (oldclr != m_WParser->GetActualColor())
|
||||
{
|
||||
m_WParser->SetActualColor(oldclr);
|
||||
m_WParser->GetContainer()->InsertCell(new wxHtmlColourCell(oldclr));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(FONT)
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(FACES_U, "U,STRIKE")
|
||||
|
||||
TAG_HANDLER_CONSTR(FACES_U) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
int underlined = m_WParser->GetFontUnderlined();
|
||||
|
||||
m_WParser->SetFontUnderlined(true);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
m_WParser->SetFontUnderlined(underlined);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(FACES_U)
|
||||
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(FACES_B, "B,STRONG")
|
||||
TAG_HANDLER_CONSTR(FACES_B) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
int bold = m_WParser->GetFontBold();
|
||||
|
||||
m_WParser->SetFontBold(true);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
m_WParser->SetFontBold(bold);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(FACES_B)
|
||||
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(FACES_I, "I,EM,CITE,ADDRESS")
|
||||
TAG_HANDLER_CONSTR(FACES_I) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
int italic = m_WParser->GetFontItalic();
|
||||
|
||||
m_WParser->SetFontItalic(true);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
m_WParser->SetFontItalic(italic);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(FACES_I)
|
||||
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(FACES_TT, "TT,CODE,KBD,SAMP")
|
||||
TAG_HANDLER_CONSTR(FACES_TT) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
int fixed = m_WParser->GetFontFixed();
|
||||
|
||||
m_WParser->SetFontFixed(true);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
m_WParser->SetFontFixed(fixed);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(FACES_TT)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(Hx, "H1,H2,H3,H4,H5,H6")
|
||||
TAG_HANDLER_CONSTR(Hx) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
int old_size, old_b, old_i, old_u, old_f, old_al;
|
||||
wxHtmlContainerCell *c;
|
||||
|
||||
old_size = m_WParser->GetFontSize();
|
||||
old_b = m_WParser->GetFontBold();
|
||||
old_i = m_WParser->GetFontItalic();
|
||||
old_u = m_WParser->GetFontUnderlined();
|
||||
old_f = m_WParser->GetFontFixed();
|
||||
old_al = m_WParser->GetAlign();
|
||||
|
||||
m_WParser->SetFontBold(true);
|
||||
m_WParser->SetFontItalic(false);
|
||||
m_WParser->SetFontUnderlined(false);
|
||||
m_WParser->SetFontFixed(false);
|
||||
|
||||
if (tag.GetName() == wxT("H1"))
|
||||
m_WParser->SetFontSize(7);
|
||||
else if (tag.GetName() == wxT("H2"))
|
||||
m_WParser->SetFontSize(6);
|
||||
else if (tag.GetName() == wxT("H3"))
|
||||
m_WParser->SetFontSize(5);
|
||||
else if (tag.GetName() == wxT("H4"))
|
||||
{
|
||||
m_WParser->SetFontSize(5);
|
||||
m_WParser->SetFontItalic(true);
|
||||
m_WParser->SetFontBold(false);
|
||||
}
|
||||
else if (tag.GetName() == wxT("H5"))
|
||||
m_WParser->SetFontSize(4);
|
||||
else if (tag.GetName() == wxT("H6"))
|
||||
{
|
||||
m_WParser->SetFontSize(4);
|
||||
m_WParser->SetFontItalic(true);
|
||||
m_WParser->SetFontBold(false);
|
||||
}
|
||||
|
||||
c = m_WParser->GetContainer();
|
||||
if (c->GetFirstChild())
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
c = m_WParser->GetContainer();
|
||||
}
|
||||
c = m_WParser->GetContainer();
|
||||
|
||||
c->SetAlign(tag);
|
||||
c->InsertCell(new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
c->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_TOP);
|
||||
m_WParser->SetAlign(c->GetAlignHor());
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
m_WParser->SetFontSize(old_size);
|
||||
m_WParser->SetFontBold(old_b);
|
||||
m_WParser->SetFontItalic(old_i);
|
||||
m_WParser->SetFontUnderlined(old_u);
|
||||
m_WParser->SetFontFixed(old_f);
|
||||
m_WParser->SetAlign(old_al);
|
||||
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
c = m_WParser->GetContainer();
|
||||
c->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_TOP);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(Hx)
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(BIGSMALL, "BIG,SMALL")
|
||||
TAG_HANDLER_CONSTR(BIGSMALL) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
int oldsize = m_WParser->GetFontSize();
|
||||
int sz = (tag.GetName() == wxT("BIG")) ? +1 : -1;
|
||||
|
||||
m_WParser->SetFontSize(sz);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
m_WParser->SetFontSize(oldsize);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(BIGSMALL)
|
||||
|
||||
|
||||
|
||||
|
||||
TAGS_MODULE_BEGIN(Fonts)
|
||||
|
||||
TAGS_MODULE_ADD(FONT)
|
||||
TAGS_MODULE_ADD(FACES_U)
|
||||
TAGS_MODULE_ADD(FACES_I)
|
||||
TAGS_MODULE_ADD(FACES_B)
|
||||
TAGS_MODULE_ADD(FACES_TT)
|
||||
TAGS_MODULE_ADD(Hx)
|
||||
TAGS_MODULE_ADD(BIGSMALL)
|
||||
|
||||
TAGS_MODULE_END(Fonts)
|
||||
|
||||
|
||||
#endif
|
111
wxWidgets/src/html/m_hline.cpp
Normal file
111
wxWidgets/src/html/m_hline.cpp
Normal file
|
@ -0,0 +1,111 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/m_hline.cpp
|
||||
// Purpose: wxHtml module for horizontal line (HR tag)
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: m_hline.cpp 38788 2006-04-18 08:11:26Z ABX $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#include "wx/brush.h"
|
||||
#include "wx/pen.h"
|
||||
#include "wx/dc.h"
|
||||
#endif
|
||||
|
||||
#include "wx/html/forcelnk.h"
|
||||
#include "wx/html/m_templ.h"
|
||||
|
||||
#include "wx/html/htmlcell.h"
|
||||
|
||||
FORCE_LINK_ME(m_hline)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlLineCell
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class wxHtmlLineCell : public wxHtmlCell
|
||||
{
|
||||
public:
|
||||
wxHtmlLineCell(int size, bool shading) : wxHtmlCell() {m_Height = size; m_HasShading = shading;}
|
||||
void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
|
||||
wxHtmlRenderingInfo& info);
|
||||
void Layout(int w)
|
||||
{ m_Width = w; wxHtmlCell::Layout(w); }
|
||||
|
||||
private:
|
||||
// Should we draw 3-D shading or not
|
||||
bool m_HasShading;
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxHtmlLineCell)
|
||||
};
|
||||
|
||||
|
||||
void wxHtmlLineCell::Draw(wxDC& dc, int x, int y,
|
||||
int WXUNUSED(view_y1), int WXUNUSED(view_y2),
|
||||
wxHtmlRenderingInfo& WXUNUSED(info))
|
||||
{
|
||||
wxBrush mybrush(wxT("GREY"), (m_HasShading) ? wxTRANSPARENT : wxSOLID);
|
||||
wxPen mypen(wxT("GREY"), 1, wxSOLID);
|
||||
dc.SetBrush(mybrush);
|
||||
dc.SetPen(mypen);
|
||||
dc.DrawRectangle(x + m_PosX, y + m_PosY, m_Width, m_Height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The list handler:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(HR, "HR")
|
||||
TAG_HANDLER_CONSTR(HR) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
wxHtmlContainerCell *c;
|
||||
int sz;
|
||||
bool HasShading;
|
||||
|
||||
m_WParser->CloseContainer();
|
||||
c = m_WParser->OpenContainer();
|
||||
|
||||
c->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_VERTICAL);
|
||||
c->SetAlignHor(wxHTML_ALIGN_CENTER);
|
||||
c->SetAlign(tag);
|
||||
c->SetWidthFloat(tag);
|
||||
sz = 1;
|
||||
tag.GetParamAsInt(wxT("SIZE"), &sz);
|
||||
HasShading = !(tag.HasParam(wxT("NOSHADE")));
|
||||
c->InsertCell(new wxHtmlLineCell((int)((double)sz * m_WParser->GetPixelScale()), HasShading));
|
||||
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(HR)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TAGS_MODULE_BEGIN(HLine)
|
||||
|
||||
TAGS_MODULE_ADD(HR)
|
||||
|
||||
TAGS_MODULE_END(HLine)
|
||||
|
||||
#endif
|
735
wxWidgets/src/html/m_image.cpp
Normal file
735
wxWidgets/src/html/m_image.cpp
Normal file
|
@ -0,0 +1,735 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/m_image.cpp
|
||||
// Purpose: wxHtml module for displaying images
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: m_image.cpp 52997 2008-04-03 18:55:46Z VS $
|
||||
// Copyright: (c) 1999 Vaclav Slavik, Joel Lucsy
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#include "wx/dynarray.h"
|
||||
#include "wx/dc.h"
|
||||
#include "wx/scrolwin.h"
|
||||
#include "wx/timer.h"
|
||||
#include "wx/dcmemory.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/math.h"
|
||||
#include "wx/image.h"
|
||||
#endif
|
||||
|
||||
#include "wx/html/forcelnk.h"
|
||||
#include "wx/html/m_templ.h"
|
||||
#include "wx/html/htmlwin.h"
|
||||
|
||||
#include "wx/gifdecod.h"
|
||||
#include "wx/artprov.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
FORCE_LINK_ME(m_image)
|
||||
|
||||
|
||||
|
||||
|
||||
WX_DECLARE_OBJARRAY(int, CoordArray);
|
||||
#include "wx/arrimpl.cpp" // this is a magic incantation which must be done!
|
||||
WX_DEFINE_OBJARRAY(CoordArray)
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// wxHtmlImageMapAreaCell
|
||||
// 0-width, 0-height cell that represents single area in
|
||||
// imagemap (it's GetLink is called from wxHtmlImageCell's)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class wxHtmlImageMapAreaCell : public wxHtmlCell
|
||||
{
|
||||
public:
|
||||
enum celltype { CIRCLE, RECT, POLY };
|
||||
protected:
|
||||
CoordArray coords;
|
||||
celltype type;
|
||||
int radius;
|
||||
public:
|
||||
wxHtmlImageMapAreaCell( celltype t, wxString &coords, double pixel_scale = 1.0);
|
||||
virtual wxHtmlLinkInfo *GetLink( int x = 0, int y = 0 ) const;
|
||||
void Draw(wxDC& WXUNUSED(dc),
|
||||
int WXUNUSED(x), int WXUNUSED(y),
|
||||
int WXUNUSED(view_y1), int WXUNUSED(view_y2),
|
||||
wxHtmlRenderingInfo& WXUNUSED(info)) {}
|
||||
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxHtmlImageMapAreaCell)
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
wxHtmlImageMapAreaCell::wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::celltype t, wxString &incoords, double pixel_scale )
|
||||
{
|
||||
int i;
|
||||
wxString x = incoords, y;
|
||||
|
||||
type = t;
|
||||
while ((i = x.Find( ',' )) != wxNOT_FOUND)
|
||||
{
|
||||
coords.Add( (int)(pixel_scale * (double)wxAtoi( x.Left( i ).c_str())) );
|
||||
x = x.Mid( i + 1 );
|
||||
}
|
||||
coords.Add( (int)(pixel_scale * (double)wxAtoi( x.c_str())) );
|
||||
}
|
||||
|
||||
wxHtmlLinkInfo *wxHtmlImageMapAreaCell::GetLink( int x, int y ) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case RECT:
|
||||
{
|
||||
int l, t, r, b;
|
||||
|
||||
l = coords[ 0 ];
|
||||
t = coords[ 1 ];
|
||||
r = coords[ 2 ];
|
||||
b = coords[ 3 ];
|
||||
if (x >= l && x <= r && y >= t && y <= b)
|
||||
{
|
||||
return m_Link;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CIRCLE:
|
||||
{
|
||||
int l, t, r;
|
||||
double d;
|
||||
|
||||
l = coords[ 0 ];
|
||||
t = coords[ 1 ];
|
||||
r = coords[ 2 ];
|
||||
d = sqrt( (double) (((x - l) * (x - l)) + ((y - t) * (y - t))) );
|
||||
if (d < (double)r)
|
||||
{
|
||||
return m_Link;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case POLY:
|
||||
{
|
||||
if (coords.GetCount() >= 6)
|
||||
{
|
||||
int intersects = 0;
|
||||
int wherex = x;
|
||||
int wherey = y;
|
||||
int totalv = coords.GetCount() / 2;
|
||||
int totalc = totalv * 2;
|
||||
int xval = coords[totalc - 2];
|
||||
int yval = coords[totalc - 1];
|
||||
int end = totalc;
|
||||
int pointer = 1;
|
||||
|
||||
if ((yval >= wherey) != (coords[pointer] >= wherey))
|
||||
{
|
||||
if ((xval >= wherex) == (coords[0] >= wherex))
|
||||
{
|
||||
intersects += (xval >= wherex) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
intersects += ((xval - (yval - wherey) *
|
||||
(coords[0] - xval) /
|
||||
(coords[pointer] - yval)) >= wherex) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
while (pointer < end)
|
||||
{
|
||||
yval = coords[pointer];
|
||||
pointer += 2;
|
||||
if (yval >= wherey)
|
||||
{
|
||||
while ((pointer < end) && (coords[pointer] >= wherey))
|
||||
{
|
||||
pointer += 2;
|
||||
}
|
||||
if (pointer >= end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if ((coords[pointer - 3] >= wherex) ==
|
||||
(coords[pointer - 1] >= wherex)) {
|
||||
intersects += (coords[pointer - 3] >= wherex) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
intersects +=
|
||||
((coords[pointer - 3] - (coords[pointer - 2] - wherey) *
|
||||
(coords[pointer - 1] - coords[pointer - 3]) /
|
||||
(coords[pointer] - coords[pointer - 2])) >= wherex) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((pointer < end) && (coords[pointer] < wherey))
|
||||
{
|
||||
pointer += 2;
|
||||
}
|
||||
if (pointer >= end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if ((coords[pointer - 3] >= wherex) ==
|
||||
(coords[pointer - 1] >= wherex))
|
||||
{
|
||||
intersects += (coords[pointer - 3] >= wherex) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
intersects +=
|
||||
((coords[pointer - 3] - (coords[pointer - 2] - wherey) *
|
||||
(coords[pointer - 1] - coords[pointer - 3]) /
|
||||
(coords[pointer] - coords[pointer - 2])) >= wherex) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((intersects & 1) != 0)
|
||||
{
|
||||
return m_Link;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_Next)
|
||||
{
|
||||
wxHtmlImageMapAreaCell *a = (wxHtmlImageMapAreaCell*)m_Next;
|
||||
return a->GetLink( x, y );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// wxHtmlImageMapCell
|
||||
// 0-width, 0-height cell that represents map from imagemaps
|
||||
// it is always placed before wxHtmlImageMapAreaCells
|
||||
// It responds to Find(wxHTML_COND_ISIMAGEMAP)
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class wxHtmlImageMapCell : public wxHtmlCell
|
||||
{
|
||||
public:
|
||||
wxHtmlImageMapCell( wxString &name );
|
||||
protected:
|
||||
wxString m_Name;
|
||||
public:
|
||||
virtual wxHtmlLinkInfo *GetLink( int x = 0, int y = 0 ) const;
|
||||
virtual const wxHtmlCell *Find( int cond, const void *param ) const;
|
||||
void Draw(wxDC& WXUNUSED(dc),
|
||||
int WXUNUSED(x), int WXUNUSED(y),
|
||||
int WXUNUSED(view_y1), int WXUNUSED(view_y2),
|
||||
wxHtmlRenderingInfo& WXUNUSED(info)) {}
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxHtmlImageMapCell)
|
||||
};
|
||||
|
||||
|
||||
wxHtmlImageMapCell::wxHtmlImageMapCell( wxString &name )
|
||||
{
|
||||
m_Name = name ;
|
||||
}
|
||||
|
||||
wxHtmlLinkInfo *wxHtmlImageMapCell::GetLink( int x, int y ) const
|
||||
{
|
||||
wxHtmlImageMapAreaCell *a = (wxHtmlImageMapAreaCell*)m_Next;
|
||||
if (a)
|
||||
return a->GetLink( x, y );
|
||||
return wxHtmlCell::GetLink( x, y );
|
||||
}
|
||||
|
||||
const wxHtmlCell *wxHtmlImageMapCell::Find( int cond, const void *param ) const
|
||||
{
|
||||
if (cond == wxHTML_COND_ISIMAGEMAP)
|
||||
{
|
||||
if (m_Name == *((wxString*)(param)))
|
||||
return this;
|
||||
}
|
||||
return wxHtmlCell::Find(cond, param);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// wxHtmlImageCell
|
||||
// Image/bitmap
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
class wxHtmlImageCell : public wxHtmlCell
|
||||
{
|
||||
public:
|
||||
wxHtmlImageCell(wxHtmlWindowInterface *windowIface,
|
||||
wxFSFile *input, int w = wxDefaultCoord, int h = wxDefaultCoord,
|
||||
double scale = 1.0, int align = wxHTML_ALIGN_BOTTOM,
|
||||
const wxString& mapname = wxEmptyString);
|
||||
virtual ~wxHtmlImageCell();
|
||||
void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
|
||||
wxHtmlRenderingInfo& info);
|
||||
virtual wxHtmlLinkInfo *GetLink(int x = 0, int y = 0) const;
|
||||
|
||||
void SetImage(const wxImage& img);
|
||||
#if wxUSE_GIF && wxUSE_TIMER
|
||||
void AdvanceAnimation(wxTimer *timer);
|
||||
virtual void Layout(int w);
|
||||
#endif
|
||||
|
||||
private:
|
||||
wxBitmap *m_bitmap;
|
||||
int m_bmpW, m_bmpH;
|
||||
bool m_showFrame:1;
|
||||
wxHtmlWindowInterface *m_windowIface;
|
||||
#if wxUSE_GIF && wxUSE_TIMER
|
||||
wxGIFDecoder *m_gifDecoder;
|
||||
wxTimer *m_gifTimer;
|
||||
int m_physX, m_physY;
|
||||
size_t m_nCurrFrame;
|
||||
#endif
|
||||
double m_scale;
|
||||
wxHtmlImageMapCell *m_imageMap;
|
||||
wxString m_mapName;
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxHtmlImageCell)
|
||||
};
|
||||
|
||||
#if wxUSE_GIF && wxUSE_TIMER
|
||||
class wxGIFTimer : public wxTimer
|
||||
{
|
||||
public:
|
||||
wxGIFTimer(wxHtmlImageCell *cell) : m_cell(cell) {}
|
||||
virtual void Notify()
|
||||
{
|
||||
m_cell->AdvanceAnimation(this);
|
||||
}
|
||||
|
||||
private:
|
||||
wxHtmlImageCell *m_cell;
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxGIFTimer)
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// wxHtmlImageCell
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
wxHtmlImageCell::wxHtmlImageCell(wxHtmlWindowInterface *windowIface,
|
||||
wxFSFile *input,
|
||||
int w, int h, double scale, int align,
|
||||
const wxString& mapname) : wxHtmlCell()
|
||||
{
|
||||
m_windowIface = windowIface;
|
||||
m_scale = scale;
|
||||
m_showFrame = false;
|
||||
m_bitmap = NULL;
|
||||
m_bmpW = w;
|
||||
m_bmpH = h;
|
||||
m_imageMap = NULL;
|
||||
m_mapName = mapname;
|
||||
SetCanLiveOnPagebreak(false);
|
||||
#if wxUSE_GIF && wxUSE_TIMER
|
||||
m_gifDecoder = NULL;
|
||||
m_gifTimer = NULL;
|
||||
m_physX = m_physY = wxDefaultCoord;
|
||||
m_nCurrFrame = 0;
|
||||
#endif
|
||||
|
||||
if ( m_bmpW && m_bmpH )
|
||||
{
|
||||
if ( input )
|
||||
{
|
||||
wxInputStream *s = input->GetStream();
|
||||
|
||||
if ( s )
|
||||
{
|
||||
#if wxUSE_GIF && wxUSE_TIMER
|
||||
bool readImg = true;
|
||||
if ( m_windowIface &&
|
||||
(input->GetLocation().Matches(wxT("*.gif")) ||
|
||||
input->GetLocation().Matches(wxT("*.GIF"))) )
|
||||
{
|
||||
m_gifDecoder = new wxGIFDecoder();
|
||||
if ( m_gifDecoder->LoadGIF(*s) == wxGIF_OK )
|
||||
{
|
||||
wxImage img;
|
||||
if ( m_gifDecoder->ConvertToImage(0, &img) )
|
||||
SetImage(img);
|
||||
|
||||
readImg = false;
|
||||
|
||||
if ( m_gifDecoder->IsAnimation() )
|
||||
{
|
||||
m_gifTimer = new wxGIFTimer(this);
|
||||
long delay = m_gifDecoder->GetDelay(0);
|
||||
if ( delay == 0 )
|
||||
delay = 1;
|
||||
m_gifTimer->Start(delay, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxDELETE(m_gifDecoder);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxDELETE(m_gifDecoder);
|
||||
}
|
||||
}
|
||||
|
||||
if ( readImg )
|
||||
#endif // wxUSE_GIF && wxUSE_TIMER
|
||||
{
|
||||
wxImage image(*s, wxBITMAP_TYPE_ANY);
|
||||
if ( image.Ok() )
|
||||
SetImage(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // input==NULL, use "broken image" bitmap
|
||||
{
|
||||
if ( m_bmpW == wxDefaultCoord && m_bmpH == wxDefaultCoord )
|
||||
{
|
||||
m_bmpW = 29;
|
||||
m_bmpH = 31;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_showFrame = true;
|
||||
if ( m_bmpW == wxDefaultCoord ) m_bmpW = 31;
|
||||
if ( m_bmpH == wxDefaultCoord ) m_bmpH = 33;
|
||||
}
|
||||
m_bitmap =
|
||||
new wxBitmap(wxArtProvider::GetBitmap(wxART_MISSING_IMAGE));
|
||||
}
|
||||
}
|
||||
//else: ignore the 0-sized images used sometimes on the Web pages
|
||||
|
||||
m_Width = (int)(scale * (double)m_bmpW);
|
||||
m_Height = (int)(scale * (double)m_bmpH);
|
||||
|
||||
switch (align)
|
||||
{
|
||||
case wxHTML_ALIGN_TOP :
|
||||
m_Descent = m_Height;
|
||||
break;
|
||||
case wxHTML_ALIGN_CENTER :
|
||||
m_Descent = m_Height / 2;
|
||||
break;
|
||||
case wxHTML_ALIGN_BOTTOM :
|
||||
default :
|
||||
m_Descent = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void wxHtmlImageCell::SetImage(const wxImage& img)
|
||||
{
|
||||
#if !defined(__WXMSW__) || wxUSE_WXDIB
|
||||
if ( img.Ok() )
|
||||
{
|
||||
delete m_bitmap;
|
||||
|
||||
int ww, hh;
|
||||
ww = img.GetWidth();
|
||||
hh = img.GetHeight();
|
||||
|
||||
if ( m_bmpW == wxDefaultCoord )
|
||||
m_bmpW = ww;
|
||||
if ( m_bmpH == wxDefaultCoord )
|
||||
m_bmpH = hh;
|
||||
|
||||
// Only scale the bitmap at the rendering stage,
|
||||
// so we don't lose quality twice
|
||||
/*
|
||||
if ((m_bmpW != ww) || (m_bmpH != hh))
|
||||
{
|
||||
wxImage img2 = img.Scale(m_bmpW, m_bmpH);
|
||||
m_bitmap = new wxBitmap(img2);
|
||||
}
|
||||
else
|
||||
*/
|
||||
m_bitmap = new wxBitmap(img);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if wxUSE_GIF && wxUSE_TIMER
|
||||
void wxHtmlImageCell::AdvanceAnimation(wxTimer *timer)
|
||||
{
|
||||
wxImage img;
|
||||
|
||||
// advance current frame
|
||||
m_nCurrFrame++;
|
||||
if (m_nCurrFrame == m_gifDecoder->GetFrameCount())
|
||||
m_nCurrFrame = 0;
|
||||
|
||||
if ( m_physX == wxDefaultCoord )
|
||||
{
|
||||
m_physX = m_physY = 0;
|
||||
for (wxHtmlCell *cell = this; cell; cell = cell->GetParent())
|
||||
{
|
||||
m_physX += cell->GetPosX();
|
||||
m_physY += cell->GetPosY();
|
||||
}
|
||||
}
|
||||
|
||||
wxWindow *win = m_windowIface->GetHTMLWindow();
|
||||
wxPoint pos =
|
||||
m_windowIface->HTMLCoordsToWindow(this, wxPoint(m_physX, m_physY));
|
||||
wxRect rect(pos, wxSize(m_Width, m_Height));
|
||||
|
||||
if ( win->GetClientRect().Intersects(rect) &&
|
||||
m_gifDecoder->ConvertToImage(m_nCurrFrame, &img) )
|
||||
{
|
||||
#if !defined(__WXMSW__) || wxUSE_WXDIB
|
||||
if ( m_gifDecoder->GetFrameSize(m_nCurrFrame) != wxSize(m_Width, m_Height) ||
|
||||
m_gifDecoder->GetFramePosition(m_nCurrFrame) != wxPoint(0, 0) )
|
||||
{
|
||||
wxBitmap bmp(img);
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(*m_bitmap);
|
||||
dc.DrawBitmap(bmp, m_gifDecoder->GetFramePosition(m_nCurrFrame),
|
||||
true /* use mask */);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
SetImage(img);
|
||||
win->Refresh(img.HasMask(), &rect);
|
||||
}
|
||||
|
||||
long delay = m_gifDecoder->GetDelay(m_nCurrFrame);
|
||||
if ( delay == 0 )
|
||||
delay = 1;
|
||||
timer->Start(delay, true);
|
||||
}
|
||||
|
||||
void wxHtmlImageCell::Layout(int w)
|
||||
{
|
||||
wxHtmlCell::Layout(w);
|
||||
m_physX = m_physY = wxDefaultCoord;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
wxHtmlImageCell::~wxHtmlImageCell()
|
||||
{
|
||||
delete m_bitmap;
|
||||
#if wxUSE_GIF && wxUSE_TIMER
|
||||
delete m_gifTimer;
|
||||
delete m_gifDecoder;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void wxHtmlImageCell::Draw(wxDC& dc, int x, int y,
|
||||
int WXUNUSED(view_y1), int WXUNUSED(view_y2),
|
||||
wxHtmlRenderingInfo& WXUNUSED(info))
|
||||
{
|
||||
if ( m_showFrame )
|
||||
{
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.SetPen(*wxBLACK_PEN);
|
||||
dc.DrawRectangle(x + m_PosX, y + m_PosY, m_Width, m_Height);
|
||||
x++, y++;
|
||||
}
|
||||
if ( m_bitmap )
|
||||
{
|
||||
// We add in the scaling from the desired bitmap width
|
||||
// and height, so we only do the scaling once.
|
||||
double imageScaleX = 1.0;
|
||||
double imageScaleY = 1.0;
|
||||
if (m_bmpW != m_bitmap->GetWidth())
|
||||
imageScaleX = (double) m_bmpW / (double) m_bitmap->GetWidth();
|
||||
if (m_bmpH != m_bitmap->GetHeight())
|
||||
imageScaleY = (double) m_bmpH / (double) m_bitmap->GetHeight();
|
||||
|
||||
double us_x, us_y;
|
||||
dc.GetUserScale(&us_x, &us_y);
|
||||
dc.SetUserScale(us_x * m_scale * imageScaleX, us_y * m_scale * imageScaleY);
|
||||
|
||||
dc.DrawBitmap(*m_bitmap, (int) ((x + m_PosX) / (m_scale*imageScaleX)),
|
||||
(int) ((y + m_PosY) / (m_scale*imageScaleY)), true);
|
||||
dc.SetUserScale(us_x, us_y);
|
||||
}
|
||||
}
|
||||
|
||||
wxHtmlLinkInfo *wxHtmlImageCell::GetLink( int x, int y ) const
|
||||
{
|
||||
if (m_mapName.empty())
|
||||
return wxHtmlCell::GetLink( x, y );
|
||||
if (!m_imageMap)
|
||||
{
|
||||
wxHtmlContainerCell *p, *op;
|
||||
op = p = GetParent();
|
||||
while (p)
|
||||
{
|
||||
op = p;
|
||||
p = p->GetParent();
|
||||
}
|
||||
p = op;
|
||||
wxHtmlCell *cell = (wxHtmlCell*)p->Find(wxHTML_COND_ISIMAGEMAP,
|
||||
(const void*)(&m_mapName));
|
||||
if (!cell)
|
||||
{
|
||||
((wxString&)m_mapName).Clear();
|
||||
return wxHtmlCell::GetLink( x, y );
|
||||
}
|
||||
{ // dirty hack, ask Joel why he fills m_ImageMap in this place
|
||||
// THE problem is that we're in const method and we can't modify m_ImageMap
|
||||
wxHtmlImageMapCell **cx = (wxHtmlImageMapCell**)(&m_imageMap);
|
||||
*cx = (wxHtmlImageMapCell*)cell;
|
||||
}
|
||||
}
|
||||
return m_imageMap->GetLink(x, y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// tag handler
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
TAG_HANDLER_BEGIN(IMG, "IMG,MAP,AREA")
|
||||
TAG_HANDLER_CONSTR(IMG) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
if (tag.GetName() == wxT("IMG"))
|
||||
{
|
||||
if (tag.HasParam(wxT("SRC")))
|
||||
{
|
||||
int w = wxDefaultCoord, h = wxDefaultCoord;
|
||||
int al;
|
||||
wxFSFile *str;
|
||||
wxString tmp = tag.GetParam(wxT("SRC"));
|
||||
wxString mn = wxEmptyString;
|
||||
|
||||
str = m_WParser->OpenURL(wxHTML_URL_IMAGE, tmp);
|
||||
|
||||
if (tag.HasParam(wxT("WIDTH")))
|
||||
tag.GetParamAsInt(wxT("WIDTH"), &w);
|
||||
if (tag.HasParam(wxT("HEIGHT")))
|
||||
tag.GetParamAsInt(wxT("HEIGHT"), &h);
|
||||
al = wxHTML_ALIGN_BOTTOM;
|
||||
if (tag.HasParam(wxT("ALIGN")))
|
||||
{
|
||||
wxString alstr = tag.GetParam(wxT("ALIGN"));
|
||||
alstr.MakeUpper(); // for the case alignment was in ".."
|
||||
if (alstr == wxT("TEXTTOP"))
|
||||
al = wxHTML_ALIGN_TOP;
|
||||
else if ((alstr == wxT("CENTER")) || (alstr == wxT("ABSCENTER")))
|
||||
al = wxHTML_ALIGN_CENTER;
|
||||
}
|
||||
if (tag.HasParam(wxT("USEMAP")))
|
||||
{
|
||||
mn = tag.GetParam( wxT("USEMAP") );
|
||||
if (mn.GetChar(0) == wxT('#'))
|
||||
{
|
||||
mn = mn.Mid( 1 );
|
||||
}
|
||||
}
|
||||
wxHtmlImageCell *cel = new wxHtmlImageCell(
|
||||
m_WParser->GetWindowInterface(),
|
||||
str, w, h,
|
||||
m_WParser->GetPixelScale(),
|
||||
al, mn);
|
||||
m_WParser->ApplyStateToCell(cel);
|
||||
cel->SetId(tag.GetParam(wxT("id"))); // may be empty
|
||||
m_WParser->GetContainer()->InsertCell(cel);
|
||||
if (str)
|
||||
delete str;
|
||||
}
|
||||
}
|
||||
if (tag.GetName() == wxT("MAP"))
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
if (tag.HasParam(wxT("NAME")))
|
||||
{
|
||||
wxString tmp = tag.GetParam(wxT("NAME"));
|
||||
wxHtmlImageMapCell *cel = new wxHtmlImageMapCell( tmp );
|
||||
m_WParser->GetContainer()->InsertCell( cel );
|
||||
}
|
||||
ParseInner( tag );
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
}
|
||||
if (tag.GetName() == wxT("AREA"))
|
||||
{
|
||||
if (tag.HasParam(wxT("SHAPE")))
|
||||
{
|
||||
wxString tmp = tag.GetParam(wxT("SHAPE"));
|
||||
wxString coords = wxEmptyString;
|
||||
tmp.MakeUpper();
|
||||
wxHtmlImageMapAreaCell *cel = NULL;
|
||||
if (tag.HasParam(wxT("COORDS")))
|
||||
{
|
||||
coords = tag.GetParam(wxT("COORDS"));
|
||||
}
|
||||
if (tmp == wxT("POLY"))
|
||||
{
|
||||
cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::POLY, coords, m_WParser->GetPixelScale() );
|
||||
}
|
||||
else if (tmp == wxT("CIRCLE"))
|
||||
{
|
||||
cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::CIRCLE, coords, m_WParser->GetPixelScale() );
|
||||
}
|
||||
else if (tmp == wxT("RECT"))
|
||||
{
|
||||
cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::RECT, coords, m_WParser->GetPixelScale() );
|
||||
}
|
||||
if (cel != NULL && tag.HasParam(wxT("HREF")))
|
||||
{
|
||||
wxString target;
|
||||
if (tag.HasParam(wxT("TARGET")))
|
||||
target = tag.GetParam(wxT("TARGET"));
|
||||
cel->SetLink(wxHtmlLinkInfo(tag.GetParam(wxT("HREF")), target));
|
||||
}
|
||||
if (cel != NULL)
|
||||
m_WParser->GetContainer()->InsertCell( cel );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(IMG)
|
||||
|
||||
|
||||
|
||||
TAGS_MODULE_BEGIN(Image)
|
||||
|
||||
TAGS_MODULE_ADD(IMG)
|
||||
|
||||
TAGS_MODULE_END(Image)
|
||||
|
||||
|
||||
#endif
|
474
wxWidgets/src/html/m_layout.cpp
Normal file
474
wxWidgets/src/html/m_layout.cpp
Normal file
|
@ -0,0 +1,474 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/m_layout.cpp
|
||||
// Purpose: wxHtml module for basic paragraphs/layout handling
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: m_layout.cpp 55881 2008-09-25 17:19:30Z VS $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#include "wx/image.h"
|
||||
#endif
|
||||
|
||||
#include "wx/html/forcelnk.h"
|
||||
#include "wx/html/m_templ.h"
|
||||
|
||||
#include "wx/html/htmlwin.h"
|
||||
|
||||
FORCE_LINK_ME(m_layout)
|
||||
|
||||
#ifdef __WXWINCE__
|
||||
#include "wx/msw/wince/missing.h" // for bsearch()
|
||||
#else
|
||||
#include <stdlib.h> // bsearch()
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlPageBreakCell
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Since html isn't a page-layout language, it doesn't support page
|
||||
// page breaks directly--that requires CSS2 support. But a page-break
|
||||
// facility is handy, and has been requested more than once on the
|
||||
// mailing lists. This wxHtml tag handler implements just enough of
|
||||
// CSS2 to support a page break by recognizing only
|
||||
// <div style="page-break-before:always">
|
||||
//
|
||||
// wxHtml maintains page breaks in wxHtmlPrintout::m_PageBreaks. The
|
||||
// tag handler below adds appropriate offsets to that array member.
|
||||
// wxHtmlDCRenderer::Render() accesses that array and makes a new page
|
||||
// begin after each page-break tag.
|
||||
|
||||
// The page-break handler does all its work in AdjustPagebreak(). For
|
||||
// all tag handlers, that function adjusts the page-break position.
|
||||
// For other tags, it determines whether the html element can fit on
|
||||
// the remainder of the page; if it cannot fit, but must not be split,
|
||||
// then the function moves the page break provided in the argument up,
|
||||
// and returns 'true' to inform the caller that the argument was
|
||||
// modified.
|
||||
//
|
||||
// Due to its special purpose, the page-break facility differs from
|
||||
// other tags. It takes up no space, but it behaves as though there is
|
||||
// never enough room to fit it on the remainder of the page--it always
|
||||
// forces a page break. Therefore, unlike other elements that trigger
|
||||
// a page break, it would never 'fit' on the following page either.
|
||||
// Therefore it's necessary to compare each pagebreak candidate to the
|
||||
// array wxHtmlPrintout::m_PageBreaks of pagebreaks already set, and
|
||||
// set a new one only if it's not in that array.
|
||||
|
||||
class wxHtmlPageBreakCell : public wxHtmlCell
|
||||
{
|
||||
public:
|
||||
wxHtmlPageBreakCell() {}
|
||||
|
||||
bool AdjustPagebreak(int* pagebreak,
|
||||
wxArrayInt& known_pagebreaks) const;
|
||||
|
||||
void Draw(wxDC& WXUNUSED(dc),
|
||||
int WXUNUSED(x), int WXUNUSED(y),
|
||||
int WXUNUSED(view_y1), int WXUNUSED(view_y2),
|
||||
wxHtmlRenderingInfo& WXUNUSED(info)) {}
|
||||
|
||||
private:
|
||||
DECLARE_NO_COPY_CLASS(wxHtmlPageBreakCell)
|
||||
};
|
||||
|
||||
// Comparison routine for bsearch into an int* array of pagebreaks.
|
||||
extern "C" int wxCMPFUNC_CONV wxInteger_compare(void const* i0, void const* i1)
|
||||
{
|
||||
return *(int*)i0 - *(int*)i1;
|
||||
}
|
||||
|
||||
bool wxHtmlPageBreakCell::AdjustPagebreak(int* pagebreak, wxArrayInt& known_pagebreaks) const
|
||||
{
|
||||
// When we are counting pages, 'known_pagebreaks' is non-NULL.
|
||||
// That's the only time we change 'pagebreak'. Otherwise, pages
|
||||
// were already counted, 'known_pagebreaks' is NULL, and we don't
|
||||
// do anything except return false.
|
||||
//
|
||||
// We also simply return false if the 'pagebreak' argument is
|
||||
// less than (vertically above) or the same as the current
|
||||
// vertical position. Otherwise we'd be setting a pagebreak above
|
||||
// the current cell, which is incorrect, or duplicating a
|
||||
// pagebreak that has already been set.
|
||||
if( known_pagebreaks.Count() == 0 || *pagebreak <= m_PosY)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// m_PosY is only the vertical offset from the parent. The pagebreak
|
||||
// required here is the total page offset, so m_PosY must be added
|
||||
// to the parent's offset and height.
|
||||
int total_height = m_PosY;
|
||||
for ( wxHtmlCell *parent = GetParent(); parent; parent = parent->GetParent() )
|
||||
{
|
||||
total_height += parent->GetPosY();
|
||||
}
|
||||
|
||||
|
||||
// Search the array of pagebreaks to see whether we've already set
|
||||
// a pagebreak here. The standard bsearch() function is appropriate
|
||||
// because the array of pagebreaks through known_pagebreaks[number_of_pages]
|
||||
// is known to be sorted in strictly increasing order. '1 + number_of_pages'
|
||||
// is used as a bsearch() argument because the array contains a leading
|
||||
// zero plus one element for each page.
|
||||
int where = known_pagebreaks.Index( total_height);
|
||||
// Add a pagebreak only if there isn't one already set here.
|
||||
if( wxNOT_FOUND != where)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pagebreak = m_PosY;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(P, "P")
|
||||
TAG_HANDLER_CONSTR(P) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
if (m_WParser->GetContainer()->GetFirstChild() != NULL)
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
}
|
||||
m_WParser->GetContainer()->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_TOP);
|
||||
m_WParser->GetContainer()->SetAlign(tag);
|
||||
return false;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(P)
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(BR, "BR")
|
||||
TAG_HANDLER_CONSTR(BR) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
int al = m_WParser->GetContainer()->GetAlignHor();
|
||||
wxHtmlContainerCell *c;
|
||||
|
||||
m_WParser->CloseContainer();
|
||||
c = m_WParser->OpenContainer();
|
||||
c->SetAlignHor(al);
|
||||
c->SetAlign(tag);
|
||||
c->SetMinHeight(m_WParser->GetCharHeight());
|
||||
return false;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(BR)
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(CENTER, "CENTER")
|
||||
TAG_HANDLER_CONSTR(CENTER) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
int old = m_WParser->GetAlign();
|
||||
wxHtmlContainerCell *c = m_WParser->GetContainer();
|
||||
|
||||
m_WParser->SetAlign(wxHTML_ALIGN_CENTER);
|
||||
if (c->GetFirstChild() != NULL)
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
}
|
||||
else
|
||||
c->SetAlignHor(wxHTML_ALIGN_CENTER);
|
||||
|
||||
if (tag.HasEnding())
|
||||
{
|
||||
ParseInner(tag);
|
||||
|
||||
m_WParser->SetAlign(old);
|
||||
if (c->GetFirstChild() != NULL)
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
}
|
||||
else
|
||||
c->SetAlignHor(old);
|
||||
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(CENTER)
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(DIV, "DIV")
|
||||
TAG_HANDLER_CONSTR(DIV) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
if(tag.HasParam(wxT("STYLE")))
|
||||
{
|
||||
if(tag.GetParam(wxT("STYLE")).IsSameAs(wxT("PAGE-BREAK-BEFORE:ALWAYS"), false))
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer()->InsertCell(new wxHtmlPageBreakCell);
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Treat other STYLE parameters here when they're supported.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(tag.HasParam(wxT("ALIGN")))
|
||||
{
|
||||
int old = m_WParser->GetAlign();
|
||||
wxHtmlContainerCell *c = m_WParser->GetContainer();
|
||||
if (c->GetFirstChild() != NULL)
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
c = m_WParser->GetContainer();
|
||||
c->SetAlign(tag);
|
||||
m_WParser->SetAlign(c->GetAlignHor());
|
||||
}
|
||||
else
|
||||
{
|
||||
c->SetAlign(tag);
|
||||
m_WParser->SetAlign(c->GetAlignHor());
|
||||
}
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
m_WParser->SetAlign(old);
|
||||
if (c->GetFirstChild() != NULL)
|
||||
{
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
}
|
||||
else
|
||||
c->SetAlignHor(old);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Same as BR
|
||||
int al = m_WParser->GetContainer()->GetAlignHor();
|
||||
wxHtmlContainerCell *c;
|
||||
|
||||
m_WParser->CloseContainer();
|
||||
c = m_WParser->OpenContainer();
|
||||
c->SetAlignHor(al);
|
||||
c->SetAlign(tag);
|
||||
c->SetMinHeight(m_WParser->GetCharHeight());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(DIV)
|
||||
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(TITLE, "TITLE")
|
||||
TAG_HANDLER_CONSTR(TITLE) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
wxHtmlWindowInterface *winIface = m_WParser->GetWindowInterface();
|
||||
if (winIface)
|
||||
{
|
||||
wxString title = m_WParser->GetSource()->Mid(
|
||||
tag.GetBeginPos(),
|
||||
tag.GetEndPos1()-tag.GetBeginPos());
|
||||
#if !wxUSE_UNICODE && wxUSE_WCHAR_T
|
||||
const wxFontEncoding enc = m_WParser->GetInputEncoding();
|
||||
if ( enc != wxFONTENCODING_DEFAULT )
|
||||
{
|
||||
// need to convert to the current one
|
||||
title = wxString(title.wc_str(wxCSConv(enc)), wxConvLocal);
|
||||
}
|
||||
#endif // !wxUSE_UNICODE
|
||||
|
||||
title = m_WParser->GetEntitiesParser()->Parse(title);
|
||||
|
||||
winIface->SetHTMLWindowTitle(title);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(TITLE)
|
||||
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(BODY, "BODY")
|
||||
TAG_HANDLER_CONSTR(BODY) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
wxColour clr;
|
||||
|
||||
if (tag.GetParamAsColour(wxT("TEXT"), &clr))
|
||||
{
|
||||
m_WParser->SetActualColor(clr);
|
||||
m_WParser->GetContainer()->InsertCell(new wxHtmlColourCell(clr));
|
||||
}
|
||||
|
||||
if (tag.GetParamAsColour(wxT("LINK"), &clr))
|
||||
m_WParser->SetLinkColor(clr);
|
||||
|
||||
wxHtmlWindowInterface *winIface = m_WParser->GetWindowInterface();
|
||||
// the rest of this function requires a window:
|
||||
if ( !winIface )
|
||||
return false;
|
||||
|
||||
if (tag.HasParam(wxT("BACKGROUND")))
|
||||
{
|
||||
wxFSFile *fileBgImage = m_WParser->OpenURL
|
||||
(
|
||||
wxHTML_URL_IMAGE,
|
||||
tag.GetParam(wxT("BACKGROUND"))
|
||||
);
|
||||
if ( fileBgImage )
|
||||
{
|
||||
wxInputStream *is = fileBgImage->GetStream();
|
||||
if ( is )
|
||||
{
|
||||
#if !defined(__WXMSW__) || wxUSE_WXDIB
|
||||
wxImage image(*is);
|
||||
if ( image.Ok() )
|
||||
winIface->SetHTMLBackgroundImage(image);
|
||||
#endif
|
||||
}
|
||||
|
||||
delete fileBgImage;
|
||||
}
|
||||
}
|
||||
|
||||
if (tag.GetParamAsColour(wxT("BGCOLOR"), &clr))
|
||||
{
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlColourCell(clr, wxHTML_CLR_BACKGROUND));
|
||||
winIface->SetHTMLBackgroundColour(clr);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(BODY)
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(BLOCKQUOTE, "BLOCKQUOTE")
|
||||
TAG_HANDLER_CONSTR(BLOCKQUOTE) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
wxHtmlContainerCell *c;
|
||||
|
||||
m_WParser->CloseContainer();
|
||||
c = m_WParser->OpenContainer();
|
||||
|
||||
if (c->GetAlignHor() == wxHTML_ALIGN_RIGHT)
|
||||
c->SetIndent(5 * m_WParser->GetCharWidth(), wxHTML_INDENT_RIGHT);
|
||||
else
|
||||
c->SetIndent(5 * m_WParser->GetCharWidth(), wxHTML_INDENT_LEFT);
|
||||
|
||||
c->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_TOP);
|
||||
m_WParser->OpenContainer();
|
||||
ParseInner(tag);
|
||||
c = m_WParser->CloseContainer();
|
||||
c->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_BOTTOM);
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->OpenContainer();
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(BLOCKQUOTE)
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(SUBSUP, "SUB,SUP")
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
bool issub = (tag.GetName() == wxT("SUB"));
|
||||
wxHtmlScriptMode oldmode = m_WParser->GetScriptMode();
|
||||
int oldbase = m_WParser->GetScriptBaseline();
|
||||
int oldsize = m_WParser->GetFontSize();
|
||||
|
||||
wxHtmlContainerCell *cont = m_WParser->GetContainer();
|
||||
wxHtmlCell *c = cont->GetLastChild();
|
||||
|
||||
m_WParser->SetScriptMode(issub ? wxHTML_SCRIPT_SUB : wxHTML_SCRIPT_SUP);
|
||||
m_WParser->SetScriptBaseline(
|
||||
oldbase + c ? c->GetScriptBaseline() : 0);
|
||||
|
||||
// select smaller font
|
||||
m_WParser->SetFontSize(m_WParser->GetFontSize()-2);
|
||||
cont->InsertCell(new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
// restore font size
|
||||
m_WParser->SetFontSize(oldsize);
|
||||
m_WParser->GetContainer()->InsertCell(
|
||||
new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
|
||||
// restore base and alignment
|
||||
m_WParser->SetScriptBaseline(oldbase);
|
||||
m_WParser->SetScriptMode(oldmode);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(SUBSUP)
|
||||
|
||||
|
||||
// Tag handler for tags that we have to ignore, otherwise non-text data
|
||||
// would show up as text:
|
||||
TAG_HANDLER_BEGIN(DoNothing, "SCRIPT")
|
||||
TAG_HANDLER_CONSTR(DoNothing) { }
|
||||
|
||||
TAG_HANDLER_PROC(WXUNUSED(tag))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
TAG_HANDLER_END(DoNothing)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TAGS_MODULE_BEGIN(Layout)
|
||||
|
||||
TAGS_MODULE_ADD(P)
|
||||
TAGS_MODULE_ADD(BR)
|
||||
TAGS_MODULE_ADD(CENTER)
|
||||
TAGS_MODULE_ADD(DIV)
|
||||
TAGS_MODULE_ADD(TITLE)
|
||||
TAGS_MODULE_ADD(BODY)
|
||||
TAGS_MODULE_ADD(BLOCKQUOTE)
|
||||
TAGS_MODULE_ADD(SUBSUP)
|
||||
TAGS_MODULE_ADD(DoNothing)
|
||||
|
||||
TAGS_MODULE_END(Layout)
|
||||
|
||||
#endif
|
107
wxWidgets/src/html/m_links.cpp
Normal file
107
wxWidgets/src/html/m_links.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/m_links.cpp
|
||||
// Purpose: wxHtml module for links & anchors
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: m_links.cpp 38788 2006-04-18 08:11:26Z ABX $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#endif
|
||||
|
||||
#include "wx/html/forcelnk.h"
|
||||
#include "wx/html/m_templ.h"
|
||||
|
||||
|
||||
FORCE_LINK_ME(m_links)
|
||||
|
||||
|
||||
class wxHtmlAnchorCell : public wxHtmlCell
|
||||
{
|
||||
private:
|
||||
wxString m_AnchorName;
|
||||
|
||||
public:
|
||||
wxHtmlAnchorCell(const wxString& name) : wxHtmlCell()
|
||||
{ m_AnchorName = name; }
|
||||
void Draw(wxDC& WXUNUSED(dc),
|
||||
int WXUNUSED(x), int WXUNUSED(y),
|
||||
int WXUNUSED(view_y1), int WXUNUSED(view_y2),
|
||||
wxHtmlRenderingInfo& WXUNUSED(info)) {}
|
||||
|
||||
virtual const wxHtmlCell* Find(int condition, const void* param) const
|
||||
{
|
||||
if ((condition == wxHTML_COND_ISANCHOR) &&
|
||||
(m_AnchorName == (*((const wxString*)param))))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
return wxHtmlCell::Find(condition, param);
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxHtmlAnchorCell)
|
||||
};
|
||||
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(A, "A")
|
||||
TAG_HANDLER_CONSTR(A) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
if (tag.HasParam( wxT("NAME") ))
|
||||
{
|
||||
m_WParser->GetContainer()->InsertCell(new wxHtmlAnchorCell(tag.GetParam( wxT("NAME") )));
|
||||
}
|
||||
|
||||
if (tag.HasParam( wxT("HREF") ))
|
||||
{
|
||||
wxHtmlLinkInfo oldlnk = m_WParser->GetLink();
|
||||
wxColour oldclr = m_WParser->GetActualColor();
|
||||
int oldund = m_WParser->GetFontUnderlined();
|
||||
wxString name(tag.GetParam( wxT("HREF") )), target;
|
||||
|
||||
if (tag.HasParam( wxT("TARGET") )) target = tag.GetParam( wxT("TARGET") );
|
||||
m_WParser->SetActualColor(m_WParser->GetLinkColor());
|
||||
m_WParser->GetContainer()->InsertCell(new wxHtmlColourCell(m_WParser->GetLinkColor()));
|
||||
m_WParser->SetFontUnderlined(true);
|
||||
m_WParser->GetContainer()->InsertCell(new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
m_WParser->SetLink(wxHtmlLinkInfo(name, target));
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
m_WParser->SetLink(oldlnk);
|
||||
m_WParser->SetFontUnderlined(oldund);
|
||||
m_WParser->GetContainer()->InsertCell(new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
m_WParser->SetActualColor(oldclr);
|
||||
m_WParser->GetContainer()->InsertCell(new wxHtmlColourCell(oldclr));
|
||||
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(A)
|
||||
|
||||
|
||||
|
||||
TAGS_MODULE_BEGIN(Links)
|
||||
|
||||
TAGS_MODULE_ADD(A)
|
||||
|
||||
TAGS_MODULE_END(Links)
|
||||
|
||||
|
||||
#endif
|
307
wxWidgets/src/html/m_list.cpp
Normal file
307
wxWidgets/src/html/m_list.cpp
Normal file
|
@ -0,0 +1,307 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/m_list.cpp
|
||||
// Purpose: wxHtml module for lists
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: m_list.cpp 38788 2006-04-18 08:11:26Z ABX $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#include "wx/brush.h"
|
||||
#include "wx/dc.h"
|
||||
#endif
|
||||
|
||||
#include "wx/html/forcelnk.h"
|
||||
#include "wx/html/m_templ.h"
|
||||
|
||||
#include "wx/html/htmlcell.h"
|
||||
|
||||
FORCE_LINK_ME(m_list)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlListmarkCell
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class wxHtmlListmarkCell : public wxHtmlCell
|
||||
{
|
||||
private:
|
||||
wxBrush m_Brush;
|
||||
public:
|
||||
wxHtmlListmarkCell(wxDC *dc, const wxColour& clr);
|
||||
void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
|
||||
wxHtmlRenderingInfo& info);
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxHtmlListmarkCell)
|
||||
};
|
||||
|
||||
wxHtmlListmarkCell::wxHtmlListmarkCell(wxDC* dc, const wxColour& clr) : wxHtmlCell(), m_Brush(clr, wxSOLID)
|
||||
{
|
||||
m_Width = dc->GetCharHeight();
|
||||
m_Height = dc->GetCharHeight();
|
||||
// bottom of list mark is lined with bottom of letters in next cell
|
||||
m_Descent = m_Height / 3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlListmarkCell::Draw(wxDC& dc, int x, int y,
|
||||
int WXUNUSED(view_y1), int WXUNUSED(view_y2),
|
||||
wxHtmlRenderingInfo& WXUNUSED(info))
|
||||
{
|
||||
dc.SetBrush(m_Brush);
|
||||
dc.DrawEllipse(x + m_PosX + m_Width / 3, y + m_PosY + m_Height / 3,
|
||||
(m_Width / 3), (m_Width / 3));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlListCell
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct wxHtmlListItemStruct
|
||||
{
|
||||
wxHtmlContainerCell *mark;
|
||||
wxHtmlContainerCell *cont;
|
||||
int minWidth;
|
||||
int maxWidth;
|
||||
};
|
||||
|
||||
class wxHtmlListCell : public wxHtmlContainerCell
|
||||
{
|
||||
private:
|
||||
wxBrush m_Brush;
|
||||
|
||||
int m_NumRows;
|
||||
wxHtmlListItemStruct *m_RowInfo;
|
||||
void ReallocRows(int rows);
|
||||
void ComputeMinMaxWidths();
|
||||
int ComputeMaxBase(wxHtmlCell *cell);
|
||||
int m_ListmarkWidth;
|
||||
|
||||
public:
|
||||
wxHtmlListCell(wxHtmlContainerCell *parent);
|
||||
virtual ~wxHtmlListCell();
|
||||
void AddRow(wxHtmlContainerCell *mark, wxHtmlContainerCell *cont);
|
||||
virtual void Layout(int w);
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxHtmlListCell)
|
||||
};
|
||||
|
||||
wxHtmlListCell::wxHtmlListCell(wxHtmlContainerCell *parent) : wxHtmlContainerCell(parent)
|
||||
{
|
||||
m_NumRows = 0;
|
||||
m_RowInfo = 0;
|
||||
m_ListmarkWidth = 0;
|
||||
}
|
||||
|
||||
wxHtmlListCell::~wxHtmlListCell()
|
||||
{
|
||||
if (m_RowInfo) free(m_RowInfo);
|
||||
}
|
||||
|
||||
int wxHtmlListCell::ComputeMaxBase(wxHtmlCell *cell)
|
||||
{
|
||||
if(!cell)
|
||||
return 0;
|
||||
|
||||
wxHtmlCell *child = cell->GetFirstChild();
|
||||
|
||||
while(child)
|
||||
{
|
||||
int base = ComputeMaxBase( child );
|
||||
if ( base > 0 ) return base + child->GetPosY();
|
||||
child = child->GetNext();
|
||||
}
|
||||
|
||||
return cell->GetHeight() - cell->GetDescent();
|
||||
}
|
||||
|
||||
void wxHtmlListCell::Layout(int w)
|
||||
{
|
||||
wxHtmlCell::Layout(w);
|
||||
|
||||
ComputeMinMaxWidths();
|
||||
m_Width = wxMax(m_Width, wxMin(w, GetMaxTotalWidth()));
|
||||
|
||||
int s_width = m_Width - m_IndentLeft;
|
||||
|
||||
int vpos = 0;
|
||||
for (int r = 0; r < m_NumRows; r++)
|
||||
{
|
||||
// do layout first time to layout contents and adjust pos
|
||||
m_RowInfo[r].mark->Layout(m_ListmarkWidth);
|
||||
m_RowInfo[r].cont->Layout(s_width - m_ListmarkWidth);
|
||||
|
||||
const int base_mark = ComputeMaxBase( m_RowInfo[r].mark );
|
||||
const int base_cont = ComputeMaxBase( m_RowInfo[r].cont );
|
||||
const int adjust_mark = vpos + wxMax(base_cont-base_mark,0);
|
||||
const int adjust_cont = vpos + wxMax(base_mark-base_cont,0);
|
||||
|
||||
m_RowInfo[r].mark->SetPos(m_IndentLeft, adjust_mark);
|
||||
m_RowInfo[r].cont->SetPos(m_IndentLeft + m_ListmarkWidth, adjust_cont);
|
||||
|
||||
vpos = wxMax(adjust_mark + m_RowInfo[r].mark->GetHeight(),
|
||||
adjust_cont + m_RowInfo[r].cont->GetHeight());
|
||||
}
|
||||
m_Height = vpos;
|
||||
}
|
||||
|
||||
void wxHtmlListCell::AddRow(wxHtmlContainerCell *mark, wxHtmlContainerCell *cont)
|
||||
{
|
||||
ReallocRows(++m_NumRows);
|
||||
m_RowInfo[m_NumRows - 1].mark = mark;
|
||||
m_RowInfo[m_NumRows - 1].cont = cont;
|
||||
}
|
||||
|
||||
void wxHtmlListCell::ReallocRows(int rows)
|
||||
{
|
||||
m_RowInfo = (wxHtmlListItemStruct*) realloc(m_RowInfo, sizeof(wxHtmlListItemStruct) * rows);
|
||||
m_RowInfo[rows - 1].mark = NULL;
|
||||
m_RowInfo[rows - 1].cont = NULL;
|
||||
m_RowInfo[rows - 1].minWidth = 0;
|
||||
m_RowInfo[rows - 1].maxWidth = 0;
|
||||
|
||||
m_NumRows = rows;
|
||||
}
|
||||
|
||||
void wxHtmlListCell::ComputeMinMaxWidths()
|
||||
{
|
||||
if (m_NumRows == 0) return;
|
||||
|
||||
m_MaxTotalWidth = 0;
|
||||
m_Width = 0;
|
||||
|
||||
for (int r = 0; r < m_NumRows; r++)
|
||||
{
|
||||
wxHtmlListItemStruct& row = m_RowInfo[r];
|
||||
row.mark->Layout(1);
|
||||
row.cont->Layout(1);
|
||||
int maxWidth = row.cont->GetMaxTotalWidth();
|
||||
int width = row.cont->GetWidth();
|
||||
if (row.mark->GetWidth() > m_ListmarkWidth)
|
||||
m_ListmarkWidth = row.mark->GetWidth();
|
||||
if (maxWidth > m_MaxTotalWidth)
|
||||
m_MaxTotalWidth = maxWidth;
|
||||
if (width > m_Width)
|
||||
m_Width = width;
|
||||
}
|
||||
m_Width += m_ListmarkWidth + m_IndentLeft;
|
||||
m_MaxTotalWidth += m_ListmarkWidth + m_IndentLeft;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlListcontentCell
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class wxHtmlListcontentCell : public wxHtmlContainerCell
|
||||
{
|
||||
public:
|
||||
wxHtmlListcontentCell(wxHtmlContainerCell *p) : wxHtmlContainerCell(p) {}
|
||||
virtual void Layout(int w) {
|
||||
// Reset top indentation, fixes <li><p>
|
||||
SetIndent(0, wxHTML_INDENT_TOP);
|
||||
wxHtmlContainerCell::Layout(w);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The list handler:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(OLULLI, "OL,UL,LI")
|
||||
|
||||
TAG_HANDLER_VARS
|
||||
wxHtmlListCell *m_List;
|
||||
int m_Numbering;
|
||||
// this is number of actual item of list or 0 for dots
|
||||
|
||||
TAG_HANDLER_CONSTR(OLULLI)
|
||||
{
|
||||
m_List = NULL;
|
||||
m_Numbering = 0;
|
||||
}
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
wxHtmlContainerCell *c;
|
||||
|
||||
// List Item:
|
||||
if (m_List && tag.GetName() == wxT("LI"))
|
||||
{
|
||||
c = m_WParser->SetContainer(new wxHtmlContainerCell(m_List));
|
||||
c->SetAlignVer(wxHTML_ALIGN_TOP);
|
||||
|
||||
wxHtmlContainerCell *mark = c;
|
||||
c->SetWidthFloat(2 * m_WParser->GetCharWidth(), wxHTML_UNITS_PIXELS);
|
||||
if (m_Numbering == 0)
|
||||
{
|
||||
// Centering gives more space after the bullet
|
||||
c->SetAlignHor(wxHTML_ALIGN_CENTER);
|
||||
c->InsertCell(new wxHtmlListmarkCell(m_WParser->GetDC(), m_WParser->GetActualColor()));
|
||||
}
|
||||
else
|
||||
{
|
||||
c->SetAlignHor(wxHTML_ALIGN_RIGHT);
|
||||
wxString markStr;
|
||||
markStr.Printf(wxT("%i. "), m_Numbering);
|
||||
c->InsertCell(new wxHtmlWordCell(markStr, *(m_WParser->GetDC())));
|
||||
}
|
||||
m_WParser->CloseContainer();
|
||||
|
||||
c = m_WParser->OpenContainer();
|
||||
|
||||
m_List->AddRow(mark, c);
|
||||
c = m_WParser->OpenContainer();
|
||||
m_WParser->SetContainer(new wxHtmlListcontentCell(c));
|
||||
|
||||
if (m_Numbering != 0) m_Numbering++;
|
||||
}
|
||||
|
||||
// Begin of List (not-numbered): "UL", "OL"
|
||||
else if (tag.GetName() == wxT("UL") || tag.GetName() == wxT("OL"))
|
||||
{
|
||||
int oldnum = m_Numbering;
|
||||
|
||||
if (tag.GetName() == wxT("UL")) m_Numbering = 0;
|
||||
else m_Numbering = 1;
|
||||
|
||||
wxHtmlContainerCell *oldcont;
|
||||
oldcont = c = m_WParser->OpenContainer();
|
||||
|
||||
wxHtmlListCell *oldList = m_List;
|
||||
m_List = new wxHtmlListCell(c);
|
||||
m_List->SetIndent(2 * m_WParser->GetCharWidth(), wxHTML_INDENT_LEFT);
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
m_WParser->SetContainer(oldcont);
|
||||
m_WParser->CloseContainer();
|
||||
|
||||
m_Numbering = oldnum;
|
||||
m_List = oldList;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(OLULLI)
|
||||
|
||||
|
||||
TAGS_MODULE_BEGIN(List)
|
||||
|
||||
TAGS_MODULE_ADD(OLULLI)
|
||||
|
||||
TAGS_MODULE_END(List)
|
||||
|
||||
#endif
|
144
wxWidgets/src/html/m_pre.cpp
Normal file
144
wxWidgets/src/html/m_pre.cpp
Normal file
|
@ -0,0 +1,144 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/m_pre.cpp
|
||||
// Purpose: wxHtml module for <PRE> ... </PRE> tag (code citation)
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: m_pre.cpp 56547 2008-10-28 10:06:32Z VS $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#endif
|
||||
|
||||
#include "wx/html/forcelnk.h"
|
||||
#include "wx/html/m_templ.h"
|
||||
|
||||
#include "wx/html/htmlcell.h"
|
||||
#include "wx/tokenzr.h"
|
||||
#include "wx/encconv.h"
|
||||
|
||||
FORCE_LINK_ME(m_pre)
|
||||
|
||||
// replaces '\t', ' ' and '\n' with HTML markup:
|
||||
static wxString LINKAGEMODE HtmlizeLinebreaks(const wxString& str)
|
||||
{
|
||||
wxString out;
|
||||
out.reserve(str.length()); // we'll certainly need at least that
|
||||
|
||||
size_t len = str.Len();
|
||||
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
switch (str[i])
|
||||
{
|
||||
case wxT('<'):
|
||||
while (i < len && str[i] != wxT('>'))
|
||||
{
|
||||
out << str[i++];
|
||||
}
|
||||
out << wxT('>');
|
||||
break;
|
||||
|
||||
// We need to translate any line break into exactly one <br>.
|
||||
// Quoting HTML spec: "A line break is defined to be a carriage
|
||||
// return (
), a line feed (
), or a carriage
|
||||
// return/line feed pair."
|
||||
case wxT('\r'):
|
||||
{
|
||||
size_t j = i + 1;
|
||||
if ( j < len && str[j] == wxT('\n') )
|
||||
i = j;
|
||||
}
|
||||
// fall through
|
||||
case wxT('\n'):
|
||||
out << wxT("<br>");
|
||||
break;
|
||||
|
||||
default:
|
||||
out << str[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The list handler:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(PRE, "PRE")
|
||||
TAG_HANDLER_CONSTR(PRE) { }
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
wxHtmlContainerCell *c;
|
||||
|
||||
const int fixed = m_WParser->GetFontFixed();
|
||||
const int italic = m_WParser->GetFontItalic();
|
||||
const int underlined = m_WParser->GetFontUnderlined();
|
||||
const int bold = m_WParser->GetFontBold();
|
||||
const int fsize = m_WParser->GetFontSize();
|
||||
const wxHtmlWinParser::WhitespaceMode whitespace =
|
||||
m_WParser->GetWhitespaceMode();
|
||||
|
||||
c = m_WParser->GetContainer();
|
||||
m_WParser->SetWhitespaceMode(wxHtmlWinParser::Whitespace_Pre);
|
||||
m_WParser->SetFontUnderlined(false);
|
||||
m_WParser->SetFontBold(false);
|
||||
m_WParser->SetFontItalic(false);
|
||||
m_WParser->SetFontFixed(true);
|
||||
m_WParser->SetFontSize(3);
|
||||
c->InsertCell(new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
|
||||
m_WParser->CloseContainer();
|
||||
c = m_WParser->OpenContainer();
|
||||
c->SetWidthFloat(tag);
|
||||
c = m_WParser->OpenContainer();
|
||||
c->SetAlignHor(wxHTML_ALIGN_LEFT);
|
||||
c->SetIndent(m_WParser->GetCharHeight(), wxHTML_INDENT_TOP);
|
||||
|
||||
wxString srcMid = m_WParser->GetInnerSource(tag);
|
||||
|
||||
// setting Whitespace_Pre mode takes care of spaces and TABs, but
|
||||
// not linebreaks, so we have to translate them into <br> by
|
||||
// calling HtmlizeLinebreaks() here
|
||||
ParseInnerSource(HtmlizeLinebreaks(srcMid));
|
||||
|
||||
m_WParser->CloseContainer();
|
||||
m_WParser->CloseContainer();
|
||||
c = m_WParser->OpenContainer();
|
||||
|
||||
m_WParser->SetWhitespaceMode(whitespace);
|
||||
m_WParser->SetFontUnderlined(underlined);
|
||||
m_WParser->SetFontBold(bold);
|
||||
m_WParser->SetFontItalic(italic);
|
||||
m_WParser->SetFontFixed(fixed);
|
||||
m_WParser->SetFontSize(fsize);
|
||||
c->InsertCell(new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(PRE)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TAGS_MODULE_BEGIN(Pre)
|
||||
|
||||
TAGS_MODULE_ADD(PRE)
|
||||
|
||||
TAGS_MODULE_END(Pre)
|
||||
|
||||
#endif
|
46
wxWidgets/src/html/m_style.cpp
Normal file
46
wxWidgets/src/html/m_style.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/m_style.cpp
|
||||
// Purpose: wxHtml module for parsing <style> tag
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: m_style.cpp 38788 2006-04-18 08:11:26Z ABX $
|
||||
// Copyright: (c) 2002 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#endif
|
||||
|
||||
#include "wx/html/forcelnk.h"
|
||||
#include "wx/html/m_templ.h"
|
||||
|
||||
FORCE_LINK_ME(m_style)
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(STYLE, "STYLE")
|
||||
TAG_HANDLER_CONSTR(STYLE) { }
|
||||
|
||||
TAG_HANDLER_PROC(WXUNUSED(tag))
|
||||
{
|
||||
// VS: Ignore styles for now. We must have this handler present,
|
||||
// because CSS style text would be rendered verbatim otherwise
|
||||
return true;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(STYLE)
|
||||
|
||||
|
||||
TAGS_MODULE_BEGIN(StyleTag)
|
||||
|
||||
TAGS_MODULE_ADD(STYLE)
|
||||
|
||||
TAGS_MODULE_END(StyleTag)
|
||||
|
||||
#endif
|
799
wxWidgets/src/html/m_tables.cpp
Normal file
799
wxWidgets/src/html/m_tables.cpp
Normal file
|
@ -0,0 +1,799 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/m_tables.cpp
|
||||
// Purpose: wxHtml module for tables
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: m_tables.cpp 59687 2009-03-21 09:41:09Z VS $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#endif
|
||||
|
||||
#include "wx/html/forcelnk.h"
|
||||
#include "wx/html/m_templ.h"
|
||||
|
||||
#include "wx/html/htmlcell.h"
|
||||
|
||||
FORCE_LINK_ME(m_tables)
|
||||
|
||||
|
||||
#define TABLE_BORDER_CLR_1 wxColour(0xC5, 0xC2, 0xC5)
|
||||
#define TABLE_BORDER_CLR_2 wxColour(0x62, 0x61, 0x62)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlTableCell
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
struct colStruct
|
||||
{
|
||||
int width, units;
|
||||
// width of the column either in pixels or percents
|
||||
// ('width' is the number, 'units' determines its meaning)
|
||||
int minWidth, maxWidth;
|
||||
// minimal/maximal column width. This is needed by HTML 4.0
|
||||
// layouting algorithm and can be determined by trying to
|
||||
// layout table cells with width=1 and width=infinity
|
||||
int leftpos, pixwidth, maxrealwidth;
|
||||
// temporary (depends on actual width of table)
|
||||
};
|
||||
|
||||
enum cellState
|
||||
{
|
||||
cellSpan,
|
||||
cellUsed,
|
||||
cellFree
|
||||
};
|
||||
|
||||
struct cellStruct
|
||||
{
|
||||
wxHtmlContainerCell *cont;
|
||||
int colspan, rowspan;
|
||||
int minheight, valign;
|
||||
cellState flag;
|
||||
bool nowrap;
|
||||
};
|
||||
|
||||
|
||||
class wxHtmlTableCell : public wxHtmlContainerCell
|
||||
{
|
||||
protected:
|
||||
/* These are real attributes: */
|
||||
|
||||
// should we draw borders or not?
|
||||
bool m_HasBorders;
|
||||
// number of columns; rows
|
||||
int m_NumCols, m_NumRows;
|
||||
// array of column information
|
||||
colStruct *m_ColsInfo;
|
||||
// 2D array of all cells in the table : m_CellInfo[row][column]
|
||||
cellStruct **m_CellInfo;
|
||||
// spaces between cells
|
||||
int m_Spacing;
|
||||
// cells internal indentation
|
||||
int m_Padding;
|
||||
|
||||
private:
|
||||
/* ...and these are valid only when parsing the table: */
|
||||
|
||||
// number of actual column (ranging from 0..m_NumCols)
|
||||
int m_ActualCol, m_ActualRow;
|
||||
|
||||
// default values (for table and row):
|
||||
wxColour m_tBkg, m_rBkg;
|
||||
wxString m_tValign, m_rValign;
|
||||
|
||||
double m_PixelScale;
|
||||
|
||||
|
||||
public:
|
||||
wxHtmlTableCell(wxHtmlContainerCell *parent, const wxHtmlTag& tag, double pixel_scale = 1.0);
|
||||
virtual ~wxHtmlTableCell();
|
||||
|
||||
virtual void RemoveExtraSpacing(bool top, bool bottom);
|
||||
|
||||
virtual void Layout(int w);
|
||||
|
||||
void AddRow(const wxHtmlTag& tag);
|
||||
void AddCell(wxHtmlContainerCell *cell, const wxHtmlTag& tag);
|
||||
|
||||
private:
|
||||
// Reallocates memory to given number of cols/rows
|
||||
// and changes m_NumCols/m_NumRows value to reflect this change
|
||||
// NOTE! You CAN'T change m_NumCols/m_NumRows before calling this!!
|
||||
void ReallocCols(int cols);
|
||||
void ReallocRows(int rows);
|
||||
|
||||
// Computes minimal and maximal widths of columns. Needs to be called
|
||||
// only once, before first Layout().
|
||||
void ComputeMinMaxWidths();
|
||||
|
||||
DECLARE_NO_COPY_CLASS(wxHtmlTableCell)
|
||||
};
|
||||
|
||||
|
||||
|
||||
wxHtmlTableCell::wxHtmlTableCell(wxHtmlContainerCell *parent, const wxHtmlTag& tag, double pixel_scale)
|
||||
: wxHtmlContainerCell(parent)
|
||||
{
|
||||
m_PixelScale = pixel_scale;
|
||||
m_HasBorders =
|
||||
(tag.HasParam(wxT("BORDER")) && tag.GetParam(wxT("BORDER")) != wxT("0"));
|
||||
m_ColsInfo = NULL;
|
||||
m_NumCols = m_NumRows = 0;
|
||||
m_CellInfo = NULL;
|
||||
m_ActualCol = m_ActualRow = -1;
|
||||
|
||||
/* scan params: */
|
||||
if (tag.HasParam(wxT("BGCOLOR")))
|
||||
{
|
||||
tag.GetParamAsColour(wxT("BGCOLOR"), &m_tBkg);
|
||||
if (m_tBkg.Ok())
|
||||
SetBackgroundColour(m_tBkg);
|
||||
}
|
||||
if (tag.HasParam(wxT("VALIGN")))
|
||||
m_tValign = tag.GetParam(wxT("VALIGN"));
|
||||
else
|
||||
m_tValign = wxEmptyString;
|
||||
if (!tag.GetParamAsInt(wxT("CELLSPACING"), &m_Spacing))
|
||||
m_Spacing = 2;
|
||||
if (!tag.GetParamAsInt(wxT("CELLPADDING"), &m_Padding))
|
||||
m_Padding = 3;
|
||||
m_Spacing = (int)(m_PixelScale * (double)m_Spacing);
|
||||
m_Padding = (int)(m_PixelScale * (double)m_Padding);
|
||||
|
||||
if (m_HasBorders)
|
||||
SetBorder(TABLE_BORDER_CLR_1, TABLE_BORDER_CLR_2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxHtmlTableCell::~wxHtmlTableCell()
|
||||
{
|
||||
if (m_ColsInfo) free(m_ColsInfo);
|
||||
if (m_CellInfo)
|
||||
{
|
||||
for (int i = 0; i < m_NumRows; i++)
|
||||
free(m_CellInfo[i]);
|
||||
free(m_CellInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wxHtmlTableCell::RemoveExtraSpacing(bool WXUNUSED(top),
|
||||
bool WXUNUSED(bottom))
|
||||
{
|
||||
// Don't remove any spacing in the table -- it's always desirable,
|
||||
// because it's part of table's definition.
|
||||
// (If wxHtmlContainerCell::RemoveExtraSpacing() was applied to tables,
|
||||
// then upper left cell of a table would be positioned above other cells
|
||||
// if the table was the first element on the page.)
|
||||
}
|
||||
|
||||
void wxHtmlTableCell::ReallocCols(int cols)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for (i = 0; i < m_NumRows; i++)
|
||||
{
|
||||
m_CellInfo[i] = (cellStruct*) realloc(m_CellInfo[i], sizeof(cellStruct) * cols);
|
||||
for (j = m_NumCols; j < cols; j++)
|
||||
m_CellInfo[i][j].flag = cellFree;
|
||||
}
|
||||
|
||||
m_ColsInfo = (colStruct*) realloc(m_ColsInfo, sizeof(colStruct) * cols);
|
||||
for (j = m_NumCols; j < cols; j++)
|
||||
{
|
||||
m_ColsInfo[j].width = 0;
|
||||
m_ColsInfo[j].units = wxHTML_UNITS_PERCENT;
|
||||
m_ColsInfo[j].minWidth = m_ColsInfo[j].maxWidth = -1;
|
||||
}
|
||||
|
||||
m_NumCols = cols;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlTableCell::ReallocRows(int rows)
|
||||
{
|
||||
m_CellInfo = (cellStruct**) realloc(m_CellInfo, sizeof(cellStruct*) * rows);
|
||||
for (int row = m_NumRows; row < rows ; row++)
|
||||
{
|
||||
if (m_NumCols == 0)
|
||||
m_CellInfo[row] = NULL;
|
||||
else
|
||||
{
|
||||
m_CellInfo[row] = (cellStruct*) malloc(sizeof(cellStruct) * m_NumCols);
|
||||
for (int col = 0; col < m_NumCols; col++)
|
||||
m_CellInfo[row][col].flag = cellFree;
|
||||
}
|
||||
}
|
||||
m_NumRows = rows;
|
||||
}
|
||||
|
||||
|
||||
void wxHtmlTableCell::AddRow(const wxHtmlTag& tag)
|
||||
{
|
||||
m_ActualCol = -1;
|
||||
// VS: real allocation of row entry is done in AddCell in order
|
||||
// to correctly handle empty rows (i.e. "<tr></tr>")
|
||||
// m_ActualCol == -1 indicates that AddCell has to allocate new row.
|
||||
|
||||
// scan params:
|
||||
m_rBkg = m_tBkg;
|
||||
if (tag.HasParam(wxT("BGCOLOR")))
|
||||
tag.GetParamAsColour(wxT("BGCOLOR"), &m_rBkg);
|
||||
if (tag.HasParam(wxT("VALIGN")))
|
||||
m_rValign = tag.GetParam(wxT("VALIGN"));
|
||||
else
|
||||
m_rValign = m_tValign;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlTableCell::AddCell(wxHtmlContainerCell *cell, const wxHtmlTag& tag)
|
||||
{
|
||||
// Is this cell in new row?
|
||||
// VS: we can't do it in AddRow, see my comment there
|
||||
if (m_ActualCol == -1)
|
||||
{
|
||||
if (m_ActualRow + 1 > m_NumRows - 1)
|
||||
ReallocRows(m_ActualRow + 2);
|
||||
m_ActualRow++;
|
||||
}
|
||||
|
||||
// cells & columns:
|
||||
do
|
||||
{
|
||||
m_ActualCol++;
|
||||
} while ((m_ActualCol < m_NumCols) &&
|
||||
(m_CellInfo[m_ActualRow][m_ActualCol].flag != cellFree));
|
||||
|
||||
if (m_ActualCol > m_NumCols - 1)
|
||||
ReallocCols(m_ActualCol + 1);
|
||||
|
||||
int r = m_ActualRow, c = m_ActualCol;
|
||||
|
||||
m_CellInfo[r][c].cont = cell;
|
||||
m_CellInfo[r][c].colspan = 1;
|
||||
m_CellInfo[r][c].rowspan = 1;
|
||||
m_CellInfo[r][c].flag = cellUsed;
|
||||
m_CellInfo[r][c].minheight = 0;
|
||||
m_CellInfo[r][c].valign = wxHTML_ALIGN_TOP;
|
||||
|
||||
/* scan for parameters: */
|
||||
|
||||
// width:
|
||||
{
|
||||
if (tag.HasParam(wxT("WIDTH")))
|
||||
{
|
||||
wxString wd = tag.GetParam(wxT("WIDTH"));
|
||||
|
||||
if (wd[wd.length()-1] == wxT('%'))
|
||||
{
|
||||
if ( wxSscanf(wd.c_str(), wxT("%i%%"), &m_ColsInfo[c].width) == 1 )
|
||||
{
|
||||
m_ColsInfo[c].units = wxHTML_UNITS_PERCENT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
long width;
|
||||
if ( wd.ToLong(&width) )
|
||||
{
|
||||
m_ColsInfo[c].width = (int)(m_PixelScale * (double)width);
|
||||
m_ColsInfo[c].units = wxHTML_UNITS_PIXELS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// spanning:
|
||||
{
|
||||
tag.GetParamAsInt(wxT("COLSPAN"), &m_CellInfo[r][c].colspan);
|
||||
tag.GetParamAsInt(wxT("ROWSPAN"), &m_CellInfo[r][c].rowspan);
|
||||
|
||||
// VS: the standard says this about col/rowspan:
|
||||
// "This attribute specifies the number of rows spanned by the
|
||||
// current cell. The default value of this attribute is one ("1").
|
||||
// The value zero ("0") means that the cell spans all rows from the
|
||||
// current row to the last row of the table." All mainstream
|
||||
// browsers act as if 0==1, though, and so does wxHTML.
|
||||
if (m_CellInfo[r][c].colspan < 1)
|
||||
m_CellInfo[r][c].colspan = 1;
|
||||
if (m_CellInfo[r][c].rowspan < 1)
|
||||
m_CellInfo[r][c].rowspan = 1;
|
||||
|
||||
if ((m_CellInfo[r][c].colspan > 1) || (m_CellInfo[r][c].rowspan > 1))
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (r + m_CellInfo[r][c].rowspan > m_NumRows)
|
||||
ReallocRows(r + m_CellInfo[r][c].rowspan);
|
||||
if (c + m_CellInfo[r][c].colspan > m_NumCols)
|
||||
ReallocCols(c + m_CellInfo[r][c].colspan);
|
||||
for (i = r; i < r + m_CellInfo[r][c].rowspan; i++)
|
||||
for (j = c; j < c + m_CellInfo[r][c].colspan; j++)
|
||||
m_CellInfo[i][j].flag = cellSpan;
|
||||
m_CellInfo[r][c].flag = cellUsed;
|
||||
}
|
||||
}
|
||||
|
||||
//background color:
|
||||
{
|
||||
wxColour bk = m_rBkg;
|
||||
if (tag.HasParam(wxT("BGCOLOR")))
|
||||
tag.GetParamAsColour(wxT("BGCOLOR"), &bk);
|
||||
if (bk.Ok())
|
||||
cell->SetBackgroundColour(bk);
|
||||
}
|
||||
if (m_HasBorders)
|
||||
cell->SetBorder(TABLE_BORDER_CLR_2, TABLE_BORDER_CLR_1);
|
||||
|
||||
// vertical alignment:
|
||||
{
|
||||
wxString valign;
|
||||
if (tag.HasParam(wxT("VALIGN")))
|
||||
valign = tag.GetParam(wxT("VALIGN"));
|
||||
else
|
||||
valign = m_tValign;
|
||||
valign.MakeUpper();
|
||||
if (valign == wxT("TOP"))
|
||||
m_CellInfo[r][c].valign = wxHTML_ALIGN_TOP;
|
||||
else if (valign == wxT("BOTTOM"))
|
||||
m_CellInfo[r][c].valign = wxHTML_ALIGN_BOTTOM;
|
||||
else m_CellInfo[r][c].valign = wxHTML_ALIGN_CENTER;
|
||||
}
|
||||
|
||||
// nowrap
|
||||
if (tag.HasParam(wxT("NOWRAP")))
|
||||
m_CellInfo[r][c].nowrap = true;
|
||||
else
|
||||
m_CellInfo[r][c].nowrap = false;
|
||||
|
||||
cell->SetIndent(m_Padding, wxHTML_INDENT_ALL, wxHTML_UNITS_PIXELS);
|
||||
}
|
||||
|
||||
void wxHtmlTableCell::ComputeMinMaxWidths()
|
||||
{
|
||||
if (m_NumCols == 0 || m_ColsInfo[0].minWidth != wxDefaultCoord) return;
|
||||
|
||||
m_MaxTotalWidth = 0;
|
||||
int percentage = 0;
|
||||
for (int c = 0; c < m_NumCols; c++)
|
||||
{
|
||||
for (int r = 0; r < m_NumRows; r++)
|
||||
{
|
||||
cellStruct& cell = m_CellInfo[r][c];
|
||||
if (cell.flag == cellUsed)
|
||||
{
|
||||
cell.cont->Layout(2*m_Padding + 1);
|
||||
int maxWidth = cell.cont->GetMaxTotalWidth();
|
||||
int width = cell.nowrap?maxWidth:cell.cont->GetWidth();
|
||||
width -= (cell.colspan-1) * m_Spacing;
|
||||
maxWidth -= (cell.colspan-1) * m_Spacing;
|
||||
// HTML 4.0 says it is acceptable to distribute min/max
|
||||
width /= cell.colspan;
|
||||
maxWidth /= cell.colspan;
|
||||
for (int j = 0; j < cell.colspan; j++) {
|
||||
if (width > m_ColsInfo[c+j].minWidth)
|
||||
m_ColsInfo[c+j].minWidth = width;
|
||||
if (maxWidth > m_ColsInfo[c+j].maxWidth)
|
||||
m_ColsInfo[c+j].maxWidth = maxWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Calculate maximum table width, required for nested tables
|
||||
if (m_ColsInfo[c].units == wxHTML_UNITS_PIXELS)
|
||||
m_MaxTotalWidth += wxMax(m_ColsInfo[c].width, m_ColsInfo[c].minWidth);
|
||||
else if ((m_ColsInfo[c].units == wxHTML_UNITS_PERCENT) && (m_ColsInfo[c].width != 0))
|
||||
percentage += m_ColsInfo[c].width;
|
||||
else
|
||||
m_MaxTotalWidth += m_ColsInfo[c].maxWidth;
|
||||
}
|
||||
|
||||
if (percentage >= 100)
|
||||
{
|
||||
// Table would have infinite length
|
||||
// Make it ridiculous large
|
||||
m_MaxTotalWidth = 0xFFFFFF;
|
||||
}
|
||||
else
|
||||
m_MaxTotalWidth = m_MaxTotalWidth * 100 / (100 - percentage);
|
||||
|
||||
m_MaxTotalWidth += (m_NumCols + 1) * m_Spacing;
|
||||
}
|
||||
|
||||
void wxHtmlTableCell::Layout(int w)
|
||||
{
|
||||
ComputeMinMaxWidths();
|
||||
|
||||
wxHtmlCell::Layout(w);
|
||||
|
||||
/*
|
||||
|
||||
WIDTH ADJUSTING :
|
||||
|
||||
*/
|
||||
|
||||
if (m_WidthFloatUnits == wxHTML_UNITS_PERCENT)
|
||||
{
|
||||
if (m_WidthFloat < 0)
|
||||
{
|
||||
if (m_WidthFloat < -100)
|
||||
m_WidthFloat = -100;
|
||||
m_Width = (100 + m_WidthFloat) * w / 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_WidthFloat > 100)
|
||||
m_WidthFloat = 100;
|
||||
m_Width = m_WidthFloat * w / 100;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_WidthFloat < 0) m_Width = w + m_WidthFloat;
|
||||
else m_Width = m_WidthFloat;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
LAYOUTING :
|
||||
|
||||
*/
|
||||
|
||||
/* 1. setup columns widths:
|
||||
|
||||
The algorithm tries to keep the table size less than w if possible.
|
||||
*/
|
||||
{
|
||||
int wpix = m_Width - (m_NumCols + 1) * m_Spacing;
|
||||
int i, j;
|
||||
|
||||
// 1a. setup fixed-width columns:
|
||||
for (i = 0; i < m_NumCols; i++)
|
||||
if (m_ColsInfo[i].units == wxHTML_UNITS_PIXELS)
|
||||
{
|
||||
m_ColsInfo[i].pixwidth = wxMax(m_ColsInfo[i].width,
|
||||
m_ColsInfo[i].minWidth);
|
||||
wpix -= m_ColsInfo[i].pixwidth;
|
||||
}
|
||||
|
||||
// 1b. Calculate maximum possible width if line wrapping would be disabled
|
||||
// Recalculate total width if m_WidthFloat is zero to keep tables as small
|
||||
// as possible.
|
||||
int maxWidth = 0;
|
||||
for (i = 0; i < m_NumCols; i++)
|
||||
if (m_ColsInfo[i].width == 0)
|
||||
{
|
||||
maxWidth += m_ColsInfo[i].maxWidth;
|
||||
}
|
||||
|
||||
if (!m_WidthFloat)
|
||||
{
|
||||
// Recalculate table width since no table width was initially given
|
||||
int newWidth = m_Width - wpix + maxWidth;
|
||||
|
||||
// Make sure that floating-width columns will have the right size.
|
||||
// Calculate sum of all floating-width columns
|
||||
int percentage = 0;
|
||||
for (i = 0; i < m_NumCols; i++)
|
||||
if ((m_ColsInfo[i].units == wxHTML_UNITS_PERCENT) && (m_ColsInfo[i].width != 0))
|
||||
percentage += m_ColsInfo[i].width;
|
||||
|
||||
if (percentage >= 100)
|
||||
newWidth = w;
|
||||
else
|
||||
newWidth = newWidth * 100 / (100 - percentage);
|
||||
|
||||
newWidth = wxMin(newWidth, w - (m_NumCols + 1) * m_Spacing);
|
||||
wpix -= m_Width - newWidth;
|
||||
m_Width = newWidth;
|
||||
}
|
||||
|
||||
|
||||
// 1c. setup floating-width columns:
|
||||
int wtemp = wpix;
|
||||
for (i = 0; i < m_NumCols; i++)
|
||||
if ((m_ColsInfo[i].units == wxHTML_UNITS_PERCENT) && (m_ColsInfo[i].width != 0))
|
||||
{
|
||||
m_ColsInfo[i].pixwidth = wxMin(m_ColsInfo[i].width, 100) * wpix / 100;
|
||||
|
||||
// Make sure to leave enough space for the other columns
|
||||
int minRequired = 0;
|
||||
for (j = 0; j < m_NumCols; j++)
|
||||
{
|
||||
if ((m_ColsInfo[j].units == wxHTML_UNITS_PERCENT && j > i) ||
|
||||
!m_ColsInfo[j].width)
|
||||
minRequired += m_ColsInfo[j].minWidth;
|
||||
}
|
||||
m_ColsInfo[i].pixwidth = wxMax(wxMin(wtemp - minRequired, m_ColsInfo[i].pixwidth), m_ColsInfo[i].minWidth);
|
||||
|
||||
wtemp -= m_ColsInfo[i].pixwidth;
|
||||
}
|
||||
wpix = wtemp;
|
||||
|
||||
// 1d. setup default columns (no width specification supplied):
|
||||
// The algorithm assigns calculates the maximum possible width if line
|
||||
// wrapping would be disabled and assigns column width as a fraction
|
||||
// based upon the maximum width of a column
|
||||
// FIXME: I'm not sure if this algorithm is conform to HTML standard,
|
||||
// though it seems to be much better than the old one
|
||||
|
||||
for (i = j = 0; i < m_NumCols; i++)
|
||||
if (m_ColsInfo[i].width == 0) j++;
|
||||
if (wpix < 0)
|
||||
wpix = 0;
|
||||
|
||||
// Assign widths
|
||||
for (i = 0; i < m_NumCols; i++)
|
||||
if (m_ColsInfo[i].width == 0)
|
||||
{
|
||||
// Assign with, make sure not to drop below minWidth
|
||||
if (maxWidth)
|
||||
m_ColsInfo[i].pixwidth = (int)(wpix * (m_ColsInfo[i].maxWidth / (float)maxWidth) + 0.5);
|
||||
else
|
||||
m_ColsInfo[i].pixwidth = wpix / j;
|
||||
|
||||
// Make sure to leave enough space for the other columns
|
||||
int minRequired = 0;
|
||||
int r;
|
||||
for (r = i + 1; r < m_NumCols; r++)
|
||||
{
|
||||
if (!m_ColsInfo[r].width)
|
||||
minRequired += m_ColsInfo[r].minWidth;
|
||||
}
|
||||
m_ColsInfo[i].pixwidth = wxMax(wxMin(wpix - minRequired, m_ColsInfo[i].pixwidth), m_ColsInfo[i].minWidth);
|
||||
|
||||
if (maxWidth)
|
||||
{
|
||||
if (m_ColsInfo[i].pixwidth > (wpix * (m_ColsInfo[i].maxWidth / (float)maxWidth) + 0.5))
|
||||
{
|
||||
int diff = (int)(m_ColsInfo[i].pixwidth - (wpix * m_ColsInfo[i].maxWidth / (float)maxWidth + 0.5));
|
||||
maxWidth += diff - m_ColsInfo[i].maxWidth;
|
||||
}
|
||||
else
|
||||
maxWidth -= m_ColsInfo[i].maxWidth;
|
||||
}
|
||||
wpix -= m_ColsInfo[i].pixwidth;
|
||||
}
|
||||
}
|
||||
|
||||
/* 2. compute positions of columns: */
|
||||
{
|
||||
int wpos = m_Spacing;
|
||||
for (int i = 0; i < m_NumCols; i++)
|
||||
{
|
||||
m_ColsInfo[i].leftpos = wpos;
|
||||
wpos += m_ColsInfo[i].pixwidth + m_Spacing;
|
||||
}
|
||||
|
||||
// add the remaining space to the last column
|
||||
if (m_NumCols > 0 && wpos < m_Width)
|
||||
m_ColsInfo[m_NumCols-1].pixwidth += m_Width - wpos;
|
||||
}
|
||||
|
||||
/* 3. sub-layout all cells: */
|
||||
{
|
||||
int *ypos = new int[m_NumRows + 1];
|
||||
|
||||
int actcol, actrow;
|
||||
int fullwid;
|
||||
wxHtmlContainerCell *actcell;
|
||||
|
||||
ypos[0] = m_Spacing;
|
||||
for (actrow = 1; actrow <= m_NumRows; actrow++) ypos[actrow] = -1;
|
||||
for (actrow = 0; actrow < m_NumRows; actrow++)
|
||||
{
|
||||
if (ypos[actrow] == -1) ypos[actrow] = ypos[actrow-1];
|
||||
// 3a. sub-layout and detect max height:
|
||||
|
||||
for (actcol = 0; actcol < m_NumCols; actcol++) {
|
||||
if (m_CellInfo[actrow][actcol].flag != cellUsed) continue;
|
||||
actcell = m_CellInfo[actrow][actcol].cont;
|
||||
fullwid = 0;
|
||||
for (int i = actcol; i < m_CellInfo[actrow][actcol].colspan + actcol; i++)
|
||||
fullwid += m_ColsInfo[i].pixwidth;
|
||||
fullwid += (m_CellInfo[actrow][actcol].colspan - 1) * m_Spacing;
|
||||
actcell->SetMinHeight(m_CellInfo[actrow][actcol].minheight, m_CellInfo[actrow][actcol].valign);
|
||||
actcell->Layout(fullwid);
|
||||
|
||||
if (ypos[actrow] + actcell->GetHeight() + m_CellInfo[actrow][actcol].rowspan * m_Spacing > ypos[actrow + m_CellInfo[actrow][actcol].rowspan])
|
||||
ypos[actrow + m_CellInfo[actrow][actcol].rowspan] =
|
||||
ypos[actrow] + actcell->GetHeight() + m_CellInfo[actrow][actcol].rowspan * m_Spacing;
|
||||
}
|
||||
}
|
||||
|
||||
for (actrow = 0; actrow < m_NumRows; actrow++)
|
||||
{
|
||||
// 3b. place cells in row & let'em all have same height:
|
||||
|
||||
for (actcol = 0; actcol < m_NumCols; actcol++)
|
||||
{
|
||||
if (m_CellInfo[actrow][actcol].flag != cellUsed) continue;
|
||||
actcell = m_CellInfo[actrow][actcol].cont;
|
||||
actcell->SetMinHeight(
|
||||
ypos[actrow + m_CellInfo[actrow][actcol].rowspan] - ypos[actrow] - m_Spacing,
|
||||
m_CellInfo[actrow][actcol].valign);
|
||||
fullwid = 0;
|
||||
for (int i = actcol; i < m_CellInfo[actrow][actcol].colspan + actcol; i++)
|
||||
fullwid += m_ColsInfo[i].pixwidth;
|
||||
fullwid += (m_CellInfo[actrow][actcol].colspan - 1) * m_Spacing;
|
||||
actcell->Layout(fullwid);
|
||||
actcell->SetPos(m_ColsInfo[actcol].leftpos, ypos[actrow]);
|
||||
}
|
||||
}
|
||||
m_Height = ypos[m_NumRows];
|
||||
delete[] ypos;
|
||||
}
|
||||
|
||||
/* 4. adjust table's width if it was too small: */
|
||||
if (m_NumCols > 0)
|
||||
{
|
||||
int twidth = m_ColsInfo[m_NumCols-1].leftpos +
|
||||
m_ColsInfo[m_NumCols-1].pixwidth + m_Spacing;
|
||||
if (twidth > m_Width)
|
||||
m_Width = twidth;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The tables handler:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
TAG_HANDLER_BEGIN(TABLE, "TABLE,TR,TD,TH")
|
||||
|
||||
TAG_HANDLER_VARS
|
||||
wxHtmlTableCell* m_Table;
|
||||
wxString m_tAlign, m_rAlign;
|
||||
wxHtmlContainerCell *m_enclosingContainer;
|
||||
|
||||
TAG_HANDLER_CONSTR(TABLE)
|
||||
{
|
||||
m_Table = NULL;
|
||||
m_enclosingContainer = NULL;
|
||||
m_tAlign = m_rAlign = wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
TAG_HANDLER_PROC(tag)
|
||||
{
|
||||
wxHtmlContainerCell *c;
|
||||
|
||||
// new table started, backup upper-level table (if any) and create new:
|
||||
if (tag.GetName() == wxT("TABLE"))
|
||||
{
|
||||
wxHtmlTableCell *oldt = m_Table;
|
||||
|
||||
wxHtmlContainerCell *oldEnclosing = m_enclosingContainer;
|
||||
m_enclosingContainer = c = m_WParser->OpenContainer();
|
||||
|
||||
m_Table = new wxHtmlTableCell(c, tag, m_WParser->GetPixelScale());
|
||||
|
||||
// width:
|
||||
{
|
||||
if (tag.HasParam(wxT("WIDTH")))
|
||||
{
|
||||
wxString wd = tag.GetParam(wxT("WIDTH"));
|
||||
|
||||
if (wd[wd.length()-1] == wxT('%'))
|
||||
{
|
||||
int width = 0;
|
||||
wxSscanf(wd.c_str(), wxT("%i%%"), &width);
|
||||
m_Table->SetWidthFloat(width, wxHTML_UNITS_PERCENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
int width = 0;
|
||||
wxSscanf(wd.c_str(), wxT("%i"), &width);
|
||||
m_Table->SetWidthFloat((int)(m_WParser->GetPixelScale() * width), wxHTML_UNITS_PIXELS);
|
||||
}
|
||||
}
|
||||
else
|
||||
m_Table->SetWidthFloat(0, wxHTML_UNITS_PIXELS);
|
||||
}
|
||||
int oldAlign = m_WParser->GetAlign();
|
||||
m_tAlign = wxEmptyString;
|
||||
if (tag.HasParam(wxT("ALIGN")))
|
||||
m_tAlign = tag.GetParam(wxT("ALIGN"));
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
m_WParser->SetAlign(oldAlign);
|
||||
m_WParser->SetContainer(m_enclosingContainer);
|
||||
m_WParser->CloseContainer();
|
||||
|
||||
m_Table = oldt;
|
||||
m_enclosingContainer = oldEnclosing;
|
||||
|
||||
return true; // ParseInner() called
|
||||
}
|
||||
|
||||
|
||||
else if (m_Table)
|
||||
{
|
||||
// new row in table
|
||||
if (tag.GetName() == wxT("TR"))
|
||||
{
|
||||
m_Table->AddRow(tag);
|
||||
m_rAlign = m_tAlign;
|
||||
if (tag.HasParam(wxT("ALIGN")))
|
||||
m_rAlign = tag.GetParam(wxT("ALIGN"));
|
||||
}
|
||||
|
||||
// new cell
|
||||
else
|
||||
{
|
||||
c = m_WParser->SetContainer(new wxHtmlContainerCell(m_Table));
|
||||
m_Table->AddCell(c, tag);
|
||||
|
||||
m_WParser->OpenContainer();
|
||||
|
||||
if (tag.GetName() == wxT("TH")) /*header style*/
|
||||
m_WParser->SetAlign(wxHTML_ALIGN_CENTER);
|
||||
else
|
||||
m_WParser->SetAlign(wxHTML_ALIGN_LEFT);
|
||||
|
||||
wxString als;
|
||||
|
||||
als = m_rAlign;
|
||||
if (tag.HasParam(wxT("ALIGN")))
|
||||
als = tag.GetParam(wxT("ALIGN"));
|
||||
als.MakeUpper();
|
||||
if (als == wxT("RIGHT"))
|
||||
m_WParser->SetAlign(wxHTML_ALIGN_RIGHT);
|
||||
else if (als == wxT("LEFT"))
|
||||
m_WParser->SetAlign(wxHTML_ALIGN_LEFT);
|
||||
else if (als == wxT("CENTER"))
|
||||
m_WParser->SetAlign(wxHTML_ALIGN_CENTER);
|
||||
|
||||
m_WParser->OpenContainer();
|
||||
|
||||
ParseInner(tag);
|
||||
|
||||
// set the current container back to the enclosing one so that
|
||||
// text outside of <th> and <td> isn't included in any cell
|
||||
// (this happens often enough in practice because it's common
|
||||
// to use whitespace between </td> and the next <td>):
|
||||
m_WParser->SetContainer(m_enclosingContainer);
|
||||
|
||||
return true; // ParseInner() called
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TAG_HANDLER_END(TABLE)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TAGS_MODULE_BEGIN(Tables)
|
||||
|
||||
TAGS_MODULE_ADD(TABLE)
|
||||
|
||||
TAGS_MODULE_END(Tables)
|
||||
|
||||
|
||||
#endif
|
853
wxWidgets/src/html/winpars.cpp
Normal file
853
wxWidgets/src/html/winpars.cpp
Normal file
|
@ -0,0 +1,853 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/html/winpars.cpp
|
||||
// Purpose: wxHtmlParser class (generic parser)
|
||||
// Author: Vaclav Slavik
|
||||
// RCS-ID: $Id: winpars.cpp 58846 2009-02-12 19:38:20Z VS $
|
||||
// Copyright: (c) 1999 Vaclav Slavik
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#if wxUSE_HTML && wxUSE_STREAMS
|
||||
|
||||
#ifndef WXPRECOMP
|
||||
#include "wx/intl.h"
|
||||
#include "wx/dc.h"
|
||||
#include "wx/log.h"
|
||||
#include "wx/settings.h"
|
||||
#endif
|
||||
|
||||
#include "wx/html/htmldefs.h"
|
||||
#include "wx/html/winpars.h"
|
||||
#include "wx/html/htmlwin.h"
|
||||
#include "wx/fontmap.h"
|
||||
#include "wx/uri.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlWordWithTabsCell
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// NB: this is backported from wx-2.9 and moved to this file so that it
|
||||
// stays private; trunk version is in htmlcell.h/cpp.
|
||||
|
||||
|
||||
// wxHtmlWordCell specialization for storing text fragments with embedded
|
||||
// '\t's; these differ from normal words in that the displayed text is
|
||||
// different from the text copied to clipboard
|
||||
class WXDLLIMPEXP_HTML wxHtmlWordWithTabsCell : public wxHtmlWordCell
|
||||
{
|
||||
public:
|
||||
wxHtmlWordWithTabsCell(const wxString& word,
|
||||
const wxString& wordOrig,
|
||||
size_t linepos,
|
||||
const wxDC& dc)
|
||||
: wxHtmlWordCell(word, dc),
|
||||
m_wordOrig(wordOrig),
|
||||
m_linepos(linepos)
|
||||
{}
|
||||
|
||||
virtual wxString ConvertToText(wxHtmlSelection *sel) const;
|
||||
|
||||
protected:
|
||||
wxString GetPartAsText(int begin, int end) const;
|
||||
|
||||
wxString m_wordOrig;
|
||||
size_t m_linepos;
|
||||
};
|
||||
|
||||
wxString wxHtmlWordWithTabsCell::ConvertToText(wxHtmlSelection *s) const
|
||||
{
|
||||
if ( s && (this == s->GetFromCell() || this == s->GetToCell()) )
|
||||
{
|
||||
wxPoint priv = this == s->GetFromCell() ? s->GetFromPrivPos()
|
||||
: s->GetToPrivPos();
|
||||
|
||||
// VZ: we may be called before we had a chance to re-render ourselves
|
||||
// and in this case GetFrom/ToPrivPos() is not set yet -- assume
|
||||
// that this only happens in case of a double/triple click (which
|
||||
// seems to be the case now) and so it makes sense to select the
|
||||
// entire contents of the cell in this case
|
||||
//
|
||||
// TODO: but this really needs to be fixed in some better way later...
|
||||
if ( priv != wxDefaultPosition )
|
||||
{
|
||||
int part1 = priv.x;
|
||||
int part2 = priv.y;
|
||||
if ( part1 == part2 )
|
||||
return wxEmptyString;
|
||||
return GetPartAsText(part1, part2);
|
||||
}
|
||||
//else: return the whole word below
|
||||
}
|
||||
|
||||
return m_wordOrig;
|
||||
}
|
||||
|
||||
wxString wxHtmlWordWithTabsCell::GetPartAsText(int begin, int end) const
|
||||
{
|
||||
// NB: The 'begin' and 'end' positions are in the _displayed_ text
|
||||
// (stored in m_Word) and not in the text with tabs that should
|
||||
// be copied to clipboard (m_wordOrig).
|
||||
//
|
||||
// NB: Because selection is performed on displayed text, it's possible
|
||||
// to select e.g. "half of TAB character" -- IOW, 'begin' and 'end'
|
||||
// may be in the middle of TAB character expansion into ' 's. In this
|
||||
// case, we copy the TAB character to clipboard once.
|
||||
|
||||
wxASSERT( begin < end );
|
||||
|
||||
const unsigned SPACES_PER_TAB = 8;
|
||||
|
||||
wxString sel;
|
||||
|
||||
int pos = 0;
|
||||
wxString::const_iterator i = m_wordOrig.begin();
|
||||
|
||||
// find the beginning of text to copy:
|
||||
for ( ; pos < begin; ++i )
|
||||
{
|
||||
if ( *i == '\t' )
|
||||
{
|
||||
pos += 8 - (m_linepos + pos) % SPACES_PER_TAB;
|
||||
if ( pos >= begin )
|
||||
{
|
||||
sel += '\t';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
// copy the content until we reach 'end':
|
||||
for ( ; pos < end; ++i )
|
||||
{
|
||||
const wxChar c = *i;
|
||||
sel += c;
|
||||
|
||||
if ( c == '\t' )
|
||||
pos += 8 - (m_linepos + pos) % SPACES_PER_TAB;
|
||||
else
|
||||
++pos;
|
||||
}
|
||||
|
||||
return sel;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlWinParser
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct wxHtmlWinParser_TextParsingState
|
||||
{
|
||||
// current whitespace handling mode
|
||||
wxHtmlWinParser::WhitespaceMode m_whitespaceMode;
|
||||
|
||||
wxHtmlWordCell *m_lastWordCell;
|
||||
|
||||
// current position on line, in num. of characters; used to properly
|
||||
// expand TABs; only updated while inside <pre>
|
||||
int m_posColumn;
|
||||
};
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinParser, wxHtmlParser)
|
||||
|
||||
wxList wxHtmlWinParser::m_Modules;
|
||||
|
||||
wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindowInterface *wndIface)
|
||||
{
|
||||
m_textParsingState = new wxHtmlWinParser_TextParsingState;
|
||||
m_textParsingState->m_whitespaceMode = Whitespace_Normal;
|
||||
m_textParsingState->m_lastWordCell = NULL;
|
||||
m_textParsingState->m_posColumn = 0;
|
||||
|
||||
m_tmpStrBuf = NULL;
|
||||
m_tmpStrBufSize = 0;
|
||||
m_windowInterface = wndIface;
|
||||
m_Container = NULL;
|
||||
m_DC = NULL;
|
||||
m_CharHeight = m_CharWidth = 0;
|
||||
m_UseLink = false;
|
||||
#if !wxUSE_UNICODE
|
||||
m_EncConv = NULL;
|
||||
m_InputEnc = wxFONTENCODING_ISO8859_1;
|
||||
m_OutputEnc = wxFONTENCODING_DEFAULT;
|
||||
#endif
|
||||
|
||||
{
|
||||
int i, j, k, l, m;
|
||||
for (i = 0; i < 2; i++)
|
||||
for (j = 0; j < 2; j++)
|
||||
for (k = 0; k < 2; k++)
|
||||
for (l = 0; l < 2; l++)
|
||||
for (m = 0; m < 7; m++)
|
||||
{
|
||||
m_FontsTable[i][j][k][l][m] = NULL;
|
||||
m_FontsFacesTable[i][j][k][l][m] = wxEmptyString;
|
||||
#if !wxUSE_UNICODE
|
||||
m_FontsEncTable[i][j][k][l][m] = wxFONTENCODING_DEFAULT;
|
||||
#endif
|
||||
}
|
||||
|
||||
SetFonts(wxEmptyString, wxEmptyString, NULL);
|
||||
}
|
||||
|
||||
// fill in wxHtmlParser's tables:
|
||||
wxList::compatibility_iterator node = m_Modules.GetFirst();
|
||||
while (node)
|
||||
{
|
||||
wxHtmlTagsModule *mod = (wxHtmlTagsModule*) node->GetData();
|
||||
mod->FillHandlersTable(this);
|
||||
node = node->GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
wxHtmlWinParser::~wxHtmlWinParser()
|
||||
{
|
||||
int i, j, k, l, m;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
for (j = 0; j < 2; j++)
|
||||
for (k = 0; k < 2; k++)
|
||||
for (l = 0; l < 2; l++)
|
||||
for (m = 0; m < 7; m++)
|
||||
{
|
||||
if (m_FontsTable[i][j][k][l][m] != NULL)
|
||||
delete m_FontsTable[i][j][k][l][m];
|
||||
}
|
||||
#if !wxUSE_UNICODE
|
||||
delete m_EncConv;
|
||||
#endif
|
||||
delete[] m_tmpStrBuf;
|
||||
|
||||
delete m_textParsingState;
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::AddModule(wxHtmlTagsModule *module)
|
||||
{
|
||||
m_Modules.Append(module);
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::RemoveModule(wxHtmlTagsModule *module)
|
||||
{
|
||||
m_Modules.DeleteObject(module);
|
||||
}
|
||||
|
||||
// build all HTML font sizes (1..7) from the given base size
|
||||
static void wxBuildFontSizes(int *sizes, int size)
|
||||
{
|
||||
// using a fixed factor (1.2, from CSS2) is a bad idea as explained at
|
||||
// http://www.w3.org/TR/CSS21/fonts.html#font-size-props but this is by far
|
||||
// simplest thing to do so still do it like this for now
|
||||
sizes[0] = int(size * 0.75); // exception to 1.2 rule, otherwise too small
|
||||
sizes[1] = int(size * 0.83);
|
||||
sizes[2] = size;
|
||||
sizes[3] = int(size * 1.2);
|
||||
sizes[4] = int(size * 1.44);
|
||||
sizes[5] = int(size * 1.73);
|
||||
sizes[6] = int(size * 2);
|
||||
}
|
||||
|
||||
static int wxGetDefaultHTMLFontSize()
|
||||
{
|
||||
// base the default font size on the size of the default system font but
|
||||
// also ensure that we have a font of reasonable size, otherwise small HTML
|
||||
// fonts are unreadable
|
||||
int size = wxNORMAL_FONT->GetPointSize();
|
||||
if ( size < 10 )
|
||||
size = 10;
|
||||
return size;
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::SetFonts(const wxString& normal_face,
|
||||
const wxString& fixed_face,
|
||||
const int *sizes)
|
||||
{
|
||||
static int default_sizes[7] = { 0 };
|
||||
if ( !sizes )
|
||||
{
|
||||
if ( !default_sizes[0] )
|
||||
wxBuildFontSizes(default_sizes, wxGetDefaultHTMLFontSize());
|
||||
|
||||
sizes = default_sizes;
|
||||
}
|
||||
|
||||
int i, j, k, l, m;
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
m_FontsSizes[i] = sizes[i];
|
||||
|
||||
m_FontFaceFixed = fixed_face;
|
||||
m_FontFaceNormal = normal_face;
|
||||
|
||||
#if !wxUSE_UNICODE
|
||||
SetInputEncoding(m_InputEnc);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
for (j = 0; j < 2; j++)
|
||||
for (k = 0; k < 2; k++)
|
||||
for (l = 0; l < 2; l++)
|
||||
for (m = 0; m < 7; m++) {
|
||||
if (m_FontsTable[i][j][k][l][m] != NULL)
|
||||
{
|
||||
delete m_FontsTable[i][j][k][l][m];
|
||||
m_FontsTable[i][j][k][l][m] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::SetStandardFonts(int size,
|
||||
const wxString& normal_face,
|
||||
const wxString& fixed_face)
|
||||
{
|
||||
if (size == -1)
|
||||
size = wxGetDefaultHTMLFontSize();
|
||||
|
||||
int f_sizes[7];
|
||||
wxBuildFontSizes(f_sizes, size);
|
||||
|
||||
wxString normal = normal_face;
|
||||
if ( normal.empty() )
|
||||
normal = wxNORMAL_FONT->GetFaceName();
|
||||
|
||||
SetFonts(normal, fixed_face, f_sizes);
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::InitParser(const wxString& source)
|
||||
{
|
||||
wxHtmlParser::InitParser(source);
|
||||
wxASSERT_MSG(m_DC != NULL, wxT("no DC assigned to wxHtmlWinParser!!"));
|
||||
|
||||
m_FontBold = m_FontItalic = m_FontUnderlined = m_FontFixed = FALSE;
|
||||
m_FontSize = 3; //default one
|
||||
CreateCurrentFont(); // we're selecting default font into
|
||||
m_DC->GetTextExtent( wxT("H"), &m_CharWidth, &m_CharHeight);
|
||||
/* NOTE : we're not using GetCharWidth/Height() because
|
||||
of differences under X and win
|
||||
*/
|
||||
|
||||
m_UseLink = false;
|
||||
m_Link = wxHtmlLinkInfo( wxEmptyString );
|
||||
m_LinkColor.Set(0, 0, 0xFF);
|
||||
m_ActualColor.Set(0, 0, 0);
|
||||
m_Align = wxHTML_ALIGN_LEFT;
|
||||
m_ScriptMode = wxHTML_SCRIPT_NORMAL;
|
||||
m_ScriptBaseline = 0;
|
||||
m_tmpLastWasSpace = false;
|
||||
m_textParsingState->m_lastWordCell = NULL;
|
||||
|
||||
// open the toplevel container that contains everything else and that
|
||||
// is never closed (this makes parser's life easier):
|
||||
OpenContainer();
|
||||
|
||||
// then open the first container into which page's content will go:
|
||||
OpenContainer();
|
||||
|
||||
#if !wxUSE_UNICODE
|
||||
wxString charset = ExtractCharsetInformation(source);
|
||||
if (!charset.empty())
|
||||
{
|
||||
wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(charset);
|
||||
if (enc != wxFONTENCODING_SYSTEM)
|
||||
SetInputEncoding(enc);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_Container->InsertCell(new wxHtmlColourCell(m_ActualColor));
|
||||
wxColour windowColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW) ;
|
||||
|
||||
m_Container->InsertCell
|
||||
(
|
||||
new wxHtmlColourCell
|
||||
(
|
||||
m_windowInterface
|
||||
? m_windowInterface->GetHTMLBackgroundColour()
|
||||
: windowColour,
|
||||
wxHTML_CLR_BACKGROUND
|
||||
)
|
||||
);
|
||||
|
||||
m_Container->InsertCell(new wxHtmlFontCell(CreateCurrentFont()));
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::DoneParser()
|
||||
{
|
||||
m_Container = NULL;
|
||||
#if !wxUSE_UNICODE
|
||||
SetInputEncoding(wxFONTENCODING_ISO8859_1); // for next call
|
||||
#endif
|
||||
wxHtmlParser::DoneParser();
|
||||
}
|
||||
|
||||
#if WXWIN_COMPATIBILITY_2_6
|
||||
wxHtmlWindow *wxHtmlWinParser::GetWindow()
|
||||
{
|
||||
if (!m_windowInterface)
|
||||
return NULL;
|
||||
return wxDynamicCast(m_windowInterface->GetHTMLWindow(), wxHtmlWindow);
|
||||
}
|
||||
#endif
|
||||
|
||||
wxObject* wxHtmlWinParser::GetProduct()
|
||||
{
|
||||
wxHtmlContainerCell *top;
|
||||
|
||||
CloseContainer();
|
||||
OpenContainer();
|
||||
|
||||
top = m_Container;
|
||||
while (top->GetParent()) top = top->GetParent();
|
||||
top->RemoveExtraSpacing(true, true);
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
wxFSFile *wxHtmlWinParser::OpenURL(wxHtmlURLType type,
|
||||
const wxString& url) const
|
||||
{
|
||||
if ( !m_windowInterface )
|
||||
return wxHtmlParser::OpenURL(type, url);
|
||||
|
||||
wxString myurl(url);
|
||||
wxHtmlOpeningStatus status;
|
||||
for (;;)
|
||||
{
|
||||
wxString myfullurl(myurl);
|
||||
|
||||
// consider url as absolute path first
|
||||
wxURI current(myurl);
|
||||
myfullurl = current.BuildUnescapedURI();
|
||||
|
||||
// if not absolute then ...
|
||||
if( current.IsReference() )
|
||||
{
|
||||
wxString basepath = GetFS()->GetPath();
|
||||
wxURI base(basepath);
|
||||
|
||||
// ... try to apply base path if valid ...
|
||||
if( !base.IsReference() )
|
||||
{
|
||||
wxURI path(myfullurl);
|
||||
path.Resolve( base );
|
||||
myfullurl = path.BuildUnescapedURI();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ... or force such addition if not included already
|
||||
if( !current.GetPath().Contains(base.GetPath()) )
|
||||
{
|
||||
basepath += myurl;
|
||||
wxURI connected( basepath );
|
||||
myfullurl = connected.BuildUnescapedURI();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxString redirect;
|
||||
status = m_windowInterface->OnHTMLOpeningURL(type, myfullurl, &redirect);
|
||||
if ( status != wxHTML_REDIRECT )
|
||||
break;
|
||||
|
||||
myurl = redirect;
|
||||
}
|
||||
|
||||
if ( status == wxHTML_BLOCK )
|
||||
return NULL;
|
||||
|
||||
int flags = wxFS_READ;
|
||||
if (type == wxHTML_URL_IMAGE)
|
||||
flags |= wxFS_SEEKABLE;
|
||||
|
||||
return GetFS()->OpenFile(myurl, flags);
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::SetWhitespaceMode(wxHtmlWinParser::WhitespaceMode mode)
|
||||
{
|
||||
m_textParsingState->m_whitespaceMode = mode;
|
||||
}
|
||||
|
||||
wxHtmlWinParser::WhitespaceMode wxHtmlWinParser::GetWhitespaceMode() const
|
||||
{
|
||||
return m_textParsingState->m_whitespaceMode;
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::AddText(const wxChar* txt)
|
||||
{
|
||||
const wxChar nbsp = GetEntitiesParser()->GetCharForCode(160 /* nbsp */);
|
||||
|
||||
if ( m_textParsingState->m_whitespaceMode == Whitespace_Normal )
|
||||
{
|
||||
size_t i = 0,
|
||||
x,
|
||||
lng = wxStrlen(txt);
|
||||
int templen = 0;
|
||||
|
||||
if (lng+1 > m_tmpStrBufSize)
|
||||
{
|
||||
delete[] m_tmpStrBuf;
|
||||
m_tmpStrBuf = new wxChar[lng+1];
|
||||
m_tmpStrBufSize = lng+1;
|
||||
}
|
||||
wxChar *temp = m_tmpStrBuf;
|
||||
|
||||
if (m_tmpLastWasSpace)
|
||||
{
|
||||
while ((i < lng) &&
|
||||
((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) || (txt[i] == wxT(' ')) ||
|
||||
(txt[i] == wxT('\t')))) i++;
|
||||
}
|
||||
|
||||
while (i < lng)
|
||||
{
|
||||
x = 0;
|
||||
const wxChar d = temp[templen++] = txt[i];
|
||||
if ((d == wxT('\n')) || (d == wxT('\r')) || (d == wxT(' ')) || (d == wxT('\t')))
|
||||
{
|
||||
i++, x++;
|
||||
while ((i < lng) && ((txt[i] == wxT('\n')) || (txt[i] == wxT('\r')) ||
|
||||
(txt[i] == wxT(' ')) || (txt[i] == wxT('\t')))) i++, x++;
|
||||
}
|
||||
else i++;
|
||||
|
||||
if (x)
|
||||
{
|
||||
temp[templen-1] = wxT(' ');
|
||||
FlushWordBuf(temp, templen, nbsp);
|
||||
m_tmpLastWasSpace = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (templen && (templen > 1 || temp[0] != wxT(' ')))
|
||||
{
|
||||
FlushWordBuf(temp, templen, nbsp);
|
||||
m_tmpLastWasSpace = false;
|
||||
}
|
||||
}
|
||||
else // m_whitespaceMode == Whitespace_Pre
|
||||
{
|
||||
if ( wxStrchr(txt, nbsp) != NULL )
|
||||
{
|
||||
// we need to substitute spaces for here just like we
|
||||
// did in the Whitespace_Normal branch above
|
||||
wxString txt2(txt);
|
||||
wxChar nbsp_str[2];
|
||||
nbsp_str[0] = nbsp;
|
||||
nbsp_str[1] = 0;
|
||||
txt2.Replace(nbsp_str, wxT(" "));
|
||||
AddPreBlock(txt2);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPreBlock(txt);
|
||||
}
|
||||
|
||||
// don't eat any whitespace in <pre> block
|
||||
m_tmpLastWasSpace = false;
|
||||
}
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::FlushWordBuf(wxChar *buf, int& len, wxChar nbsp)
|
||||
{
|
||||
buf[len] = 0;
|
||||
|
||||
for ( int i = 0; i < len; i++ )
|
||||
{
|
||||
if ( buf[i] == nbsp )
|
||||
buf[i] = ' ';
|
||||
}
|
||||
|
||||
#if !wxUSE_UNICODE
|
||||
if (m_EncConv)
|
||||
m_EncConv->Convert(buf);
|
||||
#endif
|
||||
|
||||
AddWord(wxString(buf, len));
|
||||
|
||||
len = 0;
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::AddWord(const wxString& word)
|
||||
{
|
||||
AddWord(new wxHtmlWordCell(word, *(GetDC())));
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::AddWord(wxHtmlWordCell *c)
|
||||
{
|
||||
ApplyStateToCell(c);
|
||||
|
||||
m_Container->InsertCell(c);
|
||||
c->SetPreviousWord(m_textParsingState->m_lastWordCell);
|
||||
m_textParsingState->m_lastWordCell = c;
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::AddPreBlock(const wxString& text)
|
||||
{
|
||||
if ( text.find(wxT('\t')) != wxString::npos )
|
||||
{
|
||||
wxString text2;
|
||||
text2.reserve(text.length());
|
||||
|
||||
const wxString::const_iterator end = text.end();
|
||||
wxString::const_iterator copyFrom = text.begin();
|
||||
size_t posFrom = 0;
|
||||
size_t pos = 0;
|
||||
int posColumn = m_textParsingState->m_posColumn;
|
||||
for ( wxString::const_iterator i = copyFrom; i != end; ++i, ++pos )
|
||||
{
|
||||
if ( *i == wxT('\t') )
|
||||
{
|
||||
if ( copyFrom != i )
|
||||
text2.append(copyFrom, i);
|
||||
|
||||
const unsigned SPACES_PER_TAB = 8;
|
||||
const size_t expandTo = SPACES_PER_TAB - posColumn % SPACES_PER_TAB;
|
||||
text2.append(expandTo, wxT(' '));
|
||||
|
||||
posColumn += expandTo;
|
||||
copyFrom = i + 1;
|
||||
posFrom = pos + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++posColumn;
|
||||
}
|
||||
}
|
||||
if ( copyFrom != text.end() )
|
||||
text2.append(copyFrom, text.end());
|
||||
|
||||
AddWord(new wxHtmlWordWithTabsCell(text2, text,
|
||||
m_textParsingState->m_posColumn,
|
||||
*(GetDC())));
|
||||
|
||||
m_textParsingState->m_posColumn = posColumn;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no special formatting needed
|
||||
AddWord(text);
|
||||
m_textParsingState->m_posColumn += text.length();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxHtmlContainerCell* wxHtmlWinParser::OpenContainer()
|
||||
{
|
||||
m_Container = new wxHtmlContainerCell(m_Container);
|
||||
m_Container->SetAlignHor(m_Align);
|
||||
m_textParsingState->m_posColumn = 0;
|
||||
m_tmpLastWasSpace = true;
|
||||
/* to avoid space being first character in paragraph */
|
||||
return m_Container;
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxHtmlContainerCell* wxHtmlWinParser::SetContainer(wxHtmlContainerCell *c)
|
||||
{
|
||||
m_tmpLastWasSpace = true;
|
||||
/* to avoid space being first character in paragraph */
|
||||
return m_Container = c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxHtmlContainerCell* wxHtmlWinParser::CloseContainer()
|
||||
{
|
||||
m_Container = m_Container->GetParent();
|
||||
return m_Container;
|
||||
}
|
||||
|
||||
|
||||
void wxHtmlWinParser::SetFontSize(int s)
|
||||
{
|
||||
if (s < 1) s = 1;
|
||||
else if (s > 7) s = 7;
|
||||
m_FontSize = s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxFont* wxHtmlWinParser::CreateCurrentFont()
|
||||
{
|
||||
int fb = GetFontBold(),
|
||||
fi = GetFontItalic(),
|
||||
fu = GetFontUnderlined(),
|
||||
ff = GetFontFixed(),
|
||||
fs = GetFontSize() - 1 /*remap from <1;7> to <0;6>*/ ;
|
||||
|
||||
wxString face = ff ? m_FontFaceFixed : m_FontFaceNormal;
|
||||
wxString *faceptr = &(m_FontsFacesTable[fb][fi][fu][ff][fs]);
|
||||
wxFont **fontptr = &(m_FontsTable[fb][fi][fu][ff][fs]);
|
||||
#if !wxUSE_UNICODE
|
||||
wxFontEncoding *encptr = &(m_FontsEncTable[fb][fi][fu][ff][fs]);
|
||||
#endif
|
||||
|
||||
if (*fontptr != NULL && (*faceptr != face
|
||||
#if !wxUSE_UNICODE
|
||||
|| *encptr != m_OutputEnc
|
||||
#endif
|
||||
))
|
||||
{
|
||||
delete *fontptr;
|
||||
*fontptr = NULL;
|
||||
}
|
||||
|
||||
if (*fontptr == NULL)
|
||||
{
|
||||
*faceptr = face;
|
||||
*fontptr = new wxFont(
|
||||
(int) (m_FontsSizes[fs] * m_PixelScale),
|
||||
ff ? wxMODERN : wxSWISS,
|
||||
fi ? wxITALIC : wxNORMAL,
|
||||
fb ? wxBOLD : wxNORMAL,
|
||||
fu ? true : false, face
|
||||
#if wxUSE_UNICODE
|
||||
);
|
||||
#else
|
||||
, m_OutputEnc);
|
||||
*encptr = m_OutputEnc;
|
||||
#endif
|
||||
}
|
||||
m_DC->SetFont(**fontptr);
|
||||
return (*fontptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wxHtmlWinParser::SetLink(const wxHtmlLinkInfo& link)
|
||||
{
|
||||
m_Link = link;
|
||||
m_UseLink = (link.GetHref() != wxEmptyString);
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::SetFontFace(const wxString& face)
|
||||
{
|
||||
if (GetFontFixed()) m_FontFaceFixed = face;
|
||||
else m_FontFaceNormal = face;
|
||||
|
||||
#if !wxUSE_UNICODE
|
||||
if (m_InputEnc != wxFONTENCODING_DEFAULT)
|
||||
SetInputEncoding(m_InputEnc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wxHtmlWinParser::ApplyStateToCell(wxHtmlCell *cell)
|
||||
{
|
||||
// set the link:
|
||||
if (m_UseLink)
|
||||
cell->SetLink(GetLink());
|
||||
|
||||
// apply current script mode settings:
|
||||
cell->SetScriptMode(GetScriptMode(), GetScriptBaseline());
|
||||
}
|
||||
|
||||
|
||||
#if !wxUSE_UNICODE
|
||||
void wxHtmlWinParser::SetInputEncoding(wxFontEncoding enc)
|
||||
{
|
||||
m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
|
||||
if (m_EncConv)
|
||||
{
|
||||
delete m_EncConv;
|
||||
m_EncConv = NULL;
|
||||
}
|
||||
|
||||
if (enc == wxFONTENCODING_DEFAULT) return;
|
||||
|
||||
wxFontEncoding altfix, altnorm;
|
||||
bool availfix, availnorm;
|
||||
|
||||
// exact match?
|
||||
availnorm = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceNormal);
|
||||
availfix = wxFontMapper::Get()->IsEncodingAvailable(enc, m_FontFaceFixed);
|
||||
if (availnorm && availfix)
|
||||
m_OutputEnc = enc;
|
||||
|
||||
// alternatives?
|
||||
else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, false) &&
|
||||
wxFontMapper::Get()->GetAltForEncoding(enc, &altfix, m_FontFaceFixed, false) &&
|
||||
altnorm == altfix)
|
||||
m_OutputEnc = altnorm;
|
||||
|
||||
// at least normal face?
|
||||
else if (availnorm)
|
||||
m_OutputEnc = enc;
|
||||
else if (wxFontMapper::Get()->GetAltForEncoding(enc, &altnorm, m_FontFaceNormal, false))
|
||||
m_OutputEnc = altnorm;
|
||||
|
||||
else
|
||||
{
|
||||
#ifndef __WXMAC__
|
||||
// okay, let's convert to ISO_8859-1, available always
|
||||
m_OutputEnc = wxFONTENCODING_DEFAULT;
|
||||
#else
|
||||
m_OutputEnc = wxLocale::GetSystemEncoding() ;
|
||||
#endif
|
||||
}
|
||||
|
||||
m_InputEnc = enc;
|
||||
if (m_OutputEnc == wxFONTENCODING_DEFAULT)
|
||||
GetEntitiesParser()->SetEncoding(wxFONTENCODING_SYSTEM);
|
||||
else
|
||||
GetEntitiesParser()->SetEncoding(m_OutputEnc);
|
||||
|
||||
if (m_InputEnc == m_OutputEnc) return;
|
||||
|
||||
m_EncConv = new wxEncodingConverter();
|
||||
if (!m_EncConv->Init(m_InputEnc,
|
||||
(m_OutputEnc == wxFONTENCODING_DEFAULT) ?
|
||||
wxFONTENCODING_ISO8859_1 : m_OutputEnc,
|
||||
wxCONVERT_SUBSTITUTE))
|
||||
{ // total failure :-(
|
||||
wxLogError(_("Failed to display HTML document in %s encoding"),
|
||||
wxFontMapper::GetEncodingName(enc).c_str());
|
||||
m_InputEnc = m_OutputEnc = wxFONTENCODING_DEFAULT;
|
||||
delete m_EncConv;
|
||||
m_EncConv = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlWinTagHandler
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler, wxHtmlTagHandler)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxHtmlTagsModule
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// NB: This is *NOT* winpars.cpp's initialization and shutdown code!!
|
||||
// This module is an ancestor for tag handlers modules defined
|
||||
// in m_*.cpp files with TAGS_MODULE_BEGIN...TAGS_MODULE_END construct.
|
||||
//
|
||||
// Do not add any winpars.cpp shutdown or initialization code to it,
|
||||
// create a new module instead!
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule, wxModule)
|
||||
|
||||
bool wxHtmlTagsModule::OnInit()
|
||||
{
|
||||
wxHtmlWinParser::AddModule(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxHtmlTagsModule::OnExit()
|
||||
{
|
||||
wxHtmlWinParser::RemoveModule(this);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue