From 5526e819eca4465ed5520d49bccfebc6a28045e0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Wed, 7 Jul 1999 22:04:58 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2963 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- acconfig.h | 5 + configure.in | 16 + include/wx/busyinfo.h | 58 + include/wx/filesys.h | 194 ++ include/wx/fs_inet.h | 55 + include/wx/fs_zip.h | 41 + include/wx/html/forcelink.h | 59 + include/wx/html/htmlcell.h | 292 +++ include/wx/html/htmldefs.h | 94 + include/wx/html/htmlfilter.h | 70 + include/wx/html/htmlhelp.h | 223 ++ include/wx/html/htmlparser.h | 176 ++ include/wx/html/htmltag.h | 135 ++ include/wx/html/htmlwin.h | 220 ++ include/wx/html/htmlwinparser.h | 219 ++ include/wx/html/mod_templ.h | 102 + include/wx/html/msw/back.bmp | Bin 0 -> 202 bytes include/wx/html/msw/book.ico | Bin 0 -> 318 bytes include/wx/html/msw/folder.ico | Bin 0 -> 318 bytes include/wx/html/msw/forward.bmp | Bin 0 -> 202 bytes include/wx/html/msw/page.ico | Bin 0 -> 318 bytes include/wx/html/msw/panel.bmp | Bin 0 -> 710 bytes include/wx/html/msw/wxhtml.rc | 16 + include/wx/html/version.h | 7 + include/wx/msw/setup0.h | 2 + include/wx/wxhtml.h | 27 + include/wx/zipstream.h | 70 + samples/html/Makefile.am | 8 + samples/html/about/Makefile.am | 9 + samples/html/about/about.cpp | 174 ++ samples/html/about/about.rc | 2 + samples/html/about/data/about.htm | 17 + samples/html/about/data/logo.png | Bin 0 -> 7637 bytes samples/html/help/Makefile.am | 9 + samples/html/help/help.cpp | 85 + samples/html/help/help.rc | 2 + samples/html/help/helpfiles/Index.hhk | 24 + samples/html/help/helpfiles/book1.htm | 4 + samples/html/help/helpfiles/book2.htm | 5 + samples/html/help/helpfiles/contents.hhc | 33 + samples/html/help/helpfiles/main.htm | 5 + samples/html/help/helpfiles/page2-b.htm | 5 + samples/html/help/helpfiles/testing.hhp | 15 + samples/html/printing/Makefile.am | 9 + samples/html/printing/mondrian.ico | Bin 0 -> 766 bytes samples/html/printing/mondrian.xpm | 44 + samples/html/printing/pic.png | Bin 0 -> 31315 bytes samples/html/printing/printing.cpp | 312 +++ samples/html/printing/printing.h | 76 + samples/html/printing/printing.rc | 3 + samples/html/printing/test.htm | 126 ++ samples/html/test/Makefile.am | 9 + samples/html/test/f.html | 2474 ++++++++++++++++++++++ samples/html/test/fft.html | 144 ++ samples/html/test/pic.png | Bin 0 -> 31315 bytes samples/html/test/pic2.bmp | Bin 0 -> 23244 bytes samples/html/test/tables.htm | 116 + samples/html/test/test.cpp | 203 ++ samples/html/test/test.htm | 266 +++ samples/html/test/test.rc | 2 + samples/html/virtual/Makefile.am | 9 + samples/html/virtual/start.htm | 12 + samples/html/virtual/virtual.cpp | 231 ++ samples/html/virtual/virtual.rc | 2 + samples/html/widget/Makefile.am | 9 + samples/html/widget/start.htm | 20 + samples/html/widget/widget.cpp | 244 +++ samples/html/widget/widget.rc | 2 + samples/html/zip/Makefile.am | 9 + samples/html/zip/pages.zip | Bin 0 -> 62123 bytes samples/html/zip/start.htm | 9 + samples/html/zip/zip.cpp | 195 ++ samples/html/zip/zip.rc | 2 + src/common/filesys.cpp | 294 +++ src/common/fs_inet.cpp | 130 ++ src/common/fs_zip.cpp | 75 + src/common/unzip.c | 1294 +++++++++++ src/common/unzip.h | 275 +++ src/common/zipstream.cpp | 110 + src/generic/busyinfo.cpp | 69 + src/gtk/Makefile.am | 29 +- src/gtk1/Makefile.am | 29 +- src/html/bitmaps/back.xpm | 24 + src/html/bitmaps/book.xpm | 40 + src/html/bitmaps/folder.xpm | 50 + src/html/bitmaps/forward.xpm | 24 + src/html/bitmaps/page.xpm | 25 + src/html/bitmaps/panel.xpm | 122 ++ src/html/htmlcell.cpp | 507 +++++ src/html/htmlfilter.cpp | 170 ++ src/html/htmlhelp.cpp | 864 ++++++++ src/html/htmlhelp_io.cpp | 250 +++ src/html/htmlparser.cpp | 169 ++ src/html/htmltag.cpp | 248 +++ src/html/htmlwin.cpp | 542 +++++ src/html/htmlwinparser.cpp | 288 +++ src/html/mod_fonts.cpp | 175 ++ src/html/mod_hline.cpp | 88 + src/html/mod_image.cpp | 147 ++ src/html/mod_layout.cpp | 223 ++ src/html/mod_links.cpp | 80 + src/html/mod_list.cpp | 142 ++ src/html/mod_pre.cpp | 157 ++ src/html/mod_tables.cpp | 480 +++++ src/html/search.cpp | 73 + src/html/search.h | 50 + src/motif/Makefile.am | 26 +- 107 files changed, 14270 insertions(+), 5 deletions(-) create mode 100644 include/wx/busyinfo.h create mode 100644 include/wx/filesys.h create mode 100644 include/wx/fs_inet.h create mode 100644 include/wx/fs_zip.h create mode 100644 include/wx/html/forcelink.h create mode 100644 include/wx/html/htmlcell.h create mode 100644 include/wx/html/htmldefs.h create mode 100644 include/wx/html/htmlfilter.h create mode 100644 include/wx/html/htmlhelp.h create mode 100644 include/wx/html/htmlparser.h create mode 100644 include/wx/html/htmltag.h create mode 100644 include/wx/html/htmlwin.h create mode 100644 include/wx/html/htmlwinparser.h create mode 100644 include/wx/html/mod_templ.h create mode 100644 include/wx/html/msw/back.bmp create mode 100644 include/wx/html/msw/book.ico create mode 100644 include/wx/html/msw/folder.ico create mode 100644 include/wx/html/msw/forward.bmp create mode 100644 include/wx/html/msw/page.ico create mode 100644 include/wx/html/msw/panel.bmp create mode 100644 include/wx/html/msw/wxhtml.rc create mode 100644 include/wx/html/version.h create mode 100644 include/wx/wxhtml.h create mode 100644 include/wx/zipstream.h create mode 100644 samples/html/Makefile.am create mode 100644 samples/html/about/Makefile.am create mode 100644 samples/html/about/about.cpp create mode 100644 samples/html/about/about.rc create mode 100644 samples/html/about/data/about.htm create mode 100644 samples/html/about/data/logo.png create mode 100644 samples/html/help/Makefile.am create mode 100644 samples/html/help/help.cpp create mode 100644 samples/html/help/help.rc create mode 100644 samples/html/help/helpfiles/Index.hhk create mode 100644 samples/html/help/helpfiles/book1.htm create mode 100644 samples/html/help/helpfiles/book2.htm create mode 100644 samples/html/help/helpfiles/contents.hhc create mode 100644 samples/html/help/helpfiles/main.htm create mode 100644 samples/html/help/helpfiles/page2-b.htm create mode 100644 samples/html/help/helpfiles/testing.hhp create mode 100644 samples/html/printing/Makefile.am create mode 100644 samples/html/printing/mondrian.ico create mode 100644 samples/html/printing/mondrian.xpm create mode 100644 samples/html/printing/pic.png create mode 100644 samples/html/printing/printing.cpp create mode 100644 samples/html/printing/printing.h create mode 100644 samples/html/printing/printing.rc create mode 100644 samples/html/printing/test.htm create mode 100644 samples/html/test/Makefile.am create mode 100644 samples/html/test/f.html create mode 100644 samples/html/test/fft.html create mode 100644 samples/html/test/pic.png create mode 100644 samples/html/test/pic2.bmp create mode 100644 samples/html/test/tables.htm create mode 100644 samples/html/test/test.cpp create mode 100644 samples/html/test/test.htm create mode 100644 samples/html/test/test.rc create mode 100644 samples/html/virtual/Makefile.am create mode 100644 samples/html/virtual/start.htm create mode 100644 samples/html/virtual/virtual.cpp create mode 100644 samples/html/virtual/virtual.rc create mode 100644 samples/html/widget/Makefile.am create mode 100644 samples/html/widget/start.htm create mode 100644 samples/html/widget/widget.cpp create mode 100644 samples/html/widget/widget.rc create mode 100644 samples/html/zip/Makefile.am create mode 100644 samples/html/zip/pages.zip create mode 100644 samples/html/zip/start.htm create mode 100644 samples/html/zip/zip.cpp create mode 100644 samples/html/zip/zip.rc create mode 100644 src/common/filesys.cpp create mode 100644 src/common/fs_inet.cpp create mode 100644 src/common/fs_zip.cpp create mode 100644 src/common/unzip.c create mode 100644 src/common/unzip.h create mode 100644 src/common/zipstream.cpp create mode 100644 src/generic/busyinfo.cpp create mode 100644 src/html/bitmaps/back.xpm create mode 100644 src/html/bitmaps/book.xpm create mode 100644 src/html/bitmaps/folder.xpm create mode 100644 src/html/bitmaps/forward.xpm create mode 100644 src/html/bitmaps/page.xpm create mode 100644 src/html/bitmaps/panel.xpm create mode 100644 src/html/htmlcell.cpp create mode 100644 src/html/htmlfilter.cpp create mode 100644 src/html/htmlhelp.cpp create mode 100644 src/html/htmlhelp_io.cpp create mode 100644 src/html/htmlparser.cpp create mode 100644 src/html/htmltag.cpp create mode 100644 src/html/htmlwin.cpp create mode 100644 src/html/htmlwinparser.cpp create mode 100644 src/html/mod_fonts.cpp create mode 100644 src/html/mod_hline.cpp create mode 100644 src/html/mod_image.cpp create mode 100644 src/html/mod_layout.cpp create mode 100644 src/html/mod_links.cpp create mode 100644 src/html/mod_list.cpp create mode 100644 src/html/mod_pre.cpp create mode 100644 src/html/mod_tables.cpp create mode 100644 src/html/search.cpp create mode 100644 src/html/search.h diff --git a/acconfig.h b/acconfig.h index f0b87b500b..e0f7d38429 100644 --- a/acconfig.h +++ b/acconfig.h @@ -533,6 +533,11 @@ */ #define wxUSE_MINIFRAME 0 +/* + * wxHTML + */ +#define wxUSE_HTML 0 + /* * Disable this if your compiler can't cope * with omission of prototype parameters. diff --git a/configure.in b/configure.in index 5e6a6fa14a..3aceaf4cdf 100644 --- a/configure.in +++ b/configure.in @@ -292,6 +292,7 @@ if test $DEBUG_CONFIGURE = 1; then DEFAULT_wxUSE_STARTUP_TIPS=no DEFAULT_wxUSE_PROGRESSDLG=no DEFAULT_wxUSE_MINIFRAME=no + DEFAULT_wxUSE_HTML=no DEFAULT_wxUSE_VALIDATORS=yes DEFAULT_wxUSE_ACCEL=no @@ -391,6 +392,7 @@ else DEFAULT_wxUSE_STARTUP_TIPS=yes DEFAULT_wxUSE_PROGRESSDLG=yes DEFAULT_wxUSE_MINIFRAME=yes + DEFAULT_wxUSE_HTML=no DEFAULT_wxUSE_VALIDATORS=yes DEFAULT_wxUSE_ACCEL=yes @@ -675,6 +677,7 @@ WX_ARG_ENABLE(textdlg, [ --enable-textdlg use wxTextDialog], wxUSE_T WX_ARG_ENABLE(tipdlg, [ --enable-tipdlg use startup tips], wxUSE_STARTUP_TIPS) WX_ARG_ENABLE(progressdlg, [ --enable-progressdlg use wxProgressDialog], wxUSE_PROGRESSDLG) WX_ARG_ENABLE(miniframe, [ --enable-miniframe use wxMiniFrame class], wxUSE_MINIFRAME) +WX_ARG_ENABLE(html, [ --enable-html use wxHTML sub-library], wxUSE_HTML) WX_ARG_ENABLE(tooltips, [ --enable-tooltips use wxToolTip class], wxUSE_TOOLTIPS) WX_ARG_ENABLE(splines, [ --enable-splines use spline drawing code], wxUSE_SPLINES) WX_ARG_ENABLE(validators, [ --enable-validators use wxValidator and derived classes], wxUSE_VALIDATORS) @@ -1993,6 +1996,11 @@ if test "$wxUSE_MINIFRAME" = "yes"; then SAMPLES_SUBDIRS="$SAMPLES_SUBDIRS minifram" fi +if test "$wxUSE_HTML" = "yes"; then + AC_DEFINE(wxUSE_HTML) + SAMPLES_SUBDIRS="$SAMPLES_SUBDIRS html" +fi + if test "$wxUSE_VALIDATORS" = "yes"; then AC_DEFINE(wxUSE_VALIDATORS) SAMPLES_SUBDIRS="$SAMPLES_SUBDIRS validate" @@ -2178,6 +2186,14 @@ dnl samples/Makefile samples/minimal/Makefile samples/validate/Makefile samples/wxpoem/Makefile samples/wxsocket/Makefile + samples/html/Makefile + samples/html/about/Makefile + samples/html/help/Makefile + samples/html/test/Makefile + samples/html/printing/Makefile + samples/html/widget/Makefile + samples/html/virtual/Makefile + samples/html/zip/Makefile ], [ chmod +x wx-config diff --git a/include/wx/busyinfo.h b/include/wx/busyinfo.h new file mode 100644 index 0000000000..b4266a935a --- /dev/null +++ b/include/wx/busyinfo.h @@ -0,0 +1,58 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: busyinfo.h +// Purpose: Information window (when app is busy) +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef __INFOWIN_H__ +#define __INFOWIN_H__ + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + + +#include + + + + +class wxInfoFrame : public wxFrame +{ + public: + wxInfoFrame(wxWindow *parent, const wxString& message); +}; + + +//-------------------------------------------------------------------------------- +// wxBusyInfo +// Displays progress information +// Can be used in exactly same way as wxBusyCursor +//-------------------------------------------------------------------------------- + +class wxBusyInfo : public wxObject +{ + public: + wxBusyInfo(const wxString& message); + ~wxBusyInfo(); + + private: + wxInfoFrame *m_InfoFrame; +}; + + +#endif + + diff --git a/include/wx/filesys.h b/include/wx/filesys.h new file mode 100644 index 0000000000..5ff10cb25e --- /dev/null +++ b/include/wx/filesys.h @@ -0,0 +1,194 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: filesys.h +// Purpose: class for opening files - virtual file system +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef __FILESYS_H__ +#define __FILESYS_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + +#include +#include +#include + + +class wxFSFile; +class wxFileSystemHandler; +class wxFileSystem; + +//-------------------------------------------------------------------------------- +// wxFSFile +// This class is a file opened using wxFileSystem. It consists of +// input stream, location, mime type & optional anchor +// (in 'index.htm#chapter2', 'chapter2' is anchor) +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxFSFile : public wxObject +{ + private: + wxInputStream *m_Stream; + wxString m_Location; + wxString m_MimeType; + wxString m_Anchor; + + public: + wxFSFile(wxInputStream *stream, const wxString& loc, const wxString& mimetype, const wxString& anchor) + { + m_Stream = stream; + m_Location = loc; + m_MimeType = mimetype; m_MimeType.MakeLower(); + m_Anchor = anchor; + } + virtual ~wxFSFile() + { + if (m_Stream) delete m_Stream; + } + + wxInputStream *GetStream() const {return m_Stream;} + // returns stream. This doesn't _create_ stream, it only returns + // pointer to it!! + + const wxString& GetMimeType() const {return m_MimeType;} + // returns file's mime type + + const wxString& GetLocation() const {return m_Location;} + // returns the original location (aka filename) of the file + + const wxString& GetAnchor() const {return m_Anchor;} +}; + + + + + +//-------------------------------------------------------------------------------- +// wxFileSystemHandler +// This class is FS handler for wxFileSystem. It provides +// interface to access certain +// kinds of files (HTPP, FTP, local, tar.gz etc..) +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxFileSystemHandler : public wxObject +{ + DECLARE_ABSTRACT_CLASS(wxFileSystemHandler) + + public: + wxFileSystemHandler() : wxObject() {} + + virtual bool CanOpen(const wxString& location) = 0; + // returns TRUE if this handler is able to open given location + + virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location) = 0; + // opens given file and returns pointer to input stream. + // Returns NULL if opening failed. + // The location is always absolute path. + + protected: + wxString GetProtocol(const wxString& location) const; + // returns protocol ("file", "http", "tar" etc.) The last (most right) + // protocol is used: + // {it returns "tar" for "file:subdir/archive.tar.gz#tar:/README.txt"} + + wxString GetLeftLocation(const wxString& location) const; + // returns left part of address: + // {it returns "file:subdir/archive.tar.gz" for "file:subdir/archive.tar.gz#tar:/README.txt"} + + wxString GetAnchor(const wxString& location) const; + // returns anchor part of address: + // {it returns "anchor" for "file:subdir/archive.tar.gz#tar:/README.txt#anchor"} + // NOTE: anchor is NOT a part of GetLeftLocation()'s return value + + wxString GetRightLocation(const wxString& location) const; + // returns right part of address: + // {it returns "/README.txt" for "file:subdir/archive.tar.gz#tar:/README.txt"} + + wxString GetMimeTypeFromExt(const wxString& location); + // Returns MIME type of the file - w/o need to open it + // (default behaviour is that it returns type based on extension) + + private: + static wxMimeTypesManager m_MimeMng; + // MIME manager + // (it's static and thus shared by all instances and derived classes) +}; + + + + +//-------------------------------------------------------------------------------- +// wxFileSystem +// This class provides simple interface for opening various +// kinds of files (HTPP, FTP, local, tar.gz etc..) +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxFileSystem : public wxObject +{ + DECLARE_DYNAMIC_CLASS(wxFileSystem) + + private: + wxString m_Path; + // the path (location) we are currently in + // this is path, not file! + // (so if you opened test/demo.htm, it is + // "test/", not "test/demo.htm") + wxString m_LastName; + // name of last opened file (full path) + static wxList m_Handlers; + // list of FS handlers + + public: + wxFileSystem() : wxObject() {m_Path = m_LastName = wxEmptyString; m_Handlers.DeleteContents(TRUE);} + + void ChangePathTo(const wxString& location, bool is_dir = FALSE); + // sets the current location. Every call to OpenFile is + // relative to this location. + // NOTE !! + // unless is_dir = TRUE 'location' is *not* the directory but + // file contained in this directory + // (so ChangePathTo("dir/subdir/xh.htm") sets m_Path to "dir/subdir/") + + wxString GetPath() const {return m_Path;} + + wxFSFile* OpenFile(const wxString& location); + // opens given file and returns pointer to input stream. + // Returns NULL if opening failed. + // It first tries to open the file in relative scope + // (based on ChangePathTo()'s value) and then as an absolute + // path. + + static void AddHandler(wxFileSystemHandler *handler); + // Adds FS handler. + // In fact, this class is only front-end to the FS hanlers :-) +}; + + +/* + +'location' syntax: + +To determine FS type, we're using standard KDE notation: +file:/absolute/path/file.htm +file:relative_path/xxxxx.html +/some/path/x.file ('file:' is default) +http://www.gnome.org +file:subdir/archive.tar.gz#tar:/README.txt + +special characters : + ':' - FS identificator is before this char + '#' - separator. It can be either HTML anchor ("index.html#news") + (in case there is no ':' in the string to the right from it) + or FS separator + (example : http://www.wxhtml.org/wxhtml-0.1.tar.gz#tar:/include/wxhtml/filesys.h" + this would access tgz archive stored on web) + '/' - directory (path) separator. It is used to determine upper-level path. + HEY! Don't use \ even if you're on Windows! + +*/ + +#endif // __FILESYS_H__ diff --git a/include/wx/fs_inet.h b/include/wx/fs_inet.h new file mode 100644 index 0000000000..695bdb425f --- /dev/null +++ b/include/wx/fs_inet.h @@ -0,0 +1,55 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: fs_inet.h +// Purpose: HTTP and FTP file system +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +/* + +REMARKS : + +This FS creates local cache (in /tmp directory). The cache is freed +on program exit. + +Size of cache is limited to cca 1000 items (due to GetTempFileName +limitation) + + +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include + + + +//-------------------------------------------------------------------------------- +// wxInternetFSHandler +//-------------------------------------------------------------------------------- + +class wxInternetFSHandler : public wxFileSystemHandler +{ + private: + wxHashTable m_Cache; + + public: + virtual bool CanOpen(const wxString& location); + virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location); + ~wxInternetFSHandler(); +}; + + diff --git a/include/wx/fs_zip.h b/include/wx/fs_zip.h new file mode 100644 index 0000000000..f0b481d78f --- /dev/null +++ b/include/wx/fs_zip.h @@ -0,0 +1,41 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: fs_zip.h +// Purpose: ZIP file system +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include + + + +//-------------------------------------------------------------------------------- +// wxZipFSHandler +//-------------------------------------------------------------------------------- + +class wxZipFSHandler : public wxFileSystemHandler +{ + public: + virtual bool CanOpen(const wxString& location); + virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location); + ~wxZipFSHandler(); +}; + + + diff --git a/include/wx/html/forcelink.h b/include/wx/html/forcelink.h new file mode 100644 index 0000000000..2be0bc0cf6 --- /dev/null +++ b/include/wx/html/forcelink.h @@ -0,0 +1,59 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: forcelink.h +// Purpose: see bellow +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +/* + +DESCRPITON: + +mod_*.cpp files contain handlers for tags. These files are modules - they contain +one wxTagModule class and it's OnInit() method is called from wxApp's init method. +The module is called even if you only link it into the executable, so everything +seems wonderful. + +The problem is that we have these modules in LIBRARY and mod_*.cpp files contain +no method nor class which is known out of the module. So the linker won't +link these .o/.obj files into executable because it detected that it is not used +by the program. + +To workaround this I introduced set of macros FORCE_LINK_ME and FORCE_LINK. These +macros are generic and are not limited to mod_*.cpp files. You may find them quite +useful somewhere else... + +How to use them: +let's suppose you want to always link file foo.cpp and that you have module +always.cpp that is certainly always linked (e.g. the one with main() function +or htmlwin.cpp in wxHtml library). + +Place FORCE_LINK_ME(foo) somewhere in foo.cpp and FORCE_LINK(foo) somewhere +in always.cpp +See mod_*.cpp and htmlwin.cpp for example :-) + +*/ + + +#ifndef __FORCELINK_H__ +#define __FORCELINK_H__ + + + +// This must be part of the module you want to force: +#define FORCE_LINK_ME(module_name) \ + int _link_dummy_func_##module_name () \ + { \ + return 1; \ + } + + +// And this must be somewhere where it certainly will be linked: +#define FORCE_LINK(module_name) \ + extern int _link_dummy_func_##module_name (); \ + static int _link_dummy_var_##module_name = \ + _link_dummy_func_##module_name (); + + +#endif // __FORCELINK_H__ diff --git a/include/wx/html/htmlcell.h b/include/wx/html/htmlcell.h new file mode 100644 index 0000000000..23293c93b0 --- /dev/null +++ b/include/wx/html/htmlcell.h @@ -0,0 +1,292 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmlcell.h +// Purpose: wxHtmlCell class is used by wxHtmlWindow/wxHtmlWinParser +// as a basic visual element of HTML page +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifndef __HTMLCELL_H__ +#define __HTMLCELL_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/defs.h" +#if wxUSE_HTML + + +#include +#include +#include + +class wxHtmlCell; +class wxHtmlContainerCell; + +//-------------------------------------------------------------------------------- +// wxHtmlCell +// Internal data structure. It represents fragments of parsed HTML +// page - a word, picture, table, horizontal line and so on. +// It is used by wxHtmlWindow to represent HTML page in memory. +//-------------------------------------------------------------------------------- + + +class WXDLLEXPORT wxHtmlCell : public wxObject +{ + protected: + wxHtmlCell *m_Next; + // pointer to the next cell + wxHtmlContainerCell *m_Parent; + // pointer to parent cell + long m_Width, m_Height, m_Descent; + // dimensions of fragment + // m_Descent is used to position text&images.. + long m_PosX, m_PosY; + // position where the fragment is drawn + wxString m_Link; + // destination address if this fragment is hypertext link, "" otherwise + + public: + wxHtmlCell() : wxObject() {m_Next = NULL; m_Parent = NULL; m_Width = m_Height = m_Descent = 0;}; + virtual ~wxHtmlCell() {if (m_Next) delete m_Next;}; + + void SetParent(wxHtmlContainerCell *p) {m_Parent = p;} + wxHtmlContainerCell *GetParent() const {return m_Parent;} + + int GetPosX() const {return m_PosX;} + int GetPosY() const {return m_PosY;} + int GetWidth() const {return m_Width;} + int GetHeight() const {return m_Height;} + int GetDescent() const {return m_Descent;} + virtual wxString GetLink(int x = 0, int y = 0) const {return m_Link;} + // returns the link associated with this cell. The position is position within + // the cell so it varies from 0 to m_Width, from 0 to m_Height + wxHtmlCell *GetNext() const {return m_Next;} + // members access methods + + virtual void SetPos(int x, int y) {m_PosX = x, m_PosY = y;} + void SetLink(const wxString& link) {m_Link = link;} + void SetNext(wxHtmlCell *cell) {m_Next = cell;} + // members writin methods + + virtual void Layout(int w) {SetPos(0, 0); if (m_Next) m_Next -> Layout(w);}; + // 1. adjust cell's width according to the fact that maximal possible width is w. + // (this has sense when working with horizontal lines, tables etc.) + // 2. prepare layout (=fill-in m_PosX, m_PosY (and sometime m_Height) members) + // = place items to fit window, according to the width w + + virtual void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2) {if (m_Next) m_Next -> Draw(dc, x, y, view_y1, view_y2);} + // renders the cell + + virtual void DrawInvisible(wxDC& dc, int x, int y) {if (m_Next) m_Next -> DrawInvisible(dc, x, y);}; + // proceed drawing actions in case the cell is not visible (scrolled out of screen). + // This is needed to change fonts, colors and so on + + virtual const wxHtmlCell* Find(int condition, const void* param) const {if (m_Next) return m_Next -> Find(condition, param); else return NULL;} + // This method returns pointer to the FIRST cell for that + // the condition + // is true. It first checks if the condition is true for this + // cell and then calls m_Next -> Find(). (Note: it checks + // all subcells if the cell is container) + // Condition is unique condition identifier (see htmldefs.h) + // (user-defined condition IDs should start from 10000) + // and param is optional parameter + // Example : m_Cell -> Find(HTML_COND_ISANCHOR, "news"); + // returns pointer to anchor news + + virtual void OnMouseClick(wxWindow *parent, int x, int y, bool left, bool middle, bool right); + // This function is called when mouse button is clicked over the cell. + // left, middle, right are flags indicating whether the button was or wasn't + // pressed. + // Parent is pointer to wxHtmlWindow that generated the event + // HINT: if this handling is not enough for you you should use + // wxHtmlBinderCell +}; + + + + +//-------------------------------------------------------------------------------- +// Inherited cells: +//-------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------- +// wxHtmlWordCell +// Single word in input stream. +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlWordCell : public wxHtmlCell +{ + protected: + wxString m_Word; + + public: + wxHtmlWordCell(const wxString& word, wxDC& dc); + void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2); +}; + + + + + +//-------------------------------------------------------------------------------- +// wxHtmlContainerCell +// Container - it contains other cells. Basic of layout algorithm. +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlContainerCell : public wxHtmlCell +{ + protected: + int m_IndentLeft, m_IndentRight, m_IndentTop, m_IndentBottom; + // indentation of subcells. There is always m_Indent pixels + // big space between given border of the container and the subcells + // it m_Indent < 0 it is in PERCENTS, otherwise it is in pixels + int m_MinHeight, m_MinHeightAlign; + // minimal height. + int m_MaxLineWidth; + // maximal widht of line. Filled during Layout() + wxHtmlCell *m_Cells, *m_LastCell; + // internal cells, m_Cells points to the first of them, m_LastCell to the last one. + // (LastCell is needed only to speed-up InsertCell) + int m_AlignHor, m_AlignVer; + // alignment horizontal and vertical (left, center, right) + int m_WidthFloat, m_WidthFloatUnits; + // width float is used in adjustWidth + bool m_UseBkColour; + wxColour m_BkColour; + // background color of this container + bool m_UseBorder; + wxColour m_BorderColour1, m_BorderColour2; + // borders color of this container + + public: + wxHtmlContainerCell(wxHtmlContainerCell *parent); + ~wxHtmlContainerCell() {if (m_Cells) delete m_Cells;} + + virtual void Layout(int w); + virtual void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2); + virtual void DrawInvisible(wxDC& dc, int x, int y); + + void InsertCell(wxHtmlCell *cell); + // insert cell at the end of m_Cells list + void SetAlignHor(int al) {m_AlignHor = al;} + int GetAlignHor() const {return m_AlignHor;} + void SetAlignVer(int al) {m_AlignVer = al;} + // sets horizontal/vertical alignment + int GetAlignVer() const {return m_AlignVer;} + void SetIndent(int i, int what, int units = HTML_UNITS_PIXELS); + // sets left-border indentation. units is one of HTML_UNITS_* constants + // what is combination of HTML_INDENT_* + int GetIndent(int ind) const; + // returns the indentation. ind is one of HTML_INDENT_* constants + int GetIndentUnits(int ind) const; + // returns type of value returned by GetIndent(ind) + void SetAlign(const wxHtmlTag& tag); + // sets alignment info based on given tag's params + void SetWidthFloat(int w, int units) {m_WidthFloat = w; m_WidthFloatUnits = units;} + void SetWidthFloat(const wxHtmlTag& tag); + // sets floating width adjustment + // (examples : 32 percent of parent container, + // -15 pixels percent (this means 100 % - 15 pixels) + void SetMinHeight(int h, int align = HTML_ALIGN_TOP) {m_MinHeight = h; m_MinHeightAlign = align;} + // sets minimal height of this container. + int GetMaxLineWidth() const {return m_MaxLineWidth;} + // returns maximal line width in this container. + // Call to this method is valid only after calling + // Layout() + void SetBackgroundColour(const wxColour& clr) {m_UseBkColour = TRUE; m_BkColour = clr;} + void SetBorder(const wxColour& clr1, const wxColour& clr2) {m_UseBorder = TRUE; m_BorderColour1 = clr1, m_BorderColour2 = clr2;} + virtual wxString GetLink(int x = 0, int y = 0) const; + virtual const wxHtmlCell* Find(int condition, const void* param) const; + virtual void OnMouseClick(wxWindow *parent, int x, int y, bool left, bool middle, bool right); + + wxHtmlCell* GetFirstCell() {return m_Cells;} + // returns pointer to the first cell in container or NULL +}; + + + + + +//-------------------------------------------------------------------------------- +// wxHtmlColourCell +// Color changer. +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlColourCell : public wxHtmlCell +{ + public: + wxColour m_Colour; + unsigned m_Flags; + + wxHtmlColourCell(wxColour clr, int flags = HTML_CLR_FOREGROUND) : wxHtmlCell() {m_Colour = clr; m_Flags = flags;} + virtual void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2); + virtual void DrawInvisible(wxDC& dc, int x, int y); +}; + + + + +//-------------------------------------------------------------------------------- +// wxHtmlFontCell +// Sets actual font used for text rendering +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlFontCell : public wxHtmlCell +{ + public: + wxFont *m_Font; + + wxHtmlFontCell(wxFont *font) : wxHtmlCell() {m_Font = font;}; + virtual void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2); + virtual void DrawInvisible(wxDC& dc, int x, int y); +}; + + + + + + +//-------------------------------------------------------------------------------- +// wxHtmlwidgetCell +// This cell is connected with wxWindow object +// You can use it to insert windows into HTML page +// (buttons, input boxes etc.) +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlWidgetCell : public wxHtmlCell +{ + protected: + wxWindow* m_Wnd; + int m_WidthFloat; + // width float is used in adjustWidth (it is in percents) + + public: + wxHtmlWidgetCell(wxWindow *wnd, int w = 0); + // !!! wnd must have correct parent! + // if w != 0 then the m_Wnd has 'floating' width - it adjust + // it's width according to parent container's width + // (w is percent of parent's width) + virtual void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2); + virtual void DrawInvisible(wxDC& dc, int x, int y); + virtual void Layout(int w); +}; + + + + +#endif // __HTMLCELL_H__ + +#endif + + + + + + + + diff --git a/include/wx/html/htmldefs.h b/include/wx/html/htmldefs.h new file mode 100644 index 0000000000..88d5602683 --- /dev/null +++ b/include/wx/html/htmldefs.h @@ -0,0 +1,94 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmldefs.h +// Purpose: constants for wxhtml library +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifndef __HTMLDEFS_H__ +#define __HTMLDEFS_H__ + +#include "wx/defs.h" +#if wxUSE_HTML + + +//-------------------------------------------------------------------------------- +// ALIGNMENTS +// Describes alignment of text etc. in containers +//-------------------------------------------------------------------------------- + +#define HTML_ALIGN_LEFT 0x0000 +#define HTML_ALIGN_RIGHT 0x0002 + +#define HTML_ALIGN_TOP 0x0004 +#define HTML_ALIGN_BOTTOM 0x0008 + +#define HTML_ALIGN_CENTER 0x0001 + + + +//-------------------------------------------------------------------------------- +// COLOR MODES +// Used by wxHtmlColourCell to determine clr of what is changing +//-------------------------------------------------------------------------------- + +#define HTML_CLR_FOREGROUND 0x0001 +#define HTML_CLR_BACKGROUND 0x0002 + + + +//-------------------------------------------------------------------------------- +// UNITS +// Used to specify units +//-------------------------------------------------------------------------------- + +#define HTML_UNITS_PIXELS 0x0001 +#define HTML_UNITS_PERCENT 0x0002 + + + +//-------------------------------------------------------------------------------- +// INDENTS +// Used to specify indetation relatives +//-------------------------------------------------------------------------------- + +#define HTML_INDENT_LEFT 0x0010 +#define HTML_INDENT_RIGHT 0x0020 +#define HTML_INDENT_TOP 0x0040 +#define HTML_INDENT_BOTTOM 0x0080 + +#define HTML_INDENT_HORIZONTAL HTML_INDENT_LEFT | HTML_INDENT_RIGHT +#define HTML_INDENT_VERTICAL HTML_INDENT_TOP | HTML_INDENT_BOTTOM +#define HTML_INDENT_ALL HTML_INDENT_VERTICAL | HTML_INDENT_HORIZONTAL + + + + +//-------------------------------------------------------------------------------- +// FIND CONDITIONS +// Identifiers of wxHtmlCell's Find() conditions +//-------------------------------------------------------------------------------- + +#define HTML_COND_ISANCHOR 1 + // Finds the anchor of 'param' name (pointer to wxString). + +#define HTML_COND_USER 10000 + // User-defined conditions should start from this number + + +//-------------------------------------------------------------------------------- +// INTERNALS +// wxHTML internal constants +//-------------------------------------------------------------------------------- + +#define HTML_SCROLL_STEP 16 + /* size of one scroll step of wxHtmlWindow in pixels */ +#define HTML_BUFLEN 1024 + /* size of temporary buffer used during parsing */ +#define HTML_REALLOC_STEP 32 + /* steps of array reallocation */ + +#endif +#endif \ No newline at end of file diff --git a/include/wx/html/htmlfilter.h b/include/wx/html/htmlfilter.h new file mode 100644 index 0000000000..99b00d8de6 --- /dev/null +++ b/include/wx/html/htmlfilter.h @@ -0,0 +1,70 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmlfilter.h +// Purpose: filters +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifndef __HTMLFILTER_H__ +#define __HTMLFILTER_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/defs.h" +#if wxUSE_HTML + +#include + + +//-------------------------------------------------------------------------------- +// wxHtmlFilter +// This class is input filter. It can "translate" files +// in non-HTML format to HTML format +// interface to access certain +// kinds of files (HTPP, FTP, local, tar.gz etc..) +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlFilter : public wxObject +{ + DECLARE_ABSTRACT_CLASS(wxHtmlFilter) + + public: + wxHtmlFilter() : wxObject() {} + + virtual bool CanRead(const wxFSFile& file) = 0; + // returns TRUE if this filter is able to open&read given file + + virtual wxString ReadFile(const wxFSFile& file) = 0; + // reads given file and returns HTML document. + // Returns empty string if opening failed +}; + + + +//-------------------------------------------------------------------------------- +// wxHtmlFilterPlainText +// This filter is used as default filter if no other can +// be used (= uknown type of file). It is used by +// wxHtmlWindow itself. +//-------------------------------------------------------------------------------- + + +class WXDLLEXPORT wxHtmlFilterPlainText : public wxHtmlFilter +{ + DECLARE_DYNAMIC_CLASS(wxHtmlFilterPlainText) + + public: + virtual bool CanRead(const wxFSFile& file); + virtual wxString ReadFile(const wxFSFile& file); +}; + + + + +#endif // __HTMLFILTER_H__ + +#endif \ No newline at end of file diff --git a/include/wx/html/htmlhelp.h b/include/wx/html/htmlhelp.h new file mode 100644 index 0000000000..6e56bc5815 --- /dev/null +++ b/include/wx/html/htmlhelp.h @@ -0,0 +1,223 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmlhelp.h +// Purpose: Help controller +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifndef __HTMLHELP_H__ +#define __HTMLHELP_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/defs.h" +#if wxUSE_HTML + +#include +#include +#include +#include +#include +#include + + + +//-------------------------------------------------------------------------------- +// helper classes & structs - please ignore 'em +//-------------------------------------------------------------------------------- + + + +class WXDLLEXPORT HtmlBookRecord : public wxObject +{ + public: + wxString m_BasePath; + wxString m_Title; + wxString m_Start; + + HtmlBookRecord(const wxString& basepath, const wxString& title, const wxString& start) {m_BasePath = basepath; m_Title = title; m_Start = start;} + wxString GetTitle() const {return m_Title;} + wxString GetStart() const {return m_Start;} + wxString GetBasePath() const {return m_BasePath;} +}; + + +#undef WXDLLEXPORTLOCAL +#define WXDLLEXPORTLOCAL WXDLLEXPORT + // ?? Don't know why - but Allen Van Sickel reported it to fix problems with DLL +WX_DECLARE_OBJARRAY(HtmlBookRecord, HtmlBookRecArray); + +#undef WXDLLEXPORTLOCAL +#define WXDLLEXPORTLOCAL + + +typedef struct + { + short int m_Level; + int m_ID; + char* m_Name; + char* m_Page; + HtmlBookRecord *m_Book; + } HtmlContentsItem; + + + + +//-------------------------------------------------------------------------------- +// wxHtmlHelpController +// This class ensures dislaying help. +// See documentation for details on its philosophy. +// +// WARNING!! +// This class is not derived from wxHelpController and is not +// compatible with it! +//-------------------------------------------------------------------------------- + + +class WXDLLEXPORT wxHtmlHelpController : public wxEvtHandler +{ + DECLARE_DYNAMIC_CLASS(wxHtmlHelpController) + + protected: + wxConfigBase *m_Config; + wxString m_ConfigRoot; + // configuration file/registry used to store custom settings + wxString m_TitleFormat; + // title of the help frame + wxString m_TempPath; + + wxFrame *m_Frame; + wxHtmlWindow *m_HtmlWin; + wxSplitterWindow *m_Splitter; + wxNotebook *m_NavigPan; + wxTreeCtrl *m_ContentsBox; + wxImageList *m_ContentsImageList; + wxListBox *m_IndexBox; + wxTextCtrl *m_SearchText; + wxButton *m_SearchButton; + wxListBox *m_SearchList; + // ...pointers to parts of help window + + struct { + long x, y, w, h; + long sashpos; + bool navig_on; + } m_Cfg; + // settings (window size, position, sash pos etc..) + + HtmlBookRecArray m_BookRecords; + // each book has one record in this array + HtmlContentsItem* m_Contents; + int m_ContentsCnt; + // list of all available books and pages. + HtmlContentsItem* m_Index; + int m_IndexCnt; + // list of index items + + public: + wxHtmlHelpController(); + ~wxHtmlHelpController(); + + void SetTitleFormat(const wxString& format) {m_TitleFormat = format;} + // Sets format of title of the frame. Must contain exactly one "%s" + // (for title of displayed HTML page) + + void SetTempDir(const wxString& path); + // Sets directory where temporary files are stored. + // These temp files are index & contents file in binary (much faster to read) + // form. These files are NOT deleted on program's exit. + + bool AddBook(const wxString& book, bool show_wait_msg = FALSE); + // Adds new book. 'book' is location of .htb file (stands for "html book"). + // See documentation for details on its format. + // Returns success. + // If show_wait_msg == true then message window with "loading book..." is displayed + + void Display(const wxString& x); + // Displays page x. If not found it will offect the user a choice of searching + // books. + // Looking for the page runs in these steps: + // 1. try to locate file named x (if x is for example "doc/howto.htm") + // 2. try to open starting page of book x + // 3. try to find x in contents (if x is for example "How To ...") + // 4. try to find x in index (if x is for example "How To ...") + // 5. offer searching and if the user agree, run KeywordSearch + void Display(const int id); + // Alternative version that works with numeric ID. + // (uses extension to MS format, , see docs) + + void DisplayContents(); + // Displays help window and focuses contents. + + void DisplayIndex(); + // Displays help window and focuses index. + + bool KeywordSearch(const wxString& keyword); + // Searches for keyword. Returns TRUE and display page if found, return + // FALSE otherwise + // Syntax of keyword is Altavista-like: + // * words are separated by spaces + // (but "\"hello world\"" is only one world "hello world") + // * word may be pretended by + or - + // (+ : page must contain the word ; - : page can't contain the word) + // * if there is no + or - before the word, + is default + + void UseConfig(wxConfigBase *config, const wxString& rootpath = wxEmptyString) {m_Config = config; m_ConfigRoot = rootpath;} + // Assigns config object to the controller. This config is then + // used in subsequent calls to Read/WriteCustomization of both help + // controller and it's wxHtmlWindow + + void ReadCustomization(wxConfigBase *cfg, wxString path = wxEmptyString); + // saves custom settings into cfg config. it will use the path 'path' + // if given, otherwise it will save info into currently selected path. + // saved values : things set by SetFonts, SetBorders. + void WriteCustomization(wxConfigBase *cfg, wxString path = wxEmptyString); + // ... + + protected: + virtual void CreateHelpWindow(); + // Creates frame & html window and sets m_Frame and other variables; + // Do nothing if the window already exists + void RefreshLists(); + // Refreshes Contents and Index tabs + void CreateContents(); + // Adds items to m_Contents tree control + void CreateIndex(); + // Adds items to m_IndexList + + void LoadMSProject(HtmlBookRecord *book, wxFileSystem& fsys, const wxString& indexfile, const wxString& contentsfile, bool show_wait_msg); + // Imports .hhp files (MS HTML Help Workshop) + void LoadCachedBook(HtmlBookRecord *book, wxInputStream *f); + // Reads binary book + void SaveCachedBook(HtmlBookRecord *book, wxOutputStream *f); + // Writes binary book + + void OnToolbar(wxCommandEvent& event); + void OnContentsSel(wxTreeEvent& event); + void OnIndexSel(wxCommandEvent& event); + void OnSearchSel(wxCommandEvent& event); + void OnSearch(wxCommandEvent& event); + void OnCloseWindow(wxCloseEvent& event); + + DECLARE_EVENT_TABLE() +}; + + + +#endif // __HTMLHELP_H__ + +#endif + + + + + + + + + + diff --git a/include/wx/html/htmlparser.h b/include/wx/html/htmlparser.h new file mode 100644 index 0000000000..d1c6a65070 --- /dev/null +++ b/include/wx/html/htmlparser.h @@ -0,0 +1,176 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmlparser.h +// Purpose: wxHtmlParser class (generic parser) +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifndef __HTMLPARSER_H__ +#define __HTMLPARSER_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/defs.h" +#if wxUSE_HTML + +#include +#include + +class wxHtmlParser; +class wxHtmlTagHandler; + +//-------------------------------------------------------------------------------- +// wxHtmlParser +// This class handles generic parsing of HTML document : it scans +// the document and divide it into blocks of tags (where one block +// consists of starting and ending tag and of text between these +// 2 tags. +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlParser : public wxObject +{ + DECLARE_ABSTRACT_CLASS(wxHtmlParser) + + protected: + wxString m_Source; + // source being parsed + wxHtmlTagsCache *m_Cache; + // tags cache, used during parsing. + wxHashTable m_HandlersHash; + wxList m_HandlersList; + // handlers that handle particular tags. The table is accessed by + // key = tag's name. + // This attribute MUST be filled by derived class otherwise it would + // be empty and no tags would be recognized + // (see wxHtmlWinParser for details about filling it) + // m_HandlersHash is for random access based on knowledge of tag name (BR, P, etc.) + // it may (and often does) contain more references to one object + // m_HandlersList is list of all handlers and it is guaranteed to contain + // only one reference to each handler instance. + wxFileSystem *m_FS; + // class for opening files (file system) + + public: + wxHtmlParser() : wxObject(), m_HandlersHash(wxKEY_STRING) {m_FS = NULL; m_Cache = NULL;} + virtual ~wxHtmlParser(); + + void SetFS(wxFileSystem *fs) {m_FS = fs;} + // Sets the class which will be used for opening files + wxFileSystem* GetFS() const {return m_FS;} + + wxObject* Parse(const wxString& source); + // You can simply call this method when you need parsed output. + // This method does these things: + // 1. call InitParser(source); + // 2. call DoParsing(); + // 3. call GetProduct(); (it's return value is then returned) + // 4. call DoneParser(); + + virtual void InitParser(const wxString& source); + // Sets the source. This must be called before running Parse() method. + virtual void DoneParser(); + // This must be called after Parse(). + + void DoParsing(int begin_pos, int end_pos); + inline void DoParsing() {DoParsing(0, m_Source.Length());}; + // Parses the m_Source from begin_pos to end_pos-1. + // (in noparams version it parses whole m_Source) + + virtual wxObject* GetProduct() = 0; + // Returns product of parsing + // Returned value is result of parsing of the part. The type of this result + // depends on internal representation in derived parser + // (see wxHtmlWinParser for details). + + virtual void AddTagHandler(wxHtmlTagHandler *handler); + // adds handler to the list & hash table of handlers. + + wxString* GetSource() {return &m_Source;} + + virtual wxList* GetTempData() {return NULL;} + // this method returns list of wxObjects that represents + // all data allocated by the parser. These can't be freeded + // by destructor because they must be valid as long as + // GetProduct's return value is valid - the caller must + // explicitly call delete MyParser -> GetTempData() to free + // the memory + // (this method always sets the list to delete its contents) + + protected: + + virtual void AddText(const char* txt) = 0; + // Adds text to the output. + // This is called from Parse() and must be overriden in derived classes. + // txt is not guaranteed to be only one word. It is largest continuous part of text + // (= not broken by tags) + // NOTE : using char* because of speed improvements + + virtual void AddTag(const wxHtmlTag& tag); + // Adds tag and proceeds it. Parse() may (and usually is) called from this method. + // This is called from Parse() and may be overriden. + // Default behavior is that it looks for proper handler in m_Handlers. The tag is + // ignored if no hander is found. + // Derived class is *responsible* for filling in m_Handlers table. +}; + + + + + + +//-------------------------------------------------------------------------------- +// wxHtmlTagHandler +// This class (and derived classes) cooperates with wxHtmlParser. +// Each recognized tag is passed to handler which is capable +// of handling it. Each tag is handled in 3 steps: +// 1. Handler will modifies state of parser +// (using it's public methods) +// 2. Parser parses source between starting and ending tag +// 3. Handler restores original state of the parser +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlTagHandler : public wxObject +{ + DECLARE_ABSTRACT_CLASS(wxHtmlTagHandler) + + protected: + wxHtmlParser *m_Parser; + + public: + wxHtmlTagHandler() : wxObject () {m_Parser = NULL;}; + + virtual void SetParser(wxHtmlParser *parser) {m_Parser = parser;} + // Sets the parser. + // NOTE : each _instance_ of handler is guaranteed to be called + // only by one parser. This means you don't have to care about + // reentrancy. + + virtual wxString GetSupportedTags() = 0; + // Returns list of supported tags. The list is in uppercase and + // tags are delimited by ','. + // Example : "I,B,FONT,P" + // is capable of handling italic, bold, font and paragraph tags + + virtual bool HandleTag(const wxHtmlTag& tag) = 0; + // This is hadling core method. It does all the Steps 1-3. + // To process step 2, you can call ParseInner() + // returned value : TRUE if it called ParseInner(), + // FALSE etherwise + + protected: + void ParseInner(const wxHtmlTag& tag) {m_Parser -> DoParsing(tag.GetBeginPos(), tag.GetEndPos1());} + // parses input between beginning and ending tag. + // m_Parser must be set. +}; + + + + + +#endif // __HTMLPARSER_H__ + +#endif diff --git a/include/wx/html/htmltag.h b/include/wx/html/htmltag.h new file mode 100644 index 0000000000..2f6a443e58 --- /dev/null +++ b/include/wx/html/htmltag.h @@ -0,0 +1,135 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmltag.h +// Purpose: wxHtmlTag class (represents single tag) +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifndef __HTMLTAG_H__ +#define __HTMLTAG_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/defs.h" +#if wxUSE_HTML + + +//-------------------------------------------------------------------------------- +// wxHtmlTagsCache +// !! INTERNAL STRUCTURE !! Do not use in your program! +// This structure contains information on positions of tags +// in the string being parsed +//-------------------------------------------------------------------------------- + +typedef struct { + int Key; + // this is "pos" value passed to wxHtmlTag's constructor. + // it is position of '<' character of the tag + int End1, End2; + // 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 + char *Name; + // name of this tag + } sCacheItem; + + + +class wxHtmlTagsCache : public wxObject +{ + DECLARE_DYNAMIC_CLASS(wxHtmlTagsCache) + + private: + sCacheItem *m_Cache; + int m_CacheSize; + int m_CachePos; + + public: + wxHtmlTagsCache() : wxObject() {m_CacheSize = 0; m_Cache = NULL;} + wxHtmlTagsCache(const wxString& source); + ~wxHtmlTagsCache() {free(m_Cache);} + + void QueryTag(int at, int* end1, int* end2); + // Finds parameters for tag starting at at and fills the variables +}; + + + +//-------------------------------------------------------------------------------- +// wxHtmlTag +// This represents single tag. It is used as internal structure +// by wxHtmlParser. +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlTag : public wxObject +{ + DECLARE_CLASS(wxHtmlTag) + + private: + wxString m_Name, m_Params; + int m_Begin, m_End1, m_End2; + bool m_Ending; + + public: + wxHtmlTag(const wxString& source, int pos, int end_pos, wxHtmlTagsCache* cache); + // constructs wxHtmlTag object based on HTML tag. + // The tag begins (with '<' character) at position pos in source + // end_pos is position where parsing ends (usually end of document) + + inline wxString GetName() const {return m_Name;}; + // Returns tag's name in uppercase. + + bool HasParam(const wxString& par) const; + // Returns TRUE if the tag has given parameter. Parameter + // should always be in uppercase. + // Example : HasParam("SRC") returns TRUE + + wxString GetParam(const wxString& par, bool with_commas = FALSE) const; + // Returns value of the param. Value is in uppercase unless it is + // enclosed with " + // Example :

GetParam("ALIGN") returns (RIGHT) + //

GetParam("SRC") returns (WhaT.jpg) + // (or ("WhaT.jpg") if with_commas == TRUE) + + void ScanParam(const wxString& par, char *format, ...) const; + // Scans param like scanf() functions family do. + // Example : ScanParam("COLOR", "\"#%X\"", &clr); + // This is always with with_commas=FALSE + + inline const wxString& GetAllParams() const {return m_Params;}; + // Returns string containing all params. + + inline bool IsEnding() const {return m_Ending;}; + // return TRUE if this is ending tag () or FALSE + // if it isn't () + + inline bool HasEnding() const {return m_End1 >= 0;}; + // return TRUE if this is ending tag () or FALSE + // if it isn't () + + inline int GetBeginPos() const {return m_Begin;}; + // returns beginning position of _internal_ block of text + // See explanation (returned value is marked with *): + // bla bla bla * bla bla intenal text bla bla + inline int GetEndPos1() const {return m_End1;}; + // returns ending position of _internal_ block of text. + // bla bla bla bla bla intenal text* bla bla + inline int GetEndPos2() const {return m_End2;}; + // returns end position 2 : + // bla bla bla bla bla internal text* bla bla +}; + + + + + + +#endif // __HTMLTAG_H__ + +#endif diff --git a/include/wx/html/htmlwin.h b/include/wx/html/htmlwin.h new file mode 100644 index 0000000000..351e000d0c --- /dev/null +++ b/include/wx/html/htmlwin.h @@ -0,0 +1,220 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmlwin.h +// Purpose: wxHtmlWindow class for parsing & displaying HTML +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifndef __HTMLWIN_H__ +#define __HTMLWIN_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/defs.h" +#if wxUSE_HTML + +#include +#include +#include +#include +#include +#include +#include + + +//-------------------------------------------------------------------------------- +// wxHtmlWindow +// (This is probably the only class you will directly use.) +// Purpose of this class is to display HTML page (either local +// file or downloaded via HTTP protocol) in a window. Width +// of window is constant - given in constructor - virtual height +// is changed dynamicly depending on page size. +// Once the window is created you can set it's content by calling +// SetPage(text) or LoadPage(filename). +//-------------------------------------------------------------------------------- + + +// item of history list +class WXDLLEXPORT HtmlHistoryItem : public wxObject +{ + private: + wxString m_Page; + wxString m_Anchor; + int m_Pos; + + public: + HtmlHistoryItem(const wxString& p, const wxString& a) {m_Page = p, m_Anchor = a, m_Pos = 0;} + int GetPos() const {return m_Pos;} + void SetPos(int p) {m_Pos = p;} + const wxString& GetPage() const {return m_Page;} + const wxString& GetAnchor() const {return m_Anchor;} +}; + +#undef WXDLLEXPORTLOCAL +#define WXDLLEXPORTLOCAL WXDLLEXPORT + // ?? Don't know why - but Allen Van Sickel reported it to fix problems with DLL + +WX_DECLARE_OBJARRAY(HtmlHistoryItem, HtmlHistoryArray); + +#undef WXDLLEXPORTLOCAL +#define WXDLLEXPORTLOCAL + + +class WXDLLEXPORT wxHtmlWindow : public wxScrolledWindow +{ + DECLARE_DYNAMIC_CLASS(wxHtmlWindow) + + protected: + wxHtmlContainerCell *m_Cell; + // This is pointer to the first cell in parsed data. + // (Note: the first cell is usually top one = all other cells are sub-cells of this one) + wxHtmlWinParser *m_Parser; + // parser which is used to parse HTML input. + // Each wxHtmlWindow has it's own parser because sharing one global + // parser would be problematic (because of reentrancy) + wxString m_OpenedPage; + // contains name of actualy opened page or empty string if no page opened + wxString m_OpenedAnchor; + // contains name of current anchor within m_OpenedPage + wxFileSystem* m_FS; + // class for opening files (file system) + + wxFrame *m_RelatedFrame; + wxString m_TitleFormat; + int m_RelatedStatusBar; + // frame in which page title should be displayed & number of it's statusbar + // reserved for usage with this html window + + int m_Borders; + // borders (free space between text and window borders) + // defaults to 10 pixels. + + bool m_Scrollable; + // TRUE if you can scroll the window. + // If it is FALSE you can't scroll the window even if it's contents is larger + // than window. + + + private: + bool m_tmpMouseMoved; + // a flag indicated if mouse moved + // (if TRUE we will try to change cursor in last call to OnIdle) + bool m_tmpCanDraw; + // if FALSE contents of the window is not redrawn + // (in order to avoid ugly bliking) + + static wxList m_Filters; + // list of HTML filters + static wxHtmlFilterPlainText m_DefaultFilter; + // this filter is used when no filter is able to read some file + + HtmlHistoryArray m_History; + int m_HistoryPos; + // browser history + bool m_HistoryOn; + // if this FLAG is false, items are not added to history + + public: + wxHtmlWindow() : wxScrolledWindow() {}; + wxHtmlWindow(wxWindow *parent, wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, + const wxString& name = "htmlWindow", bool scrollable = TRUE); + ~wxHtmlWindow(); + + bool SetPage(const wxString& source); + // Set HTML page and display it. !! source is HTML document itself, + // it is NOT address/filename of HTML document. If you want to + // specify document location, use LoadPage() istead + // Return value : FALSE if an error occured, TRUE otherwise + + bool LoadPage(const wxString& location); + // Load HTML page from given location. Location can be either + // a) /usr/wxGTK2/docs/html/wx.htm + // b) http://www.somewhere.uk/document.htm + // c) ftp://ftp.somesite.cz/pub/something.htm + // In case there is no prefix (http:,ftp:), the method + // will try to find it itself (1. local file, then http or ftp) + // After the page is loaded, the method calls SetPage() to display it. + // Note : you can also use path relative to previously loaded page + // Return value : same as SetPage + + wxString GetOpenedPage() const {return m_OpenedPage;} + // Returns full location of opened page + + void SetRelatedFrame(wxFrame* frame, const wxString& format); + // sets frame in which page title will be displayed. Format is format of + // frame title, e.g. "HtmlHelp : %s". It must contain exactly one %s + wxFrame* GetRelatedFrame() const {return m_RelatedFrame;} + + void SetRelatedStatusBar(int bar); + // after(!) calling SetRelatedFrame, this sets statusbar slot where messages + // will be displayed. Default is -1 = no messages. + + void SetFonts(wxString normal_face, int normal_italic_mode, wxString fixed_face, int fixed_italic_mode, int *sizes); + // sets fonts to be used when displaying HTML page. + // *_italic_mode can be either wxSLANT or wxITALIC + + void SetTitle(const wxString& title); + // Sets the title of the window + // (depending on the information passed to SetRelatedFrame() method) + + void SetBorders(int b) {m_Borders = b;} + // Sets space between text and window borders. + + virtual void ReadCustomization(wxConfigBase *cfg, wxString path = wxEmptyString); + // saves custom settings into cfg config. it will use the path 'path' + // if given, otherwise it will save info into currently selected path. + // saved values : things set by SetFonts, SetBorders. + virtual void WriteCustomization(wxConfigBase *cfg, wxString path = wxEmptyString); + // ... + + bool HistoryBack(); + bool HistoryForward(); + // Goes to previous/next page (in browsing history) + // Returns TRUE if successful, FALSE otherwise + void HistoryClear(); + // Resets history + + wxHtmlContainerCell* GetInternalRepresentation() const {return m_Cell;} + // Returns pointer to conteiners/cells structure. + // It should be used ONLY when printing + + static void AddFilter(wxHtmlFilter *filter); + // Adds input filter + + virtual void OnLinkClicked(const wxString& link); + // called when users clicked on hypertext link. Default behavior is to + // call LoadPage(loc) + + protected: + bool ScrollToAnchor(const wxString& anchor); + // Scrolls to anchor of this name. (Anchor is #news + // or #features etc. it is part of address sometimes: + // http://www.ms.mff.cuni.cz/~vsla8348/wxhtml/index.html#news) + // Return value : TRUE if anchor exists, FALSE otherwise + + void CreateLayout(); + // prepare layout (= fill m_PosX, m_PosY for fragments) based on actual size of + // window. This method also setup scrollbars + + void OnDraw(wxDC& dc); + void OnSize(wxSizeEvent& event); + void OnMouseEvent(wxMouseEvent& event); + void OnIdle(wxIdleEvent& event); + void OnKeyDown(wxKeyEvent& event); + + DECLARE_EVENT_TABLE() +}; + + + +#endif // __HTMLWIN_H__ + +#endif + + + diff --git a/include/wx/html/htmlwinparser.h b/include/wx/html/htmlwinparser.h new file mode 100644 index 0000000000..fa1769c5ba --- /dev/null +++ b/include/wx/html/htmlwinparser.h @@ -0,0 +1,219 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmlwinparser.h +// Purpose: wxHtmlWinParser class (parser to be used with wxHtmlWindow) +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifndef __HTMLWINPARSER_H__ +#define __HTMLWINPARSER_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + +#include "wx/defs.h" +#if wxUSE_HTML + +#include +#include +#include + +class wxHtmlWinParser; +class wxHtmlWinTagHandler; +class wxHtmlTagsModule; + +//-------------------------------------------------------------------------------- +// wxHtmlWinParser +// This class is derived from wxHtmlParser and its mail goal +// is to parse HTML input so that it can be displayed in +// wxHtmlWindow. It uses special wxHtmlWinTagHandler. +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlWinParser : public wxHtmlParser +{ + DECLARE_DYNAMIC_CLASS(wxHtmlWinParser) + + friend class wxHtmlWindow; + + private: + wxWindow *m_Window; + // window we're parsing for + wxDC *m_DC; + // Device Context we're parsing for + static wxList m_Modules; + // list of tags modules (see wxHtmlTagsModule for details) + // This list is used to initialize m_Handlers member. + + wxHtmlContainerCell *m_Container; + // actual container. See Open/CloseContainer for details. + + int m_FontBold, m_FontItalic, m_FontUnderlined, m_FontFixed; // this is not TRUE,FALSE but 1,0, we need it for indexing + int m_FontSize; /* -2 to +4, 0 is default */ + wxColour m_LinkColor; + wxColour m_ActualColor; + // basic font parameters. + wxString m_Link; + // actual hypertext link or empty string + bool m_UseLink; + // TRUE if m_Link is not empty + long m_CharHeight, m_CharWidth; + // average height of normal-sized text + int m_Align; + // actual alignment + + wxFont *m_FontsTable[2][2][2][2][7]; + // table of loaded fonts. 1st four indexes are 0 or 1, depending on on/off + // state of these flags (from left to right): + // [bold][italic][underlined][fixed_size] + // last index is font size : from 0 to 7 (remapped from html sizes -2 to +4) + // Note : this table covers all possible combinations of fonts, but not + // all of them are used, so many items in table are usually NULL. + int m_FontsSizes[7]; + wxString m_FontFaceFixed, m_FontFaceNormal; + int m_ItalicModeFixed, m_ItalicModeNormal; + // html font sizes and faces of fixed and proportional fonts + + public: + wxHtmlWinParser() : wxHtmlParser() {wxHtmlWinParser(NULL);} + wxHtmlWinParser(wxWindow *wnd); + + virtual void InitParser(const wxString& source); + virtual void DoneParser(); + virtual wxObject* GetProduct(); + + virtual void SetDC(wxDC *dc) {m_DC = dc;} + // Set's the DC used for parsing. If SetDC() is not called, + // parsing won't proceed + wxDC *GetDC() {return m_DC;} + int GetCharHeight() const {return m_CharHeight;} + int GetCharWidth() const {return m_CharWidth;} + // NOTE : these functions do _not_ return _actual_ + // height/width. They return h/w of default font + // for this DC. If you want actual values, call + // GetDC() -> GetChar...() + wxWindow *GetWindow() {return m_Window;} + // returns associated wxWindow + + void SetFonts(wxString normal_face, int normal_italic_mode, wxString fixed_face, int fixed_italic_mode, int *sizes); + // sets fonts to be used when displaying HTML page. + // *_italic_mode can be either wxSLANT or wxITALIC + + virtual wxList* GetTempData(); + + static void AddModule(wxHtmlTagsModule *module); + // Adds tags module. see wxHtmlTagsModule for details. + + // parsing-related methods. These methods are called by tag handlers: + wxHtmlContainerCell *GetContainer() const {return m_Container;} + // Returns pointer to actual container. Common use in tag handler is : + // m_WParser -> GetContainer() -> InsertCell(new ...); + wxHtmlContainerCell *OpenContainer(); + // opens new container. This container is sub-container of opened + // container. Sets GetContainer to newly created container + // and returns it. + wxHtmlContainerCell *SetContainer(wxHtmlContainerCell *c); + // works like OpenContainer except that new container is not created + // but c is used. You can use this to directly set actual container + wxHtmlContainerCell *CloseContainer(); + // closes the container and sets actual Container to upper-level + // container + + int GetFontSize() const {return m_FontSize;} + void SetFontSize(int s) {m_FontSize = s;} + int GetFontBold() const {return m_FontBold;} + void SetFontBold(int x) {m_FontBold = x;} + int GetFontItalic() const {return m_FontItalic;} + void SetFontItalic(int x) {m_FontItalic = x;} + int GetFontUnderlined() const {return m_FontUnderlined;} + void SetFontUnderlined(int x) {m_FontUnderlined = x;} + int GetFontFixed() const {return m_FontFixed;} + void SetFontFixed(int x) {m_FontFixed = x;} + + int GetAlign() const {return m_Align;} + void SetAlign(int a) {m_Align = a;} + const wxColour& GetLinkColor() const {return m_LinkColor;} + void SetLinkColor(const wxColour& clr) {m_LinkColor = clr;} + const wxColour& GetActualColor() const {return m_ActualColor;} + void SetActualColor(const wxColour& clr) {m_ActualColor = clr;} + const wxString& GetLink() const {return m_Link;} + void SetLink(const wxString& link) {m_Link = link; m_UseLink = link.Length() > 0;} + + virtual wxFont* CreateCurrentFont(); + // creates font depending on m_Font* members. + // (note : it calls wxHtmlWindow's CreateCurrentFont...) + + protected: + virtual void AddText(const char *txt); + + private: + bool m_tmpLastWasSpace; + // temporary variable used by AddText +}; + + + + + + +//-------------------------------------------------------------------------------- +// wxHtmlWinTagHandler +// This is basicly wxHtmlTagHandler except +// it is extended with protected member m_Parser pointing to +// the wxHtmlWinParser object +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlWinTagHandler : public wxHtmlTagHandler +{ + DECLARE_ABSTRACT_CLASS(wxHtmlWinTagHandler) + + protected: + wxHtmlWinParser *m_WParser; + // same as m_Parser, but overcasted + + public: + wxHtmlWinTagHandler() : wxHtmlTagHandler() {}; + + virtual void SetParser(wxHtmlParser *parser) {wxHtmlTagHandler::SetParser(parser); m_WParser = (wxHtmlWinParser*) parser;}; +}; + + + + + + +//-------------------------------------------------------------------------------- +// wxHtmlTagsModule +// This is basic of dynamic tag handlers binding. +// The class provides methods for filling parser's handlers +// hash table. +// (See documentation for details) +//-------------------------------------------------------------------------------- + +class WXDLLEXPORT wxHtmlTagsModule : public wxModule +{ + DECLARE_DYNAMIC_CLASS(wxHtmlTagsModule) + + public: + wxHtmlTagsModule() : wxModule() {}; + + virtual bool OnInit(); + virtual void OnExit(); + + virtual void FillHandlersTable(wxHtmlWinParser *parser) {} + // This is called by wxHtmlWinParser. + // The method must simply call parser->AddTagHandler(new ); + // for each handler + +}; + + + +#endif // __HTMLWINPARSER_H__ + +#endif + + + diff --git a/include/wx/html/mod_templ.h b/include/wx/html/mod_templ.h new file mode 100644 index 0000000000..cb9f3fadb6 --- /dev/null +++ b/include/wx/html/mod_templ.h @@ -0,0 +1,102 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: mod_templ.h +// Purpose: wxHtml tags module generic "template" +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +/* + +DESCRIPTION: +This is set of macros for easier writing of tag handlers. How to use it? +See mod_fonts.cpp for example... + +Attention! This is quite strange C++ bastard. Before using it, +I STRONGLY recommend reading and understanding these macros!! + +*/ + + +#ifndef __MOD_TEMPL_H__ +#define __MOD_TEMPL_H__ + +#include "wx/defs.h" +#if wxUSE_HTML + + +#ifdef __GNUG__ +#pragma interface +#pragma implementation +#endif + +#include + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + + + + +#include + + +#define TAG_HANDLER_BEGIN(name,tags) \ + class HTML_Handler_##name : public wxHtmlWinTagHandler \ + { \ + public: \ + wxString GetSupportedTags() {return tags;} + + + +#define TAG_HANDLER_VARS \ + private: + +#define TAG_HANDLER_CONSTR(name) \ + public: \ + HTML_Handler_##name () : wxHtmlWinTagHandler() + + +#define TAG_HANDLER_PROC(varib) \ + public: \ + bool HandleTag(const wxHtmlTag& varib) + + + +#define TAG_HANDLER_END(name) \ + }; + + + + +#define TAGS_MODULE_BEGIN(name) \ + class HTML_Module##name : public wxHtmlTagsModule \ + { \ + DECLARE_DYNAMIC_CLASS(HTML_Module##name ) \ + public: \ + void FillHandlersTable(wxHtmlWinParser *parser) \ + { + + + + +#define TAGS_MODULE_ADD(handler) \ + parser -> AddTagHandler(new HTML_Handler_##handler); + + + + +#define TAGS_MODULE_END(name) \ + } \ + }; \ + IMPLEMENT_DYNAMIC_CLASS(HTML_Module##name , wxHtmlTagsModule) + + + +#endif +#endif \ No newline at end of file diff --git a/include/wx/html/msw/back.bmp b/include/wx/html/msw/back.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a81d37879afb304478cb1bf15359fb7f2ee74f15 GIT binary patch literal 202 zcmZ?rJ;eY4UO-9%hy|dSk%0v)(EubFp_mm&gYba^2Y@64!|5jn7$zJkXJ}|>0P|sl z1BAf>r5zzOiy(w{RCIB1abRE(G87aP6kuRfHU`NK^Sb&6L6E6azv3@>YbKS9?Ip+-N+M;-7vLD)dkC`w zMk!0qljSgwfqd{4C4h;Ps*u?t=SUAKu+?qTQ md0c;%sV`h`??2^*i#KoU0P|sl z1C-$cr5&LHjv_z-7Z(>tMWBEn5EuakgpGkf5lSlwFbF9rDH#FzAbB7c1Q>x_Fb&~? J-2)LpkN_gv5l;XB literal 0 HcmV?d00001 diff --git a/include/wx/html/msw/page.ico b/include/wx/html/msw/page.ico new file mode 100644 index 0000000000000000000000000000000000000000..46114c9e2a884d19957b5b02c51265857b91a635 GIT binary patch literal 318 zcmbtMF%E!02rkDj(!^qDCH(~NfK@S@tno>&zp88>v&?0c@|3--Z%F>Z1WX3Wj`AqWDZ z(H-n;ZDC_$16^I6lp}QLOc#35`jRqLNJIpX@_GN9QOqk1_Su@b+tHRRsBNbB%)MzoMeI z7cA}NiAM2bZx4aZP1FqzLZwona&Zyg4i3Om?=9rP=^R1x_&BTs185iByWZ&Dik147)@Lf_`HQxf?V{{>b-(_>!-mGD=0^&JLizZ~)2ixQ(wf`lckb5K z%I?YQaHaTaNy)X+>t&Miq8k-AD{&z&zo6hEE=eSXMUu;O)2B}7h|lk=B=_8T`eq{g M#K{a#6Y*K%AIQzvR{#J2 literal 0 HcmV?d00001 diff --git a/include/wx/html/msw/wxhtml.rc b/include/wx/html/msw/wxhtml.rc new file mode 100644 index 0000000000..99c310f430 --- /dev/null +++ b/include/wx/html/msw/wxhtml.rc @@ -0,0 +1,16 @@ + +// +// This file contains bitmaps used +// by wxHtmlHelpController +// Include it in your .rc file if you're using wxHTML help system +// (#include "wx/html/msw/wxhtml.rc") +// + +back BITMAP "wx/html/msw/back.bmp" +forward BITMAP "wx/html/msw/forward.bmp" +panel BITMAP "wx/html/msw/panel.bmp" + +book ICON "wx/html/msw/book.ico" +folder ICON "wx/html/msw/folder.ico" +page ICON "wx/html/msw/page.ico" + diff --git a/include/wx/html/version.h b/include/wx/html/version.h new file mode 100644 index 0000000000..49ff8aeae8 --- /dev/null +++ b/include/wx/html/version.h @@ -0,0 +1,7 @@ + +#define wxHTML_VERSION_MAJOR 0 +#define wxHTML_VERSION_MINOR 2 +#define wxHTML_VERSION_REL 3 + +#define wxHTML_VERSION (wxHTML_VERSION_MAJOR * 1000 + wxHTML_VERSION_MINOR * 100 + wxHTML_VERSION_REL) + diff --git a/include/wx/msw/setup0.h b/include/wx/msw/setup0.h index d7a89dba0a..b67a81cd27 100644 --- a/include/wx/msw/setup0.h +++ b/include/wx/msw/setup0.h @@ -198,6 +198,8 @@ // wxWindow::SetToolTip() method #define wxUSE_SOCKETS 0 // Set to 1 to use socket classes +#define wxUSE_HTML 0 + // Set to 1 to use wxHTML sub-library /* * Finer detail diff --git a/include/wx/wxhtml.h b/include/wx/wxhtml.h new file mode 100644 index 0000000000..f8082a7aaa --- /dev/null +++ b/include/wx/wxhtml.h @@ -0,0 +1,27 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wxhtml.h +// Purpose: wxHTML library for wxWindows +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef __WXHTML_H__ +#define __WXHTML_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // __WXHTML_H__ diff --git a/include/wx/zipstream.h b/include/wx/zipstream.h new file mode 100644 index 0000000000..6da057c473 --- /dev/null +++ b/include/wx/zipstream.h @@ -0,0 +1,70 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: zipstream.h +// Purpose: wxZipInputStream for reading files from ZIP archive +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef __ZIPSTREAM_H__ +#define __ZIPSTREAM_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + +#if wxUSE_ZLIB && wxUSE_STREAMS + +#include + +//-------------------------------------------------------------------------------- +// wxZipInputStream +// This class is input stream from ZIP archive. The archive +// must be local file (accessible via FILE*) +//-------------------------------------------------------------------------------- + + +class WXDLLEXPORT wxZipInputStream : public wxInputStream +{ + private: + size_t m_Size; + off_t m_Pos; + void *m_Archive; + // 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. + + public: + wxZipInputStream(const wxString& archive, const wxString& file); + // archive is name of .zip archive, file is name of file to be extracted. + // Remember that archive must be local file accesible via fopen, fread functions! + ~wxZipInputStream(); + + protected: + virtual size_t StreamSize() const {return m_Size;} + virtual size_t OnSysRead(void *buffer, size_t bufsize); + virtual off_t OnSysSeek(off_t seek, wxSeekMode mode); + virtual off_t OnSysTell() const {return m_Pos;} +}; + + +#endif // if use_zlib && use_streams + +#endif // __ZIPSTREAM_H__ + + + + + + + + + + + + + + + + + diff --git a/samples/html/Makefile.am b/samples/html/Makefile.am new file mode 100644 index 0000000000..6eee574d1b --- /dev/null +++ b/samples/html/Makefile.am @@ -0,0 +1,8 @@ +## Purpose: The automake makefile for wxHTML samples +## Author: VS +## Version: $Id$ +## +## Process this file with automake to produce Makefile.in + +SUBDIRS = about help printing test virtual widget zip + diff --git a/samples/html/about/Makefile.am b/samples/html/about/Makefile.am new file mode 100644 index 0000000000..56e4183fdc --- /dev/null +++ b/samples/html/about/Makefile.am @@ -0,0 +1,9 @@ +AUTOMAKE_OPTIONS = 1.3 no-dependencies + +SUFFIXES = .cpp + +DEFS = @DEFS@ $(TOOLKIT_DEF) $(WXDEBUG_DEFINE) + +noinst_PROGRAMS = about + +about_SOURCES = about.cpp diff --git a/samples/html/about/about.cpp b/samples/html/about/about.cpp new file mode 100644 index 0000000000..7bfb813b2e --- /dev/null +++ b/samples/html/about/about.cpp @@ -0,0 +1,174 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: test.cpp +// Purpose: wxHtml testing example +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ + #pragma implementation "test.cpp" + #pragma interface "test.cpp" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all "standard" wxWindows headers +#ifndef WX_PRECOMP + #include +#endif + +#include +#include + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + + +// Define a new application type, each program should derive a class from wxApp + class MyApp : public wxApp + { + public: + // override base class virtuals + // ---------------------------- + + // this one is called on application startup and is a good place for the app + // initialization (doing it here and not in the ctor allows to have an error + // return: if OnInit() returns false, the application terminates) + virtual bool OnInit(); + }; + +// Define a new frame type: this is going to be our main frame + class MyFrame : public wxFrame + { + public: + // ctor(s) + MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); + + // event handlers (these functions should _not_ be virtual) + void OnQuit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + + private: + // any class wishing to process wxWindows events must use this macro + DECLARE_EVENT_TABLE() + }; + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// IDs for the controls and the menu commands + enum + { + // menu items + Minimal_Quit = 1, + Minimal_About, + Minimal_Back, + Minimal_Forward, + + // controls start here (the numbers are, of course, arbitrary) + Minimal_Text = 1000, + }; + +// ---------------------------------------------------------------------------- +// event tables and other macros for wxWindows +// ---------------------------------------------------------------------------- + +// the event tables connect the wxWindows events with the functions (event +// handlers) which process them. It can be also done at run-time, but for the +// simple menu events like this the static method is much simpler. + BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(Minimal_Quit, MyFrame::OnQuit) + EVT_MENU(Minimal_About, MyFrame::OnAbout) + END_EVENT_TABLE() + + // Create a new application object: this macro will allow wxWindows to create + // the application object during program execution (it's better than using a + // static object for many reasons) and also declares the accessor function + // wxGetApp() which will return the reference of the right type (i.e. MyApp and + // not wxApp) + IMPLEMENT_APP(MyApp) + + // ============================================================================ + // implementation + // ============================================================================ + + // ---------------------------------------------------------------------------- + // the application class + // ---------------------------------------------------------------------------- + // `Main program' equivalent: the program execution "starts" here + bool MyApp::OnInit() + { + wxImage::AddHandler(new wxPNGHandler); + // Create the main application window + MyFrame *frame = new MyFrame("wxHtmlWindow testing application", + wxPoint(50, 50), wxSize(150, 50)); + + // Show it and tell the application that it's our main window + // @@@ what does it do exactly, in fact? is it necessary here? + frame->Show(TRUE); + SetTopWindow(frame); + + + // success: wxApp::OnRun() will be called which will enter the main message + // loop and the application will run. If we returned FALSE here, the + // application would exit immediately. + return TRUE; + } + +// ---------------------------------------------------------------------------- +// main frame +// ---------------------------------------------------------------------------- + + +// frame constructor + MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) + : wxFrame((wxFrame *)NULL, -1, title, pos, size) + { + // create a menu bar + wxMenu *menuFile = new wxMenu; + + menuFile->Append(Minimal_About, "&About"); + menuFile->Append(Minimal_Quit, "E&xit"); + + // now append the freshly created menu to the menu bar... + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append(menuFile, "&File"); + + // ... and attach this menu bar to the frame + SetMenuBar(menuBar); + } + + +// event handlers + + void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) + { + // TRUE is to force the frame to close + Close(TRUE); + } + + void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) + { + wxHtmlWindow *html; + wxDialog dlg(this, -1, "About", wxDefaultPosition, wxSize(400, 230), wxDIALOG_MODAL | wxDEFAULT_DIALOG_STYLE); + + html = new wxHtmlWindow(&dlg, -1, wxPoint(10, 10), wxSize(380, 160), "htmlWindow", FALSE); + html -> SetBorders(0); + html -> LoadPage("data/about.htm"); + wxButton *bu1 = new wxButton(&dlg, wxID_OK, "OK", wxPoint(250, 185), wxSize(100, 30)); + bu1 -> SetDefault(); + dlg.ShowModal(); + } + + + + + + + diff --git a/samples/html/about/about.rc b/samples/html/about/about.rc new file mode 100644 index 0000000000..82bdf07561 --- /dev/null +++ b/samples/html/about/about.rc @@ -0,0 +1,2 @@ +#include "wx/msw/wx.rc" + diff --git a/samples/html/about/data/about.htm b/samples/html/about/data/about.htm new file mode 100644 index 0000000000..b3bfa67dfc --- /dev/null +++ b/samples/html/about/data/about.htm @@ -0,0 +1,17 @@ + +
+
+
wxHTML Library Sample 0.2.0
+
+
+Copyright (C) 1999 Vaclav Slavik

+ + +
+Vaclav Slavik (slavik2@czn.cz)
Someone Else (selse@hell.org)

+

+
+ +The wxHTML library is available at http://www.ms.mff.cuni.cz/~vsla8348/wxhtml
+The library is licenced under wxWindows Library Licence, Version 3. +

diff --git a/samples/html/about/data/logo.png b/samples/html/about/data/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6c5e312049f30e07bdcfdbcc00aa7a87ae5379ff GIT binary patch literal 7637 zcmV;`9V+69P)WRg_4Hl&F!!Wysl=J9qu= z{noSgQk92G39=~0q8}1xDd6A$=k)1roFD4nUDZYSOJF~7tc8#L@G_b|ogq5yAQe&l z^%P;KND3k_5tIm}0=>u*-(QRBFnFS1Urs0t6{IABC4vA@00a;L0MJ_uE8qKo6oBZB z$BqDg<3%i>R75SX#OJK&#Q+I_yBfpaFvK&pKXw3M02mQUL`VZt6Nv{9h@eHNA<*;8 z@jEN1rigf8^3gf`w`&>x!B=*F;D2WDm&FLAR|C{Mqx{nb@q{!HBI>eXCJHRV0p4xH zH@+E%#<3uNLxaaklR|{H7zv_$0C9jogaSY$AP9X29t+@t5DUITH8v2X!2&S*eV{6Z zA`$`!Lc*?wQ=4$9k3#b#2{HwL%P6sAR6~rUVtf$t0{9>SIr&JD=vb6)i)MxrfJ1-} z1Ng?p*mvJwLd^yFi~KJ0FCSa{-_Gnv+W-RiTM^vli2Q9GQ9~Ni7WZ(0*5aRFS{eLdFpFi38F6|H^qCX=h0ucfM z^!+7AMC7}^*_SGMLx{fL{ksMe2);9*0Pcn%SkjboqnAb*HNJ46d;h^z;j!+e zC0P7?>W7Yg+)wxW~0z=*h@9Sh1)Y;yZ%fV{lO()eptJJw+YWI{Kf!W5!tV&a5s#S zoJcGI3Q#Q;>Wb*)AW{*9O-)i0NlBmxpp-=|u&6$ZOcjM4MN+DLO&1Ud0(nE<34j)% zrU*4eR9i?aAQ_Pqio_8~NkkE1XSn+xUOV!U&uks}Ysv+M^@JL?cWk#4rho73SO3Ls z#TRTL8zZa837z{l7w`U+a_Hxz-_l=x_P}H3?akS>{?QiKqW=9_OP$O%{9cvlo#RIg zGAkqu=#yyZAgjY|zjtU=PtuN=du7wM>^JYTHOHU2eb=dMt7WPJ=oOPNneT;@+q-3u z@{gtt*QZ|9HpZdPznuKyZ(hCsryE%wPjyq-`L@C~!aqIv%<9?>^Jg}epPa6p>7LrV zZLh8#kN!^j{I|{=9YwoUFze%h(UAGy(zrU;kHgynCjeE?Hpt&F8jJ{ph>a-g1z|+q zZNVqkBA;kQDi#AH5gSp?i})dVx21hThSQXYA~8@Bv4(O16#Td4NQhZL3=R``zfCTJ z;zSdoh8Qt0!LYF`%2tR(^J1@_0QCV1X{0c&X_~f@!iR<5eX;X1bIHio1Wn6%aj|#GfCSxyNw%E&RY55|jONZ}DbrNB?g}cU!{H{^K`MBb8Tyga+U;9B7`0aR| zvENAGuWLR=ACK%@_%3XCvNJOf9mY;#_|G97F+IetoZ9BwB0q*_{wGTqgMy<1C6;jKCGsb zldFE?+LoDn`Ib3+_^__eE!w@oRL_=r;p-~qb=x5IA1^Na+-INH@2!K1e&l?8^PMZ% zwWEEv(d&jdj59znTth?35~i-P(y1G^rlSp_vC-K5^0nw>R&d0o1PI_Npj`~*NBbN0 zbGHtgS~M+}V>DGtuc%ceq#(|Nlm-+_hjQtRc4eh+!?m)j-m|=I8;+vSkB&!nc>!WQ z;z5pju0feH@y57$`q+Gt=@_;(uRC=fX><(`Jh=9N0g6@xpeqx?!bd4u?to z)Zshp&tB>DZ*#Xj7<7y&EvMq#V+V%sdFqkukDu9S9{CSf4*aZccp(UVYQr3T`L*qb zf8pWX=UWZm*yczVj=^;e1dAi>0?TvMOtfB&i1Gu=wD_ef>8Y~WFaU$$L0*BK!+fVG zpE`YUwmmWwr^b~1h3+ets;20ez<{umLyeI<_0XN!^$jkAx7F#DEnZpB>E|vUS{cqY zL1h8GTcEZA5shD1*^tBS&~4AtiI08t(CV6B=t|EJoP~q{5r)n^DiGZXE!_)o9BcqL ziO72(BFy5H2GgkFxo!nUD=-ofQI6j(I7{S==+}4S6L;p9j|ZjVJP1i(bjk`Y@OcY_ z7ha3+KI*3W>e7<&Iwi0m-_wiFU(4Tj^pUap#OwWs2XSjb7A=T8wsW1laHF}h+^zg; z)pEpbL$zY%gVJ9ZFW-M^!#B5l)Mg^Z4NZ~@Hl>pW+1d~FV*!i^6wBKL z2Zq=Ja__Re_ESf9zW&+U^N&^_-KWFWRi$LDmi zSI)&L?)&Ce;{*~03`4^HMxZfg<&g*S$*r#q8ZT!{2@D|+s5vY3r(aA@@3h*Abx9O} zcvMJFO?j)WLTkhci;MO+rJX1tu@0y`E~81W4WkG|(XDZuytv)&hsb~!~6JQ<2 zm7>T5yEWo0D`b6nPPxN#ML(o-^TVt^;P3C<{lN2wEeH6FkHH=Um=u06&+a$%`e`J5(<`@QxArqHW4@?T)1W88^h+}D^<%l??8nE9AkAQ z^CG^uzAm!|4^78sR{ilSn`ZF~vz{rMh6=9$Fi<<3kA~9hh>J`)ySWvzSktuG;l|5( z5>?8R_yF>RIQNJXg-Z69sRV-Ns6rJKNo~QzKoKylYATup5qJXfMog32GabVh!bwDM z00*XwnPwG{2x>)`b`l!iwG;*;78S&kkisO5uoOx;ff25h3H`ggjl0W0uTzYcw(?+- zqt#V-c`M%ERk{FGWVkgnN@?pmMJ6*cloU0pxi&ImBsMHW5KTa&h!Rb7v}@@6ftc=^ zH=rhe$Ln}kV^s5-JG9yb$f&*EPlti2azcG|zXUwC9q3NUd*8UH#MGIV(AP-2S0MGbP zJdxF7VABm{mWSzhCgY_Z?XKtMz)i1|kOx6yHJf5J^%BLJ`@P_^9O5kLrMm=s12!*a zOg=VH-eU=woLX`A;%x{Ke5A>qo~wu6Clu!;>L`LlgauPcx4{AXX>1oqRA1Rpy>8Rl ztda&ip;P@KT9JL`V&(cA|7ULA2CT@jH)3v0t@fPKA&@XgPkc29(I~*OtD&RO-cm zv<>D7m7&Jqfg|qfm22a37bZy~Z>Mx)EHrst>uDA!^A5p~Jb7;!E_^fSR~*r79KlQj zMY=?#6c)-1i%m#w;k@UdQ24W2bLnwn(-lCBxoH-iYi*__2p%x;f``6sgD{u1Xw@ z9MTv;l~$Qt#EPO=JUAjecL}DI5D8mUC5gllwN(iOs8K=DLR%$Ts59483#XP$c5>N7 zrI+kmuZ1$XrK{!bI2?b{;;q&^6LvJ3i^B0bRYgssZ`~lfo~w{SAXN$H92i1VXh>Zm zNrOCbFX}&eRX3unq$D_O>4c&(L!=3;NRA(3e{9)}U%i2{*HYD~Lt6drH*judoi^;? zp}}@j_SIP8lTMni8J9bnzVBZ8^7Vm#0^4Qlc1~0ULT&>jP7nnzrxxI+g|4;O#MMwa zF##3@31SbJh;izGt|q0FMx#1@Kq<%J^yU^X$EBd91VbbsP3V)8T@jjAiazmtNPqq@ z)jzbX=2Jz3UPtQl2ZMiYSjo_Vh9r3JJWF8ZCZ$ZKg{-agQ65_oy*Y5JFYQ=EEbtU0 zi3q%({%6qswK=HU$`T+1As~36N*G#0AR+>Y2(XuNG|asLfXpbQVsU&CVWlUwC zw1IopN8y2KA?D^tb&k#PrC)j?{>{x&Uc9myHZJ^^FxhC#>T})r&EVXn80mXUnd?P< zXPdHii*En;JLSTE`h##V1*uXrh9Xd9j;0YnMSf$K%DnU)D}pRA6bA?kj3#I;(1xm6 zA!WBkc6;hiZ|};9wGk(k5K2~PawR`@uja2^cB&nKiB*`2sOK)yT!`fSyU!*iDl`)< z=#j(F3zQ;!`9@GlH&QN05kv;D!Kie6@W#*+Sivj8dLYVnYV{~Z92m@k5E$XHGwSvq zyjtInAP@l(CCExpX(Qo%Cu9~0dpY#V9PGt`Yl{FCd8z|TRh#nU65r{jK!_0*7lbNH zYB*D|61N&NqpTca66|`=*RIEEW`#plQ>0U|Of&`HLcl9GolXpC7Zg2nNmjc?#2AIO zT{-*8y8o-SMLEcWjBECv^jVl5Y`X9DI>VWQ%oIAyV6#nCU1P8^r(U~0az9yn5(1L~ zLlMjA6~)~qitUk1A38}g_=Y>=MQAw+*sB4@K(DRBFqg8hQYa-&SM#CQ*Ta0_6*`7t z1Is%PlY8R+ID6q*-K$v?IM7x}nB5e8YFV|F@PR*k+4aAAIkX)ML4cE8lKCF-ogu5* zqxOs$5r%s+uI>!Ij)F+=`zPT2F8IbyP_-9t1AOJAo{R%Ya9{y62)#t4n-DfeOtnXF zETMAZI*E*n%5h90&N1agu%38tCiU7b?@bHY+#X4(2&$W^_~1PC?>T_OFI?w709XN< z2C~v6_r2Wg! zCmPakh^)4OV;zDorFq{WvwM7z@_qvxYe*ghD?Md<4VuhKv4xYeurj{)ka_8^Kcuf8 zXbGp9r5&>zU!b}f(KM^Y7FOy>$@!5vedzAxE29lU;Wl`joUFpP4N+}x= z-8no@+c5rja{#nnh5tSQZNLZ zT2Mg?%ER+|+Dzc@nj<;0L`=d+jX)7F-vAT|R@x%{6j*3L4)rL^N@?uPcqO;8U;|op z5Hq#>rmTt~0ozI@QS3YoG@;gf{+{2K=fzjR^GwoSSu5N|hX)YTA z41e++@eV{zzj)Ih*%)#2?6GKEIt*_O!oWFfO)DClIHIS&^dsrUYun-Qtdv%#p~{PQ zcs82J>|j@4OCub9;D}B)C)_=;sC+M`a(yD>nrZh(?uoMH4)sfqZeEF=lv3W>^^wst1GbL9?WFeP6&j7No>7-h1sGYJ?>c{r=&76DtE zBi?!KcGz2MQOKN(Mj7rJ<(S)OoX{ zxuaqcn7s_NmjMFs=9IaaYQH<Qzac&EUJjyB=0M$&$w z#9gmP_G_Qy@y0aV9GA?Qm0{^*xpI=0R($1T!h&sp2a3oiW8A7eZkAS-3(JktiL)NN zT48N#!UISUB5dciY-cquWR=8~lbQv?%G1aN@L-BA3l<$q$9j+P9@X)P|Rc~n?gtehmZgC`)HRgw=Tq!ppVf({E(7Q`Y@-;N(ygdHPPPHbUi zX1#0#!X2YAYZCc(q~2VS_SA_sKKl3)qLUWAUmKyC5&il<3i|o4a5|W9FRP?)y>uK) z;u#V|N>Z4m5oPUIc@3nMldkpXI+oP4Faw#^7}W>$P-O@ zYA9$z>H=DxrO5&v1WpmENTZGvQD7vVC9w?hEHwjDV=(TuDL>fJK|Ce1f;)LFb9Inb z9iTl+Erf|SnDpCJEVneXqa-W2n_HQyy|iqA3LnK(})=D&>*mGo^Z&uc|oeQaF)*=w4lrvg+tpH((LI`nS zF(RTxHTE%R)RWN<97a)1MiS#{&StJilG;S6E$-F#U}_ zpaoBLIb7G%YT#|~UUC;C4h$^<5Xc*Wi-a5nuxDuJG4Vm-ATS~%3UEeHD<;Q|#CplB z$Jnt%B2W-wO>kPsDIpF)bYMh*5e0c8Lrw@m5QG30(Ltbv0R;-Nf@>R9uNv(S7|q*d z@XnHTUS>WZ5`oe}!6?|aR(92Bzo;}1d~n{udWUIXL|~8tg{Fzpk9_3so__AR=eQ^e z+1lEqg9nf3vMBZCD_7Lt|J7ebzu%XC{n3wxPG^ok_`whI8+B5`%+%}kND--LzW9tj zc<`V)aNvO2-rAN2-|?W_zI|KbD28>Gu3WjIu3ovSlve2VdUWE%39PKF;E(_4kMYpE z9+FPGBXJV5F{W1(MR@el9|})D{j{7ve_rP2=kbY8eBw5M3jl^@Jr8(hqrk(05cYJa)G9OoIJ>R3xUvBH&!<4@nr!i|}$ zD=$j+GxX9TMkD}^WC`vgArv5(8b!UD8X^uG7M zAD{i~=O~UM965RvRaxPapZpX~o;-z;Ay(AAm z{P4FG@*sfA0EYAfm#h9cRlq+$o4-gO_(7|X-=dEns9m$!Y<~E|AO72En)U(2Z(|++ zfNR&T;lzm(_%o%AZ#8lGpC7lqRUcJV$ + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all "standard" wxWindows headers +#ifndef WX_PRECOMP + #include +#endif + +#include +#include +#if (( wxVERSION_NUMBER < 2100 ) || (( wxVERSION_NUMBER == 2100 ) && (wxBETA_NUMBER <= 4))) +#include +#endif +#include + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +// Define a new application type, each program should derive a class from wxApp + class MyApp : public wxApp + { + private: + wxHtmlHelpController help; + wxConfig* config; + + public: + // override base class virtuals + // ---------------------------- + + // this one is called on application startup and is a good place for the app + // initialization (doing it here and not in the ctor allows to have an error + // return: if OnInit() returns false, the application terminates) + bool OnInit(); + int OnExit(); + }; + + IMPLEMENT_APP(MyApp) + + + bool MyApp::OnInit() + { + config = new wxConfig("wxHTMLhelp"); + #if wxUSE_LIBPNG + wxImage::AddHandler(new wxPNGHandler); + #endif + #if wxUSE_LIBJPEG + wxImage::AddHandler(new wxJPEGHandler); + #endif + + help.UseConfig(config); + help.SetTempDir("tmp"); + help.AddBook("helpfiles/testing.hhp"); + help.Display("Main page"); + return TRUE; + } + + int MyApp::OnExit() + { + delete config; + return 0; + } + + + + + + + + diff --git a/samples/html/help/help.rc b/samples/html/help/help.rc new file mode 100644 index 0000000000..7fa90c817b --- /dev/null +++ b/samples/html/help/help.rc @@ -0,0 +1,2 @@ +#include "wx/msw/wx.rc" +#include "wx/html/msw/wxhtml.rc" diff --git a/samples/html/help/helpfiles/Index.hhk b/samples/html/help/helpfiles/Index.hhk new file mode 100644 index 0000000000..a9ab87b4a0 --- /dev/null +++ b/samples/html/help/helpfiles/Index.hhk @@ -0,0 +1,24 @@ + + + + + + +

    +
  • + + + + +
  • + + + + +
  • + + + + +
+ diff --git a/samples/html/help/helpfiles/book1.htm b/samples/html/help/helpfiles/book1.htm new file mode 100644 index 0000000000..fa470e3ec5 --- /dev/null +++ b/samples/html/help/helpfiles/book1.htm @@ -0,0 +1,4 @@ +Book 1 +

Book 1.

+How do you enjoy book one?? + diff --git a/samples/html/help/helpfiles/book2.htm b/samples/html/help/helpfiles/book2.htm new file mode 100644 index 0000000000..828723fc65 --- /dev/null +++ b/samples/html/help/helpfiles/book2.htm @@ -0,0 +1,5 @@ +Book 1 +

Book 2.

+How do you enjoy book two?? +

Please click HERE + diff --git a/samples/html/help/helpfiles/contents.hhc b/samples/html/help/helpfiles/contents.hhc new file mode 100644 index 0000000000..3eb7c2c974 --- /dev/null +++ b/samples/html/help/helpfiles/contents.hhc @@ -0,0 +1,33 @@ + + + + + + + + + +

    +
  • + + + +
      +
    • + + + +
    • + + + + +
        +
      • + + + +
      +
    +
+ diff --git a/samples/html/help/helpfiles/main.htm b/samples/html/help/helpfiles/main.htm new file mode 100644 index 0000000000..ca5275bfd7 --- /dev/null +++ b/samples/html/help/helpfiles/main.htm @@ -0,0 +1,5 @@ + +

This is main page.

+Book 1
+Book 2
+ diff --git a/samples/html/help/helpfiles/page2-b.htm b/samples/html/help/helpfiles/page2-b.htm new file mode 100644 index 0000000000..f51dd6d6d6 --- /dev/null +++ b/samples/html/help/helpfiles/page2-b.htm @@ -0,0 +1,5 @@ + + +Hello, you're on sub page of page 2 !!! + + diff --git a/samples/html/help/helpfiles/testing.hhp b/samples/html/help/helpfiles/testing.hhp new file mode 100644 index 0000000000..5cd4d4e87f --- /dev/null +++ b/samples/html/help/helpfiles/testing.hhp @@ -0,0 +1,15 @@ +[OPTIONS] +Compatibility=1.1 +Compiled file=testing.chm +Contents file=contents.hhc +Display compile progress=No +Index file=Index.hhk +Language=0x405 Èesky +Title=Testing HELPFILE :-) +Default topic=main.htm + +[FILES] +main.htm +book1.htm +book2.htm +page2-b.htm diff --git a/samples/html/printing/Makefile.am b/samples/html/printing/Makefile.am new file mode 100644 index 0000000000..73aa8ade60 --- /dev/null +++ b/samples/html/printing/Makefile.am @@ -0,0 +1,9 @@ +AUTOMAKE_OPTIONS = 1.3 no-dependencies + +SUFFIXES = .cpp + +DEFS = @DEFS@ $(TOOLKIT_DEF) $(WXDEBUG_DEFINE) + +noinst_PROGRAMS = printing + +printing_SOURCES = printing.cpp diff --git a/samples/html/printing/mondrian.ico b/samples/html/printing/mondrian.ico new file mode 100644 index 0000000000000000000000000000000000000000..2310c5d275a87af295d5ea8dc79ea417a5e74c53 GIT binary patch literal 766 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 +#include "wx/metafile.h" +#include "wx/print.h" +#include "wx/printdlg.h" + +#include "wx/accel.h" + +#if wxTEST_POSTSCRIPT_IN_MSW +#include "wx/generic/printps.h" +#include "wx/generic/prntdlgg.h" +#endif + +#include +#include +#include "printing.h" + +#ifndef __WXMSW__ +#include "mondrian.xpm" +#endif + +// Global print data, to remember settings during the session +wxPrintData *g_printData = (wxPrintData*) NULL ; + +// Global page setup data +wxPageSetupData* g_pageSetupData = (wxPageSetupData*) NULL; + + +// Declare a frame +MyFrame *frame = (MyFrame *) NULL; +wxHtmlWindow *html = NULL; +int orientation = wxPORTRAIT; + +// Main proc +IMPLEMENT_APP(MyApp) + + +MyApp::MyApp() +{ +} + +// The `main program' equivalent, creating the windows and returning the +// main frame +bool MyApp::OnInit(void) +{ + g_printData = new wxPrintData; + g_pageSetupData = new wxPageSetupDialogData; + + // Create the main frame window + frame = new MyFrame((wxFrame *) NULL, (char *) "wxWindows Printing Demo", wxPoint(0, 0), wxSize(600, 400)); + + // Give it a status line + frame->CreateStatusBar(2); + + // Load icon and bitmap + frame->SetIcon( wxICON( mondrian) ); + + // Make a menubar + wxMenu *file_menu = new wxMenu; + + file_menu->Append(WXPRINT_PRINT, "&Print...", "Print"); + file_menu->Append(WXPRINT_PRINT_SETUP, "Print &Setup...", "Setup printer properties"); + file_menu->Append(WXPRINT_PAGE_SETUP, "Page Set&up...", "Page setup"); + file_menu->Append(WXPRINT_PREVIEW, "Print Pre&view", "Preview"); + + // Accelerators + wxAcceleratorEntry entries[1]; + entries[0].Set(wxACCEL_CTRL, (int) 'V', WXPRINT_PREVIEW); + wxAcceleratorTable accel(1, entries); + frame->SetAcceleratorTable(accel); + + file_menu->AppendSeparator(); + file_menu->Append(WXPRINT_QUIT, "E&xit", "Exit program"); + + wxMenu *help_menu = new wxMenu; + help_menu->Append(WXPRINT_ABOUT, "&About", "About this demo"); + + wxMenuBar *menu_bar = new wxMenuBar; + + menu_bar->Append(file_menu, "&File"); + menu_bar->Append(help_menu, "&Help"); + + // Associate the menu bar with the frame + frame->SetMenuBar(menu_bar); + + frame->Centre(wxBOTH); + frame->Show(TRUE); + + frame->SetStatusText("Printing demo"); + + SetTopWindow(frame); + + return TRUE; +} + +int MyApp::OnExit() +{ + delete g_printData; + delete g_pageSetupData; + return 1; +} + +BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(WXPRINT_QUIT, MyFrame::OnExit) + EVT_MENU(WXPRINT_PRINT, MyFrame::OnPrint) + EVT_MENU(WXPRINT_PREVIEW, MyFrame::OnPrintPreview) + EVT_MENU(WXPRINT_PRINT_SETUP, MyFrame::OnPrintSetup) + EVT_MENU(WXPRINT_PAGE_SETUP, MyFrame::OnPageSetup) + EVT_MENU(WXPRINT_ABOUT, MyFrame::OnPrintAbout) +END_EVENT_TABLE() + +// Define my frame constructor +MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size): + wxFrame(frame, -1, title, pos, size) +{ + html = new wxHtmlWindow(this); + html -> LoadPage("test.htm"); +} + +void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event)) +{ + Close(TRUE); +} + +void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event)) +{ + wxPrinter printer; + MyPrintout printout("My printout"); + if (!printer.Print(this, &printout, TRUE)) + wxMessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wxOK); +} + +void MyFrame::OnPrintPreview(wxCommandEvent& WXUNUSED(event)) +{ + wxPrintData printData; + printData.SetOrientation(orientation); + + // Pass two printout objects: for preview, and possible printing. + wxPrintPreview *preview = new wxPrintPreview(new MyPrintout, new MyPrintout, & printData); + if (!preview->Ok()) + { + delete preview; + wxMessageBox("There was a problem previewing.\nPerhaps your current printer is not set correctly?", "Previewing", wxOK); + return; + } + + wxPreviewFrame *frame = new wxPreviewFrame(preview, this, "Demo Print Preview", wxPoint(100, 100), wxSize(600, 650)); + frame->Centre(wxBOTH); + frame->Initialize(); + frame->Show(TRUE); +} + +void MyFrame::OnPrintSetup(wxCommandEvent& WXUNUSED(event)) +{ + wxPrintDialogData printDialogData(* g_printData); + wxPrintDialog printerDialog(this, & printDialogData); + + printerDialog.GetPrintDialogData().SetSetupDialog(TRUE); + printerDialog.ShowModal(); + + (*g_printData) = printerDialog.GetPrintDialogData().GetPrintData(); +} + +void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event)) +{ + (*g_pageSetupData) = * g_printData; + + wxPageSetupDialog pageSetupDialog(this, g_pageSetupData); + pageSetupDialog.ShowModal(); + + (*g_printData) = pageSetupDialog.GetPageSetupData().GetPrintData(); + (*g_pageSetupData) = pageSetupDialog.GetPageSetupData(); +} + + + +void MyFrame::OnPrintAbout(wxCommandEvent& WXUNUSED(event)) +{ + (void)wxMessageBox("wxWindows printing demo\nAuthor: Julian Smart julian.smart@ukonline.co.uk\n\nModified by Vaclav Slavik to show wxHtml features", + "About wxWindows printing demo", wxOK|wxCENTRE); +} + + +bool MyPrintout::OnPrintPage(int page) +{ + wxDC *dc = GetDC(); + if (dc) + { + if (page == 1) + DrawPageOne(dc); + + return TRUE; + } + else + return FALSE; +} + +bool MyPrintout::OnBeginDocument(int startPage, int endPage) +{ + if (!wxPrintout::OnBeginDocument(startPage, endPage)) + return FALSE; + + return TRUE; +} + +void MyPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo) +{ + *minPage = 1; + *maxPage = 1; + *selPageFrom = 1; + *selPageTo = 1; +} + +bool MyPrintout::HasPage(int pageNum) +{ + return (pageNum == 1); +} + + +void MyPrintout::DrawPageOne(wxDC *dc) +{ + int leftMargin = 20; + int topMargin = 40; + +/* You might use THIS code to set the printer DC to ROUGHLY reflect + * the screen text size. This page also draws lines of actual length 5cm + * on the page. + */ + // Get the logical pixels per inch of screen and printer + int ppiScreenX, ppiScreenY; + GetPPIScreen(&ppiScreenX, &ppiScreenY); + int ppiPrinterX, ppiPrinterY; + GetPPIPrinter(&ppiPrinterX, &ppiPrinterY); + + // Here we obtain internal cell representation of HTML document: + wxHtmlContainerCell *cell = html -> GetInternalRepresentation(); + + // Now we have to check in case our real page size is reduced + // (e.g. because we're drawing to a print preview memory DC) + int pageWidth, pageHeight; + int w, h; + dc->GetSize(&w, &h); + GetPageSizePixels(&pageWidth, &pageHeight); + + // Now we must scale it somehow. The best would be to suppose that html window + // width is equal to page width: + + float scale = (float)((float)(pageWidth - 0 * leftMargin)/((float)cell -> GetMaxLineWidth() + 2 * leftMargin)); + + // If printer pageWidth == current DC width, then this doesn't + // change. But w might be the preview bitmap width, so scale down. + float overallScale = scale * (float)(w/(float)pageWidth); + dc->SetUserScale(overallScale, overallScale); + + // Calculate conversion factor for converting millimetres into + // logical units. + // There are approx. 25.1 mm to the inch. There are ppi + // device units to the inch. Therefore 1 mm corresponds to + // ppi/25.1 device units. We also divide by the + // screen-to-printer scaling factor, because we need to + // unscale to pass logical units to DrawLine. + + dc->SetBackgroundMode(wxTRANSPARENT); + + // TESTING + + int pageWidthMM, pageHeightMM; + GetPageSizeMM(&pageWidthMM, &pageHeightMM); + + + // This is all the printing : + cell -> Draw(*dc, leftMargin, topMargin, 0, cell -> GetHeight()); +} + + + diff --git a/samples/html/printing/printing.h b/samples/html/printing/printing.h new file mode 100644 index 0000000000..ba50b4e216 --- /dev/null +++ b/samples/html/printing/printing.h @@ -0,0 +1,76 @@ +/* + * File: printing.h + * Purpose: Printing demo for wxWindows class library + * Author: Julian Smart + * Created: 1995 + * Updated: + * Copyright: (c) 1995, AIAI, University of Edinburgh + */ + +/* sccsid[] = "%W% %G%" */ + +#ifdef __GNUG__ +#pragma interface +#endif + +// Define a new application +class MyApp: public wxApp +{ + public: + MyApp() ; + bool OnInit(); + int OnExit(); +}; + +DECLARE_APP(MyApp) + +class MyCanvas; + +// Define a new canvas and frame +class MyFrame: public wxFrame +{ + public: + MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size); + + void OnPrint(wxCommandEvent& event); + void OnPrintPreview(wxCommandEvent& event); + void OnPrintSetup(wxCommandEvent& event); + void OnPageSetup(wxCommandEvent& event); +#if defined(__WXMSW__) && wxTEST_POSTSCRIPT_IN_MSW + void OnPrintPS(wxCommandEvent& event); + void OnPrintPreviewPS(wxCommandEvent& event); + void OnPrintSetupPS(wxCommandEvent& event); + void OnPageSetupPS(wxCommandEvent& event); +#endif + + void OnExit(wxCommandEvent& event); + void OnPrintAbout(wxCommandEvent& event); +DECLARE_EVENT_TABLE() +}; + + +class MyPrintout: public wxPrintout +{ + public: + MyPrintout(char *title = "My printout"):wxPrintout(title) {} + bool OnPrintPage(int page); + bool HasPage(int page); + bool OnBeginDocument(int startPage, int endPage); + void GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo); + + void DrawPageOne(wxDC *dc); +}; + +#define WXPRINT_QUIT 100 +#define WXPRINT_PRINT 101 +#define WXPRINT_PRINT_SETUP 102 +#define WXPRINT_PAGE_SETUP 103 +#define WXPRINT_PREVIEW 104 + +#define WXPRINT_PRINT_PS 105 +#define WXPRINT_PRINT_SETUP_PS 106 +#define WXPRINT_PAGE_SETUP_PS 107 +#define WXPRINT_PREVIEW_PS 108 + +#define WXPRINT_ABOUT 109 + diff --git a/samples/html/printing/printing.rc b/samples/html/printing/printing.rc new file mode 100644 index 0000000000..7655c62a4c --- /dev/null +++ b/samples/html/printing/printing.rc @@ -0,0 +1,3 @@ +mondrian ICON "mondrian.ico" +#include "wx/msw/wx.rc" + diff --git a/samples/html/printing/test.htm b/samples/html/printing/test.htm new file mode 100644 index 0000000000..ca2d7dfba1 --- /dev/null +++ b/samples/html/printing/test.htm @@ -0,0 +1,126 @@ + + + + + + + +This is - - default text, now switching to +
+

center, now still ctr, now exiting

+ +

exited!.[link to down] +

Hello, this *is* default charset (helvetica, probably) and it is displayed +with one  COLOR CHANGE. Of course we +can have as many color changes as we can, what about this MADNESS? +

There was a space above. +
+


This was a line. (BTW we are in fixed font +/ typewriter font right now :-) +
This is in BOLD face. This is ITALIC. This is E +V E R Y T H I N G. +
  +
  +
+
+
+
+

Right now, centered REALLY Big Text, +how do you like (space) it?

+ +
RIGHT: text-2, text-1, +text+0, +text+1, +text+2, +text+3, +text+4 +
we are right now
+ +
we are center now
+we are left now. +

Blue italic text is displayed there.... +

+ +
This is heading one.

+this is normal +
+

+This is CENTERED heading one

+Testing image imageand this is text...... +
  +
    +
  • +item 1
  • + +
  • +item 2
  • + +
      +
    • +nested item
    • + +
    • +nested item 2
    • +
    + +
  • +item 3
  • +
+ +
    +
  1. +item one
  2. + +
  3. +item two
  4. + +
      +
    1. +nsted item
    2. +
    + +
  5. +last numbered item
  6. +
+ +

+Heading 1

+Italic text now... +

+Heading 2

+and now? +

+Heading 3

+ +

+Heading 4

+ +
+Heading 5
+ +
+Heading 6
+And this is normal text, once again :-) +

And yes, we're in HTML DOCUMENT, so +what about some nice hypertext link?? +

hello? +

+

This is centered paragraph

+ +

Now, you will see some PRE text: +

// This is sample C++ code:
+
+void main(int argc, char *argv[])
+{
+    printf("Go away, man!\n");
+    i = 666;
+    printf("\n\n\nCRASH\n  DOWN NOW. . .  \n");
+}
+ +

+WWW

+This is WWW link to KDE site! +
(one +folder up) + + diff --git a/samples/html/test/Makefile.am b/samples/html/test/Makefile.am new file mode 100644 index 0000000000..3631656b63 --- /dev/null +++ b/samples/html/test/Makefile.am @@ -0,0 +1,9 @@ +AUTOMAKE_OPTIONS = 1.3 no-dependencies + +SUFFIXES = .cpp + +DEFS = @DEFS@ $(TOOLKIT_DEF) $(WXDEBUG_DEFINE) + +noinst_PROGRAMS = test + +test_SOURCES = test.cpp diff --git a/samples/html/test/f.html b/samples/html/test/f.html new file mode 100644 index 0000000000..625ec44f81 --- /dev/null +++ b/samples/html/test/f.html @@ -0,0 +1,2474 @@ + +wxWindow + +
+Contents Up << >>

+ +

wxWindow

+

+wxWindow is the base class for all windows. Any +children of the window will be deleted automatically by the destructor +before the window itself is deleted.

+Derived from

+wxEvtHandler
+ +wxObject

+Include files

+<wx/window.h>

+Window styles

+The following styles can apply to all windows, although they will not always make sense for a particular +window class.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+wxSIMPLE_BORDER + +Displays a thin border around the window. wxBORDER is the old name +for this style. +
+wxDOUBLE_BORDER + +Displays a double border. Windows only. +
+wxSUNKEN_BORDER + +Displays a sunken border. +
+wxRAISED_BORDER + +Displays a raised border. +
+wxSTATIC_BORDER + +Displays a border suitable for a static control. +
+wxTRANSPARENT_WINDOW + +The window is transparent, that is, it will not receive paint +events. Windows only. +
+wxNO_3D + +Prevents the children of this window taking on 3D styles, even though +the application-wide policy is for 3D controls. Windows only. +
+wxTAB_TRAVERSAL + +Use this to enable tab traversal for non-dialog windows. +
+wxVSCROLL + +Use this style to enable a vertical scrollbar. +
+wxHSCROLL + +Use this style to enable a horizontal scrollbar. +
+wxCLIP_CHILDREN + +Use this style to eliminate flicker caused by the background being +repainted, then children being painted over them. Windows-only. +
+

+See also window styles overview.

+See also

+Event handling overview

+Members

+wxWindow::wxWindow
+wxWindow::~wxWindow
+wxWindow::AddChild
+wxWindow::CaptureMouse
+wxWindow::Center
+wxWindow::Centre
+wxWindow::Clear
+wxWindow::ClientToScreen
+wxWindow::Close
+wxWindow::ConvertDialogToPixels
+wxWindow::ConvertPixelsToDialog
+wxWindow::Destroy
+wxWindow::DestroyChildren
+wxWindow::DragAcceptFiles
+wxWindow::Enable
+wxWindow::FindFocus
+wxWindow::FindWindow
+wxWindow::Fit
+wxWindow::GetBackgroundColour
+wxWindow::GetCharHeight
+wxWindow::GetCharWidth
+wxWindow::GetChildren
+wxWindow::GetClientSize
+wxWindow::GetConstraints
+wxWindow::GetDefaultItem
+wxWindow::GetDropTarget
+wxWindow::GetEventHandler
+wxWindow::GetFont
+wxWindow::GetForegroundColour
+wxWindow::GetGrandParent
+wxWindow::GetHandle
+wxWindow::GetId
+wxWindow::GetPosition
+wxWindow::GetLabel
+wxWindow::GetName
+wxWindow::GetParent
+wxWindow::GetRect
+wxWindow::GetReturnCode
+wxWindow::GetScrollThumb
+wxWindow::GetScrollPos
+wxWindow::GetScrollRange
+wxWindow::GetSize
+wxWindow::GetTextExtent
+wxWindow::GetTitle
+wxWindow::GetUpdateRegion
+wxWindow::GetWindowStyleFlag
+wxWindow::InitDialog
+wxWindow::IsEnabled
+wxWindow::IsRetained
+wxWindow::IsShown
+wxWindow::Layout
+wxWindow::LoadFromResource
+wxWindow::Lower
+wxWindow::MakeModal
+wxWindow::Move
+wxWindow::OnActivate
+wxWindow::OnChar
+wxWindow::OnCharHook
+wxWindow::OnCommand
+wxWindow::OnClose
+wxWindow::OnCloseWindow
+wxWindow::OnDropFiles
+wxWindow::OnEraseBackground
+wxWindow::OnKeyDown
+wxWindow::OnKeyUp
+wxWindow::OnKillFocus
+wxWindow::OnIdle
+wxWindow::OnInitDialog
+wxWindow::OnMenuCommand
+wxWindow::OnMenuHighlight
+wxWindow::OnMouseEvent
+wxWindow::OnMove
+wxWindow::OnPaint
+wxWindow::OnScroll
+wxWindow::OnSetFocus
+wxWindow::OnSize
+wxWindow::OnSysColourChanged
+wxWindow::PopEventHandler
+wxWindow::PopupMenu
+wxWindow::PushEventHandler
+wxWindow::Raise
+wxWindow::Refresh
+wxWindow::ReleaseMouse
+wxWindow::RemoveChild
+wxWindow::ScreenToClient
+wxWindow::ScrollWindow
+wxWindow::SetAcceleratorTable
+wxWindow::SetAutoLayout
+wxWindow::SetBackgroundColour
+wxWindow::SetClientSize
+wxWindow::SetCursor
+wxWindow::SetEventHandler
+wxWindow::SetConstraints
+wxWindow::SetDropTarget
+wxWindow::SetFocus
+wxWindow::SetFont
+wxWindow::SetForegroundColour
+wxWindow::SetId
+wxWindow::SetName
+wxWindow::SetPalette
+wxWindow::SetReturnCode
+wxWindow::SetScrollbar
+wxWindow::SetScrollPos
+wxWindow::SetSize
+wxWindow::SetSizeHints
+wxWindow::SetTitle
+wxWindow::Show
+wxWindow::TransferDataFromWindow
+wxWindow::TransferDataToWindow
+wxWindow::Validate
+wxWindow::WarpPointer
+

+ +


+ +

wxWindow::wxWindow

+

+ wxWindow()

+Default constructor.

+ wxWindow(wxWindow* parent, wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxPanelNameStr)

+Constructs a window, which can be a child of a frame, dialog or any other non-control window.

+Parameters

+parent

      +Pointer to a parent window.
+

+id

      +Window identifier. If -1, will automatically create an identifier.
+

+pos

      +Window position. wxDefaultPosition is (-1, -1) which indicates that wxWindows +should generate a default position for the window. If using the wxWindow class directly, supply +an actual position.
+

+size

      +Window size. wxDefaultSize is (-1, -1) which indicates that wxWindows +should generate a default size for the window.
+

+style

      +Window style. For generic window styles, please see wxWindow.
+

+name

      +Window name.
+

+ +


+ +

wxWindow::~wxWindow

+

+ ~wxWindow()

+Destructor. Deletes all subwindows, then deletes itself. Instead of using +the delete operator explicitly, you should normally +use wxWindow::Destroy so that wxWindows +can delete a window only when it is safe to do so, in idle time.

+See also

+Window deletion overview, +wxWindow::OnCloseWindow, +wxWindow::Destroy, +wxCloseEvent

+ +


+ +

wxWindow::AddChild

+

+virtual void AddChild(wxWindow* child)

+Adds a child window. This is called automatically by window creation +functions so should not be required by the application programmer.

+Parameters

+child

      +Child window to add.
+

+ +


+ +

wxWindow::CaptureMouse

+

+virtual void CaptureMouse()

+Directs all mouse input to this window. Call wxWindow::ReleaseMouse to +release the capture.

+See also

+wxWindow::ReleaseMouse

+ +


+ +

wxWindow::Center

+

+void Center(int direction)

+A synonym for Centre.

+ +


+ +

wxWindow::Centre

+

+virtual void Centre(int direction = wxHORIZONTAL)

+Centres the window.

+Parameters

+direction

      +Specifies the direction for the centering. May be wxHORIZONTAL, wxVERTICAL +or wxBOTH.
+

+Remarks

+The actual behaviour depends on the derived window. For a frame or dialog box, +centring is relative to the whole display. For a panel item, centring is +relative to the panel.

+See also

+wxWindow::Center

+ +


+ +

wxWindow::Clear

+

+void Clear()

+Clears the window by filling it with the current background colour. Does not +cause an erase background event to be generated.

+ +


+ +

wxWindow::ClientToScreen

+

+virtual void ClientToScreen(int* x, int* y) const

+virtual wxPoint ClientToScreen(const wxPoint& pt) const

+Converts to screen coordinates from coordinates relative to this window.

+x

      +A pointer to a integer value for the x coordinate. Pass the client coordinate in, and +a screen coordinate will be passed out.
+

+y

      +A pointer to a integer value for the y coordinate. Pass the client coordinate in, and +a screen coordinate will be passed out.
+

+pt

      +The client position for the second form of the function.
+

+wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + +
      +ClientToScreen(point) + +Accepts and returns a wxPoint +
      +ClientToScreenXY(x, y) + +Returns a 2-tuple, (x, y) +
      +
+ +

+ + +


+ +

wxWindow::Close

+

+virtual bool Close(const bool force = FALSE)

+The purpose of this call is to provide a safer way of destroying a window than using +the delete operator.

+Parameters

+force

      +FALSE if the window's close handler should be able to veto the destruction +of this window, TRUE if it cannot.
+

+Remarks

+Close calls the close handler for the window, providing an opportunity for the window to +choose whether to destroy the window.

+The close handler should check whether the window is being deleted forcibly, +using wxCloseEvent::GetForce, in which case it should +destroy the window using wxWindow::Destroy.

+Applies to managed windows (wxFrame and wxDialog classes) only.

+Note that calling Close does not guarantee that the window will be destroyed; but it +provides a way to simulate a manual close of a window, which may or may not be implemented by +destroying the window. The default implementation of wxDialog::OnCloseWindow does not +necessarily delete the dialog, since it will simply simulate an wxID_CANCEL event which +itself only hides the dialog.

+To guarantee that the window will be destroyed, call wxWindow::Destroy instead.

+See also

+Window deletion overview, +wxWindow::OnCloseWindow, +wxWindow::Destroy, +wxCloseEvent

+ +


+ +

wxWindow::ConvertDialogToPixels

+

+wxPoint ConvertDialogToPixels(const wxPoint& pt)

+wxSize ConvertDialogToPixels(const wxSize& sz)

+Converts a point or size from dialog units to pixels.

+For the x dimension, the dialog units are multiplied by the average character width +and then divided by 4.

+For the y dimension, the dialog units are multiplied by the average character height +and then divided by 8.

+Remarks

+Dialog units are used for maintaining a dialog's proportions even if the font changes. +Dialogs created using Dialog Editor optionally use dialog units.

+You can also use these functions programmatically. A convenience macro is defined:

+ +

+#define wxDLG_UNIT(parent, pt) parent->ConvertDialogToPixels(pt)
+
+

+See also

+wxWindow::ConvertPixelsToDialog

+wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + +
      +ConvertDialogPointToPixels(point) + +Accepts and returns a wxPoint +
      +ConvertDialogSizeToPixels(size) + +Accepts and returns a wxSize +
      +
+

+Additionally, the following helper functions are defined:

+ +

      + + + + + + + + + + + + + + +
      +wxDLG_PNT(win, point) + +Converts a wxPoint from dialog +units to pixels +
      +wxDLG_SZE(win, size) + +Converts a wxSize from dialog +units to pixels +
      +
+ +

+ + +


+ +

wxWindow::ConvertPixelsToDialog

+

+wxPoint ConvertPixelsToDialog(const wxPoint& pt)

+wxSize ConvertPixelsToDialog(const wxSize& sz)

+Converts a point or size from pixels to dialog units.

+For the x dimension, the pixels are multiplied by 4 and then divided by the average +character width.

+For the y dimension, the pixels are multipled by 8 and then divided by the average +character height.

+Remarks

+Dialog units are used for maintaining a dialog's proportions even if the font changes. +Dialogs created using Dialog Editor optionally use dialog units.

+See also

+wxWindow::ConvertDialogToPixels

+ +wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + +
      +ConvertDialogPointToPixels(point) + +Accepts and returns a wxPoint +
      +ConvertDialogSizeToPixels(size) + +Accepts and returns a wxSize +
      +
+ +

+ +


+ +

wxWindow::Destroy

+

+virtual bool Destroy()

+Destroys the window safely. Use this function instead of the delete operator, since +different window classes can be destroyed differently. Frames and dialogs +are not destroyed immediately when this function is called - they are added +to a list of windows to be deleted on idle time, when all the window's events +have been processed. This prevents problems with events being sent to non-existant +windows.

+Return value

+TRUE if the window has either been successfully deleted, or it has been added +to the list of windows pending real deletion.

+ +


+ +

wxWindow::DestroyChildren

+

+virtual void DestroyChildren()

+Destroys all children of a window. Called automatically by the destructor.

+ +


+ +

wxWindow::DragAcceptFiles

+

+virtual void DragAcceptFiles(const bool accept)

+Enables or disables elibility for drop file events (OnDropFiles).

+Parameters

+accept

      +If TRUE, the window is eligible for drop file events. If FALSE, the window +will not accept drop file events.
+

+Remarks

+Windows only.

+See also

+wxWindow::OnDropFiles

+ +


+ +

wxWindow::Enable

+

+virtual void Enable(const bool enable)

+Enable or disable the window for user input.

+Parameters

+enable

      +If TRUE, enables the window for input. If FALSE, disables the window.
+

+See also

+wxWindow::IsEnabled

+ +


+ +

wxWindow::FindFocus

+

+static wxWindow* FindFocus()

+Finds the window or control which currently has the keyboard focus.

+Remarks

+Note that this is a static function, so it can be called without needing a wxWindow pointer.

+See also

+wxWindow::SetFocus

+ +


+ +

wxWindow::FindWindow

+

+wxWindow* FindWindow(long id)

+Find a child of this window, by identifier.

+wxWindow* FindWindow(const wxString& name)

+Find a child of this window, by name.

+wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + +
      +FindWindowById(id) + +Accepts an integer +
      +FindWindowByName(name) + +Accepts a string +
      +
+ +

+ +


+ +

wxWindow::Fit

+

+virtual void Fit()

+Sizes the window so that it fits around its subwindows.

+ +


+ +

wxWindow::GetBackgroundColour

+

+virtual wxColour GetBackgroundColour() const

+Returns the background colour of the window.

+See also

+wxWindow::SetBackgroundColour, +wxWindow::SetForegroundColour, +wxWindow::GetForegroundColour, +wxWindow::OnEraseBackground

+ +


+ +

wxWindow::GetCharHeight

+

+virtual int GetCharHeight() const

+Returns the character height for this window.

+ +


+ +

wxWindow::GetCharWidth

+

+virtual int GetCharWidth() const

+Returns the average character width for this window.

+ +


+ +

wxWindow::GetChildren

+

+wxList& GetChildren()

+Returns a reference to the list of the window's children.

+ +


+ +

wxWindow::GetClientSize

+

+virtual void GetClientSize(int* width, int* height) const

+virtual wxSize GetClientSize() const

+This gets the size of the window 'client area' in pixels. The client area is the +area which may be drawn on by the programmer, excluding title bar, border etc.

+Parameters

+width

      +Receives the client width in pixels.
+

+height

      +Receives the client height in pixels.
+

+wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + +
      +wxGetClientSizeTuple() + +Returns a 2-tuple of (width, height) +
      +wxGetClientSize() + +Returns a wxSize object +
      +
+ +

+ +


+ +

wxWindow::GetConstraints

+

+wxLayoutConstraints* GetConstraints() const

+Returns a pointer to the window's layout constraints, or NULL if there are none.

+ +


+ +

wxWindow::GetDefaultItem

+

+wxButton* GetDefaultItem() const

+Returns a pointer to the button which is the default for this window, or NULL.

+ +


+ +

wxWindow::GetDropTarget

+

+wxDropTarget* GetDropTarget() const

+Returns the associated drop target, which may be NULL.

+See also

+wxWindow::SetDropTarget, +Drag and drop overview

+ +


+ +

wxWindow::GetEventHandler

+

+wxEvtHandler* GetEventHandler() const

+Returns the event handler for this window. By default, the window is its +own event handler.

+See also

+wxWindow::SetEventHandler, +wxWindow::PushEventHandler, +wxWindow::PopEventHandler, +wxEvtHandler::ProcessEvent, +wxEvtHandler

+ +


+ +

wxWindow::GetFont

+

+wxFont& GetFont() const

+Returns a reference to the font for this window.

+See also

+wxWindow::SetFont

+ +


+ +

wxWindow::GetForegroundColour

+

+virtual wxColour GetForegroundColour()

+Returns the foreground colour of the window.

+Remarks

+The interpretation of foreground colour is open to interpretation according +to the window class; it may be the text colour or other colour, or it may not +be used at all.

+See also

+wxWindow::SetForegroundColour, +wxWindow::SetBackgroundColour, +wxWindow::GetBackgroundColour

+ +


+ +

wxWindow::GetGrandParent

+

+wxWindow* GetGrandParent() const

+Returns the grandparent of a window, or NULL if there isn't one.

+ +


+ +

wxWindow::GetHandle

+

+void* GetHandle() const

+Returns the platform-specific handle of the physical window. Cast it to an appropriate +handle, such as HWND for Windows or Widget for Motif.

+ +


+ +

wxWindow::GetId

+

+int GetId() const

+Returns the identifier of the window.

+Remarks

+Each window has an integer identifier. If the application has not provided one, +an identifier will be generated.

+See also

+wxWindow::SetId +Window identifiers

+ +


+ +

wxWindow::GetPosition

+

+virtual void GetPosition(int* x, int* y) const

+This gets the position of the window in pixels, relative to the parent window or +if no parent, relative to the whole display.

+Parameters

+x

      +Receives the x position of the window.
+

+y

      +Receives the y position of the window.
+

+wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + +
      +GetPosition() + +Returns a wxPoint +
      +GetPositionTuple() + +Returns a tuple (x, y) +
      +
+ +

+ +


+ +

wxWindow::GetLabel

+

+virtual wxString& GetLabel() const

+Generic way of getting a label from any window, for +identification purposes.

+Remarks

+The interpretation of this function differs from class to class. +For frames and dialogs, the value returned is the title. For buttons or static text controls, it is +the button text. This function can be useful for meta-programs (such as testing +tools or special-needs access programs) which need to identify windows +by name.

+ +


+ +

wxWindow::GetName

+

+virtual wxString& GetName() const

+Returns the window's name.

+Remarks

+This name is not guaranteed to be unique; it is up to the programmer to supply an appropriate +name in the window constructor or via wxWindow::SetName.

+See also

+wxWindow::SetName

+ +


+ +

wxWindow::GetParent

+

+virtual wxWindow* GetParent() const

+Returns the parent of the window, or NULL if there is no parent.

+ +


+ +

wxWindow::GetRect

+

+virtual wxRect GetRect() const

+Returns the size and position of the window as a wxRect object.

+ +


+ +

wxWindow::GetReturnCode

+

+int GetReturnCode()

+Gets the return code for this window.

+Remarks

+A return code is normally associated with a modal dialog, where wxDialog::ShowModal returns +a code to the application.

+See also

+wxWindow::SetReturnCode, wxDialog::ShowModal, +wxDialog::EndModal

+ +


+ +

wxWindow::GetScrollThumb

+

+virtual int GetScrollThumb(int orientation)

+Returns the built-in scrollbar thumb size.

+See also

+wxWindow::SetScrollbar

+ +


+ +

wxWindow::GetScrollPos

+

+virtual int GetScrollPos(int orientation)

+Returns the built-in scrollbar position.

+See also

+See wxWindow::SetScrollbar

+ +


+ +

wxWindow::GetScrollRange

+

+virtual int GetScrollRange(int orientation)

+Returns the built-in scrollbar range.

+See also

+wxWindow::SetScrollbar

+ +


+ +

wxWindow::GetSize

+

+virtual void GetSize(int* width, int* height) const

+virtual wxSize GetSize() const

+This gets the size of the entire window in pixels.

+Parameters

+width

      +Receives the window width.
+

+height

      +Receives the window height.
+

+wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + +
      +GetSize() + +Returns a wxSize +
      +GetSizeTuple() + +Returns a 2-tuple (width, height) +
      +
+ +

+ +


+ +

wxWindow::GetTextExtent

+

+virtual void GetTextExtent(const wxString& string, int* x, int* y, + int* descent = NULL, int* externalLeading = NULL, + const wxFont* font = NULL, const bool use16 = FALSE) const

+Gets the dimensions of the string as it would be drawn on the +window with the currently selected font.

+Parameters

+string

      +String whose extent is to be measured.
+

+x

      +Return value for width.
+

+y

      +Return value for height.
+

+descent

      +Return value for descent (optional).
+

+externalLeading

      +Return value for external leading (optional).
+

+font

      +Font to use instead of the current window font (optional).
+

+use16

      +If TRUE, string contains 16-bit characters. The default is FALSE.
+

+ +wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + +
      +GetTextExtent(string) + +Returns a 2-tuple, (width, height) +
      +GetFullTextExtent(string, font=NULL) + +Returns a +4-tuple, (width, height, descent, externalLeading) +
      +
+ +

+ + +


+ +

wxWindow::GetTitle

+

+virtual wxString GetTitle()

+Gets the window's title. Applicable only to frames and dialogs.

+See also

+wxWindow::SetTitle

+ +


+ +

wxWindow::GetUpdateRegion

+

+virtual wxRegion GetUpdateRegion() const

+Returns the region specifying which parts of the window have been damaged. Should +only be called within an OnPaint event handler.

+See also

+wxRegion, wxRegionIterator, wxWindow::OnPaint

+ +


+ +

wxWindow::GetWindowStyleFlag

+

+long GetWindowStyleFlag() const

+Gets the window style that was passed to the consructor or Create member.

+ +


+ +

wxWindow::InitDialog

+

+void InitDialog()

+Sends an wxWindow::OnInitDialog event, which +in turn transfers data to the dialog via validators.

+See also

+wxWindow::OnInitDialog

+ +


+ +

wxWindow::IsEnabled

+

+virtual bool IsEnabled() const

+Returns TRUE if the window is enabled for input, FALSE otherwise.

+See also

+wxWindow::Enable

+ +


+ +

wxWindow::IsRetained

+

+virtual bool IsRetained() const

+Returns TRUE if the window is retained, FALSE otherwise.

+Remarks

+Retained windows are only available on X platforms.

+ +


+ +

wxWindow::IsShown

+

+virtual bool IsShown() const

+Returns TRUE if the window is shown, FALSE if it has been hidden.

+ +


+ +

wxWindow::Layout

+

+void Layout()

+Invokes the constraint-based layout algorithm for this window. It is called +automatically by the default wxWindow::OnSize member.

+ +


+ +

wxWindow::LoadFromResource

+

+virtual bool LoadFromResource(wxWindow* parent, +const wxString& resourceName, const wxResourceTable* resourceTable = NULL)

+Loads a panel or dialog from a resource file.

+Parameters

+parent

      +Parent window.
+

+resourceName

      +The name of the resource to load.
+

+resourceTable

      +The resource table to load it from. If this is NULL, the +default resource table will be used.
+

+Return value

+TRUE if the operation succeeded, otherwise FALSE.

+ +


+ +

wxWindow::Lower

+

+void Lower()

+Lowers the window to the bottom of the window hierarchy if it is a managed window (dialog +or frame).

+ +


+ +

wxWindow::MakeModal

+

+virtual void MakeModal(const bool flag)

+Disables all other windows in the application so that +the user can only interact with this window.

+Parameters

+flag

      +If TRUE, this call disables all other windows in the application so that +the user can only interact with this window. If FALSE, the effect is reversed.
+

+ +


+ +

wxWindow::Move

+

+void Move(int x, int y)

+void Move(const wxPoint& pt)

+Moves the window to the given position.

+Parameters

+x

      +Required x position.
+

+y

      +Required y position.
+

+pt

      +wxPoint object representing the position.
+

+Remarks

+Implementations of SetSize can also implicitly implement the +wxWindow::Move function, which is defined in the base wxWindow class +as the call:

+

+  SetSize(x, y, -1, -1, wxSIZE_USE_EXISTING);
+
+See also

+wxWindow::SetSize

+wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + +
      +Move(point) + +Accepts a wxPoint +
      +MoveXY(x, y) + +Accepts a pair of integers +
      +
+ +

+ +


+ +

wxWindow::OnActivate

+

+void OnActivate(wxActivateEvent& event)

+Called when a window is activated or deactivated.

+Parameters

+event

      +Object containing activation information.
+

+Remarks

+If the window is being activated, wxActivateEvent::GetActive returns TRUE, +otherwise it returns FALSE (it is being deactivated).

+See also

+wxActivateEvent, +Event handling overview

+ +


+ +

wxWindow::OnChar

+

+void OnChar(wxKeyEvent& event)

+Called when the user has pressed a key that is not a modifier (SHIFT, CONTROL or ALT).

+Parameters

+event

      +Object containing keypress information. See wxKeyEvent for +details about this class.
+

+Remarks

+This member function is called in response to a keypress. To intercept this event, +use the EVT_CHAR macro in an event table definition. Your OnChar handler may call this +default function to achieve default keypress functionality.

+Note that the ASCII values do not have explicit key codes: they are passed as ASCII +values.

+Note that not all keypresses can be intercepted this way. If you wish to intercept modifier +keypresses, then you will need to use wxWindow::OnKeyDown or +wxWindow::OnKeyUp.

+Most, but not all, windows allow keypresses to be intercepted.

+See also

+wxWindow::OnKeyDown, wxWindow::OnKeyUp, +wxKeyEvent, wxWindow::OnCharHook, +Event handling overview

+ +


+ +

wxWindow::OnCharHook

+

+void OnCharHook(wxKeyEvent& event)

+This member is called to allow the window to intercept keyboard events +before they are processed by child windows.

+Parameters

+event

      +Object containing keypress information. See wxKeyEvent for +details about this class.
+

+Remarks

+This member function is called in response to a keypress, if the window is active. To intercept this event, +use the EVT_CHAR_HOOK macro in an event table definition. If you do not process a particular +keypress, call wxEvent::Skip to allow default processing.

+An example of using this function is in the implementation of escape-character processing for wxDialog, +where pressing ESC dismisses the dialog by OnCharHook 'forging' a cancel button press event.

+Note that the ASCII values do not have explicit key codes: they are passed as ASCII +values.

+This function is only relevant to top-level windows (frames and dialogs), and under +Windows only.

+See also

+wxKeyEvent, wxWindow::OnCharHook, +wxApp::OnCharHook, +Event handling overview

+ +


+ +

wxWindow::OnCommand

+

+virtual void OnCommand(wxEvtHandler& object, wxCommandEvent& event)

+This virtual member function is called if the control does not handle the command event.

+Parameters

+object

      +Object receiving the command event.
+

+event

      +Command event
+

+Remarks

+This virtual function is provided mainly for backward compatibility. You can also intercept commands +from child controls by using an event table, with identifiers or identifier ranges to identify +the control(s) in question.

+See also

+wxCommandEvent, +Event handling overview

+ +


+ +

wxWindow::OnClose

+

+virtual bool OnClose()

+Called when the user has tried to close a a frame +or dialog box using the window manager (X) or system menu (Windows).

+Note: This is an obsolete function. +It is superceded by the wxWindow::OnCloseWindow event +handler.

+Return value

+If TRUE is returned by OnClose, the window will be deleted by the system, otherwise the +attempt will be ignored. Do not delete the window from within this handler, although +you may delete other windows.

+See also

+Window deletion overview, +wxWindow::Close, +wxWindow::OnCloseWindow, +wxCloseEvent

+ +


+ +

wxWindow::OnCloseWindow

+

+void OnCloseWindow(wxCloseEvent& event)

+This is an event handler function called when the user has tried to close a a frame +or dialog box using the window manager (X) or system menu (Windows). It is +called via the wxWindow::Close function, so +that the application can also invoke the handler programmatically.

+Use the EVT_CLOSE event table macro to handle close events.

+You should check whether the application is forcing the deletion of the window +using wxCloseEvent::GetForce. If this is TRUE, +destroy the window using wxWindow::Destroy. +If not, it is up to you whether you respond by destroying the window.

+(Note: GetForce is now superceded by CanVeto. So to test whether forced destruction of +the window is required, test for the negative of CanVeto. If CanVeto returns FALSE, +it is not possible to skip window deletion.)

+If you don't destroy the window, you should call wxCloseEvent::Veto to +let the calling code know that you did not destroy the window. This allows the wxWindow::Close function +to return TRUE or FALSE depending on whether the close instruction was honoured or not.

+Remarks

+The wxWindow::OnClose virtual function remains +for backward compatibility with earlier versions of wxWindows. The +default OnCloseWindow handler for wxFrame and wxDialog will call OnClose, +destroying the window if it returns TRUE or if the close is being forced.

+See also

+Window deletion overview, +wxWindow::Close, +wxWindow::OnClose, +wxWindow::Destroy, +wxCloseEvent, +wxApp::OnQueryEndSession, +wxApp::OnEndSession

+ +


+ +

wxWindow::OnDropFiles

+

+void OnDropFiles(wxDropFilesEvent& event)

+Called when files have been dragged from the file manager to the window.

+Parameters

+event

+

+Remarks

+The window must have previously been enabled for dropping by calling +wxWindow::DragAcceptFiles.

+This event is only generated under Windows.

+To intercept this event, use the EVT_DROP_FILES macro in an event table definition.

+See also

+wxDropFilesEvent, wxWindow::DragAcceptFiles, +Event handling overview

+ +


+ +

wxWindow::OnEraseBackground

+

+void OnEraseBackground(wxEraseEvent& event)

+Called when the background of the window needs to be erased.

+Parameters

+event

      +Erase background event. For more information, see wxEraseEvent.
+

+Remarks

+This event is only generated under Windows.

+To intercept this event, use the EVT_ERASE_BACKGROUND macro in an event table definition.

+See also

+wxEraseEvent, Event handling overview

+ +


+ +

wxWindow::OnKeyDown

+

+void OnKeyDown(wxKeyEvent& event)

+Called when the user has pressed a key, before it is translated into an ASCII value using other +modifier keys that might be pressed at the same time.

+Parameters

+event

      +Object containing keypress information. See wxKeyEvent for +details about this class.
+

+Remarks

+This member function is called in response to a key down event. To intercept this event, +use the EVT_KEY_DOWN macro in an event table definition. Your OnKeyDown handler may call this +default function to achieve default keypress functionality.

+Note that not all keypresses can be intercepted this way. If you wish to intercept special +keys, such as shift, control, and function keys, then you will need to use wxWindow::OnKeyDown or +wxWindow::OnKeyUp.

+Most, but not all, windows allow keypresses to be intercepted.

+See also

+wxWindow::OnChar, wxWindow::OnKeyUp, +wxKeyEvent, wxWindow::OnCharHook, +Event handling overview

+ +


+ +

wxWindow::OnKeyUp

+

+void OnKeyUp(wxKeyEvent& event)

+Called when the user has released a key.

+Parameters

+event

      +Object containing keypress information. See wxKeyEvent for +details about this class.
+

+Remarks

+This member function is called in response to a key up event. To intercept this event, +use the EVT_KEY_UP macro in an event table definition. Your OnKeyUp handler may call this +default function to achieve default keypress functionality.

+Note that not all keypresses can be intercepted this way. If you wish to intercept special +keys, such as shift, control, and function keys, then you will need to use wxWindow::OnKeyDown or +wxWindow::OnKeyUp.

+Most, but not all, windows allow key up events to be intercepted.

+See also

+wxWindow::OnChar, wxWindow::OnKeyDown, +wxKeyEvent, wxWindow::OnCharHook, +Event handling overview

+ +


+ +

wxWindow::OnKillFocus

+

+void OnKillFocus(wxFocusEvent& event)

+Called when a window's focus is being killed.

+Parameters

+event

+

+Remarks

+To intercept this event, use the macro EVT_KILL_FOCUS in an event table definition.

+Most, but not all, windows respond to this event.

+See also

+wxFocusEvent, wxWindow::OnSetFocus, +Event handling overview

+ +


+ +

wxWindow::OnIdle

+

+void OnIdle(wxIdleEvent& event)

+Provide this member function for any processing which needs to be done +when the application is idle.

+See also

+wxApp::OnIdle, wxIdleEvent

+ +


+ +

wxWindow::OnInitDialog

+

+void OnInitDialog(wxInitDialogEvent& event)

+Default handler for the wxEVT_INIT_DIALOG event. Calls wxWindow::TransferDataToWindow.

+Parameters

+event

      +Dialog initialisation event.
+

+Remarks

+Gives the window the default behaviour of transferring data to child controls via +the validator that each control has.

+See also

+wxValidator, wxWindow::TransferDataToWindow

+ +


+ +

wxWindow::OnMenuCommand

+

+void OnMenuCommand(wxCommandEvent& event)

+Called when a menu command is received from a menu bar.

+Parameters

+event

+

+Remarks

+A function with this name doesn't actually exist; you can choose any member function to receive +menu command events, using the EVT_COMMAND macro for individual commands or EVT_COMMAND_RANGE for +a range of commands.

+See also

+wxCommandEvent, +wxWindow::OnMenuHighlight, +Event handling overview

+ +


+ +

wxWindow::OnMenuHighlight

+

+void OnMenuHighlight(wxMenuEvent& event)

+Called when a menu select is received from a menu bar: that is, the +mouse cursor is over a menu item, but the left mouse button has not been +pressed.

+Parameters

+event

      +The menu highlight event. For more information, see wxMenuEvent.
+

+Remarks

+You can choose any member function to receive +menu select events, using the EVT_MENU_HIGHLIGHT macro for individual menu items or EVT_MENU_HIGHLIGHT_ALL macro +for all menu items.

+The default implementation for wxFrame::OnMenuHighlight displays help +text in the first field of the status bar.

+This function was known as OnMenuSelect in earlier versions of wxWindows, but this was confusing +since a selection is normally a left-click action.

+See also

+wxMenuEvent, +wxWindow::OnMenuCommand, +Event handling overview

+ + +


+ +

wxWindow::OnMouseEvent

+

+void OnMouseEvent(wxMouseEvent& event)

+Called when the user has initiated an event with the +mouse.

+Parameters

+event

+

+Remarks

+Most, but not all, windows respond to this event.

+To intercept this event, use the EVT_MOUSE_EVENTS macro in an event table definition, or individual +mouse event macros such as EVT_LEFT_DOWN.

+See also

+wxMouseEvent, +Event handling overview

+ +


+ +

wxWindow::OnMove

+

+void OnMove(wxMoveEvent& event)

+Called when a window is moved.

+Parameters

+event

      +The move event. For more information, see wxMoveEvent.
+

+Remarks

+Use the EVT_MOVE macro to intercept move events.

+Remarks

+Not currently implemented.

+See also

+wxMoveEvent, +wxFrame::OnSize, +Event handling overview

+ +


+ +

wxWindow::OnPaint

+

+void OnPaint(wxPaintEvent& event)

+Sent to the event handler when the window must be refreshed.

+Parameters

+event

+

+Remarks

+Use the EVT_PAINT macro in an event table definition to intercept paint events.

+In a paint event handler, the application should always create a wxPaintDC object.

+For example:

+

+  void MyWindow::OnPaint(wxPaintEvent& event)
+  {
+      wxPaintDC dc(this);
+
+      DrawMyDocument(dc);
+  }
+
+You can optimize painting by retrieving the rectangles +that have been damaged and only repainting these. The rectangles are in +terms of the client area, and are unscrolled, so you will need to do +some calculations using the current view position to obtain logical, +scrolled units.

+Here is an example of using the wxRegionIterator class:

+

+// Called when window needs to be repainted.
+void MyWindow::OnPaint(wxPaintEvent& event)
+{
+  wxPaintDC dc(this);
+
+  // Find Out where the window is scrolled to
+  int vbX,vbY;                     // Top left corner of client
+  ViewStart(&vbX,&vbY);
+
+  int vX,vY,vW,vH;                 // Dimensions of client area in pixels
+  wxRegionIterator upd(GetUpdateRegion()); // get the update rect list
+
+  while (upd)
+  {
+    vX = upd.GetX();
+    vY = upd.GetY();
+    vW = upd.GetW();
+    vH = upd.GetH();
+
+    // Alternatively we can do this:
+    // wxRect rect;
+    // upd.GetRect(&rect);
+
+    // Repaint this rectangle
+    ...some code...
+
+    upd ++ ;
+  }
+}
+
+See also

+wxPaintEvent, +wxPaintDC, +Event handling overview

+ +


+ +

wxWindow::OnScroll

+

+void OnScroll(wxScrollEvent& event)

+Called when a scroll event is received from one of the window's built-in scrollbars.

+Parameters

+event

+

+Remarks

+Note that it is not possible to distinguish between horizontal and vertical scrollbars +until the function is executing (you can't have one function for vertical, another +for horizontal events).

+See also

+wxScrollEvent, +Event handling overview

+ +


+ +

wxWindow::OnSetFocus

+

+void OnSetFocus(wxFocusEvent& event)

+Called when a window's focus is being set.

+Parameters

+event

+

+Remarks

+To intercept this event, use the macro EVT_SET_FOCUS in an event table definition.

+Most, but not all, windows respond to this event.

+See also

+wxFocusEvent, wxWindow::OnKillFocus, +Event handling overview

+ +


+ +

wxWindow::OnSize

+

+void OnSize(wxSizeEvent& event)

+Called when the window has been resized.

+Parameters

+event

+

+Remarks

+You may wish to use this for frames to resize their child windows as appropriate.

+Note that the size passed is of +the whole window: call wxWindow::GetClientSize for the area which may be +used by the application.

+See also

+wxSizeEvent, +Event handling overview

+ +


+ +

wxWindow::OnSysColourChanged

+

+void OnSysColourChanged(wxOnSysColourChangedEvent& event)

+Called when the user has changed the system colours.

+Parameters

+event

+

+See also

+wxSysColourChangedEvent, +Event handling overview

+ +


+ +

wxWindow::PopEventHandler

+

+wxEvtHandler* PopEventHandler(bool deleteHandler = FALSE) const

+Removes and returns the top-most event handler on the event handler stack.

+Parameters

+deleteHandler

      +If this is TRUE, the handler will be deleted after it is removed. The +default value is FALSE.
+

+See also

+wxWindow::SetEventHandler, +wxWindow::GetEventHandler, +wxWindow::PushEventHandler, +wxEvtHandler::ProcessEvent, +wxEvtHandler

+ +


+ +

wxWindow::PopupMenu

+

+virtual bool PopupMenu(wxMenu* menu, int x, int y)

+Pops up the given menu at the specified coordinates, relative to this +window, and returns control when the user has dismissed the menu. If a +menu item is selected, the callback defined for the menu is called with +wxMenu and wxCommandEvent reference arguments. The callback should access +the commandInt member of the event to check the selected menu identifier.

+Parameters

+menu

      +Menu to pop up.
+

+x

      +Required x position for the menu to appear.
+

+y

      +Required y position for the menu to appear.
+

+See also

+wxMenu

+Remarks

+Just before the menu is popped up, wxMenu::UpdateUI is called +to ensure that the menu items are in the correct state.

+ +


+ +

wxWindow::PushEventHandler

+

+void PushEventHandler(wxEvtHandler* handler)

+Pushes this event handler onto the event stack for the window.

+Parameters

+handler

      +Specifies the handler to be pushed.
+

+Remarks

+An event handler is an object that is capable of processing the events +sent to a window. By default, the window is its own event handler, but +an application may wish to substitute another, for example to allow +central implementation of event-handling for a variety of different +window classes.

+wxWindow::PushEventHandler allows +an application to set up a chain of event handlers, where an event not handled by one event handler is +handed to the next one in the chain. Use wxWindow::PopEventHandler to +remove the event handler.

+See also

+wxWindow::SetEventHandler, +wxWindow::GetEventHandler, +wxWindow::PopEventHandler, +wxEvtHandler::ProcessEvent, +wxEvtHandler

+ +


+ +

wxWindow::Raise

+

+void Raise()

+Raises the window to the top of the window hierarchy if it is a managed window (dialog +or frame).

+ +


+ +

wxWindow::Refresh

+

+virtual void Refresh(const bool eraseBackground = TRUE, const wxRect* rect += NULL)

+Causes a message or event to be generated to repaint the +window.

+Parameters

+eraseBackground

      +If TRUE, the background will be +erased.
+

+rect

      +If non-NULL, only the given rectangle will +be treated as damaged.
+

+ +


+ +

wxWindow::ReleaseMouse

+

+virtual void ReleaseMouse()

+Releases mouse input captured with wxWindow::CaptureMouse.

+See also

+wxWindow::CaptureMouse

+ +


+ +

wxWindow::RemoveChild

+

+virtual void RemoveChild(wxWindow* child)

+Removes a child window. This is called automatically by window deletion +functions so should not be required by the application programmer.

+Parameters

+child

      +Child window to remove.
+

+ +


+ +

wxWindow::ScreenToClient

+

+virtual void ScreenToClient(int* x, int* y) const

+virtual wxPoint ScreenToClient(const wxPoint& pt) const

+Converts from screen to client window coordinates.

+Parameters

+x

      +Stores the screen x coordinate and receives the client x coordinate.
+

+y

      +Stores the screen x coordinate and receives the client x coordinate.
+

+pt

      +The screen position for the second form of the function.
+

+wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + +
      +ScreenToClient(point) + +Accepts and returns a wxPoint +
      +ScreenToClientXY(x, y) + +Returns a 2-tuple, (x, y) +
      +
+ +

+ + +


+ +

wxWindow::ScrollWindow

+

+virtual void ScrollWindow(int dx, int dy, const wxRect* rect = NULL)

+Physically scrolls the pixels in the window.

+Parameters

+dx

      +Amount to scroll horizontally.
+

+dy

      +Amount to scroll vertically.
+

+rect

      +Rectangle to invalidate. If this is NULL, the whole window is invalidated. If you +pass a rectangle corresponding to the area of the window exposed by the scroll, your painting handler +can optimise painting by checking for the invalidated region.
+

+Remarks

+Available only under Windows.

+Use this function to optimise your scrolling implementations, to minimise the area that must be +redrawn.

+ +


+ +

wxWindow::SetAcceleratorTable

+

+virtual void SetAcceleratorTable(const wxAcceleratorTable& accel)

+Sets the accelerator table for this window. See wxAcceleratorTable.

+ +


+ +

wxWindow::SetAutoLayout

+

+void SetAutoLayout(const bool autoLayout)

+Determines whether the wxWindow::Layout function will +be called automatically when the window is resized.

+Parameters

+autoLayout

      +Set this to TRUE if you wish the Layout function to be called +from within wxWindow::OnSize functions.
+

+See also

+wxWindow::SetConstraints

+ +


+ +

wxWindow::SetBackgroundColour

+

+virtual void SetBackgroundColour(const wxColour& colour)

+Sets the background colour of the window.

+Parameters

+colour

      +The colour to be used as the background colour.
+

+Remarks

+The background colour is usually painted by the default +wxWindow::OnEraseBackground event handler function.

+Note that setting the background colour does not cause an immediate refresh, so you +may wish to call wxWindow::Clear or wxWindow::Refresh after +calling this function.

+See also

+wxWindow::GetBackgroundColour, +wxWindow::SetForegroundColour, +wxWindow::GetForegroundColour, +wxWindow::Clear, +wxWindow::Refresh, +wxWindow::OnEraseBackground

+ +


+ +

wxWindow::SetClientSize

+

+virtual void SetClientSize(int width, int height)

+virtual void SetClientSize(const wxSize& size)

+This sets the size of the window client area in pixels. Using this function to size a window +tends to be more device-independent than wxWindow::SetSize, since the application need not +worry about what dimensions the border or title bar have when trying to fit the window +around panel items, for example.

+Parameters

+width

      +The required client area width.
+

+height

      +The required client area height.
+

+size

      +The required client size.
+

+wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + +
      +SetClientSize(size) + +Accepts a wxSize +
      +SetClientSizeWH(width, height) + + +
      +
+ +

+ +


+ +

wxWindow::SetCursor

+

+virtual void SetCursor(const wxCursor&cursor)

+Sets the window's cursor. Notice that setting the cursor for this window does +not set it for its children so you'll need to explicitly call SetCursor() for +them too if you need it.

+Parameters

+cursor

      +Specifies the cursor that the window should normally display.
+

+See also

+::wxSetCursor, wxCursor

+ +


+ +

wxWindow::SetEventHandler

+

+void SetEventHandler(wxEvtHandler* handler)

+Sets the event handler for this window.

+Parameters

+handler

      +Specifies the handler to be set.
+

+Remarks

+An event handler is an object that is capable of processing the events +sent to a window. By default, the window is its own event handler, but +an application may wish to substitute another, for example to allow +central implementation of event-handling for a variety of different +window classes.

+It is usually better to use wxWindow::PushEventHandler since +this sets up a chain of event handlers, where an event not handled by one event handler is +handed to the next one in the chain.

+See also

+wxWindow::GetEventHandler, +wxWindow::PushEventHandler, +wxWindow::PopEventHandler, +wxEvtHandler::ProcessEvent, +wxEvtHandler

+ +


+ +

wxWindow::SetConstraints

+

+void SetConstraints(wxLayoutConstraints* constraints)

+Sets the window to have the given layout constraints. The window +will then own the object, and will take care of its deletion. +If an existing layout constraints object is already owned by the +window, it will be deleted.

+Parameters

+constraints

      +The constraints to set. Pass NULL to disassociate and delete the window's +constraints.
+

+Remarks

+You must call wxWindow::SetAutoLayout to tell a window to use +the constraints automatically in OnSize; otherwise, you must +override OnSize and call Layout explicitly.

+ +


+ +

wxWindow::SetDropTarget

+

+void SetDropTarget(wxDropTarget* target)

+Associates a drop target with this window.

+If the window already has a drop target, it is deleted.

+See also

+wxWindow::GetDropTarget, +Drag and drop overview

+ +


+ +

wxWindow::SetFocus

+

+virtual void SetFocus()

+This sets the window to receive keyboard input.

+ +


+ +

wxWindow::SetFont

+

+void SetFont(const wxFont& font)

+Sets the font for this window.

+Parameters

+font

      +Font to associate with this window.
+

+See also

+wxWindow::GetFont

+ +


+ +

wxWindow::SetForegroundColour

+

+virtual void SetForegroundColour(const wxColour& colour)

+Sets the foreground colour of the window.

+Parameters

+colour

      +The colour to be used as the foreground colour.
+

+Remarks

+The interpretation of foreground colour is open to interpretation according +to the window class; it may be the text colour or other colour, or it may not +be used at all.

+See also

+wxWindow::GetForegroundColour, +wxWindow::SetBackgroundColour, +wxWindow::GetBackgroundColour

+ +


+ +

wxWindow::SetId

+

+void SetId(int id)

+Sets the identifier of the window.

+Remarks

+Each window has an integer identifier. If the application has not provided one, +an identifier will be generated. Normally, the identifier should be provided +on creation and should not be modified subsequently.

+See also

+wxWindow::GetId, +Window identifiers

+ +


+ +

wxWindow::SetName

+

+virtual void SetName(const wxString& name)

+Sets the window's name.

+Parameters

+name

      +A name to set for the window.
+

+See also

+wxWindow::GetName

+ +


+ +

wxWindow::SetPalette

+

+virtual void SetPalette(wxPalette* palette)

+Obsolete - use wxDC::SetPalette instead.

+ +


+ +

wxWindow::SetReturnCode

+

+void SetReturnCode(int retCode)

+Sets the return code for this window.

+Parameters

+retCode

      +The integer return code, usually a control identifier.
+

+Remarks

+A return code is normally associated with a modal dialog, where wxDialog::ShowModal returns +a code to the application. The function wxDialog::EndModal calls SetReturnCode.

+See also

+wxWindow::GetReturnCode, wxDialog::ShowModal, +wxDialog::EndModal

+ +


+ +

wxWindow::SetScrollbar

+

+virtual void SetScrollbar(int orientation, int position, +int thumbSize, int range, +const bool refresh = TRUE)

+Sets the scrollbar properties of a built-in scrollbar.

+Parameters

+orientation

      +Determines the scrollbar whose page size is to be set. May be wxHORIZONTAL or wxVERTICAL.
+

+position

      +The position of the scrollbar in scroll units.
+

+thumbSize

      +The size of the thumb, or visible portion of the scrollbar, in scroll units.
+

+range

      +The maximum position of the scrollbar.
+

+refresh

      +TRUE to redraw the scrollbar, FALSE otherwise.
+

+Remarks

+Let's say you wish to display 50 lines of text, using the same font. +The window is sized so that you can only see 16 lines at a time.

+You would use:

+

+  SetScrollbar(wxVERTICAL, 0, 16, 50);
+
+

+Note that with the window at this size, the thumb position can never go +above 50 minus 16, or 34.

+You can determine how many lines are currently visible by dividing the current view +size by the character height in pixels.

+When defining your own scrollbar behaviour, you will always need to recalculate +the scrollbar settings when the window size changes. You could therefore put your +scrollbar calculations and SetScrollbar +call into a function named AdjustScrollbars, which can be called initially and also +from your wxWindow::OnSize event handler function.

+See also

+Scrolling overview, +wxScrollBar, wxScrolledWindow

+ +


+ +

wxWindow::SetScrollPos

+

+virtual void SetScrollPos(int orientation, int pos, const bool refresh = TRUE)

+Sets the position of one of the built-in scrollbars.

+Parameters

+orientation

      +Determines the scrollbar whose position is to be set. May be wxHORIZONTAL or wxVERTICAL.
+

+pos

      +Position in scroll units.
+

+refresh

      +TRUE to redraw the scrollbar, FALSE otherwise.
+

+Remarks

+This function does not directly affect the contents of the window: it is up to the +application to take note of scrollbar attributes and redraw contents accordingly.

+See also

+wxWindow::SetScrollbar, +wxWindow::GetScrollPos, +wxWindow::GetScrollThumb, +wxScrollBar, wxScrolledWindow

+ +


+ +

wxWindow::SetSize

+

+virtual void SetSize(int x, int y, int width, int height, + int sizeFlags = wxSIZE_AUTO)

+virtual void SetSize(const wxRect& rect)

+Sets the size and position of the window in pixels.

+virtual void SetSize(int width, int height)

+virtual void SetSize(const wxSize& size)

+Sets the size of the window in pixels.

+Parameters

+x

      +Required x position in pixels, or -1 to indicate that the existing +value should be used.
+

+y

      +Required y position in pixels, or -1 to indicate that the existing +value should be used.
+

+width

      +Required width in pixels, or -1 to indicate that the existing +value should be used.
+

+height

      +Required height position in pixels, or -1 to indicate that the existing +value should be used.
+

+size

      +wxSize object for setting the size.
+

+rect

      +wxRect object for setting the position and size.
+

+sizeFlags

      +Indicates the interpretation of other parameters. It is a bit list of the following:

      +wxSIZE_AUTO_WIDTH: a -1 width value is taken to indicate +a wxWindows-supplied default width.
      + +wxSIZE_AUTO_HEIGHT: a -1 height value is taken to indicate +a wxWindows-supplied default width.
      + +wxSIZE_AUTO: -1 size values are taken to indicate +a wxWindows-supplied default size.
      + +wxSIZE_USE_EXISTING: existing dimensions should be used +if -1 values are supplied.
      + +wxSIZE_ALLOW_MINUS_ONE: allow dimensions of -1 and less to be interpreted +as real dimensions, not default values. +

+

+Remarks

+The second form is a convenience for calling the first form with default +x and y parameters, and must be used with non-default width and height values.

+The first form sets the position and optionally size, of the window. +Parameters may be -1 to indicate either that a default should be supplied +by wxWindows, or that the current value of the dimension should be used.

+See also

+wxWindow::Move

+wxPython note:
+ In place of a single overloaded method name, wxPython +implements the following methods:

+ +

      + + + + + + + + + + + + + + + + + + + +
      +SetDimensions(x, y, width, height, sizeFlags=wxSIZE_AUTO) + + +
      +SetSize(size) + + +
      +SetPosition(point) + + +
      +
+ +

+ +


+ +

wxWindow::SetSizeHints

+

+virtual void SetSizeHints(int minW=-1, int minH=-1, int maxW=-1, int maxH=-1, + int incW=-1, int incH=-1)

+Allows specification of minimum and maximum window sizes, and window size increments. +If a pair of values is not set (or set to -1), the default values will be used.

+Parameters

+minW

      +Specifies the minimum width allowable.
+

+minH

      +Specifies the minimum height allowable.
+

+maxW

      +Specifies the maximum width allowable.
+

+maxH

      +Specifies the maximum height allowable.
+

+incW

      +Specifies the increment for sizing the width (Motif/Xt only).
+

+incH

      +Specifies the increment for sizing the height (Motif/Xt only).
+

+Remarks

+If this function is called, the user will not be able to size the window outside the +given bounds.

+The resizing increments are only significant under Motif or Xt.

+ +


+ +

wxWindow::SetTitle

+

+virtual void SetTitle(const wxString& title)

+Sets the window's title. Applicable only to frames and dialogs.

+Parameters

+title

      +The window's title.
+

+See also

+wxWindow::GetTitle

+ +


+ +

wxWindow::Show

+

+virtual bool Show(const bool show)

+Shows or hides the window.

+Parameters

+show

      +If TRUE, displays the window and brings it to the front. Otherwise, +hides the window.
+

+See also

+wxWindow::IsShown

+ +


+ +

wxWindow::TransferDataFromWindow

+

+virtual bool TransferDataFromWindow()

+Transfers values from child controls to data areas specified by their validators. Returns +FALSE if a transfer failed.

+See also

+wxWindow::TransferDataToWindow, +wxValidator, wxWindow::Validate

+ +


+ +

wxWindow::TransferDataToWindow

+

+virtual bool TransferDataToWindow()

+Transfers values to child controls from data areas specified by their validators.

+Return value

+Returns FALSE if a transfer failed.

+See also

+wxWindow::TransferDataFromWindow, +wxValidator, wxWindow::Validate

+ +


+ +

wxWindow::Validate

+

+virtual bool Validate()

+Validates the current values of the child controls using their validators.

+Return value

+Returns FALSE if any of the validations failed.

+See also

+wxWindow::TransferDataFromWindow, +wxWindow::TransferDataFromWindow, +wxValidator

+ +


+ +

wxWindow::WarpPointer

+

+void WarpPointer(int x, int y)

+Moves the pointer to the given position on the window.

+Parameters

+x

      +The new x position for the cursor.
+

+y

      +The new y position for the cursor.
+

+ + diff --git a/samples/html/test/fft.html b/samples/html/test/fft.html new file mode 100644 index 0000000000..3cef164b9e --- /dev/null +++ b/samples/html/test/fft.html @@ -0,0 +1,144 @@ + + + + + wxHTML : wxWindows HTML library + + + + + + +

+ +

+[ Intro & News ] +[ Features ] +[ Download ] +[ Licence ] +[ Screenshots ] +[ Links & Apps ] +

+ + + + + + + +

+ +

+
+
+ +Latest release 0.2.3 + +
+
+
+ +

+ +
+
+ +2811 visitors since January 99 + + +
Last updated on : June 13, 1999 + + +
+

+ +
+ + + + +

News

+ +
    +
  • 13/06/1999 - CVS available!
    +Thanks to Russell Smith, development version of wxHTML is available through CVS. +See Download page for details! +
+ +
    +
  • 13/06/1999 - 0.2.3 release
    +Only minor changes and bugfixes. +
+ +
    +
  • 16/05/1999 - New release
    +Well, 0.2.1 is out. It contains some bug fixes (mainly related to Visual C++) +and new help controller that works with MS HTML Help Workshop projects as +it's native format. Patch from previous version is only 30kB so don't hesitate +to download it! +
+ +
    +
  • 02/05/1999 - Beta release 0.2 is out!
    +Ok, it's here, download it! Help controller is included (and broken under +MSW/Mingw32 - I'll fix it asap. If anyone can help with it, please do so...) +
+ + + + + + + +
+

Intro

+ +I started work on this library in January, 1999. +
The main goal was to provide light-weight HTML viewer for +wxWindows 2 toolkit. +This viewer was expected to be used as help/documentation browser rather than full-featured web browser. + +

This library is released under +wxWindows Library Licence, Version 3. It is basically +GNU Library General Public Licence except that it makes using +wxHTML in commercial products much easier. + +

The library should work on all platforms supported by wxWindows - it +is written as poor wxWindows-only code, without line of platform-specific +code (as I hope :-). It is known to compile under these enviromnets: + +

    +
  • EGCS under Linux +
  • Cygwin b20 or Mingw32 under Windows 95 +
+ + + + + + + + +

Author(s)

+wxHTML (and this page) is copyrighted by Vaclav Slavik. Parts of wxHTML are copyrighted by other +autors - all of them are listed in contributors section. + +

+Feel free to send your suggestions, comments, bug reports to me. My +e-mail address is + +
slavik2@czn.cz +
or +
vsla8348@ss1000.ms.mff.cuni.cz +

Vaclav Slavik + + +

Contributors

+
    +
  • Guillermo Rodriguez Garcia (guille@iies.es) +
    contributed GIF reading routines +
+ +
+ + diff --git a/samples/html/test/pic.png b/samples/html/test/pic.png new file mode 100644 index 0000000000000000000000000000000000000000..fcc18c1296d650b9ad75f9dc61b15d6cb0d09b03 GIT binary patch literal 31315 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 + + + + + + + +

+This is TABLES +tests page...

+ + +(yes, really, see bellow:) +
Click here to go to original testing page... +
Click here to go to manuals... +
  +
+ + + + + + + + + + + +
Top left +
(two lines expression) +

paragraph done

Top right
Bottom leftBottom right
+ +

Subsampling is shown there: +
  + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
ab
cd
+
2
3 dflkj lkjfl dkjldkfjl flk jflkf lkjflkj ljlf ajlfj alff h khg hgj +gjg jg gjhfg fg gjh gjf jgf jgj f gjfgj kfajg 4 +
gh +
gfh +
gh +
hg +
5
+ +

This is "default" table - with no sizes givev: +
  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Hellolkfdsjlk fj dlfj lkfj lkjflk jlfk lk fjlk elwkf lkejflek f jlekjflkj +ljlk lk jlkf lefjl j flkj ljl lf lfj lfjl lj lwe lekf;eh kfejh lkh kjh +kjhkj hkj hkj lkh kjh kjlh kjshortebn formo lr lkdjsf lkjlf poer oi pjr po kpk 
abcd
123
AB
+ + + + + + + diff --git a/samples/html/test/test.cpp b/samples/html/test/test.cpp new file mode 100644 index 0000000000..fa61e56489 --- /dev/null +++ b/samples/html/test/test.cpp @@ -0,0 +1,203 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: test.cpp +// Purpose: wxHtml testing example +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ + #pragma implementation "test.cpp" + #pragma interface "test.cpp" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all "standard" wxWindows headers +#ifndef WX_PRECOMP + #include +#endif + +#include +#include + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +// Define a new application type, each program should derive a class from wxApp + class MyApp : public wxApp + { + public: + // override base class virtuals + // ---------------------------- + + // this one is called on application startup and is a good place for the app + // initialization (doing it here and not in the ctor allows to have an error + // return: if OnInit() returns false, the application terminates) + virtual bool OnInit(); + }; + +// Define a new frame type: this is going to be our main frame + class MyFrame : public wxFrame + { + public: + // ctor(s) + MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); + + // event handlers (these functions should _not_ be virtual) + void OnQuit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + void OnBack(wxCommandEvent& event); + void OnForward(wxCommandEvent& event); + + private: + // any class wishing to process wxWindows events must use this macro + DECLARE_EVENT_TABLE() + }; + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// IDs for the controls and the menu commands + enum + { + // menu items + Minimal_Quit = 1, + Minimal_About, + Minimal_Back, + Minimal_Forward, + + // controls start here (the numbers are, of course, arbitrary) + Minimal_Text = 1000, + }; + +// ---------------------------------------------------------------------------- +// event tables and other macros for wxWindows +// ---------------------------------------------------------------------------- + +// the event tables connect the wxWindows events with the functions (event +// handlers) which process them. It can be also done at run-time, but for the +// simple menu events like this the static method is much simpler. + BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(Minimal_Quit, MyFrame::OnQuit) + EVT_MENU(Minimal_About, MyFrame::OnAbout) + EVT_MENU(Minimal_Back, MyFrame::OnBack) + EVT_MENU(Minimal_Forward, MyFrame::OnForward) + END_EVENT_TABLE() + + // Create a new application object: this macro will allow wxWindows to create + // the application object during program execution (it's better than using a + // static object for many reasons) and also declares the accessor function + // wxGetApp() which will return the reference of the right type (i.e. MyApp and + // not wxApp) + IMPLEMENT_APP(MyApp) + + // ============================================================================ + // implementation + // ============================================================================ + + // ---------------------------------------------------------------------------- + // the application class + // ---------------------------------------------------------------------------- + // `Main program' equivalent: the program execution "starts" here + bool MyApp::OnInit() + { + wxLogDebug("[starting testing app]"); + #if wxUSE_LIBPNG + wxImage::AddHandler(new wxPNGHandler); + #endif + #if wxUSE_LIBJPEG + wxImage::AddHandler(new wxJPEGHandler); + #endif + // Create the main application window + MyFrame *frame = new MyFrame("wxHtmlWindow testing application", + wxPoint(50, 50), wxSize(640, 480)); + + // Show it and tell the application that it's our main window + // @@@ what does it do exactly, in fact? is it necessary here? + frame->Show(TRUE); + SetTopWindow(frame); + + + // success: wxApp::OnRun() will be called which will enter the main message + // loop and the application will run. If we returned FALSE here, the + // application would exit immediately. + return TRUE; + } + +// ---------------------------------------------------------------------------- +// main frame +// ---------------------------------------------------------------------------- + +wxHtmlWindow *html; + +// frame constructor + MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) + : wxFrame((wxFrame *)NULL, -1, title, pos, size) + { + // create a menu bar + wxMenu *menuFile = new wxMenu; + wxMenu *menuNav = new wxMenu; + + menuFile->Append(Minimal_About, "&Load wxWindows manual page"); + menuFile->AppendSeparator(); + menuFile->Append(Minimal_Quit, "E&xit"); + menuNav->Append(Minimal_Back, "Go &BACK"); + menuNav->Append(Minimal_Forward, "Go &FORWARD"); + + // now append the freshly created menu to the menu bar... + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append(menuFile, "&File"); + menuBar->Append(menuNav, "&Navigate"); + + // ... and attach this menu bar to the frame + SetMenuBar(menuBar); + + CreateStatusBar(1); + + { + wxConfig *cfg = new wxConfig("wxHtmlTest"); + html = new wxHtmlWindow(this); + html -> SetRelatedFrame(this, "HTML : %s"); + html -> SetRelatedStatusBar(0); + html -> ReadCustomization(cfg); + delete cfg; + html -> LoadPage("test.htm"); + } + } + + +// event handlers + + void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) + { + // TRUE is to force the frame to close + wxLogDebug("about to save config..."); + wxConfig *cfg = new wxConfig("wxHtmlTest"); + html -> WriteCustomization(cfg); + delete cfg; + Close(TRUE); + } + + void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) + { + html -> LoadPage("fft.html"); + } + + + + void MyFrame::OnBack(wxCommandEvent& WXUNUSED(event)) + { + if (!html -> HistoryBack()) wxMessageBox("You reached prehistory era!"); + } + + + void MyFrame::OnForward(wxCommandEvent& WXUNUSED(event)) + { + if (!html -> HistoryForward()) wxMessageBox("No more items in history!"); + } diff --git a/samples/html/test/test.htm b/samples/html/test/test.htm new file mode 100644 index 0000000000..dc7ead5694 --- /dev/null +++ b/samples/html/test/test.htm @@ -0,0 +1,266 @@ + + + + + + + + +click here to go to tables test page! + +

+This is - - default text, now switching to +

+

center, now still ctr, now exiting

+exited!.[link to down] +

Hello, this *is* default charset (helvetica, probably) and it is displayed +with one  COLOR CHANGE. Of course we +can have as many color changes as we can, what about this MADNESS? +

There was a space above. +
+


This was a line. (BTW we are in fixed font +/ typewriter font right now :-) +
This is in BOLD face. This is ITALIC. This is E +V E R Y T H I N G. +
  +


+

+

Right now, centered REALLY Big Text, +how do you like (space) it?

+ +
RIGHT: text-2, text-1, +text+0, +text+1, +text+2, +text+3, +text+4 +
we are right now
+ +
we are center now
+we are left now. +

Blue italic text is displayed there.... +

+ +
This is heading one.

+this is normal +
+

+This is CENTERED heading one

+Yes, hmmmmmmmmm........, right now, we should +display some tiny nice image, he? +
Testing image imageand this is text...... +

Testing image imageand +this is text...... +
Testing image image (try clicking on the image :-) and +this is text...... +
  +
  +

    +
  • +item 1
  • + +
  • +item 2
  • + +
      +
    • +nested item
    • + +
    • +nested item 2
    • +
    + +
  • +item 3
  • +
+ +
    +
  1. +item one
  2. + +
  3. +item two
  4. + +
      +
    1. +nsted item
    2. +
    + +
  5. +last numbered item
  6. +
+ +

+Heading 1

+Italic text now... +

+Heading 2

+and now? +

+Heading 3

+ +

+Heading 4

+ +
+Heading 5
+ +
+Heading 6
+And this is normal text, once again :-) +
  +
  +
  +
  +
  +
  +

And yes, we're in HTML DOCUMENT, so +what about some nice hypertext link?? +

hello? +
  +


+

+

This is centered paragraph

+ +

This is new par? +

We switched to BOLD +

This is new paragraph Bold is off now. +

new par +

  ----------- +

Hello +

    this is standalone :-) +
  1. +This is item number one. iti lkdjfdl kjd lk jlkjdl kjlk jlf +jflkj d lfkjlkf jl jflkj flkwe lkhelf ;fk;fl kw;lfke ;ffj lkjflk wj lfjl +fkw ;k;ekf;lkfe ;kf;lk; ;j ;lrj;wfj;f ;eljfw; lfj;ewlfj dagdja gdj chga +kjegiquw iuqdb qiud iquwd hurray googoo.
  2. + +
  3. +two two two two two two twotwo TWO two two two two two two +twotwo TWO two two two two two two twotwo TWO two two two two two two twotwo +TWO two two two two two two twotwo TWO two two two two two two twotwo TWO +two two two two two two twotwo TWO
  4. + +
    (blockquote)two two two two two two twotwo +TWO two two two two two two twotwo TWO two two two two two two twotwo TWO +
    two two two two two two twotwo TWO two two two
    +two two two twotwo TWO two two two two two two twotwo TWO +two two two two two two twotwo TWO
    +two two two two two two twotwo TWO two two two two two two +twotwo TWO +
  5. +This is item nyumber 3.
  6. + +
  7. +This is item number one. iti lkdjfdl kjd lk jlkjdl kjlk jlf +jflkj d lfkjlkf jl jflkj flkwe lkhelf ;fk;fl kw;lfke ;ffj lkjflk wj lfjl +fkw ;k;ekf;lkfe ;kf;lk; ;j ;lrj;wfj;f ;eljfw; lfj;ewlfj dagdja gdj chga +kjegiquw iuqdb qiud iquwd hurray googoo.
  8. + +
  9. +two two two two two two twotwo TWO two two two two two two +twotwo TWO two two two two two two twotwo TWO two two two two two two twotwo +TWO two two two two two two twotwo TWO two two two two two two twotwo TWO +two two two two two two twotwo TWO two two two two two two twotwo TWO two +two two two two two twotwo TWO two two two two two two twotwo TWO two two +two two two two twotwo TWO two two two two two two twotwo TWO two two two +two two two twotwo TWO two two two two two two twotwo TWO two two two two +two two twotwo TWO two two two two two two twotwo TWO
  10. + +
  11. +This is item nyumber 3.
  12. + +
  13. +This is item number one. iti lkdjfdl kjd lk jlkjdl kjlk jlf +jflkj d lfkjlkf jl jflkj flkwe lkhelf ;fk;fl kw;lfke ;ffj lkjflk wj lfjl +fkw ;k;ekf;lkfe ;kf;lk; ;j ;lrj;wfj;f ;eljfw; lfj;ewlfj dagdja gdj chga +kjegiquw iuqdb qiud iquwd hurray googoo.
  14. + +
  15. +two two two two two two twotwo TWO two two two two two two +twotwo TWO two two two two two two twotwo TWO two two two two two two twotwo +TWO two two two two two two twotwo TWO two two two two two two twotwo TWO +two two two two two two twotwo TWO two two two two two two twotwo TWO two +two two two two two twotwo TWO two two two two two two twotwo TWO two two +two two two two twotwo TWO two two two two two two twotwo TWO two two two +two two two twotwo TWO two two two two two two twotwo TWO two two two two +two two twotwo TWO two two two two two two twotwo TWO
  16. + +
  17. +This is item nyumber 3.
  18. + +
  19. +This is item number one. iti lkdjfdl kjd lk jlkjdl kjlk jlf +jflkj d lfkjlkf jl jflkj flkwe lkhelf ;fk;fl kw;lfke ;ffj lkjflk wj lfjl +fkw ;k;ekf;lkfe ;kf;lk; ;j ;lrj;wfj;f ;eljfw; lfj;ewlfj dagdja gdj chga +kjegiquw iuqdb qiud iquwd hurray googoo.
  20. + +
  21. +two two two two two two twotwo TWO two two two two two two +twotwo TWO two two two two two two twotwo TWO two two two two two two twotwo +TWO two two two two two two twotwo TWO two two two two two two twotwo TWO +two two two two two two twotwo TWO two two two two two two twotwo TWO two +two two two two two twotwo TWO two two two two two two twotwo TWO two two +two two two two twotwo TWO two two two two two two twotwo TWO two two two +two two two twotwo TWO two two two two two two twotwo TWO two two two two +two two twotwo TWO two two two two two two twotwo TWO
  22. + +
  23. +This is item nyumber 3.
  24. + +
  25. +This is item number one. iti lkdjfdl kjd lk jlkjdl kjlk jlf +jflkj d lfkjlkf jl jflkj flkwe lkhelf ;fk;fl kw;lfke ;ffj lkjflk wj lfjl +fkw ;k;ekf;lkfe ;kf;lk; ;j ;lrj;wfj;f ;eljfw; lfj;ewlfj dagdja gdj chga +kjegiquw iuqdb qiud iquwd hurray googoo.
  26. + +
  27. +two two two two two two twotwo TWO two two two two two two +twotwo TWO two two two two two two twotwo TWO two two two two two two twotwo +TWO two two two two two two twotwo TWO two two two two two two twotwo TWO +two two two two two two twotwo TWO two two two two two two twotwo TWO
  28. + +


    two two two two two two twotwo TWO two two two two +two two twotwo TWO two two two two two two twotwo TWO two two two two two +two twotwo TWO +

    two two two two two two twotwo TWO two two two two two +two twotwo TWO two two two two two two twotwo TWO two two two two two two +twotwo TWO +

  29. +This is item nyumber 3.
  30. +
+Now, you will see some PRE text:

+

// This is sample C++ code:
+
+void main(int argc, char *argv[])
+{
+    printf("Go away, man!\n");
+    i = 666;
+    printf("\n\n\nCRASH\n  DOWN NOW. . .  \n");
+}
+ +

WWW

+This is WWW link to KDE site! +
+ + + + + + +(one folder up) +
+ +... +
+... +
+Link to normal text file : test.cpp +
+And link to BINARY : Unix or Windows +
+ANOTHER LINK(www.tue.nl) + + + + diff --git a/samples/html/test/test.rc b/samples/html/test/test.rc new file mode 100644 index 0000000000..82bdf07561 --- /dev/null +++ b/samples/html/test/test.rc @@ -0,0 +1,2 @@ +#include "wx/msw/wx.rc" + diff --git a/samples/html/virtual/Makefile.am b/samples/html/virtual/Makefile.am new file mode 100644 index 0000000000..e5fe674b3e --- /dev/null +++ b/samples/html/virtual/Makefile.am @@ -0,0 +1,9 @@ +AUTOMAKE_OPTIONS = 1.3 no-dependencies + +SUFFIXES = .cpp + +DEFS = @DEFS@ $(TOOLKIT_DEF) $(WXDEBUG_DEFINE) + +noinst_PROGRAMS = virtual + +virtual_SOURCES = virtual.cpp diff --git a/samples/html/virtual/start.htm b/samples/html/virtual/start.htm new file mode 100644 index 0000000000..1dc3cdd353 --- /dev/null +++ b/samples/html/virtual/start.htm @@ -0,0 +1,12 @@ + +VFS Demo + +

Virtual File Systems demonstration

+ +Hello. This sample demonstrates VFS. Try the link (and have a look +at status bar before clicking on them) +

+Enter top level Node... + + + diff --git a/samples/html/virtual/virtual.cpp b/samples/html/virtual/virtual.cpp new file mode 100644 index 0000000000..99e848ee55 --- /dev/null +++ b/samples/html/virtual/virtual.cpp @@ -0,0 +1,231 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: virtua;.cpp +// Purpose: wxHtml testing example +// demonstrates virtual file systems feature +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ + #pragma implementation "test.cpp" + #pragma interface "test.cpp" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all "standard" wxWindows headers +#ifndef WX_PRECOMP + #include +#endif + + +#include + + +// new handler class: + +#include +#include + + + +class MyVFS : public wxFileSystemHandler +{ +public: + MyVFS() : wxFileSystemHandler() {} + + wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location); + bool CanOpen(const wxString& location); +}; + + +bool MyVFS::CanOpen(const wxString& location) +{ + return (GetProtocol(location) == "myVFS"); +} + + + +wxFSFile* MyVFS::OpenFile(wxFileSystem& fs, const wxString& location) +{ + wxFSFile *f; + wxInputStream *str; + char *buf = (char*)malloc(1024); + + sprintf(buf, "

You're in Node %s

" + "Where do you want to go?

" + "sub-1
" + "sub-2
" + "sub-3
" + "
", + location.GetData(), location.GetData(), location.GetData(), location.GetData()); + str = new wxMemoryInputStream(buf, strlen(buf)); + f = new wxFSFile(str, location, "text/html", wxEmptyString); + return f; +} + + + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +// Define a new application type, each program should derive a class from wxApp + class MyApp : public wxApp + { + public: + // override base class virtuals + // ---------------------------- + + // this one is called on application startup and is a good place for the app + // initialization (doing it here and not in the ctor allows to have an error + // return: if OnInit() returns false, the application terminates) + virtual bool OnInit(); + }; + +// Define a new frame type: this is going to be our main frame + class MyFrame : public wxFrame + { + public: + // ctor(s) + MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); + + // event handlers (these functions should _not_ be virtual) + void OnQuit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + void OnBack(wxCommandEvent& event); + void OnForward(wxCommandEvent& event); + + private: + // any class wishing to process wxWindows events must use this macro + DECLARE_EVENT_TABLE() + }; + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// IDs for the controls and the menu commands + enum + { + // menu items + Minimal_Quit = 1, + Minimal_About, + Minimal_Back, + Minimal_Forward, + + // controls start here (the numbers are, of course, arbitrary) + Minimal_Text = 1000, + }; + +// ---------------------------------------------------------------------------- +// event tables and other macros for wxWindows +// ---------------------------------------------------------------------------- + +// the event tables connect the wxWindows events with the functions (event +// handlers) which process them. It can be also done at run-time, but for the +// simple menu events like this the static method is much simpler. + BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(Minimal_Quit, MyFrame::OnQuit) + EVT_MENU(Minimal_About, MyFrame::OnAbout) + EVT_MENU(Minimal_Back, MyFrame::OnBack) + EVT_MENU(Minimal_Forward, MyFrame::OnForward) + END_EVENT_TABLE() + + // Create a new application object: this macro will allow wxWindows to create + // the application object during program execution (it's better than using a + // static object for many reasons) and also declares the accessor function + // wxGetApp() which will return the reference of the right type (i.e. MyApp and + // not wxApp) + IMPLEMENT_APP(MyApp) + + // ============================================================================ + // implementation + // ============================================================================ + + // ---------------------------------------------------------------------------- + // the application class + // ---------------------------------------------------------------------------- + + // `Main program' equivalent: the program execution "starts" here + bool MyApp::OnInit() + { + // Create the main application window + MyFrame *frame = new MyFrame("wxHtmlWindow testing application", + wxPoint(50, 50), wxSize(640, 480)); + + // Show it and tell the application that it's our main window + // @@@ what does it do exactly, in fact? is it necessary here? + frame->Show(TRUE); + SetTopWindow(frame); + wxFileSystem::AddHandler(new MyVFS); + + // success: wxApp::OnRun() will be called which will enter the main message + // loop and the application will run. If we returned FALSE here, the + // application would exit immediately. + return TRUE; + } + +// ---------------------------------------------------------------------------- +// main frame +// ---------------------------------------------------------------------------- + +wxHtmlWindow *html; + +// frame constructor + MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) + : wxFrame((wxFrame *)NULL, -1, title, pos, size) + { + // create a menu bar + wxMenu *menuFile = new wxMenu; + wxMenu *menuNav = new wxMenu; + + menuFile->Append(Minimal_Quit, "E&xit"); + menuNav->Append(Minimal_Back, "Go &BACK"); + menuNav->Append(Minimal_Forward, "Go &FORWARD"); + + // now append the freshly created menu to the menu bar... + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append(menuFile, "&File"); + menuBar->Append(menuNav, "&Navigate"); + + // ... and attach this menu bar to the frame + SetMenuBar(menuBar); + + CreateStatusBar(1); + + html = new wxHtmlWindow(this); + html -> SetRelatedFrame(this, "VFS Demo: '%s'"); + html -> SetRelatedStatusBar(1); + html -> LoadPage("start.htm"); + } + + +// event handlers + + void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) + { + // TRUE is to force the frame to close + Close(TRUE); + } + + void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) + { + } + + + + void MyFrame::OnBack(wxCommandEvent& WXUNUSED(event)) + { + if (!html -> HistoryBack()) wxMessageBox("You reached prehistory era!"); + } + + + void MyFrame::OnForward(wxCommandEvent& WXUNUSED(event)) + { + if (!html -> HistoryForward()) wxMessageBox("No more items in history!"); + } diff --git a/samples/html/virtual/virtual.rc b/samples/html/virtual/virtual.rc new file mode 100644 index 0000000000..82bdf07561 --- /dev/null +++ b/samples/html/virtual/virtual.rc @@ -0,0 +1,2 @@ +#include "wx/msw/wx.rc" + diff --git a/samples/html/widget/Makefile.am b/samples/html/widget/Makefile.am new file mode 100644 index 0000000000..5e03a4a779 --- /dev/null +++ b/samples/html/widget/Makefile.am @@ -0,0 +1,9 @@ +AUTOMAKE_OPTIONS = 1.3 no-dependencies + +SUFFIXES = .cpp + +DEFS = @DEFS@ $(TOOLKIT_DEF) $(WXDEBUG_DEFINE) + +noinst_PROGRAMS = widget + +widget_SOURCES = widget.cpp diff --git a/samples/html/widget/start.htm b/samples/html/widget/start.htm new file mode 100644 index 0000000000..23c528d04e --- /dev/null +++ b/samples/html/widget/start.htm @@ -0,0 +1,20 @@ + +Binder demo + +

wxHtmlBinderCell demonstration

+ +There is binded window somewhere around. Enjoy it. + +
+
+ +
+
+ + +
+ + + + + diff --git a/samples/html/widget/widget.cpp b/samples/html/widget/widget.cpp new file mode 100644 index 0000000000..74fa22ff81 --- /dev/null +++ b/samples/html/widget/widget.cpp @@ -0,0 +1,244 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: virtua;.cpp +// Purpose: wxHtml testing example +// demonstrates virtual file systems feature +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ + #pragma implementation "test.cpp" + #pragma interface "test.cpp" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all "standard" wxWindows headers +#ifndef WX_PRECOMP + #include +#endif + + +#include + + + + +/* + + +TAG HANDER FOR 'MYBIND' TAG + + +*/ + +#include + + +TAG_HANDLER_BEGIN(MYBIND, "MYBIND") + + TAG_HANDLER_PROC(tag) + { + wxWindow *wnd; + int ax, ay; + int fl = 0; + + tag.ScanParam("X", "%i", &ax); + tag.ScanParam("Y", "%i", &ay); + if (tag.HasParam("FLOAT")) fl = ax; + + wnd = new wxTextCtrl( m_WParser -> GetWindow(), -1, tag.GetParam("NAME"), + wxPoint(0,0), wxSize(ax, ay), wxTE_MULTILINE ); + wnd -> Show(TRUE); + + m_WParser -> OpenContainer() -> InsertCell(new wxHtmlWidgetCell(wnd, fl)); + + return FALSE; + } + +TAG_HANDLER_END(MYBIND) + + + +TAGS_MODULE_BEGIN(MyBind) + + TAGS_MODULE_ADD(MYBIND) + +TAGS_MODULE_END(MyBind) + + + + + + + + + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +// Define a new application type, each program should derive a class from wxApp + class MyApp : public wxApp + { + public: + // override base class virtuals + // ---------------------------- + + // this one is called on application startup and is a good place for the app + // initialization (doing it here and not in the ctor allows to have an error + // return: if OnInit() returns false, the application terminates) + virtual bool OnInit(); + }; + +// Define a new frame type: this is going to be our main frame + class MyFrame : public wxFrame + { + public: + // ctor(s) + MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); + + // event handlers (these functions should _not_ be virtual) + void OnQuit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + void OnBack(wxCommandEvent& event); + void OnForward(wxCommandEvent& event); + + private: + // any class wishing to process wxWindows events must use this macro + DECLARE_EVENT_TABLE() + }; + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// IDs for the controls and the menu commands + enum + { + // menu items + Minimal_Quit = 1, + Minimal_About, + Minimal_Back, + Minimal_Forward, + + // controls start here (the numbers are, of course, arbitrary) + Minimal_Text = 1000, + }; + +// ---------------------------------------------------------------------------- +// event tables and other macros for wxWindows +// ---------------------------------------------------------------------------- + +// the event tables connect the wxWindows events with the functions (event +// handlers) which process them. It can be also done at run-time, but for the +// simple menu events like this the static method is much simpler. + BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(Minimal_Quit, MyFrame::OnQuit) + EVT_MENU(Minimal_About, MyFrame::OnAbout) + EVT_MENU(Minimal_Back, MyFrame::OnBack) + EVT_MENU(Minimal_Forward, MyFrame::OnForward) + END_EVENT_TABLE() + + // Create a new application object: this macro will allow wxWindows to create + // the application object during program execution (it's better than using a + // static object for many reasons) and also declares the accessor function + // wxGetApp() which will return the reference of the right type (i.e. MyApp and + // not wxApp) + IMPLEMENT_APP(MyApp) + + // ============================================================================ + // implementation + // ============================================================================ + + // ---------------------------------------------------------------------------- + // the application class + // ---------------------------------------------------------------------------- + + // `Main program' equivalent: the program execution "starts" here + bool MyApp::OnInit() + { + // Create the main application window + MyFrame *frame = new MyFrame("wxHtmlWindow testing application", + wxPoint(50, 50), wxSize(640, 480)); + + // Show it and tell the application that it's our main window + // @@@ what does it do exactly, in fact? is it necessary here? + frame->Show(TRUE); + SetTopWindow(frame); + + // success: wxApp::OnRun() will be called which will enter the main message + // loop and the application will run. If we returned FALSE here, the + // application would exit immediately. + return TRUE; + } + +// ---------------------------------------------------------------------------- +// main frame +// ---------------------------------------------------------------------------- + +wxHtmlWindow *html; + +// frame constructor + MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) + : wxFrame((wxFrame *)NULL, -1, title, pos, size) + { + // create a menu bar + wxMenu *menuFile = new wxMenu; + wxMenu *menuNav = new wxMenu; + + menuFile->Append(Minimal_Quit, "E&xit"); + menuNav->Append(Minimal_Back, "Go &BACK"); + menuNav->Append(Minimal_Forward, "Go &FORWARD"); + + // now append the freshly created menu to the menu bar... + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append(menuFile, "&File"); + menuBar->Append(menuNav, "&Navigate"); + + // ... and attach this menu bar to the frame + SetMenuBar(menuBar); + + CreateStatusBar(1); + + html = new wxHtmlWindow(this); + html -> SetRelatedFrame(this, "VFS Demo: '%s'"); + html -> SetRelatedStatusBar(1); + html -> LoadPage("start.htm"); + } + + +// event handlers + + void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) + { + // TRUE is to force the frame to close + Close(TRUE); + } + + void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) + { + } + + + + void MyFrame::OnBack(wxCommandEvent& WXUNUSED(event)) + { + if (!html -> HistoryBack()) wxMessageBox("You reached prehistory era!"); + } + + + void MyFrame::OnForward(wxCommandEvent& WXUNUSED(event)) + { + if (!html -> HistoryForward()) wxMessageBox("No more items in history!"); + } + + + + + + diff --git a/samples/html/widget/widget.rc b/samples/html/widget/widget.rc new file mode 100644 index 0000000000..82bdf07561 --- /dev/null +++ b/samples/html/widget/widget.rc @@ -0,0 +1,2 @@ +#include "wx/msw/wx.rc" + diff --git a/samples/html/zip/Makefile.am b/samples/html/zip/Makefile.am new file mode 100644 index 0000000000..814476c5da --- /dev/null +++ b/samples/html/zip/Makefile.am @@ -0,0 +1,9 @@ +AUTOMAKE_OPTIONS = 1.3 no-dependencies + +SUFFIXES = .cpp + +DEFS = @DEFS@ $(TOOLKIT_DEF) $(WXDEBUG_DEFINE) + +noinst_PROGRAMS = zip + +zip_SOURCES = zip.cpp diff --git a/samples/html/zip/pages.zip b/samples/html/zip/pages.zip new file mode 100644 index 0000000000000000000000000000000000000000..f70ded12b5c613fae7f7d649f2f4ef9f67a93e6a GIT binary patch literal 62123 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%0DMyXSd;H2zsuZeA;PHVgN4mSzOGn0 zEno*zFAHmsNckw+5-E97N;FGIv(zAD_6qsH@pk3`Z&)F(hc|{?E{5K(%wlS<`UvNl zJ|M)%fM?^fvaqnYkW&0Wv-sDX7G{9$pfnHIMwLW>EwLa3*eE3sfDJf6V9UT~V+FSV zdj5ZO_}}mGzjnA#d;jHkotd0)nk)eTHYqWA(Q09Xfd30nO9KQH000080B?D8Cg%Q7 zOP@mk0A*nT00;mO0A^-%E@*UZY*knc04#b-hBZIS2Y-7< z|2%+#1ONQs?D+MA)$NK}K7cj{Z(bc9pAV0(sQl#W_}%LV)1p|sc>H*^TJ5iH_tWh9 zG5qh}@#1gr?+f^ITFn0zB;#qCJ$Q4NCPkDKIrikM9#*%{o>8^&EXeaLnml;(VNt5` z-A_~prW4#m58nKJR=mW2OZC2gD(lg-!!gvohPv0X?qjipS0}Ix@72jOV{_n#_v-SE zC%^b{?ibU@9|d{j)AamFn)$(O=5zP?zV9C-Yi~S_XJHm4embEBTnhh#nxn`Mqghl$ zp&u-ZbRHD(7q5F#*P;9rVvG zPme#py|_9$zQQScuO1JNsI6W5D9#r%oI(IIixYp8W?=*~$kJsJ8ql%tuWq?F38?8T z^pjv7c{pQeoAV~@^GGnxo8dIhLVujjmhaQ^f0`DVlB%j8QWcdY9`R|oyU@zG`jWkH<7McZtk!SG<%Kiq5} zarpT%E&|+9hQ+)cYqv<3t%P9u-*I?m(c;PC3=wA&15uZ(#F zK1_jLEk7T_R?J30XOKU+)3`u3#Q%o<-)7{))Bfe>!;}8$5y1O~-_8|D7VHbX~ zE5|UvFddAuC`uZKNu5o=4^0iy1hENYF&z6gn&nmpT;Yf+4AV=h(B2_;RHWQ-MTgwc zFy)RLIwXQTU7KAT@u<d;X-N`k}xAO=D%jbub=Bi-Krls}m?XprUt7HrIB-=+bO^ zOkWzBOyIwhbiA}id{~fu_sbByFEghr@ z031Ftx!Z#-Y3?G7Cc$!6#6>iBx;WyJK9sa{k)?|w$lx!x2Pha)L30QCeTm$|rZ>jr zPAfZ^0J-2aeg~i08f8%fsJ&Cgt)TX;)AT)%&EX}H%?+)-b6W9Ao97&dPNRO+n$>Mjj zpy}a{lej384}JLBN;AYcKf>0X?C1OrH_?)D4uA>x*=>0xzBV?^r|BxO+YRtjL!()+ zPM6m0Ii)X6P0}DlfnpZrfcwVQp`Jq7J1DynWsTjeY_xug9~v5<0B)X!!OU!Q1|QGx zV^hQQ#+u|A{BEe8Cc(IfZveK;Mi*G z4Ngn`*xb-1)1g@lp)MMgi9OM@mEKDeqzFoM?L~t0KpRb)CQ%mTk){FdE{?HKQ-F;f zeTmkgb5AakpQH6r^G%_K%SEXfD<|q3#j{z7vWAB6xsA3?lQ^6?r_^tz1E5JI(t?Iv z&{mqvqhwhLRcBDp1+uV%DUi}LB&W+=oXDc)PLO3L^3Ul3zZ31(()=cJ8@60|63N(Y zF7Z=iBYuGGR{ZofH$wum1Q7$IE876VeXpTeGdBQD);SZgfMQKFR6LwpaL}sX;V>hi+;$;ZKc? zW)UEyl0@i=zqd(*P?mHPk z_(mB997Is0S>XyJ0MHL~@vucQft@Xjv`nX9H&D<@uH?;^C(se*c3MP5n3iLP(nWZ+d3^ z{*fVN2S&L%C&WT)+q0^HAW-}8mi8Ep@ewVxK#h?UVoIW7%S8ufjb0rpi?sQh3T)nUB)a7zDr0;b4nM;w+K z<}p^n|9GN3pOtFMN9o5QG>RuNTA=hN{-dWowpOt1uz*TJRWB^ws9zppfyk^p#zGwU zei;VPh+q!~ef0F9*kWjd)&^0|CKM9raxb5zOW5=42>D)|jV~nfY5<>YdbIHmtZ12| z#+5!wlQlL|3u6?L&elCYU!v`khelB2Vj0Zzgv(3J1q8Zl#P9nypzdaEbOoGsRZI)P zzj9t=+~mWX&Yj0&Y5O6~Jr+cN`@meC-us~v z@BOC{@%^U?^C^VqACXC5PDX9{awJ|jVS*5fLbf0TXn|`V1$3(kYRLKp#^8E1BJg`e zqWjS;8pXr}KR|8!;sBF0o8yh~fSYOB&SnLwpQkQ>AmZV9D4aw_HUL<#k{C^m{5+VD zZAO?v2R#5bAB81;5#tHm)xP0-!=8dB0{253IEcfR1(t{#^e4EBxD&8Wfo~!3ZqBVbr zwm2~wZq8;^MzaDy2yMf0c#~x^#y@g|ECs3sK4n?-uO(nYWw>Kld-;njy@m&A9%b7< zTWUE9F&r9ep{FYhTM$IGRY}Du*ybfICt+7s*n^%0#uzjZ+@r;^z=;}`bNl`wR%n38 zuJR7(*b{ZxRF7wM=L@^#beeWw80A#$yRgnNcih}*QOpoeB19%I`3)AdAj7+#uYqb> z&*{x;Sdg^$(N;eDEpyLmU`BM%1}&mm{Thg%Jh`~){}avxEg2;_NiB2h0pIpESsSKq z)L;>fktX9Y^n@hYz$XVU+P;4ltnt>r8V=vslZ6jG@%iKN)v$jkK6-cz^!e?@@Ps~< zUjMq4Tt)LB`%-0sE(onrG!1UzbeX}+v51lo4M&B=KU?X`+xCu3dWq6T3R}?Hqx81t z(a|D}2bU9|95B~S#J3f;dz#L0L&#KE_Od{l-$yf!o^Lev+{RRI*Y~i|vaJDr*;K6x zeA#BL?&fi+L~iucgha&p6QK8L3y^szrVKI5jJOHIjFV+WKvJauXYhD82`l^kkC6RV!LVoN-9jJeTWY3Z23&ie8ww0|i6Ch5%0%j3bsVAR_`e3<+wqGJrL} z+b~VpiKXYuzPxx2jNDvV{A(W{uAaZ(>nGRP?u}zZ`5qnE!zLqfw#3ZwD0~*WlKg}( zL??@Md&pmY-MafOQV;8+m~2zQHR1~3;XM-3$DeRg>OYWxP>F9KrpGJge6IaCv@ z4<5DR3{fRw^00ly!}c`~yFC>`)3>e+EyRya*S>FH^0*7WP|rxd1I1?}b|Scm#8WFB z{E%0%T~vDh@ahBg49^oV!Ej~nNPf`K(7y6bX=4qoMG(bqOJjQCVCVpV^Ia@bfQKY5 z)=ovF^vBZ_djqDO*Km?Hf;{@fY2J<$%Pl6w;LvPbnVF);*79V9g6< z6Hhi>(!8*=?PRkhk|{_*C~`)Hn3Y#vgYoz4njfA_}5DSczA~*u2t!xN|TGim;MMC z!np9njU+S|kn?07&zCb6;K76uEASx_Dz`<+bG*J8{ZFvs3WXCl?im-`lxYs>zOZmm zwP1c7Mv*(=2vF2Iy(Ah(c^+i(Y%K*!%rs!D9zHkYNcpVgIKbLi6&(L<|LF7K!TI6w zsi5;{Ii7ICC7INeHbr;K5S?za$34b;+l$a*7UumW_`0*;tHmv)>W!@SPchz1m!ht2 z(2=lKeX@FJgD#cAN%olk+tdOvbsjLWikFpz@ko~o4ixb`KhD%YLEAe;T!%5-%^bj@ zXIuu+CdeXxj_w4A;k5J(h6FU{qX8uF$oR^mKZO^tS91b=AjYBk-&&)scQV?PTs|s? z`?2{dRX?^z?j*=Za6)(w_7whQx`ihTBm&mYeF!#(LGyeJ+D#oZ%x>#qdb zJ*WhPD|IEecgI4B?ft|41bmLU=Y(VQ#(xc-#~dE96waHVNL-6rkGP3 zN<@%iC4s9_6f#2NB&PvPI3^((%{5<+ajui)ObI^19=$*o@} zC+C3`*}%S{IctD({yUn*qj)Bzt!Rf&G1Mf`?HRsw54V?i>xn2#-k*?Yy64DXVLsQf zj6&s3hb$6FR&F-)bX+wWrrhjq5^rHcX2?W$_f~iGV62BP8JVL3tYnCe7HE>y>VPN` ze?Jyw4i`CR4$M>L_Fp!Z$zHIsmJ{mG9@INnEGa z)H8N8^0I&twAJ@Vm@&=501dXQ6MB83F1gY`uakNjxsRjSd4~3dUEAvSk#wsw0`Jc2 za381DMEmqKoLnwQ7Zlfm)d6+4A28Rbgo|4lU~p+_unpoD*}`sQ-ol@Q$6z6^?3T-T=wD4a4Qm-7j$$tQ>i1!8$54hLrJ#Rp%?e@&p z%dgg_z3S^Hu0(z`mp^eJO)AZZ@zsFivx;a!j^dyRl{tUc&Lzx%t4w6nL8~rszM(WmA};I{h;-)288;-O!SFm<`gD zGrY*s{-Ll!Z#i3`-;$wsORc6QuK>x`oTZQzba3Z+G)yMl$0cX$5Uv8`HGSdy!@&q5 z@&2Pp3bjLXhZEtsPASCq>D0l_HBcpZxGwvcVCckUG*O#ap!vJfwx-;pryk(sapCjNB$=y97d|7*^1Zb+vxd0VDE_IF z(tU#c$0eKVigGAgr0Bp-?1K|H-ZC*5t9M{*Kb1&`@+b0rSk@HYt%Fh4t9{hk_|L+7bFpg1+DJ^EPUSs4?J=k_gKsBRQ~+@Yb#OheAw zKbkjNhHwJ`*2~{@8+B==@YP4SOB+Npe2OE?XTDO$gREz3qbfDVtxdp@1YE3=$M-YV zIeD0+R8*{SbZyVLXvZSj6^9-I{$lU9D<;xq&{JEKW6)JZop|E;f&%4@YbE;6jph(0 z%~_bui1a_S=5CJP?Y4v?QY9)q7c9j$JT&6EOdr(~H$-Vzisf?zv`^zEQbP4~4c*_| zi4Rd2mik8O_2}{k6d7*EmUJAoBjLyi95FMyZ2HywBC^tAoz@yUzUT)CTU?Z|=yOZ~UV;EeKWmGY0;;&}|yK2NZjix~-4O?ZfM& z#1UrR28I3me6LXFYUn_T%cFD5QR2zC=K^jg?Gm@?J~d*`Nus06DIP3`tS*P>GoCVt zA9q%K2+nA81@75**!>5;NSF_tL=i4Q)#MTm>L`CrQ|rT#@RguU)Sas0!&yhd&CHYL zH7VKQJXCs1{&R-_(XE|B=DiHY3fLi7z=y5_4HMCm_1x-Xti2FimWVBObP@s&EI-i( zHA5~aEeHS^=Wn}~K9?;zFlRigIr`E1NE*43CEmmnrPE#A`E)muW{Z=ssNXcZ z)i-hK4=8|*mgBgut?sd1a`Jb5d6&7Hirpu_&aqU9RNt8hki4XlMqQC6;2n^#wTY_l zI6UC$&n8t0iwXF1ouPXcUp202}w&s*da$r2c9QE)$NhXJi#J@y-p9ux#AUehyx`wnfzo0tQ?6D*30VpW{k2W z;x6b+`7{S=NRuyvUxeIKA&kD=xnk6ekB*M)F3m%qQ2aWxWA&d!hN!g00NO~(CPYe` z_{CebsovxGK1W+bJ9A#vkv9%pQI{Fomkn+=1~4}bK6E8DBg+?&+BQ@6&2i+LKz)i5 z;K{=2G<&GIf?s$~nDndKIY^y4tzrZ}o6}4= zXr-UtyNhEy5s0AI2s^Q0N+{GmwF1L|cMrwuDRpr`= z@7ScE^%0UPzt6!|jJtC~v7AzOK5bqEq6bgcO)SxC?mCjvTGqZfAv`|ffC%j~^Ge|4 zIPXHGM~gKro&nm06_%``jhT{ZrY7Bi_AQLkZ#bOGg-tGw!)wLgx_bLayi)a%*-!C7 z7#^Gam7USu3&LEjtL?%rY!mv|c~TsUO+QI5ltu_Jnmy{n*;;p~PuaDYT$}Y@yfxr; z*Jz35vr}ImeHw{Tz+o9%Vy~czbEG`WKGr+y*UoCLkh5ZuISwnUOv<^>M%Qmr zv^$sEG$gl%6;nBDgm;Jb+NWlKDJDjIU+kz0sq{b{K%m8cbM zISLa?(YtP=8xBylOBsCdK`(N>Zx1EVx^2vSye zdve#i_W3iyBO!-YHKjQI6oufJPQ^y<_f(_l+G=!ZhcH z*}AfSSCbXWk!ii1L5kZYwby>ZI$B?PC-Ja~5f9WH{;f+h$&bmQn$97vt9J?Nu~tOA zFqL*i@3Z_|xFL$&7t!TAR#3{%A!)}~dq$2QV0T_Wh+Sjj+SGV5D5o_5Gu%bmE?V%5 zT`k$*>vB*};IYBuhu!1f3EU6=Bmjp$WlLs{2QPcHOi0dj0M}%=-IF1sIE;s$Y);C? z91af3R!KA22G?HCX)R8~Z%($>xJk{`ZZ3R#!If8)Gq5*IiE-G z`)|7v5Bt)*Ci`J1U1ee2EtBGfCtjbP|Ix1b*~@zq&0y40CN8QCDO|RC3OHh@y?yX+dn+8= zV{ev9d=#Y@=ZOb__IOzTLxTun460cySf6>@6VDQt&(Sdbm7Y}f?Aly9T@f4{_8-jB zp}c(F6fU|~w(BN5f%HL+NuAp~XB)ciXLf50xqn-odtHxrmJt`!TUVL6V-Yzkbvo!Q z3io02Us-|YyA%-?`^^tOmBW}~3C(F5osOU)F-B@S0q1u0>}(yI*m2X9g;a6}Otw!Z zi52j)6pYE(%lSmwbjpf??b5wcBhY4cpOzTJ;}{yJ{g*sbyNEgIQ#Nm*aoKxIV$w#H z>va?J+!DNdo6gRsm1gM;Vy*ZF?ZWZ`sDQ}ymC30I*gW|3wY)LS2`4J)Bv`6D21o3=%#9BMO=a-P;!Gx9r1sV@-r*QV5m4^L|&5#u0b4B z;h}pc{^`2rajEEDzLJ-Nm8EjV-eY3>X#Ni9^4rRQ>g`mG94a&M@4Nf2iq)Uf>+Gxh=%m8P`(I3vF?j^}3Y!7EX0k#G-SI9NwjH zWV}}so{ol&kAfh1f?A@mQbJQ=B3RWV)MWfM8-gHS(z5xc3i<9>j9cx`gq$)4;m^IpdjHuH19~B#v5QD!n{G4nCL}>3x76_kiTqk&gl#!+6wFngtCK_@m2}6TO@~fD>(F7cyqx43*&|jejndniS30~e zg30{VJTe$B_mywHfcCc<+`U{+*lOSG7alO_xBi2X`MTk~Ry3y5FaZI_0t7oDdq6A+ z052dbnq24$zlJl=OuT|PJbDJTT?!aNjY<(V#WhA1!w-0ZqWtg}AiR8e{oV(~*!$dd z^$dS;(FY+s7ENyK+w!0T<_WxM;8UwD4MFCUJ?* zKSqjt`}-8$0yONdPh7K&IlL#vWhkm*Y`F_2xe`s&>KsB>6ln8p(2N{`F;h-w*#%&5QA}+`FuB^XJ~Y95 zg@?0~D?ZS{zrSYY{D0GVn9o}UKkwd;4GqoY5<&)kOKxI~NRxSM3?3ZO%}UkhkXDBR$Sy#%>}UF zDkgZro7tJ&!c8ItmL6mWT)9NK-op5cvp&*YrXr#esys>k%nbQ^>4)~{j!OGnRb*Ac zhKvQ@dE0M%n@#-UDuA41O;0!(CaYUgAt4`m1n8B*IMp66VkDo>F9%A91Nde#x46{%blJLyBm$&u4T z-4XhvNon)4`M~)QbH6!3L~8x9g2s<~b8Ua08>2>+R(M~7%k;X$U~I>unrK(6zEyr+ zp*HV^;G8%lr{HuvAas27RNb|8?xY&eOKTtC@p(k@8ee-)nl)f2m-d<0Hy#xzU;zt| zv!fDa9f0Q=SCtvhN4xW`-kwT_hoA*ePAJ^nF<*M+Ru|zdI*JsKULvmMVwX~fH5Lk- z(M9Go30H@;jxVk#FAjhSFu*NQ^(d&Yy*|dPBx;F}|4eDA^jrz4$5AFQw)!hD%~bgK zxF`w+%WazZ`A6;P-CmU*?v(N9Z}%^RSP%KeQv}_g7Dq3Sn~B=80=eFVcF3eVG?W6F z?g(G>wSpTqp2m(%Z`SQokCF~Uj?Wm0*48w!9zmT-`YMx?NEB z#C5De2D^w!xP%Pc0H9r(p^LH9ld-d5eegetjLrG!hEE+0IJ)SbaM#`lXi)k`x-yR> z?nwE*-b{J2LCstO>{h3E1875rz@bLk6HG3IqX`Nlna2 zadIo&nz~2rrwU%dae1%x@iCM#$X~WKJi8|4?SZgo5z@cC^@m)r(0cRpie}jE7ZQJl zr7+c`mvOj*tt0V@;>fHP%j8qM*^n2)N#Sef>|-K~SlA=Zrpzk`;Tqdyy{;4G9?6c( zF}f_`lFUT&;Mt<+XFinwB(1AJVm{f|RUXFq_E5~HwI{3rD_gnrj}I-uHZ1Vc4|1?P zPb6(#UD*sEI0v*ujhPFcacKg7qrFuSyV8v&Gk=<%zsdmX9pIwlYZ({>doO+wB6mnd z-$aaX@bpSh@0oW#vxgv-9Ac+>bf-WTJq@Q@(@+y**;bBnCgra#7vq;lHHS2XP_`?c3iPwAWz9kQfpl7jM49Wr1JFe;NbuC_i=o=f2)c{K9Mv$Fm_v`c@x>1p;zkI zl{wXv+0!Z4WOui3n!gV{PijYYuF0BX9*9(-Qx{bQyzrnsc#ii#dXHs7XQ(DcDi?t4~pACl8MV@*N1VJOAoCO|qJCM$jp&t2lZ-y`K z@V=dTwlQ{sdiHTPuY+HIntE;Issi>r;%&3-5Wiwzu=^?mrkLo6#wQ}f2nMSzqz+{T zH`I*PrxAA!bM&=jxt+o~&G5qyAA^Ez|1ggyytFQ=<+d4|F>noYU?toFNG3ne&Q3hA z!-=4-CJhG&QqPH!hKIbcX|tbr*Q}~^Y9-Y_kD>=B``+1WCGnRBU)!brsax?pl$?gM z4(vexY}OB#ZMofZaWvG$05djn8~9Wjc}ufomrEX1U5qK(9xT};Sj%d#*~TYtKE~_> zTI9)`fi7$0=RXyFKx7S6t&)hID-Iyl|FJ0SX`YKD?afVALD)jRrFfco8<>&&2wsSO zMk^pTpUB?Tg);1)r4`p{3CD@L15go_uG1NpIXf>ap%#J^Qd&q=wD@cw#CCgt8)YdI zNzAbcadVy+qh1vEd9xtJnq<49Ll;wP+*)Q(L^GjAv*AM&eq6_CtB@B%{Xu`F`q{K! zZ8y_|`aY*qw03-tV6C?9r-R*BS%RS1vF5yf!?qSLMJuhcq1v~gG@PG*r#x%i-TWGD z7uz{Du(f9UH%{qietq*(OW7>8<#N<9WIs;xVq-JW*09%Y(y7-WU|0yc5Qx0%fqj!4 zmdCM5>manv8sk4Ia=d?eDFhqJO{0u6P!%-pWCaohXI6A~QWbpvJTfQ%Wjhmzt*Y@E zYs(>f2*TixXQ*gFh3}`-0YceuYJ&Dl>q$-u$&@s~es z1@fg>f8P2U!R9|h&fbCjkjmeGzj;XEGn60Clx2T!>i$tw6)AhH*+0JSKBVX-fg;E- zxF-8m1Zecj+x^D21={bSkDVk<0f*$ts?x`!snCs%KH0M9`Nq=#dUg~}VH^fdZ18T2 zJNY1aasmV`v~XFt1>c;&q?ubw@O9}9=~;&&=J*g}w7EkmE;-8s{+Ah?SejQgi2CXU zHI!LFJaF=lP`;AuTEz>n6oR^f!td3uz%AoH-f9sr!gNJ=$i|TMP2OadYAQHNej5@I z6Cw0)#~2=T1LCaH8{CDYlT?3`Y5P7D@(SAZzok%7((AGk4!2Rc?S@`F=0$($D{ZF4 zkDLrJ3=`yFssov3R%z^WX@OKv{@(BQQsb?>JIx9kpXxAS9bD2d{}2bcN`;J+LU-sySznj z7-p{<_*=-<{R+&QNFJFcv_uWTr^PLIWrVPqgKS9jQ)HFOe%aLtM1&ZgFUr5y8bB<} z+lPQcPzJo0c6P(EtxVPSKi{odPAm#vsNcMh>JdK7gcCS6`^jT@1AP_$!H#Gp88*wR zQqvLWPC++fCIy(lRbHBky?wT~L+@$X_01KaHpC43NpeGtCT9ox%yAgO{9c*a9+fhL zQT$w62W{tvPxD+yE_nJ1{CP{nUP=`A{CCLbWgcBzQoD{vm#E}`eEYiF5kb7?>!*4K z)3*H>gpo=RHxysd5sc3iod`7Hkx^9p4p_`$YGbq<^)Xk)SIAEDIke6(Dkb?WK?0{o z4hS%JN}bAuSp8NlpUOy{R6~a%#}KBQ_O7W~3PF`o@#HWq!2T7#Po9;61svQMB=-tw zy#%0U^49o(=jZO7hYxvA59i5^O8p)rBkB7lV~bIgqrTx*_xGjVK_D0tE7I5l6xlO7 z01-?cv9B-VCLjLGSUcj~O(DdvomU*L`4(y`#{cZw{LVB#z_$<=AYHZ&*krl<*ncrL zeZhn?Qw3G8zVW()f4!!b2@{C+_CDDQJlZRa=ZcOy&k0eLACFbCbM0 z6AJi7@*BXJ{qNxS`2pp} zZSp_QLczStF?jfUt_fXrdI-{E#En`>jp}IeZ zbsYg}9lgCXnv{rum+WjI!_S`|=`(GAhOj(Hka+m51bUD%}674$P?#iTRD`+eMP=j+ ziYqBe&D~#ah-EahnFp}ayFCj9sfX{{zG-&u$Y>k-4Wusje8yGLJR6CCExb+m57ram z;v;`e9s|PkRb#mqG&^wJxVgzS4SoV*{gCyqnF_sf;NZE3cMwH3m;8@7w2ob(3CeO!EzAP zwKXU%WNtoUlUq1pOYC)}J0uy9ySQjMwF5Y57 z$y%f1!cQol&5_2OB_`((O5$K;*#VaKaCdFR>7}ri^AO#W;{04AlgoOw;fiOj58H4{&j>j z3{U%~JlV~~+A@MykNcDgWBxm6IIq%}OW*4G(4faIAFAzCoPexs&^0N?WtVTnO_j4! z5a%hAGNUo0O=ij7FNKdwFG>nd_z3a+piU(lHpMHm!WxD}f%QVp4dYUZB@W}q6&~(N zpEs(1w;Z)Bc(>j4Jd{N99Cr;Ciy-ZEQWQ@VhPF(_7gd4Vl<+#u-`+T=LEV#ZqdOG`^`qzUFyX+ibo~m`|d?bgxO|$L#o=e0~3n?tyhScOr7baL*u*q^dga0 zCBoXohJyhDk5ns)cC2EL<#RKuYFQsKi)D77La*Q15ser*Z?izY-*qU-t5J}Ircq6TIDt8lsEnzTc^)2j3#mZPsbzFf-|U+FFlqgE%R4NPsqx)p zJ21!jqQEQ``f8OTa++pJZwthoMUCuxI=@6bFzP?UrYxNZT94SAfJ{qJ$@crY(#a~; zM#W2X?-T2;8eHOxOA8IZJw!+?8hbvPP&ODGLQ9RKi@b;wJE{&%N-W}+L(lCWP(l5~ zh4w9$l3*zX$0Lg_GLAh0@_qNS8ufiBPC~0s@py@gPB6T-c1lzZL{<-Y_*s2I$4Pwy zE1r_{myD)^fjN$<$2C5A-{JhB4L0iv$nPcWRP6U9+IRzuw6`Zt=Vrr0_cdF8AZ*b2 znv?3h3;VFA?xc&b+21z+O4EO0mat$kd{mDwLCH<|ozP)GkuF8=HY~$zROV&ZDB&`% zlXwOUh(48*N}jecsRYNt&y2x%wq>TZl52YngvnVvZwa!<9hpO5#H^FfFIwVo*K)ahi*X5X2kM;FfJ!@^_akF{xjWA4N<98?Hthh?4!11KhWfP~W zs>!^s^24?-VB;ovWEyjnjL{mK68Bq~%#xm3ykiDMdHIy~*UXPUBxz%45=kyuy*ug} zv%;XZSc103i@GK_B(%gEA)9O`EVRuH#m}t6h1HOl-RUpee0W6~DB?4B^%|&$8*Rv& zvw{lOvOfqp$AYY2LOCWPtdQ5pIgeBEPS%Qy+xxnZHp^|SC%yT=eo*o2SJlI)CDhhl zaSfJNGew|9XpUe0abq7N8>2%b=OSA;a?OQjo1rx_GOFSnJK9X;gS)c%34%O~)t^@rT7P)NP2ae0bn&(5Uaa=ZW zUOfzW#k6zVFtSXI?aOP$*u1x=6PLVhQ$SpLg3(j24ya$!2wU6?V_q!K*lxcAXo% z;~HcEDV@fFG!@z_WFd<-9&AwcE2UQPQd)$dAuecGtXNobfg4(_67n0Y_a$vDES1t8 zzuRg;L|tQWNwYT-5ed$du+pGA=4=@+nlAF?8)vKcubo*Z>@Ks%4CzHY>1aBz=Xa+= z$pb@w-}E(>gVHA{Bm61r!SFhzp==1o**F>k62{~NGr?T^d_{v@b7?%VqegKtc{j_P zEl;@^Vx|VOOjIDmRMn848>TuJmbOROG{tF5<&VrPRt>ip@7+L17;YRzN^y@M5>sm{ z4U-YjAi)yVW~aGLt#5b~yVl`y(s!Gp!?k@aZ5joRrC?G;WHF2>sAG9t-gUH3JnOn@ z|8$R?%2KQyI`dUsb&!ZJz0zejW{cfjS1#1ny+yhsFc<~7796{iC6wL0B94Tzxx56b668_X&CKUL_26!;7&*Cnr1G=1&GDQW)*Y5 z-I!vPPO5=yWr~D1(d-If-X)bP#I1^;-`aZmofHIdp{#Ppd(T#G4e3z=EbT_F)t!rk zNE&9SoBt(mU~EvruV=(*71?IF1wnR<^Go6Bl-OsV4ln$I2DxIy8biDct4P_3(w4%S z$CSX2J#k8F(WQdt2(};d$&Z+0-wCpv;o73R9SJeP8GigzhK21L%4VGY8V;Qn6>!!DtwjM%B`N zNvpX^;r$_a5TIW}9Q1(4{E4tedfC=zQp(1^{r%nS z5CAdq71y13R)Tc71Lm4XN zrJ<^bq!gkV6tY8x0*zKyqw2}Li|CSt`oe7RC1Isgq+P0$iQzXsI$@%!{hW)%y{&Dp zT5b#r&q13p|4d-}mmX-*aL96J^p5enuzKw3hJpR#*oy*K)}}HhpJf}0&FX&Bads6l zrSxldu+G3VjO$NjbBnW*Q}^HbiZ5AXDCkYg+Su7FNc@);b)wtw8!Iq{p&}};pN!m_ zNtP@-_{`~9Cy0Nl{_7A?Lw!CH%A;=p;lfnzkEpX&!t#r5OaqA-e$+6@L}^7ov=3dF zl5b?{Xop9t^!Zf#=Mt`@??n$B=7zG>6Ot?|k@$IO?Qm%=AogaeDa9&xf!;vTr-xjG zp<0vVqzZ2;KhLv)j^9e6ltRldk9OP>U<5!B9qa^A45`8~Vv9{Y${5_u_PC_McZO*fz7<<)-b&=ujD z!l2KO6F=sAvfk)i#Zv!?mPqJ>*hoO1)ane)>MuIzfV4c?tUO$Xr7->V9Khf~Pw;!O zr*OwPV{*&!hmCxYz3)} zvdg7*rVAUSmi*F@h$QoIhaYx24G`-UfMMi}8qgzOU8cRv*OOqjBlw#ms*PPd`G{{O z5txZXCzhkstOE+ba)@^|J6WHN1RQ_=b*(6$3lJ%6t6aQ$hObW>qfROvD|_Il>uny1 zsi_lyCJRudIg`*v9JJvaQP=av>sd`afAf(>jxhp{1)3~E6}%mvgs58+Y;3C|l&8-% z#?8aRm5N|}GMi;2{BfPvfRJ6crx>Po9)sD;S&zrEgXRe9s$jK3uYa@Rsy!z0febTn zf(#W>d&DTjEZ}`W4=m~fv&%x|ABX$N=8WKj#Mx^j8e^<OohTG5(?qw@cmJjKYJ?HD7R+`s+(7;s~tJEmXiS3CLLvZv4{B z5migLkDI&~)*u8u*uTo=NXX;!v2rgxWkW3(?VwZi$__G>fXsj4G11HnGYdE3zedf@ z*mkHK^-!7Nk$wF(P41&^tc)&R6}@L&kj>x!mi!1^WD!ozL{0fCr{%O??SrTGK(c?B z45K=vS7yK@GNZqW)y6cDBLR`%{aK>}He{5_IsVI-&3-b4R3k@Rg31jx0wpF{E{?X<j*sy=ER|TFTnN2#Kd^jnyOHujbEJLj4jU! z!hBg|UQ`x;{b2%<%GSs%%2sSA)b_Q_{w-|ir?- zrbi{9s`6IFvv$!|JXE#iD`H_e-l#OKQ_RyvEKJa>)fF#zkUM*F9uT+kZ)aRkK+`I^ z!(wbbz;7J8w<)v%2wW=+?AyP+j8|M8UNs-QRMl=6cJ92yHlUMH)9x`zl;L+BB*W^` zB;ZvL0~llx9z;%snPyRyKl0G^g4iN06~e9_NFc-$hli(<*`>1 z2d?IY52AFc1D)2^j{-Mg`J+>}5b6&-!m{ut?K<(+morv%w!Q8SI?hd?O*ZpRF!ly_ zrocQc42x3WB7V(46NOCxz731fzt$oKjaYe{YdWm{M64>^gM`(%JW-{u+$c__|FO^%01NDQz_!eNA=cn8M#4gETlGc+h??aFr6k4G) z1B!{u36%?Qd7&a#84A>>&rY>GT9lrRcW$Do*orb-jHoC*tpqI&p(5fpr-E3kH6@^CK4{WFt^Q{7C8c3|e3|Cmo@g`FeQRUpQ&}d=2kE ziM}_f*Z1@{f2Mv6CuWa!mX4)C2?PaqZ6=GXv0X4>nToN@y7BQSfxOCxhww9raY`J- zSVeURb{|uD<*a9@|D1ojN?UH=$j_voFukKwfl!4#kEaBDJ z{dJk7hz6}|cy=Z!d0s~#hc)ykHEoa*&VF%k!sLmmE_xc)IxCzO6kH#i8Pv^|Jf}@} zJZ%BoIw&Ujb1B5-eW2a<)K(P3qwqwR0heEXyPG3ngdz{G8Q|fUw09N#I_E=P=UQC6NyNC(d+FTQ)yEI;Mcwnlxf)HiO z%JEs0AI`FQt<~L%!3E^D=pqZ52wS92Z>iHkg66kCSg-|;?&&o}Cm{q&6o68n_L1Wt zcJ_LB0M57~rZtz;i|`U!A^_n#w|A$Bv8k14?IC&a)KKU>B?x%XGTQ4Yx#mmr77bbz zU_tUlB?(GHcIRi4d9)~=_kT`2$DXu#q+#72-ZDattr2NF@31Ybe-15fK&@V4rq5|j zPKwfXm~jSl)9ZpIUPzfYBnbUt0QC!b7&B?SL&c*wgU&1zR5C(yV~xNwb`$f> zoed2(bJ;}KAs0yNZNha+O1B^w#xn+D+mh3?te0Zw{a)q@9e@4+$Fiv~VmNge_YxYd zOLObq*fC{?m%TcY+c&V&9IVw9p{fs0B`qM;A3P{i?D5m_Q(4Hels7+gt5w5(AuChy zVo()3$bf)1n&&IHYSnu(jN__Mna&=k<2q87u+GvVkIpqMFTQ6?x$V--+wRWQ&N+ZX zyC40>eXTlAI!N0UUOR;HUW1p0mh3jh z0I6kX(>Z=vJO7)$TU`--@ZIVlTj3ao*k7-dRK16HI^arG(@-*GL3NF45_Fgg2@c!~ zZ94Le*(hbHQDP)Z{GLpi(M5)P6Jvi7dOigIkEn-DcN_&% zBJ_h52ndMhw;_Lvdbqe5n_4+Dn%SHF|Joj>@R*$czU@ES9+9Tewpg3Z28j^4AzpJmFzr+TNtVc$V-^^No!`?xExsO zg60Z+$#ge?GTrz#p)_u&L_bq*5NZdRr~`>upvZ%^i7a=*T|t#(LBTM=F}}Tm0ntmc zplIC%fck-hfK)+)fWUzud_M;P0R;gODh~Y5l`GKL*39KU9;<7?fY60uaDFxIbNn}k z{&%dl0Y8p{VL(6>0sle$Z;a+|WLGnn|EXv4AB6GmaQDCMzY!8_?I_+3D&kHkKtLvS z{tv?U>%YCQ|Auq4GGX~Hp>X`)KFsKz|6e{Zdzn*Y02UXAzmu)%4FUrF|M~F05TaTC zCjx_`y~Y0qAmH5lzX1MU6_)=FBCHzZzcg9?R~r7K$@1Sp{J)?4zY%o*g8aV&00!iL Y4*(@uNT~m08|wQ=`A$CQ?SJn62LeMZp#T5? literal 0 HcmV?d00001 diff --git a/samples/html/zip/start.htm b/samples/html/zip/start.htm new file mode 100644 index 0000000000..cca461e6b0 --- /dev/null +++ b/samples/html/zip/start.htm @@ -0,0 +1,9 @@ + +

ZIP archive

+

feature demo

+

+Click on this link to load page stored in ZIP +archive (pages.zip). Enjoy it! + + + diff --git a/samples/html/zip/zip.cpp b/samples/html/zip/zip.cpp new file mode 100644 index 0000000000..3f518da664 --- /dev/null +++ b/samples/html/zip/zip.cpp @@ -0,0 +1,195 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: test.cpp +// Purpose: wxHtml testing example +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ + #pragma implementation "test.cpp" + #pragma interface "test.cpp" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all "standard" wxWindows headers +#ifndef WX_PRECOMP + #include +#endif + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +// Define a new application type, each program should derive a class from wxApp + class MyApp : public wxApp + { + public: + // override base class virtuals + // ---------------------------- + + // this one is called on application startup and is a good place for the app + // initialization (doing it here and not in the ctor allows to have an error + // return: if OnInit() returns false, the application terminates) + virtual bool OnInit(); + }; + +// Define a new frame type: this is going to be our main frame + class MyFrame : public wxFrame + { + public: + // ctor(s) + MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); + + // event handlers (these functions should _not_ be virtual) + void OnQuit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + void OnBack(wxCommandEvent& event); + void OnForward(wxCommandEvent& event); + + private: + // any class wishing to process wxWindows events must use this macro + DECLARE_EVENT_TABLE() + }; + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// IDs for the controls and the menu commands + enum + { + // menu items + Minimal_Quit = 1, + Minimal_About, + Minimal_Back, + Minimal_Forward, + + // controls start here (the numbers are, of course, arbitrary) + Minimal_Text = 1000, + }; + +// ---------------------------------------------------------------------------- +// event tables and other macros for wxWindows +// ---------------------------------------------------------------------------- + +// the event tables connect the wxWindows events with the functions (event +// handlers) which process them. It can be also done at run-time, but for the +// simple menu events like this the static method is much simpler. + BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(Minimal_Quit, MyFrame::OnQuit) + EVT_MENU(Minimal_About, MyFrame::OnAbout) + EVT_MENU(Minimal_Back, MyFrame::OnBack) + EVT_MENU(Minimal_Forward, MyFrame::OnForward) + END_EVENT_TABLE() + + // Create a new application object: this macro will allow wxWindows to create + // the application object during program execution (it's better than using a + // static object for many reasons) and also declares the accessor function + // wxGetApp() which will return the reference of the right type (i.e. MyApp and + // not wxApp) + IMPLEMENT_APP(MyApp) + + // ============================================================================ + // implementation + // ============================================================================ + + // ---------------------------------------------------------------------------- + // the application class + // ---------------------------------------------------------------------------- + // `Main program' equivalent: the program execution "starts" here + bool MyApp::OnInit() + { + #if wxUSE_LIBPNG + wxImage::AddHandler(new wxPNGHandler); + #endif + #if wxUSE_LIBJPEG + wxImage::AddHandler(new wxJPEGHandler); + #endif + + wxFileSystem::AddHandler(new wxZipFSHandler); + + // Create the main application window + MyFrame *frame = new MyFrame("wxHtmlWindow testing application", + wxPoint(50, 50), wxSize(640, 480)); + + // Show it and tell the application that it's our main window + // @@@ what does it do exactly, in fact? is it necessary here? + frame->Show(TRUE); + SetTopWindow(frame); + + // success: wxApp::OnRun() will be called which will enter the main message + // loop and the application will run. If we returned FALSE here, the + // application would exit immediately. + return TRUE; + } + +// ---------------------------------------------------------------------------- +// main frame +// ---------------------------------------------------------------------------- + +wxHtmlWindow *html; + +// frame constructor + MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) + : wxFrame((wxFrame *)NULL, -1, title, pos, size) + { + // create a menu bar + wxMenu *menuFile = new wxMenu; + wxMenu *menuNav = new wxMenu; + + menuFile->Append(Minimal_Quit, "E&xit"); + menuNav->Append(Minimal_Back, "Go &BACK"); + menuNav->Append(Minimal_Forward, "Go &FORWARD"); + + // now append the freshly created menu to the menu bar... + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append(menuFile, "&File"); + menuBar->Append(menuNav, "&Navigate"); + + // ... and attach this menu bar to the frame + SetMenuBar(menuBar); + + CreateStatusBar(1); + + { + html = new wxHtmlWindow(this); + html -> SetRelatedFrame(this, "HTML : %s"); + html -> SetRelatedStatusBar(0); + html -> LoadPage("start.htm"); + } + } + + +// event handlers + + void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) + { + // TRUE is to force the frame to close + Close(TRUE); + } + + void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) + { + } + + + + void MyFrame::OnBack(wxCommandEvent& WXUNUSED(event)) + { + if (!html -> HistoryBack()) wxMessageBox("You reached prehistory era!"); + } + + + void MyFrame::OnForward(wxCommandEvent& WXUNUSED(event)) + { + if (!html -> HistoryForward()) wxMessageBox("No more items in history!"); + } diff --git a/samples/html/zip/zip.rc b/samples/html/zip/zip.rc new file mode 100644 index 0000000000..82bdf07561 --- /dev/null +++ b/samples/html/zip/zip.rc @@ -0,0 +1,2 @@ +#include "wx/msw/wx.rc" + diff --git a/src/common/filesys.cpp b/src/common/filesys.cpp new file mode 100644 index 0000000000..5712bf60ba --- /dev/null +++ b/src/common/filesys.cpp @@ -0,0 +1,294 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: filesys.cpp +// Purpose: wxFileSystem class - interface for opening files +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include +#include +#include +#include + + + +//-------------------------------------------------------------------------------- +// wxFileSystemHandler +//-------------------------------------------------------------------------------- + +IMPLEMENT_ABSTRACT_CLASS(wxFileSystemHandler, wxObject) + +wxMimeTypesManager wxFileSystemHandler::m_MimeMng; + + +wxString wxFileSystemHandler::GetMimeTypeFromExt(const wxString& location) +{ + wxString ext = wxEmptyString, mime = wxEmptyString; + wxString loc = GetRightLocation(location); + char c; + int l = loc.Length(), l2; + wxFileType *ft; + + l2 = l; + for (int i = l-1; i >= 0; i--) { + c = loc[i]; + if (c == '#') l2 = i + 1; + if (c == '.') {ext = loc.Right(l2-i-1); break;} + if ((c == '/') || (c == '\\') || (c == ':')) {return wxEmptyString;} + } + ft = m_MimeMng.GetFileTypeFromExtension(ext); + if (ft && (ft -> GetMimeType(&mime))) return mime; + else return wxEmptyString; +} + + + +wxString wxFileSystemHandler::GetProtocol(const wxString& location) const +{ + wxString s = wxEmptyString; + int i, l = location.Length(); + bool fnd; + + fnd = FALSE; + for (i = l-1; (i >= 0) && ((location[i] != '#') || (!fnd)); i--) { + if ((location[i] == ':') && (i != 1 /*win: C:\path*/)) fnd = TRUE; + } + if (!fnd) return "file"; + for (++i; (i < l) && (location[i] != ':'); i++) s << location[i]; + return s; +} + + + +wxString wxFileSystemHandler::GetLeftLocation(const wxString& location) const +{ + int i; + bool fnd; + + fnd = FALSE; + for (i = location.Length()-1; i >= 0; i--) { + if ((location[i] == ':') && (i != 1 /*win: C:\path*/)) fnd = TRUE; + else if (fnd && (location[i] == '#')) return location.Left(i); + } + return wxEmptyString; +} + + + +wxString wxFileSystemHandler::GetRightLocation(const wxString& location) const +{ + int i, l = location.Length(); + int l2 = l + 1; + for (i = l-1; (i >= 0) && ((location[i] != ':') || (i == 1) || (location[i-2] == ':')); i--) {if (location[i] == '#') l2 = i + 1;} + if (i == 0) return wxEmptyString; + else return location.Mid(i + 1, l2 - i - 2); +} + + + +wxString wxFileSystemHandler::GetAnchor(const wxString& location) const +{ + char c; + int l = location.Length(); + + for (int i = l-1; i >= 0; i--) { + c = location[i]; + if (c == '#') return location.Right(l-i-1); + else if ((c == '.') || (c == '/') || (c == '\\') || (c == ':')) return wxEmptyString; + } + return wxEmptyString; +} + + + + + +//-------------------------------------------------------------------------------- +// wxLocalFSHandler +//-------------------------------------------------------------------------------- + +class wxLocalFSHandler : public wxFileSystemHandler +{ + public: + virtual bool CanOpen(const wxString& location); + virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location); +}; + + + +bool wxLocalFSHandler::CanOpen(const wxString& location) +{ + return GetProtocol(location) == "file"; +} + + + +wxFSFile* wxLocalFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location) +{ + wxString right = GetRightLocation(location); + if (wxFileExists(right)) + return new wxFSFile(new wxFileInputStream(right), + right, + GetMimeTypeFromExt(location), + GetAnchor(location)); + else return NULL; +} + + + + + + +//----------------------------------------------------------------------------- +// wxFileSystem +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxFileSystem, wxObject) + + +wxList wxFileSystem::m_Handlers; + + + +void wxFileSystem::ChangePathTo(const wxString& location, bool is_dir) +{ + int i, pathpos = -1; + m_Path = location; + + for (i = m_Path.Length()-1; i >= 0; i--) + if (m_Path[i] == '\\') m_Path.GetWritableChar(i) = '/'; // wanna be windows-safe + + if (is_dir == FALSE) { + for (i = m_Path.Length()-1; i >= 0; i--) { + if (m_Path[i] == '/') { + if ((i > 1) && (m_Path[i-1] == '/') && (m_Path[i-2] == ':')) { + i -= 2; + continue; + } + else { + pathpos = i; + break; + } + } + else if (m_Path[i] == ':') { + pathpos = i; + break; + } + } + if (pathpos == -1) { + for (i = 0; i < (int) m_Path.Length(); i++) { + if (m_Path[i] == ':') { + //m_Path << '/'; + m_Path.Remove(i+1); + break; + } + } + if (i == (int) m_Path.Length()) m_Path = wxEmptyString; + } + else { + if (m_Path[m_Path.Length()-1] != '/') m_Path << '/'; + m_Path.Remove(pathpos+1); + } + } +} + + + +wxFSFile* wxFileSystem::OpenFile(const wxString& location) +{ + wxString loc = location; + int i, ln; + char meta; + wxFSFile *s = NULL; + wxNode *node; + + ln = loc.Length(); + meta = 0; + for (i = 0; i < ln; i++) { + if (loc[i] == '\\') loc.GetWritableChar(i) = '/'; // wanna be windows-safe + if (!meta) switch (loc[i]) { + case '/' : case ':' : case '#' : meta = loc[i]; + } + } + m_LastName = wxEmptyString; + + // try relative paths first : + if (meta != ':') { + node = m_Handlers.GetFirst(); + while (node){ + wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData(); + if (h -> CanOpen(m_Path + location)) { + s = h -> OpenFile(*this, m_Path + location); + if (s) {m_LastName = m_Path + location; break;} + } + node = node -> GetNext(); + } + } + + // if failed, try absolute paths : + if (s == NULL) { + node = m_Handlers.GetFirst(); + while (node){ + wxFileSystemHandler *h = (wxFileSystemHandler*) node -> GetData(); + if (h -> CanOpen(location)) { + s = h -> OpenFile(*this, location); + if (s) {m_LastName = location; break; } + } + node = node -> GetNext(); + } + } + return (s); +} + + + +void wxFileSystem::AddHandler(wxFileSystemHandler *handler) +{ + m_Handlers.Append(handler); +} + + + + + + + + + + + +///// Module: + +class wxFileSystemModule : public wxModule +{ + DECLARE_DYNAMIC_CLASS(wxFileSystemModule) + + public: + virtual bool OnInit() + { + wxFileSystem::AddHandler(new wxLocalFSHandler); + return TRUE; + } + virtual void OnExit() {} +}; + +IMPLEMENT_DYNAMIC_CLASS(wxFileSystemModule, wxModule) + + + + diff --git a/src/common/fs_inet.cpp b/src/common/fs_inet.cpp new file mode 100644 index 0000000000..acb0c25831 --- /dev/null +++ b/src/common/fs_inet.cpp @@ -0,0 +1,130 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: fs_inet.cpp +// Purpose: HTTP and FTP file system +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +/* + +REMARKS : + +This FS creates local cache (in /tmp directory). The cache is freed +on program exit. + +Size of cache is limited to cca 1000 items (due to GetTempFileName +limitation) + + +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include "wx/wfstream.h" +#include "wx/url.h" +#include "wx/filesys.h" +#include "wx/fs_inet.h" + +class wxInetCacheNode : public wxObject +{ + private: + wxString m_Temp; + wxString m_Mime; + + public: + wxInetCacheNode(const wxString& l, const wxString& m) : wxObject() {m_Temp = l; m_Mime = m;} + const wxString& GetTemp() const {return m_Temp;} + const wxString& GetMime() const {return m_Mime;} +}; + + + + + +//-------------------------------------------------------------------------------- +// wxInternetFSHandler +//-------------------------------------------------------------------------------- + + +bool wxInternetFSHandler::CanOpen(const wxString& location) +{ + wxString p = GetProtocol(location); + return (p == "http") || (p == "ftp"); +} + + + + +wxFSFile* wxInternetFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location) +{ + wxString right = GetProtocol(location) + ":" + GetRightLocation(location); + wxInputStream *s; + wxString content; + wxInetCacheNode *info; + + info = (wxInetCacheNode*) m_Cache.Get(right); + + // Add item into cache: + if (info == NULL) { + wxURL url(right); + s = url.GetInputStream(); + content = url.GetProtocol().GetContentType(); + if (content == wxEmptyString) content = GetMimeTypeFromExt(location); + if (s) { + char buf[256]; + + wxGetTempFileName("wxhtml", buf); + info = new wxInetCacheNode(buf, content); + m_Cache.Put(right, info); + + { // ok, now copy it: + wxFileOutputStream sout(buf); + s -> Read(sout); // copy the stream + } + delete s; + } + else return NULL; //we can't open the URL + } + + // Load item from cache: + s = new wxFileInputStream(info -> GetTemp()); + if (s) { + return new wxFSFile(s, + right, + info -> GetMime(), + GetAnchor(location)); + } + else return NULL; +} + + + +wxInternetFSHandler::~wxInternetFSHandler() +{ + wxNode *n; + wxInetCacheNode *n2; + + m_Cache.BeginFind(); + while ((n = m_Cache.Next()) != NULL) { + n2 = (wxInetCacheNode*) n -> GetData(); + wxRemoveFile(n2 -> GetTemp()); + delete n2; + } +} + + + + diff --git a/src/common/fs_zip.cpp b/src/common/fs_zip.cpp new file mode 100644 index 0000000000..2bd3b224ed --- /dev/null +++ b/src/common/fs_zip.cpp @@ -0,0 +1,75 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: fs_zip.cpp +// Purpose: ZIP file system +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include "wx/filesys.h" +#include "wx/zipstream.h" +#include "wx/fs_zip.h" + + +//-------------------------------------------------------------------------------- +// wxZipFSHandler +//-------------------------------------------------------------------------------- + + + +bool wxZipFSHandler::CanOpen(const wxString& location) +{ + wxString p = GetProtocol(location); + return (p == "zip"); +} + + + + +wxFSFile* wxZipFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location) +{ + wxString right = GetRightLocation(location); + wxString left = GetLeftLocation(location); + wxInputStream *s; + + if (GetProtocol(left) != "file") { + return NULL; + } + + s = new wxZipInputStream(left, right); + if (s && (s -> LastError() == wxStream_NOERROR)) { + return new wxFSFile(s, + left + "#zip:" + right, + GetMimeTypeFromExt(location), + GetAnchor(location)); + } + else return NULL; +} + + + +wxZipFSHandler::~wxZipFSHandler() +{ +} + + + + + + + diff --git a/src/common/unzip.c b/src/common/unzip.c new file mode 100644 index 0000000000..ff71a474da --- /dev/null +++ b/src/common/unzip.c @@ -0,0 +1,1294 @@ +/* unzip.c -- IO on .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Read unzip.h for more info +*/ + + +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + + +#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \ + !defined(CASESENSITIVITYDEFAULT_NO) +#define CASESENSITIVITYDEFAULT_NO +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +const char unz_copyright[] = + " unzip 0.15 Copyright 1998 Gilles Vollant "; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + FILE* file; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + FILE* file; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ +} unz_s; + + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte(fin,pi) + FILE *fin; + int *pi; +{ + unsigned char c; + int err = fread(&c, 1, 1, fin); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ferror(fin)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort (fin,pX) + FILE* fin; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(fin,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong (fin,pX) + FILE* fin; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(fin,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (fileName1,fileName2) + const char* fileName1; + const char* fileName2; +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) + const char* fileName1; + const char* fileName2; + int iCaseSensitivity; +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#define BUFREADCOMMENT (0x400) + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir(fin) + FILE *fin; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (fseek(fin,0,SEEK_END) != 0) + return 0; + + + uSizeFile = ftell( fin ); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (fseek(fin,uReadPos,SEEK_SET)!=0) + break; + + if (fread(buf,(uInt)uReadSize,1,fin)!=1) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer + "zlib/zlib109.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen (path) + const char *path; +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + FILE * fin ; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + fin=fopen(path,"rb"); + if (fin==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(fin); + if (central_pos==0) + err=UNZ_ERRNO; + + if (fseek(fin,central_pos,SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(fin,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + fclose(s->file); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) + unzFile file; + unz_global_info *pglobal_info; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) + uLong ulDosDate; + tm_unz* ptm; +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unzlocal_GetCurrentFileInfoInternal (file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + unz_file_info_internal *pfile_info_internal; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extrafile,lSeek,SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentfile,lSeek,SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (file) + unzFile file; +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (file) + unzFile file; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) + unzFile file; + const char *szFileName; + int iCaseSensitivity; +{ + unz_s* s; + int err; + + + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + return err; +} + + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield) + unz_s* s; + uInt* piSizeVar; + uLong *poffset_local_extrafield; + uInt *psize_local_extrafield; +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (fseek(s->file,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(s->file,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + int Store; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + Store = s->cur_file_info.compression_method==0; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->file=s->file; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if (!Store) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + + s->pfile_in_zip_read = pfile_in_zip_read_info; + return UNZ_OK; +} + + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (file, buf, len) + unzFile file; + voidp buf; + unsigned len; +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->read_buffer == NULL)) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if (len>pfile_in_zip_read_info->rest_read_uncompressed) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (fseek(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) + return UNZ_ERRNO; + if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1, + pfile_in_zip_read_info->file)!=1) + return UNZ_ERRNO; + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if (pfile_in_zip_read_info->compression_method==0) + { + uInt uDoCopy,i ; + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (fseek(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + int err=UNZ_OK; + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (fread(szComment,(uInt)uReadThis,1,s->file)!=1) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} diff --git a/src/common/unzip.h b/src/common/unzip.h new file mode 100644 index 0000000000..76692cb703 --- /dev/null +++ b/src/common/unzip.h @@ -0,0 +1,275 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Copyright (C) 1998 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Encryption and multi volume ZipFile (span) are not supported. + Old compressions used by old PKZip 1.x are not supported + + THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE + CAN CHANGE IN FUTURE VERSION !! + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ +/* for more info about .ZIP format, see + ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip */ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer + "zlib/zlib111.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/src/common/zipstream.cpp b/src/common/zipstream.cpp new file mode 100644 index 0000000000..39f4888df6 --- /dev/null +++ b/src/common/zipstream.cpp @@ -0,0 +1,110 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: zipstream.cpp +// Purpose: input stream for ZIP archive access +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include +#include +#include +#include "unzip.h" + + + + +wxZipInputStream::wxZipInputStream(const wxString& archive, const wxString& file) : wxInputStream() +{ + unz_file_info zinfo; + + m_Pos = 0; + m_Size = 0; + m_Archive = (void*) unzOpen(archive); + if (m_Archive == NULL) { + m_lasterror = wxStream_READ_ERR; + return; + } + if (unzLocateFile((unzFile)m_Archive, file, 0) != UNZ_OK) { + m_lasterror = wxStream_READ_ERR; + return; + } + unzGetCurrentFileInfo((unzFile)m_Archive, &zinfo, NULL, 0, NULL, 0, NULL, 0); + + if (unzOpenCurrentFile((unzFile)m_Archive) != UNZ_OK) { + m_lasterror = wxStream_READ_ERR; + return; + } + m_Size = zinfo.uncompressed_size; +} + + + +wxZipInputStream::~wxZipInputStream() +{ + if (m_Archive) { + if (m_Size != 0) + unzCloseCurrentFile((unzFile)m_Archive); + unzClose((unzFile)m_Archive); + } +} + + + +size_t wxZipInputStream::OnSysRead(void *buffer, size_t bufsize) +{ + if (m_Pos + bufsize > m_Size) bufsize = m_Size - m_Pos; + unzReadCurrentFile((unzFile)m_Archive, buffer, bufsize); + m_Pos += bufsize; + return bufsize; +} + + + +off_t wxZipInputStream::OnSysSeek(off_t seek, wxSeekMode mode) +{ + off_t nextpos; + void *buf; + + 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 */ + } + + // cheated seeking : + if (nextpos > m_Pos) { + buf = malloc(nextpos - m_Pos); + unzReadCurrentFile((unzFile)m_Archive, buf, nextpos - m_Pos); + free(buf); + } + else if (nextpos < m_Pos) { + unzCloseCurrentFile((unzFile)m_Archive); + if (unzOpenCurrentFile((unzFile)m_Archive) != UNZ_OK) { + m_lasterror = wxStream_READ_ERR; + return m_Pos; + } + buf = malloc(nextpos); + unzReadCurrentFile((unzFile)m_Archive, buf, nextpos); + free(buf); + } + + m_Pos = nextpos; + return m_Pos; +} + diff --git a/src/generic/busyinfo.cpp b/src/generic/busyinfo.cpp new file mode 100644 index 0000000000..c443c1daa3 --- /dev/null +++ b/src/generic/busyinfo.cpp @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: busyinfo.cpp +// Purpose: Information window when app is busy +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include "wx/busyinfo.h" + + + + + +wxInfoFrame::wxInfoFrame(wxWindow *parent, const wxString& message) + : wxFrame(parent, -1, "", wxPoint(0, 0), wxSize(400, 80), wxTHICK_FRAME | wxSIMPLE_BORDER | wxFRAME_TOOL_WINDOW) +{ + wxPanel *p = new wxPanel(this); + wxStaticText *s = new wxStaticText(p, -1, message, wxPoint(20, 20), wxSize(360, 40), wxALIGN_CENTER); + Centre(wxBOTH); + p -> SetCursor(*wxHOURGLASS_CURSOR); + s -> SetCursor(*wxHOURGLASS_CURSOR); +} + + + + +wxBusyInfo::wxBusyInfo(const wxString& message) : wxObject() +{ + m_InfoFrame = new wxInfoFrame(NULL, message); + m_InfoFrame -> Show(TRUE); + wxYield(); + m_InfoFrame -> Refresh(); + wxYield(); +} + + + +wxBusyInfo::~wxBusyInfo() +{ + m_InfoFrame -> Show(FALSE); + m_InfoFrame -> Close(); + wxYield(); +} + + + + + + + + + + + diff --git a/src/gtk/Makefile.am b/src/gtk/Makefile.am index 5bff538335..596102f8d1 100644 --- a/src/gtk/Makefile.am +++ b/src/gtk/Makefile.am @@ -12,7 +12,7 @@ SUFFIXES = .cpp .c DEFS = $(TOOLKIT_DEF) $(WXDEBUG_DEFINE) LIBS = $(GUILIBS) -VPATH = .:${srcdir}:${srcdir}/../common:${srcdir}/../generic:${EXTRA_VPATH} +VPATH = .:${srcdir}:${srcdir}/../common:${srcdir}/../generic:${srcdir}/../html:${EXTRA_VPATH} lib_LTLIBRARIES = @WX_LIBRARY_NAME@ EXTRA_LTLIBRARIES = libwx_gtk.la libwx_motif.la libwx_msw.la @@ -44,7 +44,10 @@ libwx_gtk_la_SOURCES = \ file.cpp \ fileconf.cpp \ filefn.cpp \ + filesys.cpp \ framecmn.cpp \ + fs_inet.cpp \ + fs_zip.cpp \ ftp.cpp \ gdicmn.cpp \ hash.cpp \ @@ -90,6 +93,7 @@ libwx_gtk_la_SOURCES = \ time.cpp \ timercmn.cpp \ tokenzr.cpp \ + unzip.c \ url.cpp \ utilscmn.cpp \ valgen.cpp \ @@ -101,10 +105,12 @@ libwx_gtk_la_SOURCES = \ wxchar.cpp \ wxexpr.cpp \ zstream.cpp \ + zipstream.cpp \ \ db.cpp \ dbtable.cpp \ \ + busyinfo.cpp \ caret.cpp \ colrdlgg.cpp \ dcpsg.cpp \ @@ -192,7 +198,26 @@ libwx_gtk_la_SOURCES = \ utilsgtk.cpp \ utilsres.cpp \ wave.cpp \ - window.cpp + window.cpp \ +\ + htmlcell.cpp \ + htmlfilter.cpp \ + htmlhelp.cpp \ + htmlhelp_io.cpp \ + htmlparser.cpp \ + htmltag.cpp \ + htmlwin.cpp \ + htmlwinparser.cpp \ + mod_fonts.cpp \ + mod_hline.cpp \ + mod_image.cpp \ + mod_layout.cpp \ + mod_links.cpp \ + mod_list.cpp \ + mod_pre.cpp \ + mod_tables.cpp \ + search.cpp + # these are the sources which we build by our own rules # diff --git a/src/gtk1/Makefile.am b/src/gtk1/Makefile.am index 5bff538335..596102f8d1 100644 --- a/src/gtk1/Makefile.am +++ b/src/gtk1/Makefile.am @@ -12,7 +12,7 @@ SUFFIXES = .cpp .c DEFS = $(TOOLKIT_DEF) $(WXDEBUG_DEFINE) LIBS = $(GUILIBS) -VPATH = .:${srcdir}:${srcdir}/../common:${srcdir}/../generic:${EXTRA_VPATH} +VPATH = .:${srcdir}:${srcdir}/../common:${srcdir}/../generic:${srcdir}/../html:${EXTRA_VPATH} lib_LTLIBRARIES = @WX_LIBRARY_NAME@ EXTRA_LTLIBRARIES = libwx_gtk.la libwx_motif.la libwx_msw.la @@ -44,7 +44,10 @@ libwx_gtk_la_SOURCES = \ file.cpp \ fileconf.cpp \ filefn.cpp \ + filesys.cpp \ framecmn.cpp \ + fs_inet.cpp \ + fs_zip.cpp \ ftp.cpp \ gdicmn.cpp \ hash.cpp \ @@ -90,6 +93,7 @@ libwx_gtk_la_SOURCES = \ time.cpp \ timercmn.cpp \ tokenzr.cpp \ + unzip.c \ url.cpp \ utilscmn.cpp \ valgen.cpp \ @@ -101,10 +105,12 @@ libwx_gtk_la_SOURCES = \ wxchar.cpp \ wxexpr.cpp \ zstream.cpp \ + zipstream.cpp \ \ db.cpp \ dbtable.cpp \ \ + busyinfo.cpp \ caret.cpp \ colrdlgg.cpp \ dcpsg.cpp \ @@ -192,7 +198,26 @@ libwx_gtk_la_SOURCES = \ utilsgtk.cpp \ utilsres.cpp \ wave.cpp \ - window.cpp + window.cpp \ +\ + htmlcell.cpp \ + htmlfilter.cpp \ + htmlhelp.cpp \ + htmlhelp_io.cpp \ + htmlparser.cpp \ + htmltag.cpp \ + htmlwin.cpp \ + htmlwinparser.cpp \ + mod_fonts.cpp \ + mod_hline.cpp \ + mod_image.cpp \ + mod_layout.cpp \ + mod_links.cpp \ + mod_list.cpp \ + mod_pre.cpp \ + mod_tables.cpp \ + search.cpp + # these are the sources which we build by our own rules # diff --git a/src/html/bitmaps/back.xpm b/src/html/bitmaps/back.xpm new file mode 100644 index 0000000000..fbb4378bf6 --- /dev/null +++ b/src/html/bitmaps/back.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char * back_xpm[] = { +"16 16 5 1", +" c None", +". c #000000", +"+ c #C0E4CB", +"@ c #77C490", +"# c #808080", +" ", +" ", +" . ", +" .. ", +" .+. ", +" .++........ ", +" .++@+++++++. ", +" .++@@@@@@@@@. ", +" .+@@@@@@@@@. ", +" #.+@........ ", +" #.+.####### ", +" #..# ", +" #.# ", +" ## ", +" # ", +" "}; diff --git a/src/html/bitmaps/book.xpm b/src/html/bitmaps/book.xpm new file mode 100644 index 0000000000..3146053f85 --- /dev/null +++ b/src/html/bitmaps/book.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static char * book_xpm[] = { +"16 16 21 1", +" c None", +". c #007F7F", +"+ c #660000", +"@ c #CC0000", +"# c #E50000", +"$ c #FF0000", +"% c #F20000", +"& c #D80000", +"* c #720000", +"= c #7F0000", +"- c #BFBFBF", +"; c #E57F7F", +"> c #7F7F7F", +", c #FFFFFF", +"' c #F2BFBF", +") c #723F3F", +"! c #A5A5A5", +"~ c #E5E5E5", +"{ c #B2B2B2", +"] c #003F3F", +"^ c #000000", +" ", +" ......... ", +" +@#$$$$$%&+ ", +" +##$$$$$$$* ", +" +##$$$$$$$=- ", +" +##$$$$$$$=;> ", +" +##$$$$$$$=;,. ", +" +##$$$$$$$=;,. ", +" +##$$$$$$$=''. ", +" +##$$$$$$$=,;. ", +" +##$$$$$$%+,;. ", +" +&++++++++),;. ", +" ++!~~~~~~~~~,. ", +" ++!~~~~~~~~~{. ", +" ]^^^^^^^^^^^ ", +" "}; diff --git a/src/html/bitmaps/folder.xpm b/src/html/bitmaps/folder.xpm new file mode 100644 index 0000000000..a7fbf85369 --- /dev/null +++ b/src/html/bitmaps/folder.xpm @@ -0,0 +1,50 @@ +/* XPM */ +static char * folder_xpm[] = { +"16 16 31 1", +" c None", +". c #000000", +"+ c #7F6E54", +"@ c #555555", +"# c #7F6140", +"$ c #FFCF94", +"% c #FFFFFF", +"& c #D5D5D5", +"* c #4B4336", +"= c #FFDCA8", +"- c #BFA57E", +"; c #EFEFEF", +"> c #DFDFDF", +", c #B8B8B9", +"' c #6E6E6F", +") c #BF7E42", +"! c #FFA858", +"~ c #FFC280", +"{ c #CFCFCF", +"] c #55402C", +"^ c #3C2C2C", +"/ c #7F542C", +"( c #C0C0C0", +"_ c #B0B0B2", +": c #969698", +"< c #A8A8AB", +"[ c #A0A0A4", +"} c #2C2C2C", +"| c #7C7C7E", +"1 c #161616", +"2 c #3F2A16", +" .+. ", +".@#$+. ", +".%&@#$+.+* ", +".%%%&@#$==-. ", +".%%;>,')!~$+ ", +".%;>{{,']^/~. ", +".;>{{((,,_:]/ ", +".>{{((,,_<[}/ ", +".{{((,,_<[[^/ ", +"._((,,_<[[[}/ ", +" }|_,_<[[[[}/ ", +" .}|<[[[[[}/ ", +" .}|[[[[}/ ", +" .}|[[}/.. ", +" .}|}/.. ", +" .12. "}; diff --git a/src/html/bitmaps/forward.xpm b/src/html/bitmaps/forward.xpm new file mode 100644 index 0000000000..6e3de64511 --- /dev/null +++ b/src/html/bitmaps/forward.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char * forward_xpm[] = { +"16 16 5 1", +" c None", +". c #000000", +"+ c #C0E4CB", +"@ c #77C490", +"# c #808080", +" ", +" ", +" . ", +" .. ", +" .+. ", +" ........++. ", +" .+++++++@++. ", +" .@@@@@@@@@++. ", +" .@@@@@@@@@+. ", +" ........@+.# ", +" #######.+.# ", +" #..# ", +" #.# ", +" ## ", +" # ", +" "}; diff --git a/src/html/bitmaps/page.xpm b/src/html/bitmaps/page.xpm new file mode 100644 index 0000000000..f8bf0c0057 --- /dev/null +++ b/src/html/bitmaps/page.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * page_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 3 1", +/* colors */ +" s None c None", +". c #000000", +"+ c #ffffff", +/* pixels */ +" ", +" ........ ", +" .++++++.. ", +" .+.+.++.+. ", +" .++++++.... ", +" .+.+.+++++. ", +" .+++++++++. ", +" .+.+.+.+.+. ", +" .+++++++++. ", +" .+.+.+.+.+. ", +" .+++++++++. ", +" .+.+.+.+.+. ", +" .+++++++++. ", +" ........... ", +" ", +" "}; diff --git a/src/html/bitmaps/panel.xpm b/src/html/bitmaps/panel.xpm new file mode 100644 index 0000000000..42798ebbe3 --- /dev/null +++ b/src/html/bitmaps/panel.xpm @@ -0,0 +1,122 @@ +/* XPM */ +static char * panel_xpm[] = { +"16 15 104 2", +" c None", +". c #7F7C7C", +"+ c #8A8E8E", +"@ c #D03232", +"# c #BA7E7E", +"$ c #555858", +"% c #5F5F5F", +"& c #656565", +"* c #5D5D5D", +"= c #939696", +"- c #FFFFFF", +"; c #F4C8C8", +"> c #DCDCF4", +", c #D3D3D3", +"' c #4E5151", +") c #7E7E7E", +"! c #9E9E9E", +"~ c #A7A7A7", +"{ c #5C5C5C", +"] c #9B9E9E", +"^ c #A3A3FF", +"/ c #BBBBFF", +"( c #DBDBDB", +"_ c #808B8B", +": c #5E5E5E", +"< c #858571", +"[ c #AEAE4B", +"} c #90902D", +"| c #8B8B8B", +"1 c #000027", +"2 c #D7D7FF", +"3 c #C3C3FF", +"4 c #A7A7FF", +"5 c #9B9BFF", +"6 c #D7D7D7", +"7 c #717474", +"8 c #727D7D", +"9 c #575721", +"0 c #BFBF7F", +"a c #DFDF8F", +"b c #DFDF60", +"c c #7F7F3B", +"d c #2F2F7F", +"e c #AFAFF3", +"f c #E7E7E7", +"g c #9797E7", +"h c #8787F3", +"i c #AFAFC3", +"j c #4F4F37", +"k c #8E9898", +"l c #484824", +"m c #4D4D0B", +"n c #8C8C8C", +"o c #7D7D36", +"p c #74742D", +"q c #535353", +"r c #636363", +"s c #5C5C4C", +"t c #818149", +"u c #78784C", +"v c #787840", +"w c #7E7E40", +"x c #787E46", +"y c #757F7F", +"z c #616121", +"A c #87874B", +"B c #C8C88C", +"C c #F6F6B6", +"D c #D4D498", +"E c #6C6C30", +"F c #424242", +"G c #9D9D23", +"H c #FDFD7B", +"I c #FFFF7F", +"J c #7F7F3F", +"K c #737C7C", +"L c #808038", +"M c #6B6B5F", +"N c #797935", +"O c #6E6E62", +"P c #8B8B43", +"Q c #8D8D8D", +"R c #1C4B4B", +"S c #959523", +"T c #F9F973", +"U c #7F7F43", +"V c #737D7D", +"W c #939343", +"X c #4FD3D3", +"Y c #185353", +"Z c #8D8D27", +"` c #F5F56B", +" . c #9B9B43", +".. c #57CFCF", +"+. c #145B5B", +"@. c #85851E", +"#. c #A3A343", +"$. c #3BA7A7", +"%. c #636300", +"&. c #CFCF67", +"*. c #F3F367", +"=. c #909A9A", +"-. c #4B4B07", +";. c #434325", +" . ", +" + @ # ", +" $ % & * = - ; > , ", +" ' ) ! ~ ~ { ] - - ^ / - ( ", +"_ : < [ [ } | 1 2 - 3 / 4 5 6 7 ", +"8 9 0 a b c 3 d e f f g h i j ", +"k l m n o p q r s t t t u v w x ", +"y z A B C D E F G H I I I I I J ", +"K I L M N O P Q R S T I I I I U ", +"V I I I I I I W X Y Z ` I I I U ", +"8 I I I I I I I ...+.@.I I I U ", +"K I I I I I I I I #.$.%.I I I U ", +"8 I I I I I I I I I &.*.I I I U ", +"V I I I I I I I I I I I I I I U ", +"=.-.-.-.-.-.-.-.-.-.-.-.-.-.-.;."}; diff --git a/src/html/htmlcell.cpp b/src/html/htmlcell.cpp new file mode 100644 index 0000000000..c70e0a281c --- /dev/null +++ b/src/html/htmlcell.cpp @@ -0,0 +1,507 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmlcell.cpp +// Purpose: wxHtmlCell - basic element of HTML output +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#include "wx/defs.h" +#if wxUSE_HTML + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include +#include +#include + + + + +//----------------------------------------------------------------------------- +// wxHtmlCell +//----------------------------------------------------------------------------- + + +void wxHtmlCell::OnMouseClick(wxWindow *parent, int x, int y, bool left, bool middle, bool right) +{ + if (GetLink() != wxEmptyString) + ((wxHtmlWindow*)parent) -> OnLinkClicked(GetLink()); + // note : this overcasting is legal because parent is *always* wxHtmlWindow +} + + + +//----------------------------------------------------------------------------- +// wxHtmlWordCell +//----------------------------------------------------------------------------- + +wxHtmlWordCell::wxHtmlWordCell(const wxString& word, wxDC& dc) : wxHtmlCell() +{ + m_Word = word; + m_Word.Replace(" ", " ", TRUE); + m_Word.Replace(""", "\"", TRUE); + m_Word.Replace("<", "<", TRUE); + m_Word.Replace(">", ">", TRUE); + m_Word.Replace("&", "&", TRUE); + dc.GetTextExtent(m_Word, &m_Width, &m_Height, &m_Descent); +} + + + +void wxHtmlWordCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2) +{ + dc.DrawText(m_Word, x + m_PosX, y + m_PosY); + wxHtmlCell::Draw(dc, x, y, view_y1, view_y2); +} + + + + + + + +//----------------------------------------------------------------------------- +// wxHtmlContainerCell +//----------------------------------------------------------------------------- + + +wxHtmlContainerCell::wxHtmlContainerCell(wxHtmlContainerCell *parent) : wxHtmlCell() +{ + m_Cells = m_LastCell = NULL; + m_Parent = parent; + if (m_Parent) m_Parent -> InsertCell(this); + m_AlignHor = HTML_ALIGN_LEFT; + m_AlignVer = HTML_ALIGN_BOTTOM; + m_IndentLeft = m_IndentRight = m_IndentTop = m_IndentBottom = 0; + m_WidthFloat = 100; m_WidthFloatUnits = HTML_UNITS_PERCENT; + m_UseBkColour = FALSE; + m_UseBorder = FALSE; + m_MinHeight = m_MaxLineWidth = 0; + m_MinHeightAlign = HTML_ALIGN_TOP; +} + + + +void wxHtmlContainerCell::SetIndent(int i, int what, int units) +{ + int val = (units == HTML_UNITS_PIXELS) ? i : -i; + if (what & HTML_INDENT_LEFT) m_IndentLeft = val; + if (what & HTML_INDENT_RIGHT) m_IndentRight = val; + if (what & HTML_INDENT_TOP) m_IndentTop = val; + if (what & HTML_INDENT_BOTTOM) m_IndentBottom = val; +} + + + +int wxHtmlContainerCell::GetIndent(int ind) const +{ + if (ind & HTML_INDENT_LEFT) return m_IndentLeft; + else if (ind & HTML_INDENT_RIGHT) return m_IndentRight; + else if (ind & HTML_INDENT_TOP) return m_IndentTop; + else if (ind & HTML_INDENT_BOTTOM) return m_IndentBottom; + else return -1; /* BUG! Should not be called... */ +} + + + + +int wxHtmlContainerCell::GetIndentUnits(int ind) const +{ + bool p = FALSE; + if (ind & HTML_INDENT_LEFT) p = m_IndentLeft < 0; + else if (ind & HTML_INDENT_RIGHT) p = m_IndentRight < 0; + else if (ind & HTML_INDENT_TOP) p = m_IndentTop < 0; + else if (ind & HTML_INDENT_BOTTOM) p = m_IndentBottom < 0; + if (p) return HTML_UNITS_PERCENT; + else return HTML_UNITS_PIXELS; +} + + + +void wxHtmlContainerCell::Layout(int w) +{ + wxHtmlCell *cell = m_Cells, *line = m_Cells; + long xpos = 0, ypos = m_IndentTop; + int xdelta = 0, ybasicpos = 0, ydiff; + int s_width, s_indent; + int ysizeup = 0, ysizedown = 0; + + /* + + WIDTH ADJUSTING : + + */ + + if (m_WidthFloatUnits == HTML_UNITS_PERCENT) { + if (m_WidthFloat < 0) m_Width = (100 + m_WidthFloat) * w / 100; + else m_Width = m_WidthFloat * w / 100; + } + else { + if (m_WidthFloat < 0) m_Width = w + m_WidthFloat; + else m_Width = m_WidthFloat; + } + + if (m_Cells) { + int l = (m_IndentLeft < 0) ? (-m_IndentLeft * m_Width / 100) : m_IndentLeft; + int r = (m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight; + m_Cells -> Layout(m_Width - (l + r)); + } + + /* + + LAYOUTING : + + */ + + // adjust indentation: + s_indent = (m_IndentLeft < 0) ? (-m_IndentLeft * m_Width / 100) : m_IndentLeft; + s_width = m_Width - s_indent - ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight); + + m_MaxLineWidth = 0; + + // my own layouting: + while (cell != NULL) { + switch (m_AlignVer) { + case HTML_ALIGN_TOP : ybasicpos = 0; break; + case HTML_ALIGN_BOTTOM : ybasicpos = - cell -> GetHeight(); break; + case HTML_ALIGN_CENTER : ybasicpos = - cell -> GetHeight() / 2; break; + } + ydiff = cell -> GetHeight() + ybasicpos; + + if (cell -> GetDescent() + ydiff > ysizedown) ysizedown = cell -> GetDescent() + ydiff; + if (ybasicpos + cell -> GetDescent() < -ysizeup) ysizeup = - (ybasicpos + cell -> GetDescent()); + + cell -> SetPos(xpos, ybasicpos + cell -> GetDescent()); + xpos += cell -> GetWidth(); + cell = cell -> GetNext(); + + // force new line if occured: + if ((cell == NULL) || (xpos + cell -> GetWidth() > s_width)) { + if (xpos > m_MaxLineWidth) m_MaxLineWidth = xpos; + if (ysizeup < 0) ysizeup = 0; + if (ysizedown < 0) ysizedown = 0; + switch (m_AlignHor) { + case HTML_ALIGN_LEFT : xdelta = 0; break; + case HTML_ALIGN_RIGHT : xdelta = 0 + (s_width - xpos); break; + case HTML_ALIGN_CENTER : xdelta = 0 + (s_width - xpos) / 2; break; + } + if (xdelta < 0) xdelta = 0; + xdelta += s_indent; + + ypos += ysizeup; + while (line != cell) { + line -> SetPos(line -> GetPosX() + xdelta, ypos + line -> GetPosY()); + line = line -> GetNext(); + } + + ypos += ysizedown; + xpos = 0; + ysizeup = ysizedown = 0; + line = cell; + } + } + + // setup height & width, depending on container layout: + m_Height = ypos + (ysizedown + ysizeup) + m_IndentBottom; + + if (m_Height < m_MinHeight) { + if (m_MinHeightAlign != HTML_ALIGN_TOP) { + int diff = m_MinHeight - m_Height; + if (m_MinHeightAlign == HTML_ALIGN_CENTER) diff /= 2; + cell = m_Cells; + while (cell) { + cell -> SetPos(cell -> GetPosX(), cell -> GetPosY() + diff); + cell = cell -> GetNext(); + } + } + m_Height = m_MinHeight; + } + + m_MaxLineWidth += s_indent + ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight); + if (m_Width < m_MaxLineWidth) m_Width = m_MaxLineWidth; + + wxHtmlCell::Layout(w); +} + + +#define mMin(a, b) (((a) < (b)) ? (a) : (b)) +#define mMax(a, b) (((a) < (b)) ? (b) : (a)) + +void wxHtmlContainerCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2) +{ + // container visible, draw it: + if ((y + m_PosY < view_y2) && (y + m_PosY + m_Height > view_y1)) { + + if (m_UseBkColour) { + wxBrush myb = wxBrush(m_BkColour, wxSOLID); + + int real_y1 = mMax(y + m_PosY, view_y1); + int real_y2 = mMin(y + m_PosY + m_Height - 1, view_y2); + + dc.SetBrush(myb); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(x + m_PosX, real_y1, m_Width, real_y2 - real_y1 + 1); + } + + if (m_UseBorder) { + wxPen mypen1(m_BorderColour1, 1, wxSOLID); + wxPen mypen2(m_BorderColour2, 1, wxSOLID); + + dc.SetPen(mypen1); + dc.DrawLine(x + m_PosX, y + m_PosY, x + m_PosX, y + m_PosY + m_Height - 1); + dc.DrawLine(x + m_PosX, y + m_PosY, x + m_PosX + m_Width - 1, y + m_PosY); + dc.SetPen(mypen2); + dc.DrawLine(x + m_PosX + m_Width - 1, y + m_PosY, x + m_PosX + m_Width - 1, y + m_PosY + m_Height - 1); + dc.DrawLine(x + m_PosX, y + m_PosY + m_Height - 1, x + m_PosX + m_Width - 1, y + m_PosY + m_Height - 1); + } + + if (m_Cells) m_Cells -> Draw(dc, x + m_PosX, y + m_PosY, view_y1, view_y2); + } + // container invisible, just proceed font+color changing: + else { + if (m_Cells) m_Cells -> DrawInvisible(dc, x + m_PosX, y + m_PosY); + } + + wxHtmlCell::Draw(dc, x, y, view_y1, view_y2); +} + + + +void wxHtmlContainerCell::DrawInvisible(wxDC& dc, int x, int y) +{ + if (m_Cells) m_Cells -> DrawInvisible(dc, x + m_PosX, y + m_PosY); + wxHtmlCell::DrawInvisible(dc, x, y); +} + + + +wxString wxHtmlContainerCell::GetLink(int x, int y) const +{ + wxHtmlCell *c = m_Cells; + int cx, cy, cw, ch; + + while (c) { + cx = c -> GetPosX(), cy = c -> GetPosY(); + cw = c -> GetWidth(), ch = c -> GetHeight(); + if ((x >= cx) && (x < cx + cw) && (y >= cy) && (y < cy + ch)) + return c -> GetLink(x - cx, y - cy); + c = c -> GetNext(); + } + return wxEmptyString; +} + + + +void wxHtmlContainerCell::InsertCell(wxHtmlCell *f) +{ + if (!m_Cells) m_Cells = m_LastCell = f; + else { + m_LastCell -> SetNext(f); + m_LastCell = f; + if (m_LastCell) while (m_LastCell -> GetNext()) m_LastCell = m_LastCell -> GetNext(); + } + f -> SetParent(this); +} + + + +void wxHtmlContainerCell::SetAlign(const wxHtmlTag& tag) +{ + if (tag.HasParam("ALIGN")) { + wxString alg = tag.GetParam("ALIGN"); + alg.MakeUpper(); + if (alg == "CENTER") + SetAlignHor(HTML_ALIGN_CENTER); + else if (alg == "LEFT") + SetAlignHor(HTML_ALIGN_LEFT); + else if (alg == "RIGHT") + SetAlignHor(HTML_ALIGN_RIGHT); + } +} + + + +void wxHtmlContainerCell::SetWidthFloat(const wxHtmlTag& tag) +{ + if (tag.HasParam("WIDTH")) { + int wdi; + wxString wd = tag.GetParam("WIDTH"); + + if (wd[wd.Length()-1] == '%') { + sscanf(wd.c_str(), "%i%%", &wdi); + SetWidthFloat(wdi, HTML_UNITS_PERCENT); + } + else { + sscanf(wd.c_str(), "%i", &wdi); + SetWidthFloat(wdi, HTML_UNITS_PIXELS); + } + } +} + + + +const wxHtmlCell* wxHtmlContainerCell::Find(int condition, const void* param) const +{ + const wxHtmlCell *r = NULL; + + if (m_Cells) { + r = m_Cells -> Find(condition, param); + if (r) return r; + } + + return wxHtmlCell::Find(condition, param); +} + + + +void wxHtmlContainerCell::OnMouseClick(wxWindow *parent, int x, int y, bool left, bool middle, bool right) +{ + if (m_Cells) { + wxHtmlCell *c = m_Cells; + while (c) { + if ( (c -> GetPosX() <= x) && + (c -> GetPosY() <= y) && + (c -> GetPosX() + c -> GetWidth() > x) && + (c -> GetPosY() + c -> GetHeight() > y)) { + c -> OnMouseClick(parent, x - c -> GetPosX(), y - c -> GetPosY(), left, middle, right); + break; + } + c = c -> GetNext(); + } + } +} + + + + + +//-------------------------------------------------------------------------------- +// wxHtmlColourCell +//-------------------------------------------------------------------------------- + +void wxHtmlColourCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2) +{ + if (m_Flags & HTML_CLR_FOREGROUND) + dc.SetTextForeground(m_Colour); + if (m_Flags & HTML_CLR_BACKGROUND) { + dc.SetBackground(wxBrush(m_Colour, wxSOLID)); + dc.SetTextBackground(m_Colour); + } + wxHtmlCell::Draw(dc, x, y, view_y1, view_y2); +} + +void wxHtmlColourCell::DrawInvisible(wxDC& dc, int x, int y) +{ + if (m_Flags & HTML_CLR_FOREGROUND) + dc.SetTextForeground(m_Colour); + if (m_Flags & HTML_CLR_BACKGROUND) { + dc.SetBackground(wxBrush(m_Colour, wxSOLID)); + dc.SetTextBackground(m_Colour); + } + wxHtmlCell::DrawInvisible(dc, x, y); +} + + + + +//-------------------------------------------------------------------------------- +// wxHtmlFontCell +//-------------------------------------------------------------------------------- + +void wxHtmlFontCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2) +{ + dc.SetFont(*m_Font); + wxHtmlCell::Draw(dc, x, y, view_y1, view_y2); +} + +void wxHtmlFontCell::DrawInvisible(wxDC& dc, int x, int y) +{ + dc.SetFont(*m_Font); + wxHtmlCell::DrawInvisible(dc, x, y); +} + + + + + + + + +//-------------------------------------------------------------------------------- +// wxHtmlWidgetCell +//-------------------------------------------------------------------------------- + +wxHtmlWidgetCell::wxHtmlWidgetCell(wxWindow *wnd, int w) +{ + int sx, sy; + m_Wnd = wnd; + m_Wnd -> GetSize(&sx, &sy); + m_Width = sx, m_Height = sy; + m_WidthFloat = w; +} + + +void wxHtmlWidgetCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2) +{ + int absx = 0, absy = 0, stx, sty; + wxHtmlCell *c = this; + + while (c) { + absx += c -> GetPosX(); + absy += c -> GetPosY(); + c = c -> GetParent(); + } + + ((wxScrolledWindow*)(m_Wnd -> GetParent())) -> ViewStart(&stx, &sty); + + m_Wnd -> SetSize(absx - HTML_SCROLL_STEP * stx, absy - HTML_SCROLL_STEP * sty, m_Width, m_Height); +// m_Wnd -> Refresh(); + + wxHtmlCell::Draw(dc, x, y, view_y1, view_y2); +} + + + +void wxHtmlWidgetCell::DrawInvisible(wxDC& dc, int x, int y) +{ + int absx = 0, absy = 0, stx, sty; + wxHtmlCell *c = this; + + while (c) { + absx += c -> GetPosX(); + absy += c -> GetPosY(); + c = c -> GetParent(); + } + ((wxScrolledWindow*)(m_Wnd -> GetParent())) -> ViewStart(&stx, &sty); + + m_Wnd -> SetSize(absx - HTML_SCROLL_STEP * stx, absy - HTML_SCROLL_STEP * sty, m_Width, m_Height); + wxHtmlCell::DrawInvisible(dc, x, y); +} + + + +void wxHtmlWidgetCell::Layout(int w) +{ + if (m_WidthFloat != 0) { + m_Width = (w * m_WidthFloat) / 100; + m_Wnd -> SetSize(m_Width, m_Height); + } + + wxHtmlCell::Layout(w); +} + +#endif diff --git a/src/html/htmlfilter.cpp b/src/html/htmlfilter.cpp new file mode 100644 index 0000000000..792240be7e --- /dev/null +++ b/src/html/htmlfilter.cpp @@ -0,0 +1,170 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: filter.cpp +// Purpose: wxHtmlFilter - input filter for translating into HTML format +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#include "wx/defs.h" +#if wxUSE_HTML + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include +#include + + +/* + +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& file) +{ + return TRUE; +} + + + +wxString wxHtmlFilterPlainText::ReadFile(const wxFSFile& file) +{ + wxInputStream *s = file.GetStream(); + char *src; + wxString doc, doc2; + + if (s == NULL) return wxEmptyString; + src = (char*) malloc(s -> StreamSize()); + src[s -> StreamSize()] = 0; + s -> Read(src, s -> StreamSize()); + doc = src; + free(src); + + doc.Replace("<", "<", TRUE); + doc.Replace(">", ">", TRUE); + doc2 = "

\n" + doc + "\n
"; + return doc2; +} + + + + + +//-------------------------------------------------------------------------------- +// wxHtmlFilterImage +// filter for image/* +//-------------------------------------------------------------------------------- + +class wxHtmlFilterImage : public wxHtmlFilter +{ + DECLARE_DYNAMIC_CLASS(wxHtmlFilterImage) + + public: + virtual bool CanRead(const wxFSFile& file); + virtual wxString ReadFile(const wxFSFile& file); +}; + +IMPLEMENT_DYNAMIC_CLASS(wxHtmlFilterImage, wxHtmlFilter) + + + +bool wxHtmlFilterImage::CanRead(const wxFSFile& file) +{ + return (file.GetMimeType().Left(6) == "image/"); +} + + + +wxString wxHtmlFilterImage::ReadFile(const wxFSFile& file) +{ + return (""); +} + + + + +//-------------------------------------------------------------------------------- +// wxHtmlFilterPlainText +// filter for text/plain or uknown +//-------------------------------------------------------------------------------- + +class wxHtmlFilterHTML : public wxHtmlFilter +{ + DECLARE_DYNAMIC_CLASS(wxHtmlFilterHTML) + + public: + virtual bool CanRead(const wxFSFile& file); + virtual wxString ReadFile(const wxFSFile& file); +}; + + +IMPLEMENT_DYNAMIC_CLASS(wxHtmlFilterHTML, wxHtmlFilter) + +bool wxHtmlFilterHTML::CanRead(const wxFSFile& file) +{ + return (file.GetMimeType() == "text/html"); +} + + + +wxString wxHtmlFilterHTML::ReadFile(const wxFSFile& file) +{ + wxInputStream *s = file.GetStream(); + char *src; + wxString doc; + + if (s == NULL) return wxEmptyString; + src = (char*) malloc(s -> StreamSize() + 1); + src[s -> StreamSize()] = 0; + s -> Read(src, s -> StreamSize()); + doc = src; + free(src); + + 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 \ No newline at end of file diff --git a/src/html/htmlhelp.cpp b/src/html/htmlhelp.cpp new file mode 100644 index 0000000000..22d69b06cd --- /dev/null +++ b/src/html/htmlhelp.cpp @@ -0,0 +1,864 @@ +// Name: htmlhelp.cpp +// Purpose: Help controller +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#include "wx/defs.h" +#if wxUSE_HTML + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include + +#if !((wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7))) +#include +#endif + + +// Bitmaps: + +#ifndef __WXMSW__ +#include "bitmaps/panel.xpm" +#include "bitmaps/back.xpm" +#include "bitmaps/forward.xpm" +#include "bitmaps/book.xpm" +#include "bitmaps/folder.xpm" +#include "bitmaps/page.xpm" +#endif + +#include "search.h" + + + +//----------------------------------------------------------------------------- +// Helper constants +//----------------------------------------------------------------------------- + + +// Command IDs : + +enum { + wxID_HTML_PANEL = wxID_HIGHEST + 1, + wxID_HTML_BACK, + wxID_HTML_FORWARD, + wxID_HTML_TREECTRL, + wxID_HTML_INDEXPAGE, + wxID_HTML_INDEXLIST, + wxID_HTML_NOTEBOOK, + wxID_HTML_SEARCHPAGE, + wxID_HTML_SEARCHTEXT, + wxID_HTML_SEARCHLIST, + wxID_HTML_SEARCHBUTTON +}; + + +// Images: + +enum { + IMG_Book = 0, + IMG_Folder, + IMG_Page +}; + + + + + + +class HtmlHelpTreeItemData : public wxTreeItemData +{ + private: + wxString m_Page; + + public: + HtmlHelpTreeItemData(HtmlContentsItem *it) : wxTreeItemData() {m_Page = it -> m_Book -> GetBasePath() + it -> m_Page;} + const wxString& GetPage() {return m_Page;} +}; + + + + + +#include +WX_DEFINE_OBJARRAY(HtmlBookRecArray) + + + + + + + + + +//----------------------------------------------------------------------------- +// wxHtmlHelpController +//----------------------------------------------------------------------------- + + +IMPLEMENT_DYNAMIC_CLASS(wxHtmlHelpController, wxEvtHandler) + + +wxHtmlHelpController::wxHtmlHelpController() : wxEvtHandler() +{ + m_Frame = NULL; + m_Config = NULL; + m_ConfigRoot = wxEmptyString; + m_TitleFormat = _("Help : %s"); + m_TempPath = wxEmptyString; + + m_Cfg.x = m_Cfg.y = 0; + m_Cfg.w = 700; m_Cfg.h = 480; + m_Cfg.sashpos = 240; + m_Cfg.navig_on = TRUE; + + m_ContentsImageList = new wxImageList(12, 12); + m_ContentsImageList -> Add(wxICON(book)); + m_ContentsImageList -> Add(wxICON(folder)); + m_ContentsImageList -> Add(wxICON(page)); + + m_Contents = NULL; + m_ContentsCnt = 0; + m_Index = NULL; + m_IndexCnt = 0; +} + + + +wxHtmlHelpController::~wxHtmlHelpController() +{ + int i; + + m_BookRecords.Empty(); + delete m_ContentsImageList; + if (m_Contents) { + for (i = 0; i < m_ContentsCnt; i++) { + free(m_Contents[i].m_Page); + free(m_Contents[i].m_Name); + } + free(m_Contents); + } + if (m_Index) { + for (i = 0; i < m_IndexCnt; i++) { + free(m_Index[i].m_Page); + free(m_Index[i].m_Name); + } + free(m_Index); + } +} + + + +void wxHtmlHelpController::SetTempDir(const wxString& path) +{ + if (path == wxEmptyString) m_TempPath = path; + else { + if (wxIsAbsolutePath(path)) m_TempPath = path; + else m_TempPath = wxGetCwd() + "/" + path; + + if (m_TempPath[m_TempPath.Length() - 1] != '/') + m_TempPath << "/"; + } +} + + + + +// Reads one line, stores it into buf and returns pointer to new line or NULL. +static char* ReadLine(char *line, char *buf) +{ + char *writeptr = buf, *readptr = line; + + while (*readptr != 0 && *readptr != '\r' && *readptr != '\n') *(writeptr++) = *(readptr++); + *writeptr = 0; + while (*readptr == '\r' || *readptr == '\n') readptr++; + if (*readptr == 0) return NULL; + else return readptr; +} + + +static wxString SafeFileName(const wxString& s) +{ + wxString res = s; + res.Replace(":", "_", TRUE); + res.Replace(" ", "_", TRUE); + res.Replace("/", "_", TRUE); + res.Replace("\\", "_", TRUE); + res.Replace("#", "_", TRUE); + res.Replace(".", "_", TRUE); + return res; +} + + +static int IndexCompareFunc(const void *a, const void *b) +{ + return strcmp(((HtmlContentsItem*)a) -> m_Name, ((HtmlContentsItem*)b) -> m_Name); +} + + + +bool wxHtmlHelpController::AddBook(const wxString& book, bool show_wait_msg = FALSE) +{ + wxFSFile *fi; + wxFileSystem fsys; + wxInputStream *s; + HtmlBookRecord *bookr; + wxString bookFull; + + int sz; + char *buff, *lineptr; + char linebuf[300]; + + wxString title = _("noname"), + safetitle, + start = wxEmptyString, + contents = wxEmptyString, index = wxEmptyString; + + if (wxIsAbsolutePath(book)) bookFull = book; + else bookFull = wxGetCwd() + "/" + book; + + fi = fsys.OpenFile(bookFull); + if (fi == NULL) return FALSE; + fsys.ChangePathTo(bookFull); + s = fi -> GetStream(); + sz = s -> StreamSize(); + buff = (char*) malloc(sz+1); + buff[sz] = 0; + s -> Read(buff, sz); + lineptr = buff; + delete fi; + + while ((lineptr = ReadLine(lineptr, linebuf)) != NULL) { + if (strstr(linebuf, "Title=") == linebuf) + title = linebuf + strlen("Title="); + if (strstr(linebuf, "Default topic=") == linebuf) + start = linebuf + strlen("Default topic="); + if (strstr(linebuf, "Index file=") == linebuf) + index = linebuf + strlen("Index file="); + if (strstr(linebuf, "Contents file=") == linebuf) + contents = linebuf + strlen("Contents file="); + } + free(buff); + + bookr = new HtmlBookRecord(fsys.GetPath(), title, start); + + if (m_ContentsCnt % HTML_REALLOC_STEP == 0) + m_Contents = (HtmlContentsItem*) realloc(m_Contents, (m_ContentsCnt + HTML_REALLOC_STEP) * sizeof(HtmlContentsItem)); + m_Contents[m_ContentsCnt].m_Level = 0; + m_Contents[m_ContentsCnt].m_ID = 0; + m_Contents[m_ContentsCnt].m_Page = (char*) malloc(start.Length() + 1); + strcpy(m_Contents[m_ContentsCnt].m_Page, start.c_str()); + m_Contents[m_ContentsCnt].m_Name = (char*) malloc(title.Length() + 1); + strcpy(m_Contents[m_ContentsCnt].m_Name, title.c_str()); + m_Contents[m_ContentsCnt].m_Book = bookr; + m_ContentsCnt++; + + // Try to find cached binary versions: + safetitle = SafeFileName(title); + fi = fsys.OpenFile(safetitle + ".cached"); + if (fi == NULL) fi = fsys.OpenFile(m_TempPath + safetitle + ".cached"); + if ((fi == NULL) || (m_TempPath == wxEmptyString)) { + LoadMSProject(bookr, fsys, index, contents, show_wait_msg); + if (m_TempPath != wxEmptyString) { + wxFileOutputStream *outs = new wxFileOutputStream(m_TempPath + safetitle + ".cached"); + SaveCachedBook(bookr, outs); + delete outs; + } + } + else { + LoadCachedBook(bookr, fi -> GetStream()); + delete fi; + } + + m_BookRecords.Add(bookr); + if (m_IndexCnt > 0) + qsort(m_Index, m_IndexCnt, sizeof(HtmlContentsItem), IndexCompareFunc); + + return TRUE; +} + + + + +void wxHtmlHelpController::Display(const wxString& x) +{ + int cnt; + int i; + wxFileSystem fsys; + wxFSFile *f; + + CreateHelpWindow(); + + /* 1. try to open given file: */ + + cnt = m_BookRecords.GetCount(); + for (i = 0; i < cnt; i++) { + f = fsys.OpenFile(m_BookRecords[i].GetBasePath() + x); + if (f) { + m_HtmlWin -> LoadPage(m_BookRecords[i].GetBasePath() + x); + delete f; + return; + } + } + + + /* 2. try to find a book: */ + + for (i = 0; i < cnt; i++) { + if (m_BookRecords[i].GetTitle() == x) { + m_HtmlWin -> LoadPage(m_BookRecords[i].GetBasePath() + m_BookRecords[i].GetStart()); + return; + } + } + + /* 3. try to find in contents: */ + + cnt = m_ContentsCnt; + for (i = 0; i < cnt; i++) { + if (strcmp(m_Contents[i].m_Name, x) == 0) { + m_HtmlWin -> LoadPage(m_Contents[i].m_Book -> GetBasePath() + m_Contents[i].m_Page); + return; + } + } + + + /* 4. try to find in index: */ + + cnt = m_IndexCnt; + for (i = 0; i < cnt; i++) { + if (strcmp(m_Index[i].m_Name, x) == 0) { + m_HtmlWin -> LoadPage(m_Index[i].m_Book -> GetBasePath() + m_Index[i].m_Page); + return; + } + } + + + /* 5. if everything failed, search the documents: */ + + KeywordSearch(x); +} + + + +void wxHtmlHelpController::Display(const int id) +{ + CreateHelpWindow(); + + for (int i = 0; i < m_ContentsCnt; i++) { + if (m_Contents[i].m_ID == id) { + m_HtmlWin -> LoadPage(m_Contents[i].m_Book -> GetBasePath() + m_Contents[i].m_Page); + return; + } + } +} + + + +void wxHtmlHelpController::DisplayContents() +{ + CreateHelpWindow(); + m_Frame -> Raise(); + if (!m_Splitter -> IsSplit()) { + m_NavigPan -> Show(TRUE); + m_HtmlWin -> Show(TRUE); + m_Splitter -> SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos); + } + m_NavigPan -> SetSelection(0); +} + + + +void wxHtmlHelpController::DisplayIndex() +{ + CreateHelpWindow(); + m_Frame -> Raise(); + if (!m_Splitter -> IsSplit()) { + m_NavigPan -> Show(TRUE); + m_HtmlWin -> Show(TRUE); + m_Splitter -> SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos); + } + m_NavigPan -> SetSelection(1); +} + + + + +#if (wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7)) + +class MyProgressDlg : public wxDialog +{ + public: + bool m_Canceled; + + MyProgressDlg(wxWindow *parent) : wxDialog(parent, -1, + _("Searching..."), + wxPoint(0, 0), +#ifdef __WXGTK__ + wxSize(300, 110)) +#else + wxSize(300, 130)) +#endif + {m_Canceled = FALSE;} + void OnCancel(wxCommandEvent& event) {m_Canceled = TRUE;} + DECLARE_EVENT_TABLE() +}; +BEGIN_EVENT_TABLE(MyProgressDlg, wxDialog) + EVT_BUTTON(wxID_CANCEL, MyProgressDlg::OnCancel) +END_EVENT_TABLE() + +#endif + + +bool wxHtmlHelpController::KeywordSearch(const wxString& keyword) +{ + int foundcnt = 0; + + CreateHelpWindow(); + m_Frame -> Raise(); + if (!m_Splitter -> IsSplit()) { + m_NavigPan -> Show(TRUE); + m_HtmlWin -> Show(TRUE); + m_Splitter -> SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos); + } + m_NavigPan -> SetSelection(2); + m_SearchList -> Clear(); + m_SearchText -> SetValue(keyword); + m_SearchButton -> Enable(FALSE); + + { + int cnt = m_ContentsCnt; + wxSearchEngine engine; + wxFileSystem fsys; + wxFSFile *file; + wxString lastpage = wxEmptyString; + wxString foundstr; + +#if (wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7)) + MyProgressDlg progress(m_Frame); + + wxStaticText *prompt = new wxStaticText(&progress, -1, "", wxPoint(20, 50), wxSize(260, 25), wxALIGN_CENTER); + wxGauge *gauge = new wxGauge(&progress, -1, cnt, wxPoint(20, 20), wxSize(260, 25)); + wxButton *btn = new wxButton(&progress, wxID_CANCEL, _("Cancel"), wxPoint(110, 70), wxSize(80, 25)); + btn = btn; /* fool compiler :-) */ + prompt -> SetLabel(_("No matching page found yet")); + + progress.Centre(wxBOTH); + progress.Show(TRUE); +#else + wxProgressDialog progress(_("Searching..."), _("No matching page found yet"), cnt, m_Frame, wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_AUTO_HIDE); +#endif + + engine.LookFor(keyword); + + for (int i = 0; i < cnt; i++) { +#if (wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7)) + gauge -> SetValue(i); + if (progress.m_Canceled) break; +#else + if (progress.Update(i) == FALSE) break; +#endif + wxYield(); + + file = fsys.OpenFile(m_Contents[i].m_Book -> GetBasePath() + m_Contents[i].m_Page); + if (file) { + if (lastpage != file -> GetLocation()) { + lastpage = file -> GetLocation(); + if (engine.Scan(file -> GetStream())) { + foundstr.Printf(_("Found %i matches"), ++foundcnt); +#if (wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7)) + prompt -> SetLabel(foundstr); +#else + progress.Update(i, foundstr); +#endif + wxYield(); + m_SearchList -> Append(m_Contents[i].m_Name, (char*)(m_Contents + i)); + } + } + delete file; + } + } + +#if (wxVERSION_NUMBER < 2100) || ((wxVERSION_NUMBER == 2100) && (wxBETA_NUMBER < 7)) + progress.Close(TRUE); +#endif + } + + m_SearchButton -> Enable(TRUE); + m_SearchText -> SetSelection(0, keyword.Length()); + m_SearchText -> SetFocus(); + if (foundcnt) { + HtmlContentsItem *it = (HtmlContentsItem*) m_SearchList -> GetClientData(0); + if (it) m_HtmlWin -> LoadPage(it -> m_Book -> GetBasePath() + it -> m_Page); + } + return (foundcnt > 0); +} + + + + + + +void wxHtmlHelpController::CreateHelpWindow() +{ + wxBusyCursor cur; + wxString oldpath; + wxStatusBar *sbar; + + if (m_Frame) { + m_Frame -> Raise(); + m_Frame -> Show(TRUE); + return; + } + + wxBusyInfo busyinfo(_("Preparing help window...")); + + if (m_Config) ReadCustomization(m_Config, m_ConfigRoot); + + m_Frame = new wxFrame(NULL, -1, "", wxPoint(m_Cfg.x, m_Cfg.y), wxSize(m_Cfg.w, m_Cfg.h)); + m_Frame -> PushEventHandler(this); + sbar = m_Frame -> CreateStatusBar(); + + { + wxToolBar *toolBar; + toolBar = m_Frame -> CreateToolBar(wxNO_BORDER | wxTB_HORIZONTAL | wxTB_FLAT | wxTB_DOCKABLE); + toolBar -> SetMargins(2, 2); + wxBitmap* toolBarBitmaps[3]; + +#ifdef __WXMSW__ + toolBarBitmaps[0] = new wxBitmap("panel"); + toolBarBitmaps[1] = new wxBitmap("back"); + toolBarBitmaps[2] = new wxBitmap("forward"); + int width = 24; +#else + toolBarBitmaps[0] = new wxBitmap(panel_xpm); + toolBarBitmaps[1] = new wxBitmap(back_xpm); + toolBarBitmaps[2] = new wxBitmap(forward_xpm); + int width = 16; +#endif + + int currentX = 5; + + toolBar -> AddTool(wxID_HTML_PANEL, *(toolBarBitmaps[0]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, _("Show/hide navigation panel")); + currentX += width + 5; + toolBar -> AddSeparator(); + toolBar -> AddTool(wxID_HTML_BACK, *(toolBarBitmaps[1]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, _("Go back to the previous HTML page")); + currentX += width + 5; + toolBar -> AddTool(wxID_HTML_FORWARD, *(toolBarBitmaps[2]), wxNullBitmap, FALSE, currentX, -1, (wxObject *) NULL, _("Go forward to the next HTML page")); + currentX += width + 5; + + toolBar -> Realize(); + + // Can delete the bitmaps since they're reference counted + for (int i = 0; i < 3; i++) delete toolBarBitmaps[i]; + } + + + { + m_Splitter = new wxSplitterWindow(m_Frame); + + m_HtmlWin = new wxHtmlWindow(m_Splitter); + m_HtmlWin -> SetRelatedFrame(m_Frame, m_TitleFormat); + m_HtmlWin -> SetRelatedStatusBar(0); + if (m_Config) m_HtmlWin -> ReadCustomization(m_Config, m_ConfigRoot); + + m_NavigPan = new wxNotebook(m_Splitter, wxID_HTML_NOTEBOOK, wxDefaultPosition, wxDefaultSize); + { + m_ContentsBox = new wxTreeCtrl(m_NavigPan, wxID_HTML_TREECTRL, wxDefaultPosition, wxDefaultSize, wxTR_HAS_BUTTONS | wxSUNKEN_BORDER); + m_ContentsBox -> SetImageList(m_ContentsImageList); + m_NavigPan -> AddPage(m_ContentsBox, _("Contents")); + } + + { + wxWindow *dummy = new wxPanel(m_NavigPan, wxID_HTML_INDEXPAGE); + wxLayoutConstraints *b1 = new wxLayoutConstraints; + b1 -> top.SameAs (dummy, wxTop, 0); + b1 -> left.SameAs (dummy, wxLeft, 0); + b1 -> width.PercentOf (dummy, wxWidth, 100); + b1 -> bottom.SameAs (dummy, wxBottom, 0); + m_IndexBox = new wxListBox(dummy, wxID_HTML_INDEXLIST, wxDefaultPosition, wxDefaultSize, 0); + m_IndexBox -> SetConstraints(b1); + dummy -> SetAutoLayout(TRUE); + m_NavigPan -> AddPage(dummy, _("Index")); + } + + { + wxWindow *dummy = new wxPanel(m_NavigPan, wxID_HTML_SEARCHPAGE); + + wxLayoutConstraints *b1 = new wxLayoutConstraints; + m_SearchText = new wxTextCtrl(dummy, wxID_HTML_SEARCHTEXT); + b1 -> top.SameAs (dummy, wxTop, 0); + b1 -> left.SameAs (dummy, wxLeft, 0); + b1 -> right.SameAs (dummy, wxRight, 0); + b1 -> height.AsIs(); + m_SearchText -> SetConstraints(b1); + + wxLayoutConstraints *b2 = new wxLayoutConstraints; + m_SearchButton = new wxButton(dummy, wxID_HTML_SEARCHBUTTON, _("Search!")); + b2 -> top.Below (m_SearchText, 10); + b2 -> right.SameAs (dummy, wxRight, 10); + b2 -> width.AsIs(); + b2 -> height.AsIs(); + m_SearchButton -> SetConstraints(b2); + + wxLayoutConstraints *b3 = new wxLayoutConstraints; + m_SearchList = new wxListBox(dummy, wxID_HTML_SEARCHLIST, wxDefaultPosition, wxDefaultSize, 0); + b3 -> top.Below (m_SearchButton, 10); + b3 -> left.SameAs (dummy, wxLeft, 0); + b3 -> right.SameAs (dummy, wxRight, 0); + b3 -> bottom.SameAs (dummy, wxBottom, 0); + m_SearchList -> SetConstraints(b3); + + dummy -> SetAutoLayout(TRUE); + dummy -> Layout(); + m_NavigPan -> AddPage(dummy, _("Search")); + } + + RefreshLists(); + m_NavigPan -> Show(TRUE); + m_HtmlWin -> Show(TRUE); + m_Splitter -> SetMinimumPaneSize(20); + m_Splitter -> SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos); + if (!m_Cfg.navig_on) m_Splitter -> Unsplit(m_NavigPan); + wxYield(); + } + + m_Frame -> Show(TRUE); + wxYield(); +} + + + +#define MAX_ROOTS 64 + +void wxHtmlHelpController::CreateContents() +{ + HtmlContentsItem *it; + wxTreeItemId roots[MAX_ROOTS]; + bool imaged[MAX_ROOTS]; + int count = m_ContentsCnt; + + m_ContentsBox -> DeleteAllItems(); + roots[0] = m_ContentsBox -> AddRoot(_("(Help)")); + imaged[0] = TRUE; + + for (int i = 0; i < count; i++) { + it = m_Contents + i; + roots[it -> m_Level + 1] = m_ContentsBox -> AppendItem(roots[it -> m_Level], it -> m_Name, IMG_Page, -1, new HtmlHelpTreeItemData(it)); + if (it -> m_Level == 0) { + m_ContentsBox -> SetItemBold(roots[1], TRUE); + m_ContentsBox -> SetItemImage(roots[1], IMG_Book); + m_ContentsBox -> SetItemSelectedImage(roots[1], IMG_Book); + imaged[1] = TRUE; + } + else imaged[it -> m_Level + 1] = FALSE; + + if (!imaged[it -> m_Level]) { + m_ContentsBox -> SetItemImage(roots[it -> m_Level], IMG_Folder); + m_ContentsBox -> SetItemSelectedImage(roots[it -> m_Level], IMG_Folder); + imaged[it -> m_Level] = TRUE; + } + } + + m_ContentsBox -> Expand(roots[0]); +} + + + + +void wxHtmlHelpController::CreateIndex() +{ + m_IndexBox -> Clear(); + + for (int i = 0; i < m_IndexCnt; i++) + m_IndexBox -> Append(m_Index[i].m_Name, (char*)(m_Index + i)); +} + + + +void wxHtmlHelpController::RefreshLists() +{ + if (m_Frame) { + CreateContents(); + CreateIndex(); + m_SearchList -> Clear(); + } +} + + + + + + + +void wxHtmlHelpController::ReadCustomization(wxConfigBase *cfg, wxString path) +{ + wxString oldpath; + wxString tmp; + + if (path != wxEmptyString) { + oldpath = cfg -> GetPath(); + cfg -> SetPath(path); + } + + m_Cfg.navig_on = (bool) cfg -> Read("hcNavigPanel", m_Cfg.navig_on); + m_Cfg.sashpos = cfg -> Read("hcSashPos", m_Cfg.sashpos); + m_Cfg.x = cfg -> Read("hcX", m_Cfg.x); + m_Cfg.y = cfg -> Read("hcY", m_Cfg.y); + m_Cfg.w = cfg -> Read("hcW", m_Cfg.w); + m_Cfg.h = cfg -> Read("hcH", m_Cfg.h); + + if (path != wxEmptyString) + cfg -> SetPath(oldpath); +} + + + +void wxHtmlHelpController::WriteCustomization(wxConfigBase *cfg, wxString path) +{ + wxString oldpath; + wxString tmp; + + if (path != wxEmptyString) { + oldpath = cfg -> GetPath(); + cfg -> SetPath(path); + } + + cfg -> Write("hcNavigPanel", m_Cfg.navig_on); + cfg -> Write("hcSashPos", (long)m_Cfg.sashpos); + cfg -> Write("hcX", (long)m_Cfg.x); + cfg -> Write("hcY", (long)m_Cfg.y); + cfg -> Write("hcW", (long)m_Cfg.w); + cfg -> Write("hcH", (long)m_Cfg.h); + + if (path != wxEmptyString) + cfg -> SetPath(oldpath); +} + + + + + +/* +EVENT HANDLING : +*/ + + +void wxHtmlHelpController::OnToolbar(wxCommandEvent& event) +{ + switch (event.GetId()) { + case wxID_HTML_BACK : + m_HtmlWin -> HistoryBack(); + break; + case wxID_HTML_FORWARD : + m_HtmlWin -> HistoryForward(); + break; + case wxID_HTML_PANEL : + if (m_Splitter -> IsSplit()) { + m_Cfg.sashpos = m_Splitter -> GetSashPosition(); + m_Splitter -> Unsplit(m_NavigPan); + } + else { + m_NavigPan -> Show(TRUE); + m_HtmlWin -> Show(TRUE); + m_Splitter -> SplitVertically(m_NavigPan, m_HtmlWin, m_Cfg.sashpos); + } + break; + } +} + + + +void wxHtmlHelpController::OnContentsSel(wxTreeEvent& event) +{ + HtmlHelpTreeItemData *pg; + + pg = (HtmlHelpTreeItemData*) m_ContentsBox -> GetItemData(event.GetItem()); + if (pg) m_HtmlWin -> LoadPage(pg -> GetPage()); +} + + + +void wxHtmlHelpController::OnIndexSel(wxCommandEvent& event) +{ + HtmlContentsItem *it = (HtmlContentsItem*) m_IndexBox -> GetClientData(m_IndexBox -> GetSelection()); + if (it) m_HtmlWin -> LoadPage(it -> m_Book -> GetBasePath() + it -> m_Page); +} + + + +void wxHtmlHelpController::OnSearchSel(wxCommandEvent& event) +{ + HtmlContentsItem *it = (HtmlContentsItem*) m_SearchList -> GetClientData(m_SearchList -> GetSelection()); + if (it) m_HtmlWin -> LoadPage(it -> m_Book -> GetBasePath() + it -> m_Page); +} + + + +void wxHtmlHelpController::OnCloseWindow(wxCloseEvent& event) +{ + int a, b; + + m_Cfg.navig_on = m_Splitter -> IsSplit(); + if (m_Cfg.navig_on) + m_Cfg.sashpos = m_Splitter -> GetSashPosition(); + m_Frame -> GetPosition(&a, &b); + m_Cfg.x = a, m_Cfg.y = b; + m_Frame -> GetSize(&a, &b); + m_Cfg.w = a, m_Cfg.h = b; + + if (m_Config) { + WriteCustomization(m_Config, m_ConfigRoot); + m_HtmlWin -> WriteCustomization(m_Config, m_ConfigRoot); + } + m_Frame = NULL; + + event.Skip(); +} + + + +void wxHtmlHelpController::OnSearch(wxCommandEvent& event) +{ + wxString sr = m_SearchText -> GetLineText(0); + + if (sr != wxEmptyString) KeywordSearch(sr); +} + + + +BEGIN_EVENT_TABLE(wxHtmlHelpController, wxEvtHandler) + EVT_TOOL_RANGE(wxID_HTML_PANEL, wxID_HTML_FORWARD, wxHtmlHelpController::OnToolbar) + EVT_TREE_SEL_CHANGED(wxID_HTML_TREECTRL, wxHtmlHelpController::OnContentsSel) + EVT_LISTBOX(wxID_HTML_INDEXLIST, wxHtmlHelpController::OnIndexSel) + EVT_LISTBOX(wxID_HTML_SEARCHLIST, wxHtmlHelpController::OnSearchSel) + EVT_CLOSE(wxHtmlHelpController::OnCloseWindow) + EVT_BUTTON(wxID_HTML_SEARCHBUTTON, wxHtmlHelpController::OnSearch) + EVT_TEXT_ENTER(wxID_HTML_SEARCHTEXT, wxHtmlHelpController::OnSearch) +END_EVENT_TABLE() + + + +#endif + diff --git a/src/html/htmlhelp_io.cpp b/src/html/htmlhelp_io.cpp new file mode 100644 index 0000000000..b4d82e7ec9 --- /dev/null +++ b/src/html/htmlhelp_io.cpp @@ -0,0 +1,250 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmlhelp.cpp +// Purpose: Help controller +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +//#ifdef __GNUG__ +//#pragma implementation "htmlhelp.h" +//#endif +// --- already in htmlhelp.cpp + +#include + +#include "wx/defs.h" +#if wxUSE_HTML + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + + +#include +#include + + + + +class HP_Parser : public wxHtmlParser +{ + public: + void AddText(const char* text) {} + wxObject* GetProduct() {return NULL;} +}; + + + +class HP_TagHandler : public wxHtmlTagHandler +{ + private: + wxString m_Name, m_Page; + int m_Level; + int m_ID; + int m_Index; + HtmlContentsItem *m_Items; + int m_ItemsCnt; + HtmlBookRecord *m_Book; + + public: + HP_TagHandler(HtmlBookRecord *b) : wxHtmlTagHandler() {m_Book = b; m_Items = NULL; m_ItemsCnt = 0; m_Name = m_Page = wxEmptyString; m_Level = 0;} + wxString GetSupportedTags() {return "UL,OBJECT,PARAM";} + bool HandleTag(const wxHtmlTag& tag); + void WriteOut(HtmlContentsItem*& array, int& size); + void ReadIn(HtmlContentsItem* array, int size); +}; + + +bool HP_TagHandler::HandleTag(const wxHtmlTag& tag) +{ + if (tag.GetName() == "UL") { + m_Level++; + ParseInner(tag); + m_Level--; + return TRUE; + } + + else if (tag.GetName() == "OBJECT") { + m_Name = m_Page = wxEmptyString; + ParseInner(tag); + if (m_Page != wxEmptyString) { + if (m_ItemsCnt % HTML_REALLOC_STEP == 0) + m_Items = (HtmlContentsItem*) realloc(m_Items, (m_ItemsCnt + HTML_REALLOC_STEP) * sizeof(HtmlContentsItem)); + m_Items[m_ItemsCnt].m_Level = m_Level; + m_Items[m_ItemsCnt].m_ID = m_ID; + m_Items[m_ItemsCnt].m_Page = (char*) malloc(m_Page.Length() + 1); + strcpy(m_Items[m_ItemsCnt].m_Page, m_Page.c_str()); + m_Items[m_ItemsCnt].m_Name = (char*) malloc(m_Name.Length() + 1); + strcpy(m_Items[m_ItemsCnt].m_Name, m_Name.c_str()); + m_Items[m_ItemsCnt].m_Book = m_Book; + m_ItemsCnt++; + } + return TRUE; + } + + else { // "PARAM" + if (m_Name == wxEmptyString && tag.GetParam("NAME") == "Name") m_Name = tag.GetParam("VALUE"); + if (tag.GetParam("NAME") == "Local") m_Page = tag.GetParam("VALUE"); + if (tag.GetParam("NAME") == "ID") tag.ScanParam("VALUE", "%i", &m_ID); + return FALSE; + } +} + + + +void HP_TagHandler::WriteOut(HtmlContentsItem*& array, int& size) +{ + array = m_Items; + size = m_ItemsCnt; + m_Items = NULL; + m_ItemsCnt = 0; +} + +void HP_TagHandler::ReadIn(HtmlContentsItem* array, int size) +{ + m_Items = array; + m_ItemsCnt = size; +} + + + + +void wxHtmlHelpController::LoadMSProject(HtmlBookRecord *book, wxFileSystem& fsys, const wxString& indexfile, const wxString& contentsfile, bool show_wait_msg) +{ + wxFSFile *f; + char *buf; + int sz; + wxString string; + wxBusyInfo *busyinfo = (show_wait_msg) ? new wxBusyInfo(_("Importing help file : \n") + book -> m_Title) : NULL; + + HP_Parser parser; + HP_TagHandler *handler = new HP_TagHandler(book); + parser.AddTagHandler(handler); + + f = fsys.OpenFile(contentsfile); + if (f) { + sz = f -> GetStream() -> StreamSize(); + buf = (char*) malloc(sz+1); + buf[sz] = 0; + f -> GetStream() -> Read(buf, sz); + delete f; + handler -> ReadIn(m_Contents, m_ContentsCnt); + parser.Parse(buf); + handler -> WriteOut(m_Contents, m_ContentsCnt); + free(buf); + } + + f = fsys.OpenFile(indexfile); + if (f) { + sz = f -> GetStream() -> StreamSize(); + buf = (char*) malloc(sz+1); + buf[sz] = 0; + f -> GetStream() -> Read(buf, sz); + delete f; + handler -> ReadIn(m_Index, m_IndexCnt); + parser.Parse(buf); + handler -> WriteOut(m_Index, m_IndexCnt); + free(buf); + } + if (show_wait_msg) delete busyinfo; +} + + + + + + +void wxHtmlHelpController::LoadCachedBook(HtmlBookRecord *book, wxInputStream *f) +{ + int i, st; + int x; + + /* load contents : */ + + f -> Read(&x, sizeof(x)); + st = m_ContentsCnt; + m_ContentsCnt += x; + m_Contents = (HtmlContentsItem*) realloc(m_Contents, (m_ContentsCnt / HTML_REALLOC_STEP + 1) * HTML_REALLOC_STEP * sizeof(HtmlContentsItem)); + for (i = st; i < m_ContentsCnt; i++) { + f -> Read(&x, sizeof(x)); + m_Contents[i].m_Level = x; + f -> Read(&x, sizeof(x)); + m_Contents[i].m_ID = x; + f -> Read(&x, sizeof(x)); + m_Contents[i].m_Name = (char*) malloc(x); + f -> Read(m_Contents[i].m_Name, x); + f -> Read(&x, sizeof(x)); + m_Contents[i].m_Page = (char*) malloc(x); + f -> Read(m_Contents[i].m_Page, x); + m_Contents[i].m_Book = book; + } + + /* load index : */ + + f -> Read(&x, sizeof(x)); + st = m_IndexCnt; + m_IndexCnt += x; + m_Index = (HtmlContentsItem*) realloc(m_Index, (m_IndexCnt / HTML_REALLOC_STEP + 1) * HTML_REALLOC_STEP * sizeof(HtmlContentsItem)); + for (i = st; i < m_IndexCnt; i++) { + f -> Read(&x, sizeof(x)); + m_Index[i].m_Name = (char*) malloc(x); + f -> Read(m_Index[i].m_Name, x); + f -> Read(&x, sizeof(x)); + m_Index[i].m_Page = (char*) malloc(x); + f -> Read(m_Index[i].m_Page, x); + m_Index[i].m_Book = book; + } +} + + + + + + +void wxHtmlHelpController::SaveCachedBook(HtmlBookRecord *book, wxOutputStream *f) +{ + int i; + int x; + + /* save contents : */ + + x = 0; + for (i = 0; i < m_ContentsCnt; i++) if (m_Contents[i].m_Book == book && m_Contents[i].m_Level > 0) x++; + f -> Write(&x, sizeof(x)); + for (i = 0; i < m_ContentsCnt; i++) { + if (m_Contents[i].m_Book != book || m_Contents[i].m_Level == 0) continue; + x = m_Contents[i].m_Level; + f -> Write(&x, sizeof(x)); + x = m_Contents[i].m_ID; + f -> Write(&x, sizeof(x)); + x = strlen(m_Contents[i].m_Name) + 1; + f -> Write(&x, sizeof(x)); + f -> Write(m_Contents[i].m_Name, x); + x = strlen(m_Contents[i].m_Page) + 1; + f -> Write(&x, sizeof(x)); + f -> Write(m_Contents[i].m_Page, x); + } + + /* save index : */ + + x = 0; + for (i = 0; i < m_IndexCnt; i++) if (m_Index[i].m_Book == book && m_Index[i].m_Level > 0) x++; + f -> Write(&x, sizeof(x)); + for (i = 0; i < m_IndexCnt; i++) { + if (m_Index[i].m_Book != book || m_Index[i].m_Level == 0) continue; + x = strlen(m_Index[i].m_Name) + 1; + f -> Write(&x, sizeof(x)); + f -> Write(m_Index[i].m_Name, x); + x = strlen(m_Index[i].m_Page) + 1; + f -> Write(&x, sizeof(x)); + f -> Write(m_Index[i].m_Page, x); + } +} + +#endif \ No newline at end of file diff --git a/src/html/htmlparser.cpp b/src/html/htmlparser.cpp new file mode 100644 index 0000000000..ff72c7d6cb --- /dev/null +++ b/src/html/htmlparser.cpp @@ -0,0 +1,169 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmlparser.cpp +// Purpose: wxHtmlParser class (generic parser) +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#include "wx/defs.h" +#if wxUSE_HTML + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include +#include +#include +#include +#include + + + +//----------------------------------------------------------------------------- +// wxHtmlParser +//----------------------------------------------------------------------------- + +IMPLEMENT_ABSTRACT_CLASS(wxHtmlParser,wxObject) + + +wxObject* wxHtmlParser::Parse(const wxString& source) +{ + wxObject *result; + + InitParser(source); + DoParsing(); + result = GetProduct(); + DoneParser(); + return result; +} + + + +void wxHtmlParser::InitParser(const wxString& source) +{ + m_Source = source; + m_Cache = new wxHtmlTagsCache(m_Source); +} + + + +void wxHtmlParser::DoneParser() +{ + delete m_Cache; + m_Cache = NULL; +} + + + +#define HTML_MAX_BUFLEN 1024 + +void wxHtmlParser::DoParsing(int begin_pos, int end_pos) +{ + char temp[HTML_BUFLEN], c; + int i; + int templen; + + templen = 0; + i = begin_pos; + + while (i < end_pos) { + c = m_Source[i]; + + // continue building word: + if (c != '<') { + temp[templen++] = c; + if (templen == HTML_BUFLEN-1) { + temp[templen] = 0; + AddText(temp); + templen = 0; + } + i++; + } + + else if (c == '<') { + wxHtmlTag tag(m_Source, i, end_pos, m_Cache); + + if (templen) { + temp[templen] = 0; + AddText(temp); + templen = 0; + } + AddTag(tag); + if (tag.HasEnding()) i = tag.GetEndPos2(); + else i = tag.GetBeginPos(); + } + } + + if (templen) { // last word of block :-( + temp[templen] = 0; + AddText(temp); + } +} + + + +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 (!inner) { + if (tag.HasEnding()) + DoParsing(tag.GetBeginPos(), tag.GetEndPos1()); + } +} + + + +void wxHtmlParser::AddTagHandler(wxHtmlTagHandler *handler) +{ + wxString s(handler -> GetSupportedTags()); + wxStringTokenizer tokenizer(s, ", "); + +#if (wxVERSION_NUMBER < 2100) + while (tokenizer.HasMoreToken()) +#else + while (tokenizer.HasMoreTokens()) +#endif + m_HandlersHash.Put(tokenizer.NextToken(), handler); + + if (m_HandlersList.IndexOf(handler) == wxNOT_FOUND) + m_HandlersList.Append(handler); + + handler -> SetParser(this); +} + + + +wxHtmlParser::~wxHtmlParser() +{ + m_HandlersHash.Clear(); + m_HandlersList.DeleteContents(TRUE); + m_HandlersList.Clear(); +} + + + +//----------------------------------------------------------------------------- +// wxHtmlTagHandler +//----------------------------------------------------------------------------- + +IMPLEMENT_ABSTRACT_CLASS(wxHtmlTagHandler,wxObject) + +#endif \ No newline at end of file diff --git a/src/html/htmltag.cpp b/src/html/htmltag.cpp new file mode 100644 index 0000000000..16e780335f --- /dev/null +++ b/src/html/htmltag.cpp @@ -0,0 +1,248 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmltag.cpp +// Purpose: wxHtmlTag class (represents single tag) +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#include "wx/defs.h" +#if wxUSE_HTML + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include +#include + + + + +//----------------------------------------------------------------------------- +// wxHtmlTagsCache +//----------------------------------------------------------------------------- + +IMPLEMENT_CLASS(wxHtmlTagsCache,wxObject) + +#define CACHE_INCREMENT 64 + +wxHtmlTagsCache::wxHtmlTagsCache(const wxString& source) +{ + const char *src = source.c_str(); + int i, tg, pos, stpos; + int lng = source.Length(); + char dummy[256]; + + m_Cache = NULL; + m_CacheSize = 0; + m_CachePos = 0; + + pos = 0; + while (pos < lng) { + if (src[pos] == '<') { // tag found: + if (m_CacheSize % CACHE_INCREMENT == 0) + m_Cache = (sCacheItem*) realloc(m_Cache, (m_CacheSize + CACHE_INCREMENT) * sizeof(sCacheItem)); + tg = m_CacheSize++; + m_Cache[tg].Key = stpos = pos++; + dummy[0] = 0; i = 0; + while ((src[pos] != '>') && (src[pos] != ' ')) { + dummy[i] = src[pos++]; + if ((dummy[i] >= 'a') && (dummy[i] <= 'z')) dummy[i] -= ('a' - 'A'); + i++; + } + dummy[i] = 0; + m_Cache[tg].Name = (char*) malloc(i+1); + memcpy(m_Cache[tg].Name, dummy, i+1); + + while (src[pos] != '>') pos++; + + if (src[stpos+1] == '/') { // 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) && (strcmp(m_Cache[i].Name, dummy+1) == 0)) { + m_Cache[i].End1 = stpos; + m_Cache[i].End2 = pos + 1; + break; + } + } + else { + m_Cache[tg].End1 = m_Cache[tg].End2 = -1; + } + } + + pos++; + } + + // ok, we're done, now we'll free .Name members of cache - we don't need it anymore: + for (i = 0; i < m_CacheSize; i++) { + free(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 {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(const wxString& source, int pos, int end_pos, wxHtmlTagsCache* cache) : wxObject() +{ + int i; + char c; + + // fill-in name, params and begin pos: + m_Name = m_Params = wxEmptyString; + i = pos+1; + if (source[i] == '/') {m_Ending = TRUE; i++;} + else m_Ending = FALSE; + + while ((i < end_pos) && ((c = source[i++]) != ' ') && (c != '>')) { + if ((c >= 'a') && (c <= 'z')) c -= ('a' - 'A'); + m_Name += c; + } + + if (source[i-1] != '>') + while ((i < end_pos) && ((c = source[i++]) != '>')) { + if ((c >= 'a') && (c <= 'z')) c -= ('a' - 'A'); + m_Params += c; + if (c == '"') { + while ((i < end_pos) && ((c = source[i++]) != '"')) m_Params += c; + m_Params += c; + } + } + 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; +} + + + +bool wxHtmlTag::HasParam(const wxString& par) const +{ + const char *st = m_Params, *p = par; + const char *st2, *p2; + + if (*st == 0) return FALSE; + if (*p == 0) return FALSE; + for (st2 = st, p2 = p; ; st2++) { + if (*p2 == 0) return TRUE; + if (*st2 == 0) return FALSE; + if (*p2 != *st2) p2 = p; + if (*p2 == *st2) p2++; + if (*st2 == ' ') p2 = p; + else if (*st2 == '=') { + p2 = p; + while (*st2 != ' ') { + if (*st2 == '"') { + st2++; + while (*st2 != '"') st2++; + } + st2++; + if (*st2 == 0) return FALSE; + } + } + } +} + + + +wxString wxHtmlTag::GetParam(const wxString& par, bool with_commas) const +{ + const char *st = m_Params, *p = par; + const char *st2, *p2; + bool comma; + + if (*st == 0) return ""; + if (*p == 0) return ""; + for (st2 = st, p2 = p; ; st2++) { + if (*p2 == 0) { // found + wxString fnd = ""; + st2++; // '=' character + comma = FALSE; + if (!with_commas && (*(st2) == '"')) {st2++; comma = TRUE;} + while (*st2 != 0) { + if (*st2 == '"') comma = !comma; + else if ((*st2 == ' ') && (!comma)) break; + fnd += (*(st2++)); + } + if (!with_commas && (*(st2-1) == '"')) fnd.RemoveLast(); + return fnd; + } + if (*st2 == 0) return ""; + if (*p2 != *st2) p2 = p; + if (*p2 == *st2) p2++; + if (*st2 == ' ') p2 = p; + else if (*st2 == '=') { + p2 = p; + while (*st2 != ' ') { + if (*st2 == '"') { + st2++; + while (*st2 != '"') st2++; + } + st2++; + } + } + } +} + + + +void wxHtmlTag::ScanParam(const wxString& par, char *format, ...) const +{ + va_list argptr; + wxString parval = GetParam(par); + + va_start(argptr, format); + +#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__VISUALC__) + sscanf((const char*)parval, format, va_arg(argptr, void *)); +#else + vsscanf((const char*)parval, format, argptr); +#endif + +/* + --- vsscanf is not defined under Cygwin or Mingw32 or M$ Visual C++ environment + if this module doesn't compile with your compiler, + modify the def statement and let me know. Thanks... + + So far wxHtml functions are scanning only _one_ value + so I workarounded this by supposing that there is only + one ...-parameter +*/ + + va_end(argptr); +} + +#endif \ No newline at end of file diff --git a/src/html/htmlwin.cpp b/src/html/htmlwin.cpp new file mode 100644 index 0000000000..b0077c8b1a --- /dev/null +++ b/src/html/htmlwin.cpp @@ -0,0 +1,542 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmlwin.cpp +// Purpose: wxHtmlWindow class for parsing & displaying HTML (implementation) +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#include "wx/defs.h" +#if wxUSE_HTML + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include + +#include + +///// This is my own wxBusyCursor. It works only with one window. + +#if (defined __WXGTK__) && (wxVERSION_NUMBER < 2100) +class wxLocalBusyCursor +#else +class wxLocalBusyCursor : public wxBusyCursor +#endif +{ + private: + wxWindow *m_Wnd; + public: +#if (defined __WXGTK__) && (wxVERSION_NUMBER < 2100) + wxLocalBusyCursor(wxWindow *w) {m_Wnd = w; m_Wnd -> SetCursor(*wxHOURGLASS_CURSOR);} + ~wxLocalBusyCursor() {m_Wnd -> SetCursor(*wxSTANDARD_CURSOR);} +#else + wxLocalBusyCursor(wxWindow *w) : wxBusyCursor() {} +#endif +}; + + + + +//----------------------------------------------------------------------------- +// wxHtmlWindow +//----------------------------------------------------------------------------- + + + +#include +WX_DEFINE_OBJARRAY(HtmlHistoryArray) + + +wxHtmlWindow::wxHtmlWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, + const wxString& name, bool scrollable) : wxScrolledWindow(parent, id, pos, size, wxVSCROLL, name) +{ + m_tmpMouseMoved = FALSE; + m_tmpCanDraw = TRUE; + m_FS = new wxFileSystem(); + m_RelatedStatusBar = -1; + m_RelatedFrame = NULL; + m_TitleFormat = "%s"; + m_OpenedPage = m_OpenedAnchor = wxEmptyString; + m_Cell = NULL; + m_Parser = new wxHtmlWinParser(this); + m_Parser -> SetFS(m_FS); + SetBorders(10); + m_HistoryPos = -1; + m_HistoryOn = TRUE; + m_Scrollable = scrollable; + SetPage(""); +} + + + +wxHtmlWindow::~wxHtmlWindow() +{ + HistoryClear(); + + if (m_Cell) delete m_Cell; + + wxList *parser_data = m_Parser -> GetTempData(); + if (parser_data) delete parser_data; + + delete m_Parser; + delete m_FS; +} + + + +void wxHtmlWindow::SetRelatedFrame(wxFrame* frame, const wxString& format) +{ + m_RelatedFrame = frame; + m_TitleFormat = format; +} + + + +void wxHtmlWindow::SetRelatedStatusBar(int bar) +{ + m_RelatedStatusBar = bar; +} + + + +void wxHtmlWindow::SetFonts(wxString normal_face, int normal_italic_mode, wxString fixed_face, int fixed_italic_mode, int *sizes) +{ + m_Parser -> SetFonts(normal_face, normal_italic_mode, fixed_face, fixed_italic_mode, sizes); + if (!m_OpenedPage.IsEmpty()) LoadPage(m_OpenedPage); +} + + + +bool wxHtmlWindow::SetPage(const wxString& source) +{ + wxClientDC *dc = new wxClientDC(this); + + dc -> SetMapMode(wxMM_TEXT); + SetBackgroundColour(wxColour(0xFF, 0xFF, 0xFF)); + m_OpenedPage = m_OpenedAnchor = wxEmptyString; + m_Parser -> SetDC(dc); + if (m_Cell) delete m_Cell; + m_Cell = (wxHtmlContainerCell*) m_Parser -> Parse(source); + delete dc; + m_Cell -> SetIndent(m_Borders, HTML_INDENT_ALL, HTML_UNITS_PIXELS); + m_Cell -> SetAlignHor(HTML_ALIGN_CENTER); + CreateLayout(); + Refresh(); + return TRUE; +} + + +bool wxHtmlWindow::LoadPage(const wxString& location) +{ + wxFSFile *f; + bool rt_val; + wxLocalBusyCursor b(this); + + m_tmpCanDraw = FALSE; + if (m_HistoryOn && (m_HistoryPos != -1)) { // store scroll position into history item + int x, y; + ViewStart(&x, &y); + m_History[m_HistoryPos].SetPos(y); + } + + if (location[0] == '#') { // local anchor + wxString anch = location.Mid(1) /*1 to end*/; + m_tmpCanDraw = TRUE; + rt_val = ScrollToAnchor(anch); + } + + else { + // load&display it: + if (m_RelatedStatusBar != -1) { + m_RelatedFrame -> SetStatusText(_("Connecting..."), m_RelatedStatusBar); + Refresh(); + } + + f = m_FS -> OpenFile(location); + if (f == NULL) { + wxString err; + + err.Printf(_("The browser is unable to open requested location :\n\n%s"), WXSTRINGCAST location); + wxMessageBox(err, "Error"); + m_tmpCanDraw = TRUE; + return FALSE; + } + + else { + wxNode *node; + wxString src = wxEmptyString; + + if (m_RelatedStatusBar != -1) { + wxString msg = _("Loading : ") + location; + m_RelatedFrame -> SetStatusText(msg, m_RelatedStatusBar); + Refresh(); + } + + node = m_Filters.GetFirst(); + while (node){ + wxHtmlFilter *h = (wxHtmlFilter*) node -> GetData(); + if (h -> CanRead(*f)) { + src = h -> ReadFile(*f); + break; + } + node = node -> GetNext(); + } + if (src == wxEmptyString) src = m_DefaultFilter.ReadFile(*f); + + m_FS -> ChangePathTo(f -> GetLocation()); + rt_val = SetPage(src); + m_OpenedPage = f -> GetLocation(); + if (f -> GetAnchor() != wxEmptyString) { + m_tmpCanDraw = TRUE; + ScrollToAnchor(f -> GetAnchor()); + m_tmpCanDraw = FALSE; + } + + delete f; + + if (m_RelatedStatusBar != -1) m_RelatedFrame -> SetStatusText(_("Done"), m_RelatedStatusBar); + } + } + + if (m_HistoryOn) { // add this page to history there: + int c = m_History.GetCount() - (m_HistoryPos + 1); + + m_HistoryPos++; + for (int i = 0; i < c; i++) + m_History.Remove(m_HistoryPos); + m_History.Add(new HtmlHistoryItem(m_OpenedPage, m_OpenedAnchor)); + } + + m_tmpCanDraw = TRUE; + Refresh(); + return rt_val; +} + + + +bool wxHtmlWindow::ScrollToAnchor(const wxString& anchor) +{ + const wxHtmlCell *c = m_Cell -> Find(HTML_COND_ISANCHOR, &anchor); + if (!c) return FALSE; + else { + int y; + + for (y = 0; c != NULL; c = c -> GetParent()) y += c -> GetPosY(); + Scroll(-1, y / HTML_SCROLL_STEP); + m_OpenedAnchor = anchor; + return TRUE; + } +} + + +void wxHtmlWindow::SetTitle(const wxString& title) +{ + if (m_RelatedFrame) { + wxString tit; + tit.Printf(m_TitleFormat, title.c_str()); + m_RelatedFrame -> SetTitle(tit); + } +} + + + + + +void wxHtmlWindow::CreateLayout() +{ + int ClientWidth, ClientHeight; + + if (!m_Cell) return; + GetClientSize(&ClientWidth, &ClientHeight); + m_Cell -> Layout(ClientWidth); + if (m_Scrollable) + SetScrollbars(HTML_SCROLL_STEP, HTML_SCROLL_STEP, + m_Cell -> GetWidth() / HTML_SCROLL_STEP, + m_Cell -> GetHeight() / HTML_SCROLL_STEP + /*cheat: top-level frag is always container*/ ); +} + + + +void wxHtmlWindow::ReadCustomization(wxConfigBase *cfg, wxString path) +{ + wxString oldpath; + wxString tmp; + + if (path != wxEmptyString) { + oldpath = cfg -> GetPath(); + cfg -> SetPath(path); + } + + m_Borders = cfg -> Read("wxHtmlWindow/Borders", m_Borders); + m_Parser -> m_FontFaceFixed = cfg -> Read("wxHtmlWindow/FontFaceFixed", m_Parser -> m_FontFaceFixed); + m_Parser -> m_FontFaceNormal = cfg -> Read("wxHtmlWindow/FontFaceNormal", m_Parser -> m_FontFaceNormal); + m_Parser -> m_ItalicModeFixed = cfg -> Read("wxHtmlWindow/ItalicModeFixed", m_Parser -> m_ItalicModeFixed); + m_Parser -> m_ItalicModeNormal = cfg -> Read("wxHtmlWindow/ItalicModeNormal", m_Parser -> m_ItalicModeNormal); + for (int i = 0; i < 7; i++) { + tmp.Printf("wxHtmlWindow/FontsSize%i", i); + m_Parser -> m_FontsSizes[i] = cfg -> Read(tmp, m_Parser -> m_FontsSizes[i]); + } + + if (path != wxEmptyString) + cfg -> SetPath(oldpath); +} + + + +void wxHtmlWindow::WriteCustomization(wxConfigBase *cfg, wxString path) +{ + wxString oldpath; + wxString tmp; + + if (path != wxEmptyString) { + oldpath = cfg -> GetPath(); + cfg -> SetPath(path); + } + + cfg -> Write("wxHtmlWindow/Borders", (long) m_Borders); + cfg -> Write("wxHtmlWindow/FontFaceFixed", m_Parser -> m_FontFaceFixed); + cfg -> Write("wxHtmlWindow/FontFaceNormal", m_Parser -> m_FontFaceNormal); + cfg -> Write("wxHtmlWindow/ItalicModeFixed", (long) m_Parser -> m_ItalicModeFixed); + cfg -> Write("wxHtmlWindow/ItalicModeNormal", (long) m_Parser -> m_ItalicModeNormal); + for (int i = 0; i < 7; i++) { + tmp.Printf("wxHtmlWindow/FontsSize%i", i); + cfg -> Write(tmp, (long) m_Parser -> m_FontsSizes[i]); + } + + if (path != wxEmptyString) + cfg -> SetPath(oldpath); +} + + + +bool wxHtmlWindow::HistoryBack() +{ + wxString a, l; + + if (m_HistoryPos < 1) return FALSE; + + m_HistoryPos--; + + l = m_History[m_HistoryPos].GetPage(); + a = m_History[m_HistoryPos].GetAnchor(); + m_HistoryOn = FALSE; + if (a == wxEmptyString) LoadPage(l); + else LoadPage(l + "#" + a); + m_HistoryOn = TRUE; + Scroll(0, m_History[m_HistoryPos].GetPos()); + Refresh(); + return TRUE; +} + + + +bool wxHtmlWindow::HistoryForward() +{ + wxString a, l; + + if (m_HistoryPos == -1) return FALSE; + if (m_HistoryPos >= (int)m_History.GetCount() - 1)return FALSE; + + m_OpenedPage = wxEmptyString; // this will disable adding new entry into history in LoadPage() + + m_HistoryPos++; + l = m_History[m_HistoryPos].GetPage(); + a = m_History[m_HistoryPos].GetAnchor(); + m_HistoryOn = FALSE; + if (a == wxEmptyString) LoadPage(l); + else LoadPage(l + "#" + a); + m_HistoryOn = TRUE; + Scroll(0, m_History[m_HistoryPos].GetPos()); + Refresh(); + return TRUE; +} + + + +void wxHtmlWindow::HistoryClear() +{ + m_History.Empty(); + m_HistoryPos = -1; +} + + + +wxList wxHtmlWindow::m_Filters; +wxHtmlFilterPlainText wxHtmlWindow::m_DefaultFilter; + +void wxHtmlWindow::AddFilter(wxHtmlFilter *filter) +{ + m_Filters.DeleteContents(TRUE); + m_Filters.Append(filter); +} + + + + +void wxHtmlWindow::OnLinkClicked(const wxString& link) +{ + LoadPage(link); +} + + + +void wxHtmlWindow::OnDraw(wxDC& dc) +{ + int x, y; + wxRegionIterator upd(GetUpdateRegion()); // get the update rect list + int v_y, v_h; + + if (!m_tmpCanDraw) return; + dc.SetMapMode(wxMM_TEXT); +#if defined(_MSC_VER) && (_MSC_VER == 1200) + ::SetMapMode((HDC)dc.GetHDC(), MM_TEXT); +#endif + dc.SetBackgroundMode(wxTRANSPARENT); + ViewStart(&x, &y); + + while (upd) { + v_y = upd.GetY(); + v_h = upd.GetH(); + if (m_Cell) m_Cell -> Draw(dc, 0, 0, y * HTML_SCROLL_STEP + v_y, y * HTML_SCROLL_STEP + v_h + v_y); + upd++; + } +} + + + + +void wxHtmlWindow::OnSize(wxSizeEvent& event) +{ + wxScrolledWindow::OnSize(event); + CreateLayout(); +} + + + +void wxHtmlWindow::OnKeyDown(wxKeyEvent& event) +{ + int dummy; + int sty, szy, cliy; + + ViewStart(&dummy, &sty); + GetClientSize(&dummy, &cliy); cliy /= HTML_SCROLL_STEP; + GetVirtualSize(&dummy, &szy); szy /= HTML_SCROLL_STEP; + + switch (event.KeyCode()) { + case WXK_PAGEUP : + case WXK_PRIOR : + Scroll(-1, sty - cliy); + break; + case WXK_PAGEDOWN : + case WXK_NEXT : + Scroll(-1, sty + cliy); + break; + case WXK_HOME : + Scroll(-1, 0); + break; + case WXK_END : + Scroll(-1, szy - cliy); + break; + case WXK_UP : + Scroll(-1, sty - 1); + break; + case WXK_DOWN : + Scroll(-1, sty + 1); + break; + } +} + + + +void wxHtmlWindow::OnMouseEvent(wxMouseEvent& event) +{ + m_tmpMouseMoved = TRUE; + + if (event.ButtonDown()) { + int sx, sy; + wxPoint pos; + wxString lnk; + + ViewStart(&sx, &sy); sx *= HTML_SCROLL_STEP; sy *= HTML_SCROLL_STEP; + pos = event.GetPosition(); + + if (m_Cell) + m_Cell -> OnMouseClick(this, sx + pos.x, sy + pos.y, event.ButtonDown(1), event.ButtonDown(2), event.ButtonDown(3)); + } +} + + + +void wxHtmlWindow::OnIdle(wxIdleEvent& event) +{ + static wxCursor cur_hand(wxCURSOR_HAND), cur_arrow(wxCURSOR_ARROW); + + if (m_tmpMouseMoved && (m_Cell != NULL)) { + int sx, sy; + int x, y; + wxString lnk; + + ViewStart(&sx, &sy); sx *= HTML_SCROLL_STEP; sy *= HTML_SCROLL_STEP; + wxGetMousePosition(&x, &y); + ScreenToClient(&x, &y); + lnk = m_Cell -> GetLink(sx + x, sy + y); + + if (lnk == wxEmptyString) { + SetCursor(cur_arrow); + if (m_RelatedStatusBar != -1) m_RelatedFrame -> SetStatusText(wxEmptyString, m_RelatedStatusBar); + } + else { + SetCursor(cur_hand); + if (m_RelatedStatusBar != -1) m_RelatedFrame -> SetStatusText(lnk, m_RelatedStatusBar); + } + m_tmpMouseMoved = FALSE; + } +} + + + + +IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindow,wxScrolledWindow) + +BEGIN_EVENT_TABLE(wxHtmlWindow, wxScrolledWindow) + EVT_SIZE(wxHtmlWindow::OnSize) + EVT_LEFT_DOWN(wxHtmlWindow::OnMouseEvent) + EVT_MOTION(wxHtmlWindow::OnMouseEvent) + EVT_IDLE(wxHtmlWindow::OnIdle) + EVT_KEY_DOWN(wxHtmlWindow::OnKeyDown) +END_EVENT_TABLE() + + + + + + + + +///// default mod handlers are forced there: + +FORCE_LINK(mod_layout) +FORCE_LINK(mod_fonts) +FORCE_LINK(mod_image) +FORCE_LINK(mod_list) +FORCE_LINK(mod_pre) +FORCE_LINK(mod_hline) +FORCE_LINK(mod_links) +FORCE_LINK(mod_tables) + + +#endif \ No newline at end of file diff --git a/src/html/htmlwinparser.cpp b/src/html/htmlwinparser.cpp new file mode 100644 index 0000000000..efc1d0d198 --- /dev/null +++ b/src/html/htmlwinparser.cpp @@ -0,0 +1,288 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: htmlwinparser.cpp +// Purpose: wxHtmlParser class (generic parser) +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#include "wx/defs.h" +#if wxUSE_HTML + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include +#include +#include + + +//----------------------------------------------------------------------------- +// wxHtmlWinParser +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxHtmlWinParser,wxHtmlParser) + +wxList wxHtmlWinParser::m_Modules; + +wxHtmlWinParser::wxHtmlWinParser(wxWindow *wnd) : wxHtmlParser() +{ + m_Window = wnd; + m_Container = NULL; + m_DC = NULL; + m_CharHeight = m_CharWidth = 0; + m_UseLink = FALSE; + + { + 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; +#ifdef __WXMSW__ + int default_sizes[7] = {7, 8, 10, 12, 16, 22, 30}; +#else + int default_sizes[7] = {10, 12, 14, 16, 19, 24, 32}; +#endif + SetFonts("", wxSLANT, "", wxSLANT, default_sizes); + } + + // fill in wxHtmlParser's tables: + wxNode *node = m_Modules.GetFirst(); + while (node){ + wxHtmlTagsModule *mod = (wxHtmlTagsModule*) node -> GetData(); + mod -> FillHandlersTable(this); + node = node -> GetNext(); + } +} + + + +void wxHtmlWinParser::AddModule(wxHtmlTagsModule *module) +{ + m_Modules.Append(module); +} + + + +void wxHtmlWinParser::SetFonts(wxString normal_face, int normal_italic_mode, wxString fixed_face, int fixed_italic_mode, int *sizes) +{ + for (int i = 0; i < 7; i++) m_FontsSizes[i] = sizes[i]; + m_FontFaceFixed = fixed_face; + m_FontFaceNormal = normal_face; + m_ItalicModeFixed = fixed_italic_mode; + m_ItalicModeNormal = normal_italic_mode; +} + + + +void wxHtmlWinParser::InitParser(const wxString& source) +{ + wxHtmlParser::InitParser(source); + wxASSERT_MSG(m_DC != NULL, _("no DC assigned to wxHtmlWinParser!!")); + + m_FontBold = m_FontItalic = m_FontUnderlined = m_FontFixed = FALSE; + m_FontSize = 0; + CreateCurrentFont(); // we're selecting default font into + m_DC -> GetTextExtent("H", &m_CharWidth, &m_CharHeight); + /* NOTE : we're not using GetCharWidth/Height() because + of differences under X and win + */ + + m_Link = ""; + m_LinkColor.Set(0, 0, 0xFF); + m_ActualColor.Set(0, 0, 0); + m_Align = HTML_ALIGN_LEFT; + m_tmpLastWasSpace = FALSE; + + OpenContainer(); + + OpenContainer(); + m_Container -> InsertCell(new wxHtmlColourCell(m_ActualColor)); + m_Container -> InsertCell(new wxHtmlFontCell(CreateCurrentFont())); +} + + + +void wxHtmlWinParser::DoneParser() +{ + m_Container = NULL; + wxHtmlParser::DoneParser(); +} + + + +wxObject* wxHtmlWinParser::GetProduct() +{ + wxHtmlContainerCell *top; + + CloseContainer(); + OpenContainer(); + GetContainer() -> SetIndent(m_CharHeight, HTML_INDENT_TOP); + top = m_Container; + while (top -> GetParent()) top = top -> GetParent(); + return top; +} + + + +wxList* wxHtmlWinParser::GetTempData() +{ + int i, j, k, l, m; + wxFont *f; + wxList *lst = wxHtmlParser::GetTempData(); + + if (lst == NULL) lst = new wxList; + lst -> DeleteContents(TRUE); + + 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++) { + f = m_FontsTable[i][j][k][l][m]; + if (f) lst -> Append(f); + } + return lst; +} + + + +void wxHtmlWinParser::AddText(const char* txt) +{ + wxHtmlCell *c; + int i = 0, x, lng = strlen(txt); + char temp[HTML_BUFLEN]; + register char d; + int templen = 0; + + if (m_tmpLastWasSpace) { + while ((i < lng) && ((txt[i] == '\n') || (txt[i] == '\r') || (txt[i] == ' ') || (txt[i] == '\t'))) i++; + } + + while (i < lng) { + x = 0; + d = temp[templen++] = txt[i]; + if ((d == '\n') || (d == '\r') || (d == ' ') || (d == '\t')) { + i++, x++; + while ((i < lng) && ((txt[i] == '\n') || (txt[i] == '\r') || (txt[i] == ' ') || (txt[i] == '\t'))) i++, x++; + } + else i++; + + if (x) { + temp[templen-1] = ' '; + temp[templen] = 0; + templen = 0; + c = new wxHtmlWordCell(temp, *(GetDC())); + if (m_UseLink) c -> SetLink(m_Link); + m_Container -> InsertCell(c); + m_tmpLastWasSpace = TRUE; + } + } + if (templen) { + temp[templen] = 0; + c = new wxHtmlWordCell(temp, *(GetDC())); + if (m_UseLink) c -> SetLink(m_Link); + m_Container -> InsertCell(c); + m_tmpLastWasSpace = FALSE; + } +} + + + +wxHtmlContainerCell* wxHtmlWinParser::OpenContainer() +{ + m_Container = new wxHtmlContainerCell(m_Container); + m_Container -> SetAlignHor(m_Align); + 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; +} + + + +wxFont* wxHtmlWinParser::CreateCurrentFont() +{ + int fb = GetFontBold(), + fi = GetFontItalic(), + fu = GetFontUnderlined(), + ff = GetFontFixed(), + fs = GetFontSize() + 2 /*remap from <-2;4> to <0;7>*/ ; + + if (m_FontsTable[fb][fi][fu][ff][fs] == NULL) { + m_FontsTable[fb][fi][fu][ff][fs] = + //wxTheFontList -> FindOrCreateFont( + new wxFont( + m_FontsSizes[fs], + ff ? wxMODERN : wxSWISS, + fi ? (ff ? m_ItalicModeFixed : m_ItalicModeNormal) : wxNORMAL, + fb ? wxBOLD : wxNORMAL, + fu ? TRUE : FALSE, ff ? m_FontFaceFixed : m_FontFaceNormal); + } + m_DC -> SetFont(*(m_FontsTable[fb][fi][fu][ff][fs])); + return (m_FontsTable[fb][fi][fu][ff][fs]); +} + + + + +//----------------------------------------------------------------------------- +// wxHtmlWinTagHandler +//----------------------------------------------------------------------------- + +IMPLEMENT_ABSTRACT_CLASS(wxHtmlWinTagHandler, wxHtmlTagHandler) + + + +//----------------------------------------------------------------------------- +// wxHtmlTagsModule +//----------------------------------------------------------------------------- + + +IMPLEMENT_DYNAMIC_CLASS(wxHtmlTagsModule, wxModule) + + +bool wxHtmlTagsModule::OnInit() +{ + wxHtmlWinParser::AddModule(this); + return TRUE; +} + + + +void wxHtmlTagsModule::OnExit() +{ +} + +#endif \ No newline at end of file diff --git a/src/html/mod_fonts.cpp b/src/html/mod_fonts.cpp new file mode 100644 index 0000000000..45c723c1fb --- /dev/null +++ b/src/html/mod_fonts.cpp @@ -0,0 +1,175 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: mod_fonts.cpp +// Purpose: wxHtml module for fonts & colors of fonts +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#include "wx/defs.h" +#if wxUSE_HTML + +#include +#include + +FORCE_LINK_ME(mod_fonts) + + +TAG_HANDLER_BEGIN(FONT, "FONT") + + TAG_HANDLER_PROC(tag) + { + unsigned long tmp; + wxColour oldclr = m_WParser -> GetActualColor(); + int oldsize = m_WParser -> GetFontSize(); + + if (tag.HasParam("COLOR")) { + wxColour clr; + tag.ScanParam("COLOR", "#%lX", &tmp); + clr = wxColour((tmp & 0xFF0000) >> 16 , (tmp & 0x00FF00) >> 8, (tmp & 0x0000FF)); + m_WParser -> SetActualColor(clr); + m_WParser -> GetContainer() -> InsertCell(new wxHtmlColourCell(clr)); + } + + if (tag.HasParam("SIZE")) { + tag.ScanParam("SIZE", "%li", &tmp); + m_WParser -> SetFontSize(tmp); + m_WParser -> GetContainer() -> InsertCell(new wxHtmlFontCell(m_WParser -> CreateCurrentFont())); + } + + ParseInner(tag); + + if (oldclr != m_WParser -> GetActualColor()) { + m_WParser -> SetActualColor(oldclr); + m_WParser -> GetContainer() -> InsertCell(new wxHtmlColourCell(oldclr)); + } + if (oldsize != m_WParser -> GetFontSize()) { + m_WParser -> SetFontSize(oldsize); + m_WParser -> GetContainer() -> InsertCell(new wxHtmlFontCell(m_WParser -> CreateCurrentFont())); + } + return TRUE; + } + +TAG_HANDLER_END(FONT) + + +TAG_HANDLER_BEGIN(FACES, "U,I,B,TT") + + TAG_HANDLER_PROC(tag) + { + int fixed = m_WParser -> GetFontFixed(), + italic = m_WParser -> GetFontItalic(), + underlined = m_WParser -> GetFontUnderlined(), + bold = m_WParser -> GetFontBold(); + + if (tag.GetName() == "U") + m_WParser -> SetFontUnderlined(TRUE); + else if (tag.GetName() == "B") + m_WParser -> SetFontBold(TRUE); + else if (tag.GetName() == "I") + m_WParser -> SetFontItalic(TRUE); + else + m_WParser -> SetFontFixed(TRUE); + m_WParser -> GetContainer() -> InsertCell(new wxHtmlFontCell(m_WParser -> CreateCurrentFont())); + + ParseInner(tag); + + m_WParser -> SetFontUnderlined(underlined); + m_WParser -> SetFontBold(bold); + m_WParser -> SetFontItalic(italic); + m_WParser -> SetFontFixed(fixed); + m_WParser -> GetContainer() -> InsertCell(new wxHtmlFontCell(m_WParser -> CreateCurrentFont())); + return TRUE; + } + +TAG_HANDLER_END(FACES) + + + + + +TAG_HANDLER_BEGIN(Hx, "H1,H2,H3,H4,H5,H6") + + 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() == "H1") + m_WParser -> SetFontSize(+4); + else if (tag.GetName() == "H2") + m_WParser -> SetFontSize(+3); + else if (tag.GetName() == "H3") + m_WParser -> SetFontSize(+2); + else if (tag.GetName() == "H4") { + m_WParser -> SetFontSize(+2); + m_WParser -> SetFontItalic(TRUE); + m_WParser -> SetFontBold(FALSE); + } + else if (tag.GetName() == "H5") + m_WParser -> SetFontSize(+1); + else if (tag.GetName() == "H6") { + m_WParser -> SetFontSize(+1); + m_WParser -> SetFontItalic(TRUE); + m_WParser -> SetFontBold(FALSE); + } + + c = m_WParser -> GetContainer(); + if (c -> GetFirstCell()) { + 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(), HTML_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(), HTML_INDENT_TOP); + + return TRUE; + } + +TAG_HANDLER_END(Hx) + + + + +TAGS_MODULE_BEGIN(Fonts) + + TAGS_MODULE_ADD(FONT) + TAGS_MODULE_ADD(FACES) + TAGS_MODULE_ADD(Hx) + +TAGS_MODULE_END(Fonts) + + +#endif \ No newline at end of file diff --git a/src/html/mod_hline.cpp b/src/html/mod_hline.cpp new file mode 100644 index 0000000000..c79c3ad13e --- /dev/null +++ b/src/html/mod_hline.cpp @@ -0,0 +1,88 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: mod_hline.cpp +// Purpose: wxHtml module for horizontal line (HR tag) +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + +#include "wx/defs.h" +#if wxUSE_HTML + +#include +#include + +#include + +FORCE_LINK_ME(mod_hline) + + +//----------------------------------------------------------------------------- +// wxHtmlLineCell +//----------------------------------------------------------------------------- + +class wxHtmlLineCell : public wxHtmlCell +{ + public: + wxHtmlLineCell(int size) : wxHtmlCell() {m_Height = size;} + void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2); + void Layout(int w) {m_Width = w; if (m_Next) m_Next -> Layout(w);} +}; + + +void wxHtmlLineCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2) +{ + wxBrush mybrush("BLACK", wxSOLID); + wxPen mypen("BLACK", 1, wxSOLID); + dc.SetBrush(mybrush); + dc.SetPen(mypen); + dc.DrawRectangle(x + m_PosX, y + m_PosY, m_Width, m_Height); + wxHtmlCell::Draw(dc, x, y, view_y1, view_y2); +} + + + + +//----------------------------------------------------------------------------- +// The list handler: +//----------------------------------------------------------------------------- + + +TAG_HANDLER_BEGIN(HR, "HR") + + TAG_HANDLER_PROC(tag) + { + wxHtmlContainerCell *c; + int sz; + + m_WParser -> CloseContainer(); + c = m_WParser -> OpenContainer(); + + c -> SetIndent(m_WParser -> GetCharHeight(), HTML_INDENT_VERTICAL); + c -> SetAlignHor(HTML_ALIGN_CENTER); + c -> SetAlign(tag); + c -> SetWidthFloat(tag); + if (tag.HasParam("SIZE")) tag.ScanParam("SIZE", "%i", &sz); + else sz = 1; + c -> InsertCell(new wxHtmlLineCell(sz)); + + 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 diff --git a/src/html/mod_image.cpp b/src/html/mod_image.cpp new file mode 100644 index 0000000000..908e4b6241 --- /dev/null +++ b/src/html/mod_image.cpp @@ -0,0 +1,147 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: mod_image.cpp +// Purpose: wxHtml module for displaying images +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#include "wx/defs.h" +#if wxUSE_HTML + +#include +#include + +#include +#include + +FORCE_LINK_ME(mod_image) + + +//-------------------------------------------------------------------------------- +// wxHtmlImageCell +// Image/bitmap +//-------------------------------------------------------------------------------- + +class wxHtmlImageCell : public wxHtmlCell +{ + public: + wxBitmap *m_Image; + + wxHtmlImageCell(wxFSFile *input, int w = -1, int h = -1, int align = HTML_ALIGN_BOTTOM); + ~wxHtmlImageCell() {if (m_Image) delete m_Image;} + void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2); +}; + + + +//-------------------------------------------------------------------------------- +// wxHtmlImageCell +//-------------------------------------------------------------------------------- + +wxHtmlImageCell::wxHtmlImageCell(wxFSFile *input, int w, int h, int align) : wxHtmlCell() +{ + wxImage *img; + int ww, hh; + wxString m = input -> GetMimeType(); + wxInputStream *s = input -> GetStream(); + +#if wxVERSION_NUMBER < 2100 +/* NOTE : use this *old* code only if you have old 2.0.1 wxWindows distribution + and don't want to upgrade it with stuffs from add-on/wxwin201 */ + if (wxMimeTypesManager::IsOfType(m, "image/png")) img = new wxImage(*s, wxBITMAP_TYPE_PNG); + else if (wxMimeTypesManager::IsOfType(m, "image/jpeg")) img = new wxImage(*s, wxBITMAP_TYPE_JPEG); + else if (wxMimeTypesManager::IsOfType(m, "image/bmp")) img = new wxImage(*s, wxBITMAP_TYPE_BMP); + else if (wxMimeTypesManager::IsOfType(m, "image/gif")) img = new wxImage(*s, wxBITMAP_TYPE_GIF); + else if (wxMimeTypesManager::IsOfType(m, "image/tiff")) img = new wxImage(*s, wxBITMAP_TYPE_TIF); + else if (wxMimeTypesManager::IsOfType(m, "image/xpm")) img = new wxImage(*s, wxBITMAP_TYPE_XPM); + else if (wxMimeTypesManager::IsOfType(m, "image/xbm")) img = new wxImage(*s, wxBITMAP_TYPE_XBM); + else img = NULL; +#else + img = new wxImage(*s, m); +#endif + + m_Image = NULL; + if (img && (img -> Ok())) { + ww = img -> GetWidth(); + hh = img -> GetHeight(); + if (w != -1) m_Width = w; else m_Width = ww; + if (h != -1) m_Height = h; else m_Height = hh; + if ((m_Width != ww) || (m_Height != hh)) { + wxImage img2 = img -> Scale(m_Width, m_Height); + m_Image = new wxBitmap(img2.ConvertToBitmap()); + } + else + m_Image = new wxBitmap(img -> ConvertToBitmap()); + delete img; + } + switch (align) { + case HTML_ALIGN_TOP : + m_Descent = m_Height; break; + case HTML_ALIGN_CENTER : + m_Descent = m_Height / 2; break; + case HTML_ALIGN_BOTTOM : default : + m_Descent = 0; break; + } +} + + + +void wxHtmlImageCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2) +{ + if (m_Image) + dc.DrawBitmap(*m_Image, x + m_PosX, y + m_PosY, TRUE); + wxHtmlCell::Draw(dc, x, y, view_y1, view_y2); +} + + + + + +//-------------------------------------------------------------------------------- +// tag handler +//-------------------------------------------------------------------------------- + +TAG_HANDLER_BEGIN(IMG, "IMG") + + TAG_HANDLER_PROC(tag) + { + if (tag.HasParam("SRC")) { + int w = -1, h = -1; + int al; + wxFSFile *str; + wxString tmp = tag.GetParam("SRC"); + + str = m_WParser -> GetFS() -> OpenFile(tmp); + if (tag.HasParam("WIDTH")) tag.ScanParam("WIDTH", "%i", &w); + if (tag.HasParam("HEIGHT")) tag.ScanParam("HEIGHT", "%i", &h); + al = HTML_ALIGN_BOTTOM; + if (tag.HasParam("ALIGN")) { + wxString alstr = tag.GetParam("ALIGN"); + alstr.MakeUpper(); // for the case alignment was in ".." + if (alstr == "TEXTTOP") al = HTML_ALIGN_TOP; + else if ((alstr == "CENTER") || (alstr == "ABSCENTER")) al = HTML_ALIGN_CENTER; + } + if (str) { + wxHtmlCell *cel = new wxHtmlImageCell(str, w, h, al); + cel -> SetLink(m_WParser -> GetLink()); + m_WParser -> GetContainer() -> InsertCell(cel); + delete str; + } + } + + return FALSE; + } + +TAG_HANDLER_END(IMAGE) + + + +TAGS_MODULE_BEGIN(Image) + + TAGS_MODULE_ADD(IMG) + +TAGS_MODULE_END(Image) + + +#endif \ No newline at end of file diff --git a/src/html/mod_layout.cpp b/src/html/mod_layout.cpp new file mode 100644 index 0000000000..42b1de108c --- /dev/null +++ b/src/html/mod_layout.cpp @@ -0,0 +1,223 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: mod_layout.cpp +// Purpose: wxHtml module for basic paragraphs/layout handling +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#include "wx/defs.h" +#if wxUSE_HTML + +#include +#include + +#include + +FORCE_LINK_ME(mod_layout) + + +TAG_HANDLER_BEGIN(P, "P") + + TAG_HANDLER_PROC(tag) + { + if (m_WParser -> GetContainer() -> GetFirstCell() != NULL) { + m_WParser -> CloseContainer(); + m_WParser -> OpenContainer(); + } + m_WParser -> GetContainer() -> SetIndent(m_WParser -> GetCharHeight(), HTML_INDENT_TOP); + m_WParser -> GetContainer() -> SetAlign(tag); + return FALSE; + } + +TAG_HANDLER_END(P) + + + +TAG_HANDLER_BEGIN(BR, "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); + return FALSE; + } + +TAG_HANDLER_END(BR) + + + +TAG_HANDLER_BEGIN(CENTER, "CENTER") + + TAG_HANDLER_PROC(tag) + { + int old = m_WParser -> GetAlign(); + wxHtmlContainerCell *c = m_WParser -> GetContainer(); + + m_WParser -> SetAlign(HTML_ALIGN_CENTER); + if (c -> GetFirstCell() != NULL) { + m_WParser -> CloseContainer(); + m_WParser -> OpenContainer(); + } + else + c -> SetAlignHor(HTML_ALIGN_CENTER); + + if (tag.HasEnding()) { + ParseInner(tag); + + m_WParser -> SetAlign(old); + if (c -> GetFirstCell() != 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_PROC(tag) + { + int old = m_WParser -> GetAlign(); + wxHtmlContainerCell *c = m_WParser -> GetContainer(); + if (c -> GetFirstCell() != 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 -> GetFirstCell() != NULL) { + m_WParser -> CloseContainer(); + m_WParser -> OpenContainer(); + } + else + c -> SetAlignHor(old); + + return TRUE; + } + +TAG_HANDLER_END(DIV) + + + + +TAG_HANDLER_BEGIN(TITLE, "TITLE") + + TAG_HANDLER_PROC(tag) + { + if (m_WParser -> GetWindow()) { + wxHtmlWindow *wfr = (wxHtmlWindow*)(m_WParser -> GetWindow()); + if (wfr) { + wxString title = ""; + wxString *src = m_WParser -> GetSource(); + + for (int i = tag.GetBeginPos(); i < tag.GetEndPos1(); i++) title += (*src)[i]; + wfr -> SetTitle(title); + } + } + return TRUE; + } + +TAG_HANDLER_END(TITLE) + + + + +TAG_HANDLER_BEGIN(BODY, "BODY") + + TAG_HANDLER_PROC(tag) + { + unsigned long tmp; + wxColour clr; + + if (tag.HasParam("TEXT")) { + tag.ScanParam("TEXT", "#%lX", &tmp); + clr = wxColour((tmp & 0xFF0000) >> 16 , (tmp & 0x00FF00) >> 8, (tmp & 0x0000FF)); + m_WParser -> SetActualColor(clr); + m_WParser -> GetContainer() -> InsertCell(new wxHtmlColourCell(clr)); + } + + if (tag.HasParam("LINK")) { + tag.ScanParam("LINK", "#%lX", &tmp); + clr = wxColour((tmp & 0xFF0000) >> 16 , (tmp & 0x00FF00) >> 8, (tmp & 0x0000FF)); + m_WParser -> SetLinkColor(clr); + } + + if (tag.HasParam("BGCOLOR")) { + tag.ScanParam("BGCOLOR", "#%lX", &tmp); + clr = wxColour((tmp & 0xFF0000) >> 16 , (tmp & 0x00FF00) >> 8, (tmp & 0x0000FF)); + m_WParser -> GetContainer() -> InsertCell(new wxHtmlColourCell(clr, HTML_CLR_BACKGROUND)); + if (m_WParser -> GetWindow() != NULL) + m_WParser -> GetWindow() -> SetBackgroundColour(clr); + } + return FALSE; + } + +TAG_HANDLER_END(BODY) + + + +TAG_HANDLER_BEGIN(BLOCKQUOTE, "BLOCKQUOTE") + + TAG_HANDLER_PROC(tag) + { + wxHtmlContainerCell *c; + + m_WParser -> CloseContainer(); + c = m_WParser -> OpenContainer(); + if (c -> GetAlignHor() == HTML_ALIGN_RIGHT) + c -> SetIndent(5 * m_WParser -> GetCharWidth(), HTML_INDENT_RIGHT); + else + c -> SetIndent(5 * m_WParser -> GetCharWidth(), HTML_INDENT_LEFT); + c -> SetIndent(m_WParser -> GetCharHeight(), HTML_INDENT_TOP); + m_WParser -> OpenContainer(); + ParseInner(tag); + c = m_WParser -> CloseContainer(); + c -> SetIndent(m_WParser -> GetCharHeight(), HTML_INDENT_BOTTOM); + m_WParser -> CloseContainer(); + m_WParser -> OpenContainer(); + return TRUE; + } + +TAG_HANDLER_END(BLOCKQUOTE) + + + + + + +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_END(Layout) + +#endif diff --git a/src/html/mod_links.cpp b/src/html/mod_links.cpp new file mode 100644 index 0000000000..9b92982866 --- /dev/null +++ b/src/html/mod_links.cpp @@ -0,0 +1,80 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: mod_links.cpp +// Purpose: wxHtml module for links & anchors +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#include "wx/defs.h" +#if wxUSE_HTML + +#include +#include +#include + +FORCE_LINK_ME(mod_links) + + +class wxHtmlAnchorCell : public wxHtmlCell +{ + private: + wxString m_AnchorName; + + public: + wxHtmlAnchorCell(const wxString& name) : wxHtmlCell() {m_AnchorName = name;} + virtual const wxHtmlCell* Find(int condition, const void* param) const + { + if ((condition == HTML_COND_ISANCHOR) && (m_AnchorName == (*((const wxString*)param)))) + return this; + else + return wxHtmlCell::Find(condition, param); + } +}; + + + +TAG_HANDLER_BEGIN(A, "A") + + TAG_HANDLER_PROC(tag) + { + if (tag.HasParam("NAME")) { + m_WParser -> GetContainer() -> InsertCell(new wxHtmlAnchorCell(tag.GetParam("NAME"))); + } + + if (tag.HasParam("HREF")) { + wxString oldlnk = m_WParser -> GetLink(); + wxColour oldclr = m_WParser -> GetActualColor(); + int oldund = m_WParser -> GetFontUnderlined(); + + 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(tag.GetParam("HREF")); + + 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 diff --git a/src/html/mod_list.cpp b/src/html/mod_list.cpp new file mode 100644 index 0000000000..4222d6bc02 --- /dev/null +++ b/src/html/mod_list.cpp @@ -0,0 +1,142 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: mod_list.cpp +// Purpose: wxHtml module for lists +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#include "wx/defs.h" +#if wxUSE_HTML + +#include +#include + +#include + +FORCE_LINK_ME(mod_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); +}; + +wxHtmlListmarkCell::wxHtmlListmarkCell(wxDC* dc, const wxColour& clr) : wxHtmlCell(), m_Brush(clr, wxSOLID) +{ + m_Width = dc -> GetCharWidth(); + m_Height = dc -> GetCharHeight(); + m_Descent = 0; +} + + + +void wxHtmlListmarkCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2) +{ + dc.SetBrush(m_Brush); + dc.DrawEllipse(x + m_PosX + m_Width / 4, y + m_PosY + m_Height / 4, m_Width / 2, m_Width / 2); + wxHtmlCell::Draw(dc, x, y, view_y1, view_y2); +} + + + + +//----------------------------------------------------------------------------- +// The list handler: +//----------------------------------------------------------------------------- + + +TAG_HANDLER_BEGIN(OLULLI, "OL,UL,LI") + + TAG_HANDLER_VARS + int m_Numbering; + // this is number of actual item of list or 0 for dots + + TAG_HANDLER_CONSTR(OLULLI) + { + m_Numbering = 0; + } + + TAG_HANDLER_PROC(tag) + { + wxHtmlContainerCell *c; + + // List Item: + if (tag.GetName() == "LI") { + if (!tag.IsEnding()) { + m_WParser -> CloseContainer(); + m_WParser -> CloseContainer(); + + c = m_WParser -> OpenContainer(); + c -> SetWidthFloat(2 * m_WParser -> GetCharWidth(), HTML_UNITS_PIXELS); + c -> SetAlignHor(HTML_ALIGN_RIGHT); + if (m_Numbering == 0) + c -> InsertCell(new wxHtmlListmarkCell(m_WParser -> GetDC(), m_WParser -> GetActualColor())); + else { + wxString mark; + mark.Printf("%i.", m_Numbering); + c -> InsertCell(new wxHtmlWordCell(mark, *(m_WParser -> GetDC()))); + } + m_WParser -> CloseContainer(); + + c = m_WParser -> OpenContainer(); + c -> SetIndent(m_WParser -> GetCharWidth() / 4, HTML_INDENT_LEFT); + c -> SetWidthFloat(-2 * m_WParser -> GetCharWidth(), HTML_UNITS_PIXELS); + + m_WParser -> OpenContainer(); + + if (m_Numbering != 0) m_Numbering++; + } + return FALSE; + } + + // Begin of List (not-numbered): "UL", "OL" + else { + int oldnum = m_Numbering; + + if (tag.GetName() == "UL") m_Numbering = 0; + else m_Numbering = 1; + + c = m_WParser -> GetContainer(); + if (c -> GetFirstCell() != NULL) { + m_WParser -> CloseContainer(); + m_WParser -> OpenContainer(); + c = m_WParser -> GetContainer(); + } + c -> SetAlignHor(HTML_ALIGN_LEFT); + c -> SetIndent(2 * m_WParser -> GetCharWidth(), HTML_INDENT_LEFT); + m_WParser -> OpenContainer() -> SetAlignVer(HTML_ALIGN_TOP); + + m_WParser -> OpenContainer(); + m_WParser -> OpenContainer(); + ParseInner(tag); + m_WParser -> CloseContainer(); + + m_WParser -> CloseContainer(); + m_WParser -> CloseContainer(); + m_WParser -> CloseContainer(); + m_WParser -> OpenContainer(); + + m_Numbering = oldnum; + return TRUE; + } + } + +TAG_HANDLER_END(OLULLI) + + +TAGS_MODULE_BEGIN(List) + + TAGS_MODULE_ADD(OLULLI) + +TAGS_MODULE_END(List) + +#endif diff --git a/src/html/mod_pre.cpp b/src/html/mod_pre.cpp new file mode 100644 index 0000000000..e2fa697bda --- /dev/null +++ b/src/html/mod_pre.cpp @@ -0,0 +1,157 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: mod_pre.cpp +// Purpose: wxHtml module for
 ... 
tag (code citation) +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#include "wx/defs.h" +#if wxUSE_HTML + +#include +#include + +#include +#include + +FORCE_LINK_ME(mod_pre) + + +//----------------------------------------------------------------------------- +// wxHtmlCodeCell +//----------------------------------------------------------------------------- + +class wxHtmlPRECell : public wxHtmlCell +{ + private: + wxString** m_Text; + // list of wxString objects. + int m_LinesCnt; + // number of lines + int m_LineHeight; + // height of single line of text + + public: + wxHtmlPRECell(const wxString& s, wxDC& dc); + ~wxHtmlPRECell(); + void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2); +}; + + +wxHtmlPRECell::wxHtmlPRECell(const wxString& s, wxDC& dc) : wxHtmlCell() +{ + wxStringTokenizer tokenizer(s, "\n"); + wxString tmp; + long int x, z; + int i; + + m_LineHeight = dc.GetCharHeight(); + m_LinesCnt = 0; + m_Text = NULL; + m_Width = m_Height = 0; + + i = 0; +#if (wxVERSION_NUMBER < 2100) + while (tokenizer.HasMoreToken()) { +#else + while (tokenizer.HasMoreTokens()) { +#endif + if (i % 10 == 0) m_Text = (wxString**) realloc(m_Text, sizeof(wxString*) * (i + 10)); + tmp = tokenizer.NextToken(); + tmp.Replace(" ", " ", TRUE); + tmp.Replace(""", "\"", TRUE); + tmp.Replace("<", "<", TRUE); + tmp.Replace(">", ">", TRUE); + tmp.Replace("&", "&", TRUE); + tmp.Replace("\t", " ", TRUE); + tmp.Replace("\r", "", TRUE); + m_Text[i++] = new wxString(tmp); + + dc.GetTextExtent(tmp, &x, &z, &z); + if (x > m_Width) m_Width = x; + m_Height += m_LineHeight; + m_LinesCnt++; + } +} + + + +wxHtmlPRECell::~wxHtmlPRECell() +{ + for (int i = 0; i < m_LinesCnt; i++) delete m_Text[i]; + free(m_Text); +} + + +void wxHtmlPRECell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2) +{ + for (int i = 0; i < m_LinesCnt; i++) + dc.DrawText(*(m_Text[i]), x + m_PosX, y + m_PosY + m_LineHeight * i); + + wxHtmlCell::Draw(dc, x, y, view_y1, view_y2); +} + + + + +//----------------------------------------------------------------------------- +// The list handler: +//----------------------------------------------------------------------------- + + +TAG_HANDLER_BEGIN(PRE, "PRE") + + TAG_HANDLER_PROC(tag) + { + wxHtmlContainerCell *c; + + int fixed = m_WParser -> GetFontFixed(), + italic = m_WParser -> GetFontItalic(), + underlined = m_WParser -> GetFontUnderlined(), + bold = m_WParser -> GetFontBold(), + fsize = m_WParser -> GetFontSize(); + + m_WParser -> CloseContainer(); + c = m_WParser -> OpenContainer(); + c -> SetAlignHor(HTML_ALIGN_LEFT); + c -> SetIndent(m_WParser -> GetCharHeight(), HTML_INDENT_VERTICAL); + + m_WParser -> SetFontUnderlined(FALSE); + m_WParser -> SetFontBold(FALSE); + m_WParser -> SetFontItalic(FALSE); + m_WParser -> SetFontFixed(TRUE); + m_WParser -> SetFontSize(0); + c -> InsertCell(new wxHtmlFontCell(m_WParser -> CreateCurrentFont())); + + { + wxString cit; + cit = m_WParser -> GetSource() -> Mid(tag.GetBeginPos(), tag.GetEndPos1() - tag.GetBeginPos()); + c -> InsertCell(new wxHtmlPRECell(cit, *(m_WParser -> GetDC()))); + } + + 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())); + + m_WParser -> CloseContainer(); + m_WParser -> OpenContainer(); + return TRUE; + } + +TAG_HANDLER_END(PRE) + + + + + +TAGS_MODULE_BEGIN(Pre) + + TAGS_MODULE_ADD(PRE) + +TAGS_MODULE_END(Pre) + +#endif diff --git a/src/html/mod_tables.cpp b/src/html/mod_tables.cpp new file mode 100644 index 0000000000..7f9e31c08e --- /dev/null +++ b/src/html/mod_tables.cpp @@ -0,0 +1,480 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: mod_tables.cpp +// Purpose: wxHtml module for tables +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#include "wx/defs.h" +#if wxUSE_HTML + +/* +REMARKS: + 1. This version of mod_tables doesn't support auto-layout algorithm. + This means that all columns are of same width unless explicitly specified. +*/ + + +#include +#include + +#include + +FORCE_LINK_ME(mod_tables) + + +#define TABLE_BORDER_CLR_1 wxColour(0xC5, 0xC2, 0xC5) +#define TABLE_BORDER_CLR_2 wxColour(0x62, 0x61, 0x62) + + +//----------------------------------------------------------------------------- +// wxHtmlTableCell +//----------------------------------------------------------------------------- + + +typedef struct { + int width, units; // universal + int leftpos, pixwidth, maxrealwidth; // temporary (depends on width of table) + } colStruct; + +typedef enum { + cellSpan, + cellUsed, + cellFree + } cellState; + +typedef struct { + wxHtmlContainerCell *cont; + int colspan, rowspan; + int minheight, valign; + cellState flag; + } cellStruct; + + +class wxHtmlTableCell : public wxHtmlContainerCell +{ + protected: + /* These are real attributes: */ + bool m_HasBorders; + // should we draw borders or not? + int m_NumCols, m_NumRows; + // number of columns; rows + colStruct *m_ColsInfo; + // array of column information + cellStruct **m_CellInfo; + // 2D array of all cells in the table : m_CellInfo[row][column] + int m_Spacing; + // spaces between cells + int m_Padding; + // cells internal indentation + + private: + /* ...and these are valid only during parsing of table: */ + int m_ActualCol, m_ActualRow; + // number of actual column (ranging from 0..m_NumCols) + + // default values (for table and row): + int m_tBkg, m_rBkg; + wxString m_tValign, m_rValign; + + + public: + wxHtmlTableCell(wxHtmlContainerCell *parent, const wxHtmlTag& tag); + ~wxHtmlTableCell(); + virtual void Layout(int w); + + void AddRow(const wxHtmlTag& tag); + void AddCell(wxHtmlContainerCell *cell, const wxHtmlTag& tag); + private: + void ReallocCols(int cols); + void ReallocRows(int rows); + // 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!! +}; + + + +wxHtmlTableCell::wxHtmlTableCell(wxHtmlContainerCell *parent, const wxHtmlTag& tag) + : wxHtmlContainerCell(parent) +{ + m_HasBorders = tag.HasParam("BORDER"); + m_ColsInfo = NULL; + m_NumCols = m_NumRows = 0; + m_CellInfo = NULL; + m_ActualCol = m_ActualRow = -1; + + /* scan params: */ + m_tBkg = m_rBkg = -1; + if (tag.HasParam("BGCOLOR")) tag.ScanParam("BGCOLOR", "#%lX", &m_tBkg); + if (tag.HasParam("VALIGN")) m_tValign = tag.GetParam("VALIGN"); else m_tValign = wxEmptyString; + if (tag.HasParam("CELLSPACING")) tag.ScanParam("CELLSPACING", "%i", &m_Spacing); else m_Spacing = 2; + if (tag.HasParam("CELLPADDING")) tag.ScanParam("CELLPADDING", "%i", &m_Padding); else m_Padding = 3; + + 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::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 = HTML_UNITS_PERCENT; + } + + m_NumCols = cols; +} + + + +void wxHtmlTableCell::ReallocRows(int rows) +{ + m_CellInfo = (cellStruct**) realloc(m_CellInfo, sizeof(cellStruct*) * rows); + if (m_NumCols != 0) { + int x = rows - 1; + m_CellInfo[x] = (cellStruct*) malloc(sizeof(cellStruct) * m_NumCols); + for (int i = 0; i < m_NumCols; i++) + m_CellInfo[x][i].flag = cellFree; + } + else + m_CellInfo[rows - 1] = NULL; + m_NumRows = rows; +} + + + +void wxHtmlTableCell::AddRow(const wxHtmlTag& tag) +{ + if (m_ActualRow + 1 > m_NumRows - 1) + ReallocRows(m_ActualRow + 2); + m_ActualRow++; + m_ActualCol = -1; + + /* scan params: */ + m_rBkg = m_tBkg; + if (tag.HasParam("BGCOLOR")) tag.ScanParam("BGCOLOR", "#%lX", &m_rBkg); + if (tag.HasParam("VALIGN")) m_rValign = tag.GetParam("VALIGN"); else m_rValign = m_tValign; +} + + + +void wxHtmlTableCell::AddCell(wxHtmlContainerCell *cell, const wxHtmlTag& tag) +{ + 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 = HTML_ALIGN_TOP; + + /* scan for parameters: */ + + // width: + { + if (tag.HasParam("WIDTH")) { + wxString wd = tag.GetParam("WIDTH"); + + if (wd[wd.Length()-1] == '%') { + sscanf(wd.c_str(), "%i%%", &m_ColsInfo[c].width); + m_ColsInfo[c].units = HTML_UNITS_PERCENT; + } + else { + sscanf(wd.c_str(), "%i", &m_ColsInfo[c].width); + m_ColsInfo[c].units = HTML_UNITS_PIXELS; + } + } + } + + + // spanning: + { + if (tag.HasParam("COLSPAN")) tag.ScanParam("COLSPAN", "%i", &m_CellInfo[r][c].colspan); + if (tag.HasParam("ROWSPAN")) tag.ScanParam("ROWSPAN", "%i", &m_CellInfo[r][c].rowspan); + 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: + { + int bk = m_rBkg; + if (tag.HasParam("BGCOLOR")) tag.ScanParam("BGCOLOR", "#%lX", &bk); + if (bk != -1) { + wxColour clr = wxColour((bk & 0xFF0000) >> 16 , (bk & 0x00FF00) >> 8, (bk & 0x0000FF)); + cell -> SetBackgroundColour(clr); + } + } + if (m_HasBorders) + cell -> SetBorder(TABLE_BORDER_CLR_2, TABLE_BORDER_CLR_1); + + // vertical alignment: + { + wxString valign; + if (tag.HasParam("VALIGN")) valign = tag.GetParam("VALIGN"); else valign = m_tValign; + valign.MakeUpper(); + if (valign == "TOP") m_CellInfo[r][c].valign = HTML_ALIGN_TOP; + else if (valign == "BOTTOM") m_CellInfo[r][c].valign = HTML_ALIGN_BOTTOM; + else m_CellInfo[r][c].valign = HTML_ALIGN_CENTER; + } + + cell -> SetIndent(m_Padding, HTML_INDENT_ALL, HTML_UNITS_PIXELS); +} + + + + + +void wxHtmlTableCell::Layout(int w) +{ + /* + + WIDTH ADJUSTING : + + */ + + if (m_WidthFloatUnits == HTML_UNITS_PERCENT) { + if (m_WidthFloat < 0) m_Width = (100 + m_WidthFloat) * w / 100; + else 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: */ + { + int wpix = m_Width - (m_NumCols + 1) * m_Spacing; + int i, j; + int wtemp = 0; + + // 1a. setup fixed-width columns: + for (i = 0; i < m_NumCols; i++) + if (m_ColsInfo[i].units == HTML_UNITS_PIXELS) + wpix -= (m_ColsInfo[i].pixwidth = m_ColsInfo[i].width); + + // 1b. setup floating-width columns: + for (i = 0; i < m_NumCols; i++) + if ((m_ColsInfo[i].units == HTML_UNITS_PERCENT) && (m_ColsInfo[i].width != 0)) + wtemp += (m_ColsInfo[i].pixwidth = m_ColsInfo[i].width * wpix / 100); + wpix -= wtemp; + + // 1c. setup defalut columns (no width specification supplied): + // NOTE! This algorithm doesn't conform to HTML standard : it assigns equal widths + // instead of optimal + for (i = j = 0; i < m_NumCols; i++) + if (m_ColsInfo[i].width == 0) j++; + for (i = 0; i < m_NumCols; i++) + if (m_ColsInfo[i].width == 0) + m_ColsInfo[i].pixwidth = wpix / j; + } + + /* 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; + } + } + + /* 3. sub-layout all cells: */ + { + int *ypos = (int*) malloc(sizeof(int) * (m_NumRows + 1)); + + int actcol, actrow; + int fullwid; + wxHtmlContainerCell *actcell; + + for (actrow = 0; actrow <= m_NumRows; actrow++) ypos[actrow] = m_Spacing; + + for (actrow = 0; actrow < m_NumRows; actrow++) { + + // 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; + 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_CellInfo[actrow][actcol].rowspan * 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; + actcell -> Layout(fullwid); + actcell -> SetPos(m_ColsInfo[actcol].leftpos, ypos[actrow]); + } + + } + m_Height = ypos[m_NumRows]; + free(ypos); + } +} + + + + + + +//----------------------------------------------------------------------------- +// The tables handler: +//----------------------------------------------------------------------------- + + +TAG_HANDLER_BEGIN(TABLE, "TABLE,TR,TD,TH") + + TAG_HANDLER_VARS + wxHtmlTableCell* m_Table; + wxString m_tAlign, m_rAlign; + int m_OldAlign; + + TAG_HANDLER_CONSTR(TABLE) + { + m_Table = NULL; + m_tAlign = m_rAlign = wxEmptyString; + m_OldAlign = HTML_ALIGN_LEFT; + } + + + TAG_HANDLER_PROC(tag) + { + wxHtmlContainerCell *c; + + // new table started, backup upper-level table (if any) and create new: + if (tag.GetName() == "TABLE") { + wxHtmlTableCell *oldt = m_Table; + wxHtmlContainerCell *oldcont; + int m_OldAlign; + + oldcont = c = m_WParser -> OpenContainer(); + + c -> SetWidthFloat(tag); + m_Table = new wxHtmlTableCell(c, tag); + m_OldAlign = m_WParser -> GetAlign(); + m_tAlign = wxEmptyString; + if (tag.HasParam("ALIGN")) m_tAlign = tag.GetParam("ALIGN"); + + ParseInner(tag); + + m_WParser -> SetAlign(m_OldAlign); + m_WParser -> SetContainer(oldcont); + m_WParser -> CloseContainer(); + m_Table = oldt; + return TRUE; + } + + + else if (m_Table && !tag.IsEnding()) { + // new row in table + if (tag.GetName() == "TR") { + m_Table -> AddRow(tag); + m_rAlign = m_tAlign; + if (tag.HasParam("ALIGN")) m_rAlign = tag.GetParam("ALIGN"); + } + + // new cell + else { + m_WParser -> SetAlign(m_OldAlign); + c = m_WParser -> SetContainer(new wxHtmlContainerCell(m_Table)); + m_Table -> AddCell(c, tag); + + m_WParser -> OpenContainer(); + + if (tag.GetName() == "TH") /*header style*/ { + m_WParser -> SetAlign(HTML_ALIGN_CENTER); + } + + { + wxString als; + + als = m_rAlign; + if (tag.HasParam("ALIGN")) als = tag.GetParam("ALIGN"); + als.MakeUpper(); + if (als == "RIGHT") m_WParser -> SetAlign(HTML_ALIGN_RIGHT); + else if (als == "CENTER") m_WParser -> SetAlign(HTML_ALIGN_CENTER); + } + m_WParser -> OpenContainer(); + } + } + return FALSE; + } + +TAG_HANDLER_END(TABLE) + + + + + +TAGS_MODULE_BEGIN(Tables) + + TAGS_MODULE_ADD(TABLE) + +TAGS_MODULE_END(Tables) + + +#endif diff --git a/src/html/search.cpp b/src/html/search.cpp new file mode 100644 index 0000000000..aab3906fd5 --- /dev/null +++ b/src/html/search.cpp @@ -0,0 +1,73 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: search.cpp +// Purpose: search engine +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + + + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include + +#include +#if wxUSE_HTML + +#ifdef __BORDLANDC__ +#pragma hdrstop +#endif + +#ifndef WXPRECOMP +#include +#endif + +#include "search.h" + + + +//-------------------------------------------------------------------------------- +// wxSearchEngine +//-------------------------------------------------------------------------------- + +void wxSearchEngine::LookFor(const wxString& keyword) +{ + if (m_Keyword) free(m_Keyword); + m_Keyword = (char*) malloc(keyword.Length() + 1); + strcpy(m_Keyword, keyword.c_str()); + for (int i = strlen(m_Keyword) - 1; i >= 0; i--) + if ((m_Keyword[i] >= 'A') && (m_Keyword[i] <= 'Z')) + m_Keyword[i] += 'a' - 'A'; +} + + + +bool wxSearchEngine::Scan(wxInputStream *stream) +{ + wxASSERT_MSG(m_Keyword != NULL, _("wxSearchEngine::LookFor must be called before scanning!")); + + int i, j; + int lng = stream -> StreamSize(); + int wrd = strlen(m_Keyword); + bool found = FALSE; + char *buf = (char*) malloc(lng + 1); + stream -> Read(buf, lng); + buf[lng] = 0; + + for (i = 0; i < lng; i++) + if ((buf[i] >= 'A') && (buf[i] <= 'Z')) buf[i] += 'a' - 'A'; + + for (i = 0; i < lng - wrd; i++) { + j = 0; + while ((j < wrd) && (buf[i + j] == m_Keyword[j])) j++; + if (j == wrd) {found = TRUE; break;} + } + + free(buf); + return found; +} + +#endif diff --git a/src/html/search.h b/src/html/search.h new file mode 100644 index 0000000000..ff9db742e0 --- /dev/null +++ b/src/html/search.h @@ -0,0 +1,50 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: search.h +// Purpose: wxSearchEngine - class for searching keywords +// Author: Vaclav Slavik +// Copyright: (c) 1999 Vaclav Slavik +// Licence: wxWindows Licence +///////////////////////////////////////////////////////////////////////////// + +#if wxUSE_HTML + +#ifndef __SEARCH_H__ +#define __SEARCH_H__ + +#ifdef __GNUG__ +#pragma interface +#endif + + +#include + +//-------------------------------------------------------------------------------- +// wxSearchEngine +// This class takes input streams and scans them for occurence +// of keyword(s) +//-------------------------------------------------------------------------------- + + +class wxSearchEngine : public wxObject +{ + private: + char *m_Keyword; + + public: + wxSearchEngine() : wxObject() {m_Keyword = NULL;} + ~wxSearchEngine() {if (m_Keyword) free(m_Keyword);} + + virtual void LookFor(const wxString& keyword); + // Sets the keyword we will be searching for + + virtual bool Scan(wxInputStream *stream); + // Scans the stream for the keyword. + // Returns TRUE if the stream contains keyword, fALSE otherwise +}; + + + + +#endif + +#endif \ No newline at end of file diff --git a/src/motif/Makefile.am b/src/motif/Makefile.am index 7a692f9537..5822878182 100644 --- a/src/motif/Makefile.am +++ b/src/motif/Makefile.am @@ -61,6 +61,9 @@ libwx_motif_la_SOURCES = \ event.cpp \ file.cpp \ fileconf.cpp \ + filesys.cpp \ + fs_inet.cpp \ + fs_zip.cpp \ framecmn.cpp \ ftp.cpp \ gdicmn.cpp \ @@ -105,8 +108,11 @@ libwx_motif_la_SOURCES = \ wfstream.cpp \ wincmn.cpp \ wxexpr.cpp \ + unzip.c \ + zipstream.cpp \ zstream.cpp \ \ + busyinfo.cpp \ caret.cpp \ choicdgg.cpp \ colrdlgg.cpp \ @@ -188,7 +194,25 @@ libwx_motif_la_SOURCES = \ timer.cpp \ toolbar.cpp \ utils.cpp \ - window.cpp + window.cpp \ +\ + htmlcell.cpp \ + htmlfilter.cpp \ + htmlhelp.cpp \ + htmlhelp_io.cpp \ + htmlparser.cpp \ + htmltag.cpp \ + htmlwin.cpp \ + htmlwinparser.cpp \ + mod_fonts.cpp \ + mod_hline.cpp \ + mod_image.cpp \ + mod_layout.cpp \ + mod_links.cpp \ + mod_list.cpp \ + mod_pre.cpp \ + mod_tables.cpp \ + search.cpp # propform.cpp \ # proplist.cpp \ -- 2.45.2