diff options
Diffstat (limited to 'tkhtml1')
140 files changed, 45864 insertions, 0 deletions
diff --git a/tkhtml1/.gitignore b/tkhtml1/.gitignore new file mode 100644 index 0000000..a53b4c4 --- /dev/null +++ b/tkhtml1/.gitignore @@ -0,0 +1,34 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ + +*~ diff --git a/tkhtml1/LICENSE b/tkhtml1/LICENSE new file mode 100644 index 0000000..23cb790 --- /dev/null +++ b/tkhtml1/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/> + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/tkhtml1/Makefile.in b/tkhtml1/Makefile.in new file mode 100755 index 0000000..13db13d --- /dev/null +++ b/tkhtml1/Makefile.in @@ -0,0 +1,459 @@ +# Makefile.in -- +# +# This file is a Makefile for Sample TEA Extension. If it has the name +# "Makefile.in" then it is a template for a Makefile; to generate the +# actual Makefile, run "./configure", which is a configuration script +# generated by the "autoconf" program (constructs like "@foo@" will get +# replaced in the actual Makefile. +# +# Copyright (c) 1999 Scriptics Corporation. +# Copyright (c) 2002-2005 ActiveState Corporation. +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. + +#======================================================================== +# Add additional lines to handle any additional AC_SUBST cases that +# have been added in a customized configure script. +#======================================================================== + +#SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@ + +#======================================================================== +# Nothing of the variables below this line should need to be changed. +# Please check the TARGETS section below to make sure the make targets +# are correct. +#======================================================================== + +#======================================================================== +# The names of the source files is defined in the configure script. +# The object files are used for linking into the final library. +# This will be used when a dist target is added to the Makefile. +# It is not important to specify the directory, as long as it is the +# $(srcdir) or in the generic, win or unix subdirectory. +#======================================================================== + +PKG_SOURCES = @PKG_SOURCES@ +PKG_OBJECTS = @PKG_OBJECTS@ + +PKG_STUB_SOURCES = @PKG_STUB_SOURCES@ +PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@ + +#======================================================================== +# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with +# this package that need to be installed, if any. +#======================================================================== + +PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ + +#======================================================================== +# This is a list of public header files to be installed, if any. +#======================================================================== + +PKG_HEADERS = @PKG_HEADERS@ + +#======================================================================== +# "PKG_LIB_FILE" refers to the library (dynamic or static as per +# configuration options) composed of the named objects. +#======================================================================== + +PKG_LIB_FILE = @PKG_LIB_FILE@ +PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@ + +lib_BINARIES = $(PKG_LIB_FILE) +BINARIES = $(lib_BINARIES) + +SHELL = @SHELL@ + +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +libdir = @libdir@ +includedir = @includedir@ +datarootdir = @datarootdir@ +datadir = @datadir@ +mandir = @mandir@ + +DESTDIR = + +PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION) +pkgdatadir = $(datadir)/$(PKG_DIR) +pkglibdir = $(libdir)/$(PKG_DIR) +pkgincludedir = $(includedir)/$(PKG_DIR) + +top_builddir = . + +INSTALL_OPTIONS = +INSTALL = $(SHELL) $(srcdir)/tclconfig/install-sh -c ${INSTALL_OPTIONS} +INSTALL_DATA_DIR = ${INSTALL} -d -m 755 +INSTALL_PROGRAM = ${INSTALL} -m 555 +INSTALL_DATA = ${INSTALL} -m 444 +INSTALL_SCRIPT = ${INSTALL_PROGRAM} +INSTALL_LIBRARY = ${INSTALL} -m 644 + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +CC = @CC@ +CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ +CFLAGS_WARNING = @CFLAGS_WARNING@ +EXEEXT = @EXEEXT@ +LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ +MAKE_LIB = @MAKE_LIB@ +MAKE_SHARED_LIB = @MAKE_SHARED_LIB@ +MAKE_STATIC_LIB = @MAKE_STATIC_LIB@ +MAKE_STUB_LIB = @MAKE_STUB_LIB@ +OBJEXT = @OBJEXT@ +RANLIB = @RANLIB@ +RANLIB_STUB = @RANLIB_STUB@ +SHLIB_CFLAGS = @SHLIB_CFLAGS@ +SHLIB_LD = @SHLIB_LD@ +SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ +STLIB_LD = @STLIB_LD@ +#TCL_DEFS = @TCL_DEFS@ +TCL_BIN_DIR = @TCL_BIN_DIR@ +TCL_SRC_DIR = @TCL_SRC_DIR@ +#TK_BIN_DIR = @TK_BIN_DIR@ +#TK_SRC_DIR = @TK_SRC_DIR@ + +# Not used, but retained for reference of what libs Tcl required +#TCL_LIBS = @TCL_LIBS@ + +#======================================================================== +# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our +# package without installing. The other environment variables allow us +# to test against an uninstalled Tcl. Add special env vars that you +# require for testing here (like TCLX_LIBRARY). +#======================================================================== + +EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) +#EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR) +TCLLIBPATH = $(top_builddir) +TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` +PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ + PATH="$(EXTRA_PATH):$(PATH)" \ + TCLLIBPATH="$(TCLLIBPATH)" + +TCLSH_PROG = @TCLSH_PROG@ +TCLSH = $(PKG_ENV) $(TCLSH_ENV) $(TCLSH_PROG) + +#WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library` +#WISH_PROG = @WISH_PROG@ +#WISH = $(PKG_ENV) $(TCLSH_ENV) $(WISH_ENV) $(WISH_PROG) + +SHARED_BUILD = @SHARED_BUILD@ + +#INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ +INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ + +PKG_CFLAGS = @PKG_CFLAGS@ + +# TCL_DEFS is not strictly need here, but if you remove it, then you +# must make sure that configure.in checks for the necessary components +# that your library may use. TCL_DEFS can actually be a problem if +# you do not compile with a similar machine setup as the Tcl core was +# compiled with. +#DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS) +DEFS = @DEFS@ $(PKG_CFLAGS) + +# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile +CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl +CLEANFILES = @CLEANFILES@ + +CPPFLAGS = @CPPFLAGS@ +LIBS = @PKG_LIBS@ @LIBS@ +AR = @AR@ +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) + +.SUFFIXES: .c .$(OBJEXT) + +#======================================================================== +# Start of user-definable TARGETS section +#======================================================================== + +#======================================================================== +# TEA TARGETS. Please note that the "libraries:" target refers to platform +# independent files, and the "binaries:" target includes executable programs and +# platform-dependent libraries. Modify these targets so that they install +# the various pieces of your package. The make and install rules +# for the BINARIES that you specified above have already been done. +#======================================================================== + +all: binaries libraries #doc + +headers: src/makeheaders src/htmltokens.c + cd src; \ + ./makeheaders src/htmlcmd.c src/htmldraw.c src/htmlform.c src/htmlimage.c src/htmlindex.c src/htmllayout.c src/htmlparse.c src/htmlsizer.c src/htmltable.c src/htmltest.c src/htmlurl.c src/htmlwidget.c src/htmlexts.c htmltokens.c html.h + +src/makeheaders: tools/makeheaders.c + $(COMPILE) $< -o $@ + +src/htmltokens.c: src/tokenlist.txt tools/maketokens.tcl + $(TCLSH) tools/maketokens.tcl src/tokenlist.txt > src/htmltokens.c + +#======================================================================== +# The binaries target builds executable programs, Windows .dll's, unix +# shared/static libraries, and any other platform-dependent files. +# The list of targets to build for "binaries:" is specified at the top +# of the Makefile, in the "BINARIES" variable. +#======================================================================== + +binaries: $(BINARIES) + +libraries: + +#======================================================================== +# Your doc target should differentiate from doc builds (by the developer) +# and doc installs (see install-doc), which just install the docs on the +# end user machine when building from source. +#======================================================================== + +doc: + @echo "If you have documentation to create, place the commands to" + @echo "build the docs in the 'doc:' target. For example:" + @echo " xml2nroff sample.xml > sample.n" + @echo " xml2html sample.xml > sample.html" + +install: all install-binaries install-libraries #install-doc + +install-binaries: binaries install-lib-binaries install-bin-binaries + +#======================================================================== +# This rule installs platform-independent files, such as header files. +# The list=...; for p in $$list handles the empty list case x-platform. +#======================================================================== + +install-libraries: libraries + @$(INSTALL_DATA_DIR) $(DESTDIR)$(includedir) + @echo "Installing header files in $(DESTDIR)$(includedir)" + @list='$(PKG_HEADERS)'; for i in $$list; do \ + echo "Installing $(srcdir)/$$i" ; \ + $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \ + done; + +#======================================================================== +# Install documentation. Unix manpages should go in the $(mandir) +# directory. +#======================================================================== + +install-doc: doc + @$(INSTALL_DATA_DIR) $(DESTDIR)$(mandir)/mann + @echo "Installing documentation in $(DESTDIR)$(mandir)" + @list='$(srcdir)/doc/*.n'; for i in $$list; do \ + echo "Installing $$i"; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \ + done + +test: binaries libraries + $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \ + -load "package ifneeded ${PACKAGE_NAME} ${PACKAGE_VERSION} \ + [list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)]" + +shell: binaries libraries + @$(TCLSH) $(SCRIPT) + +gdb: + $(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT) + +VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high \ + --leak-check=yes --show-reachable=yes -v + +valgrind: binaries libraries + $(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) \ + `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) + +valgrindshell: binaries libraries + $(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT) + +depend: + +#======================================================================== +# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable +# mentioned above. That will ensure that this target is built when you +# run "make binaries". +# +# The $(PKG_OBJECTS) objects are created and linked into the final +# library. In most cases these object files will correspond to the +# source files above. +#======================================================================== + +$(PKG_LIB_FILE): $(PKG_OBJECTS) + -rm -f $(PKG_LIB_FILE) + ${MAKE_LIB} + $(RANLIB) $(PKG_LIB_FILE) + +$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS) + -rm -f $(PKG_STUB_LIB_FILE) + ${MAKE_STUB_LIB} + $(RANLIB_STUB) $(PKG_STUB_LIB_FILE) + +#======================================================================== +# We need to enumerate the list of .c to .o lines here. +# +# In the following lines, $(srcdir) refers to the toplevel directory +# containing your extension. If your sources are in a subdirectory, +# you will have to modify the paths to reflect this: +# +# sample.$(OBJEXT): $(srcdir)/generic/sample.c +# $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@ +# +# Setting the VPATH variable to a list of paths will cause the makefile +# to look into these paths when resolving .c to .obj dependencies. +# As necessary, add $(srcdir):$(srcdir)/compat:.... +#======================================================================== + +VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx + +.c.@OBJEXT@: + $(COMPILE) -c `@CYGPATH@ $<` -o $@ + +#======================================================================== +# Distribution creation +# You may need to tweak this target to make it work correctly. +#======================================================================== + +#COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar +COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR) +DIST_ROOT = /tmp/dist +DIST_DIR = $(DIST_ROOT)/$(PKG_DIR) + +dist-clean: + rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.* + +dist: dist-clean + $(INSTALL_DATA_DIR) $(DIST_DIR) + cp -p $(srcdir)/ChangeLog $(srcdir)/README* $(srcdir)/license* \ + $(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \ + $(DIST_DIR)/ + chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4 + chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in + + for i in $(srcdir)/*.[ch]; do \ + if [ -f $$i ]; then \ + cp -p $$i $(DIST_DIR)/ ; \ + fi; \ + done; + + $(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig + cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \ + $(DIST_DIR)/tclconfig/ + chmod 664 $(DIST_DIR)/tclconfig/tcl.m4 + chmod +x $(DIST_DIR)/tclconfig/install-sh + + list='demos doc generic library mac tests unix win'; \ + for p in $$list; do \ + if test -d $(srcdir)/$$p ; then \ + $(INSTALL_DATA_DIR) $(DIST_DIR)/$$p; \ + cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \ + fi; \ + done + + (cd $(DIST_ROOT); $(COMPRESS);) + +#======================================================================== +# End of user-definable section +#======================================================================== + +#======================================================================== +# Don't modify the file to clean here. Instead, set the "CLEANFILES" +# variable in configure.in +#======================================================================== + +clean: + -test -z "$(BINARIES)" || rm -f $(BINARIES) + -rm -f $(PKG_OBJECTS) *.$(OBJEXT) core *.core + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean: clean + -rm -f *.tab.c + -rm -f $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log config.status + +#======================================================================== +# Install binary object libraries. On Windows this includes both .dll and +# .lib files. Because the .lib files are not explicitly listed anywhere, +# we need to deduce their existence from the .dll file of the same name. +# Library files go into the lib directory. +# In addition, this will generate the pkgIndex.tcl +# file in the install location (assuming it can find a usable tclsh shell) +# +# You should not have to modify this target. +#======================================================================== + +install-lib-binaries: binaries + @$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir) + @list='$(lib_BINARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ + $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p; \ + stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \ + if test "x$$stub" = "xstub"; then \ + echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \ + $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \ + else \ + echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \ + $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \ + fi; \ + ext=`echo $$p|sed -e "s/.*\.//"`; \ + if test "x$$ext" = "xdll"; then \ + lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ + if test -f $$lib; then \ + echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \ + $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \ + fi; \ + fi; \ + fi; \ + done + @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + destp=`basename $$p`; \ + echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \ + fi; \ + done + @if test "x$(SHARED_BUILD)" = "x1"; then \ + echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \ + $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \ + fi + +#======================================================================== +# Install binary executables (e.g. .exe files and dependent .dll files) +# This is for files that must go in the bin directory (located next to +# wish and tclsh), like dependent .dll files on Windows. +# +# You should not have to modify this target, except to define bin_BINARIES +# above if necessary. +#======================================================================== + +install-bin-binaries: binaries + @$(INSTALL_DATA_DIR) $(DESTDIR)$(bindir) + @list='$(bin_BINARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \ + fi; \ + done + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +uninstall-binaries: + list='$(lib_BINARIES)'; for p in $$list; do \ + rm -f $(DESTDIR)$(pkglibdir)/$$p; \ + done + list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ + p=`basename $$p`; \ + rm -f $(DESTDIR)$(pkglibdir)/$$p; \ + done + list='$(bin_BINARIES)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/$$p; \ + done + +.PHONY: all binaries clean depend distclean doc install libraries test + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tkhtml1/README.md b/tkhtml1/README.md new file mode 100644 index 0000000..6c1f853 --- /dev/null +++ b/tkhtml1/README.md @@ -0,0 +1,5 @@ +# tkhtml1 +TK HTML Widget. +Tcl/Tk 8.5/8.6 TEA compatible. +Full support for MacOSX and Windows. +Based on tkhtml version 1 by D. Richard Hipp. diff --git a/tkhtml1/aclocal.m4 b/tkhtml1/aclocal.m4 new file mode 100755 index 0000000..0b05739 --- /dev/null +++ b/tkhtml1/aclocal.m4 @@ -0,0 +1,9 @@ +# +# Include the TEA standard macro set +# + +builtin(include,tclconfig/tcl.m4) + +# +# Add here whatever m4 macros you want to define for your package +# diff --git a/tkhtml1/configure b/tkhtml1/configure new file mode 100755 index 0000000..20aaa88 --- /dev/null +++ b/tkhtml1/configure @@ -0,0 +1,10451 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for tkhtml1 1.0. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 </dev/null +exec 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='tkhtml1' +PACKAGE_TARNAME='tkhtml1' +PACKAGE_VERSION='1.0' +PACKAGE_STRING='tkhtml1 1.0' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +WISH_PROG +TCLSH_PROG +VC_MANIFEST_EMBED_EXE +VC_MANIFEST_EMBED_DLL +RANLIB_STUB +MAKE_STUB_LIB +MAKE_STATIC_LIB +MAKE_SHARED_LIB +MAKE_LIB +TCL_DBGX +LDFLAGS_DEFAULT +CFLAGS_DEFAULT +LD_LIBRARY_PATH_VAR +SHLIB_CFLAGS +SHLIB_LD_LIBS +SHLIB_LD +STLIB_LD +CFLAGS_WARNING +CFLAGS_OPTIMIZE +CFLAGS_DEBUG +RC +CELIB_DIR +AR +SHARED_BUILD +TCL_THREADS +XMKMF +TK_INCLUDES +TCL_INCLUDES +PKG_OBJECTS +PKG_SOURCES +MATH_LIBS +EGREP +GREP +RANLIB +SET_MAKE +INSTALL +CPP +TK_XINCLUDES +TK_LIBS +TK_STUB_LIB_SPEC +TK_STUB_LIB_FLAG +TK_STUB_LIB_FILE +TK_LIB_SPEC +TK_LIB_FLAG +TK_LIB_FILE +TK_SRC_DIR +TK_BIN_DIR +TK_VERSION +TCL_SHLIB_LD_LIBS +TCL_LD_FLAGS +TCL_EXTRA_CFLAGS +TCL_DEFS +TCL_LIBS +CLEANFILES +OBJEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +TCL_STUB_LIB_SPEC +TCL_STUB_LIB_FLAG +TCL_STUB_LIB_FILE +TCL_LIB_SPEC +TCL_LIB_FLAG +TCL_LIB_FILE +TCL_SRC_DIR +TCL_BIN_DIR +TCL_PATCH_LEVEL +TCL_VERSION +PKG_CFLAGS +PKG_LIBS +PKG_INCLUDES +PKG_HEADERS +PKG_TCL_SOURCES +PKG_STUB_OBJECTS +PKG_STUB_SOURCES +PKG_STUB_LIB_FILE +PKG_LIB_FILE +EXEEXT +CYGPATH +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_tcl +with_tk +with_tclinclude +with_tkinclude +with_x +enable_threads +enable_shared +enable_64bit +enable_64bit_vis +enable_rpath +enable_wince +with_celib +enable_symbols +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +XMKMF' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures tkhtml1 1.0 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/tkhtml1] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of tkhtml1 1.0:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-threads build with threads + --enable-shared build and link with shared libraries (default: on) + --enable-64bit enable 64bit support (default: off) + --enable-64bit-vis enable 64bit Sparc VIS support (default: off) + --disable-rpath disable rpath support (default: on) + --enable-wince enable Win/CE support (where applicable) + --enable-symbols build with debugging symbols (default: off) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-tcl directory containing tcl configuration + (tclConfig.sh) + --with-tk directory containing tk configuration (tkConfig.sh) + --with-tclinclude directory containing the public Tcl header files + --with-tkinclude directory containing the public Tk header files + --with-x use the X Window System + --with-celib=DIR use Windows/CE support library from DIR + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + LIBS libraries to pass to the linker, e.g. -l<library> + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> + CPP C preprocessor + XMKMF Path to xmkmf, Makefile generator for X Window System + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +tkhtml1 configure 1.0 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by tkhtml1 $as_me 1.0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +#-------------------------------------------------------------------- +# Call TEA_INIT as the first TEA_ macro to set up initial vars. +# This will define a ${TEA_PLATFORM} variable == "unix" or "windows" +# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. +#-------------------------------------------------------------------- + + + # TEA extensions pass this us the version of TEA they think they + # are compatible with. + TEA_VERSION="3.9" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for correct TEA configuration" >&5 +$as_echo_n "checking for correct TEA configuration... " >&6; } + if test x"${PACKAGE_NAME}" = x ; then + as_fn_error $? " +The PACKAGE_NAME variable must be defined by your TEA configure.in" "$LINENO" 5 + fi + if test x"3.9" = x ; then + as_fn_error $? " +TEA version not specified." "$LINENO" 5 + elif test "3.9" != "${TEA_VERSION}" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&5 +$as_echo "warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok (TEA ${TEA_VERSION})" >&5 +$as_echo "ok (TEA ${TEA_VERSION})" >&6; } + fi + + # If the user did not set CFLAGS, set it now to keep macros + # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". + if test "${CFLAGS+set}" != "set" ; then + CFLAGS="" + fi + + case "`uname -s`" in + *win32*|*WIN32*|*MINGW32_*) + # Extract the first word of "cygpath", so it can be a program name with args. +set dummy cygpath; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CYGPATH+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CYGPATH"; then + ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CYGPATH="cygpath -w" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" +fi +fi +CYGPATH=$ac_cv_prog_CYGPATH +if test -n "$CYGPATH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 +$as_echo "$CYGPATH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *CYGWIN_*) + CYGPATH=echo + EXEEXT=".exe" + # TEA_PLATFORM is determined later in LOAD_TCLCONFIG + ;; + *) + CYGPATH=echo + # Maybe we are cross-compiling.... + case ${host_alias} in + *mingw32*) + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *) + EXEEXT="" + TEA_PLATFORM="unix" + ;; + esac + ;; + esac + + # Check if exec_prefix is set. If not use fall back to prefix. + # Note when adjusted, so that TEA_PREFIX can correct for this. + # This is needed for recursive configures, since autoconf propagates + # $prefix, but not $exec_prefix (doh!). + if test x$exec_prefix = xNONE ; then + exec_prefix_default=yes + exec_prefix=$prefix + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&5 +$as_echo "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;} + + + + + # This package name must be replaced statically for AC_SUBST to work + + # Substitute STUB_LIB_FILE in case package creates a stub library too. + + + # We AC_SUBST these here to ensure they are subst'ed, + # in case the user doesn't call TEA_ADD_... + + + + + + + + + +ac_aux_dir= +for ac_dir in tclconfig "$srcdir"/tclconfig; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in tclconfig \"$srcdir\"/tclconfig" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +#-------------------------------------------------------------------- +# Load the tclConfig.sh file +#-------------------------------------------------------------------- + + + + # + # Ok, lets find the tcl configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tcl + # + + if test x"${no_tcl}" = x ; then + # we reset no_tcl in case something fails here + no_tcl=true + +# Check whether --with-tcl was given. +if test "${with_tcl+set}" = set; then : + withval=$with_tcl; with_tclconfig="${withval}" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5 +$as_echo_n "checking for Tcl configuration... " >&6; } + if ${ac_cv_c_tclconfig+:} false; then : + $as_echo_n "(cached) " >&6 +else + + + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + case "${with_tclconfig}" in + */tclConfig.sh ) + if test -f "${with_tclconfig}"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 +$as_echo "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;} + with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" + else + as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5 + fi + fi + + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + ; do + if test -f "$i/Tcl.framework/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + +fi + + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + as_fn_error $? "Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" "$LINENO" 5 + else + no_tcl= + TCL_BIN_DIR="${ac_cv_c_tclconfig}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 +$as_echo "found ${TCL_BIN_DIR}/tclConfig.sh" >&6; } + fi + fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 +$as_echo_n "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; } + + if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5 +$as_echo "loading" >&6; } + . "${TCL_BIN_DIR}/tclConfig.sh" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 +$as_echo "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; } + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" + + # If the TCL_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TCL_LIB_SPEC will be set to the value + # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC + # instead of TCL_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" + TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" + TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tcl.framework installed in an arbitrary location. + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then + for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ + "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then + TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" + break + fi + done + fi + if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then + TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" + TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" + eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking platform" >&5 +$as_echo_n "checking platform... " >&6; } + hold_cc=$CC; CC="$TCL_CC" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + #ifdef _WIN32 + #error win32 + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + TEA_PLATFORM="unix" +else + TEA_PLATFORM="windows" + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CC=$hold_cc + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEA_PLATFORM" >&5 +$as_echo "$TEA_PLATFORM" >&6; } + + # The BUILD_$pkg is to define the correct extern storage class + # handling when making this package + +cat >>confdefs.h <<_ACEOF +#define BUILD_${PACKAGE_NAME} /**/ +_ACEOF + + # Do this here as we have fully defined TEA_PLATFORM now + if test "${TEA_PLATFORM}" = "windows" ; then + EXEEXT=".exe" + CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" + fi + + # TEA specific: + + + + + + + + +#-------------------------------------------------------------------- +# Load the tkConfig.sh file if necessary (Tk extension) +#-------------------------------------------------------------------- + + + # + # Ok, lets find the tk configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tk + # + + if test x"${no_tk}" = x ; then + # we reset no_tk in case something fails here + no_tk=true + +# Check whether --with-tk was given. +if test "${with_tk+set}" = set; then : + withval=$with_tk; with_tkconfig="${withval}" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tk configuration" >&5 +$as_echo_n "checking for Tk configuration... " >&6; } + if ${ac_cv_c_tkconfig+:} false; then : + $as_echo_n "(cached) " >&6 +else + + + # First check to see if --with-tkconfig was specified. + if test x"${with_tkconfig}" != x ; then + case "${with_tkconfig}" in + */tkConfig.sh ) + if test -f "${with_tkconfig}"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself" >&5 +$as_echo "$as_me: WARNING: --with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself" >&2;} + with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tkconfig}/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" + else + as_fn_error $? "${with_tkconfig} directory doesn't contain tkConfig.sh" "$LINENO" 5 + fi + fi + + # then check for a private Tk library + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ../tk \ + `ls -dr ../tk[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../tk[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../tk[8-9].[0-9]* 2>/dev/null` \ + ../../tk \ + `ls -dr ../../tk[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../tk[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../tk[8-9].[0-9]* 2>/dev/null` \ + ../../../tk \ + `ls -dr ../../../tk[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../../tk[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../../tk[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + ; do + if test -f "$i/Tk.framework/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ${srcdir}/../tk \ + `ls -dr ${srcdir}/../tk[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[8-9].[0-9] 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[8-9].[0-9]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + +fi + + + if test x"${ac_cv_c_tkconfig}" = x ; then + TK_BIN_DIR="# no Tk configs found" + as_fn_error $? "Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh" "$LINENO" 5 + else + no_tk= + TK_BIN_DIR="${ac_cv_c_tkconfig}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found ${TK_BIN_DIR}/tkConfig.sh" >&5 +$as_echo "found ${TK_BIN_DIR}/tkConfig.sh" >&6; } + fi + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of ${TK_BIN_DIR}/tkConfig.sh" >&5 +$as_echo_n "checking for existence of ${TK_BIN_DIR}/tkConfig.sh... " >&6; } + + if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5 +$as_echo "loading" >&6; } + . "${TK_BIN_DIR}/tkConfig.sh" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find ${TK_BIN_DIR}/tkConfig.sh" >&5 +$as_echo "could not find ${TK_BIN_DIR}/tkConfig.sh" >&6; } + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FILE=\"${TK_LIB_FILE}\"" + eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\"" + + # If the TK_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TK_LIB_SPEC will be set to the value + # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC + # instead of TK_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TK_BIN_DIR}/Makefile" ; then + TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}" + TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}" + TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tk.framework installed in an arbitrary location. + case ${TK_DEFS} in + *TK_FRAMEWORK*) + if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then + for i in "`cd "${TK_BIN_DIR}"; pwd`" \ + "`cd "${TK_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then + TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}" + break + fi + done + fi + if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then + TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" + TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\"" + eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\"" + eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\"" + eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\"" + + # TEA specific: Ensure windowingsystem is defined + if test "${TEA_PLATFORM}" = "unix" ; then + case ${TK_DEFS} in + *MAC_OSX_TK*) + +$as_echo "#define MAC_OSX_TK 1" >>confdefs.h + + TEA_WINDOWINGSYSTEM="aqua" + ;; + *) + TEA_WINDOWINGSYSTEM="x11" + ;; + esac + elif test "${TEA_PLATFORM}" = "windows" ; then + TEA_WINDOWINGSYSTEM="win32" + fi + + + + + + + + + + + + + + # TEA specific: + + + + +#----------------------------------------------------------------------- +# Handle the --prefix=... option by defaulting to what Tcl gave. +# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. +#----------------------------------------------------------------------- + + + if test "${prefix}" = "NONE"; then + prefix_default=yes + if test x"${TCL_PREFIX}" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5 +$as_echo "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;} + prefix=${TCL_PREFIX} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to /usr/local" >&5 +$as_echo "$as_me: --prefix defaulting to /usr/local" >&6;} + prefix=/usr/local + fi + fi + if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ + -o x"${exec_prefix_default}" = x"yes" ; then + if test x"${TCL_EXEC_PREFIX}" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5 +$as_echo "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;} + exec_prefix=${TCL_EXEC_PREFIX} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to ${prefix}" >&5 +$as_echo "$as_me: --exec-prefix defaulting to ${prefix}" >&6;} + exec_prefix=$prefix + fi + fi + + +#----------------------------------------------------------------------- +# Standard compiler checks. +# This sets up CC by using the CC env var, or looks for gcc otherwise. +# This also calls AC_PROG_CC and a few others to create the basic setup +# necessary to compile executables. +#----------------------------------------------------------------------- + + + # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) + # in this macro, they need to go into TEA_SETUP_COMPILER instead. + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + INSTALL="\$(SHELL) \$(srcdir)/tclconfig/install-sh -c" + + + #-------------------------------------------------------------------- + # Checks to see if the make program sets the $MAKE variable. + #-------------------------------------------------------------------- + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + + #-------------------------------------------------------------------- + # Find ranlib + #-------------------------------------------------------------------- + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + + #-------------------------------------------------------------------- + # Determines the correct binary file extension (.o, .obj, .exe etc.) + #-------------------------------------------------------------------- + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. + + + #------------------------------------------------------------------------ + # If we're using GCC, see if the compiler understands -pipe. If so, use it. + # It makes compiling go faster. (This is only a performance feature.) + #------------------------------------------------------------------------ + + if test -z "$no_pipe" -a -n "$GCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5 +$as_echo_n "checking if the compiler understands -pipe... " >&6; } +if ${tcl_cv_cc_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_cc_pipe=yes +else + tcl_cv_cc_pipe=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5 +$as_echo "$tcl_cv_cc_pipe" >&6; } + if test $tcl_cv_cc_pipe = yes; then + CFLAGS="$CFLAGS -pipe" + fi + fi + + #-------------------------------------------------------------------- + # Common compiler flag setup + #-------------------------------------------------------------------- + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + if test "${TEA_PLATFORM}" = "unix" ; then + + #-------------------------------------------------------------------- + # On a few very rare systems, all of the libm.a stuff is + # already in libc.a. Set compiler flags accordingly. + # Also, Linux requires the "ieee" library for math to work + # right (and it must appear before "-lm"). + #-------------------------------------------------------------------- + + ac_fn_c_check_func "$LINENO" "sin" "ac_cv_func_sin" +if test "x$ac_cv_func_sin" = xyes; then : + MATH_LIBS="" +else + MATH_LIBS="-lm" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lieee" >&5 +$as_echo_n "checking for main in -lieee... " >&6; } +if ${ac_cv_lib_ieee_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lieee $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ieee_main=yes +else + ac_cv_lib_ieee_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ieee_main" >&5 +$as_echo "$ac_cv_lib_ieee_main" >&6; } +if test "x$ac_cv_lib_ieee_main" = xyes; then : + MATH_LIBS="-lieee $MATH_LIBS" +fi + + + #-------------------------------------------------------------------- + # Interactive UNIX requires -linet instead of -lsocket, plus it + # needs net/errno.h to define the socket-related error codes. + #-------------------------------------------------------------------- + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5 +$as_echo_n "checking for main in -linet... " >&6; } +if ${ac_cv_lib_inet_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-linet $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_inet_main=yes +else + ac_cv_lib_inet_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main" >&5 +$as_echo "$ac_cv_lib_inet_main" >&6; } +if test "x$ac_cv_lib_inet_main" = xyes; then : + LIBS="$LIBS -linet" +fi + + ac_fn_c_check_header_mongrel "$LINENO" "net/errno.h" "ac_cv_header_net_errno_h" "$ac_includes_default" +if test "x$ac_cv_header_net_errno_h" = xyes; then : + + +$as_echo "#define HAVE_NET_ERRNO_H 1" >>confdefs.h + +fi + + + + #-------------------------------------------------------------------- + # Check for the existence of the -lsocket and -lnsl libraries. + # The order here is important, so that they end up in the right + # order in the command line generated by make. Here are some + # special considerations: + # 1. Use "connect" and "accept" to check for -lsocket, and + # "gethostbyname" to check for -lnsl. + # 2. Use each function name only once: can't redo a check because + # autoconf caches the results of the last check and won't redo it. + # 3. Use -lnsl and -lsocket only if they supply procedures that + # aren't already present in the normal libraries. This is because + # IRIX 5.2 has libraries, but they aren't needed and they're + # bogus: they goof up name resolution if used. + # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. + # To get around this problem, check for both libraries together + # if -lsocket doesn't work by itself. + #-------------------------------------------------------------------- + + tcl_checkBoth=0 + ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" +if test "x$ac_cv_func_connect" = xyes; then : + tcl_checkSocket=0 +else + tcl_checkSocket=1 +fi + + if test "$tcl_checkSocket" = 1; then + ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt" +if test "x$ac_cv_func_setsockopt" = xyes; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5 +$as_echo_n "checking for setsockopt in -lsocket... " >&6; } +if ${ac_cv_lib_socket_setsockopt+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char setsockopt (); +int +main () +{ +return setsockopt (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_setsockopt=yes +else + ac_cv_lib_socket_setsockopt=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5 +$as_echo "$ac_cv_lib_socket_setsockopt" >&6; } +if test "x$ac_cv_lib_socket_setsockopt" = xyes; then : + LIBS="$LIBS -lsocket" +else + tcl_checkBoth=1 +fi + +fi + + fi + if test "$tcl_checkBoth" = 1; then + tk_oldLibs=$LIBS + LIBS="$LIBS -lsocket -lnsl" + ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept" +if test "x$ac_cv_func_accept" = xyes; then : + tcl_checkNsl=0 +else + LIBS=$tk_oldLibs +fi + + fi + ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" +if test "x$ac_cv_func_gethostbyname" = xyes; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 +$as_echo_n "checking for gethostbyname in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nsl_gethostbyname=yes +else + ac_cv_lib_nsl_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 +$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } +if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : + LIBS="$LIBS -lnsl" +fi + +fi + + + # TEA specific: Don't perform the eval of the libraries here because + # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS + + TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dirent.h" >&5 +$as_echo_n "checking dirent.h... " >&6; } +if ${tcl_cv_dirent_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> +#include <dirent.h> +int +main () +{ + +#ifndef _POSIX_SOURCE +# ifdef __Lynx__ + /* + * Generate compilation error to make the test fail: Lynx headers + * are only valid if really in the POSIX environment. + */ + + missing_procedure(); +# endif +#endif +DIR *d; +struct dirent *entryPtr; +char *p; +d = opendir("foobar"); +entryPtr = readdir(d); +p = entryPtr->d_name; +closedir(d); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_dirent_h=yes +else + tcl_cv_dirent_h=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_dirent_h" >&5 +$as_echo "$tcl_cv_dirent_h" >&6; } + + if test $tcl_cv_dirent_h = no; then + +$as_echo "#define NO_DIRENT_H 1" >>confdefs.h + + fi + + # TEA specific: + ac_fn_c_check_header_mongrel "$LINENO" "errno.h" "ac_cv_header_errno_h" "$ac_includes_default" +if test "x$ac_cv_header_errno_h" = xyes; then : + +else + +$as_echo "#define NO_ERRNO_H 1" >>confdefs.h + +fi + + + ac_fn_c_check_header_mongrel "$LINENO" "float.h" "ac_cv_header_float_h" "$ac_includes_default" +if test "x$ac_cv_header_float_h" = xyes; then : + +else + +$as_echo "#define NO_FLOAT_H 1" >>confdefs.h + +fi + + + ac_fn_c_check_header_mongrel "$LINENO" "values.h" "ac_cv_header_values_h" "$ac_includes_default" +if test "x$ac_cv_header_values_h" = xyes; then : + +else + +$as_echo "#define NO_VALUES_H 1" >>confdefs.h + +fi + + + ac_fn_c_check_header_mongrel "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default" +if test "x$ac_cv_header_limits_h" = xyes; then : + +$as_echo "#define HAVE_LIMITS_H 1" >>confdefs.h + +else + +$as_echo "#define NO_LIMITS_H 1" >>confdefs.h + +fi + + + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + tcl_ok=1 +else + tcl_ok=0 +fi + + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtol" >/dev/null 2>&1; then : + +else + tcl_ok=0 +fi +rm -f conftest* + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtoul" >/dev/null 2>&1; then : + +else + tcl_ok=0 +fi +rm -f conftest* + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strtod" >/dev/null 2>&1; then : + +else + tcl_ok=0 +fi +rm -f conftest* + + if test $tcl_ok = 0; then + +$as_echo "#define NO_STDLIB_H 1" >>confdefs.h + + fi + ac_fn_c_check_header_mongrel "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" +if test "x$ac_cv_header_string_h" = xyes; then : + tcl_ok=1 +else + tcl_ok=0 +fi + + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strstr" >/dev/null 2>&1; then : + +else + tcl_ok=0 +fi +rm -f conftest* + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "strerror" >/dev/null 2>&1; then : + +else + tcl_ok=0 +fi +rm -f conftest* + + + # See also memmove check below for a place where NO_STRING_H can be + # set and why. + + if test $tcl_ok = 0; then + +$as_echo "#define NO_STRING_H 1" >>confdefs.h + + fi + + ac_fn_c_check_header_mongrel "$LINENO" "sys/wait.h" "ac_cv_header_sys_wait_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_wait_h" = xyes; then : + +else + +$as_echo "#define NO_SYS_WAIT_H 1" >>confdefs.h + +fi + + + ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + +else + +$as_echo "#define NO_DLFCN_H 1" >>confdefs.h + +fi + + + + # OS/390 lacks sys/param.h (and doesn't need it, by chance). + for ac_header in sys/param.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_param_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_PARAM_H 1 +_ACEOF + +fi + +done + + + # Let the user call this, because if it triggers, they will + # need a compat/strtod.c that is correct. Users can also + # use Tcl_GetDouble(FromObj) instead. + #TEA_BUGGY_STRTOD + fi + + +#----------------------------------------------------------------------- +# __CHANGE__ +# Specify the C source files to compile in TEA_ADD_SOURCES, +# public headers that need to be installed in TEA_ADD_HEADERS, +# stub library C source files to compile in TEA_ADD_STUB_SOURCES, +# and runtime Tcl library files in TEA_ADD_TCL_SOURCES. +# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS +# and PKG_TCL_SOURCES. +#----------------------------------------------------------------------- + + + vars=" +src/htmlcmd.c +src/htmldraw.c +src/htmlform.c +src/htmlimage.c +src/htmlindex.c +src/htmllayout.c +src/htmlparse.c +src/htmlsizer.c +src/htmltable.c +src/htmltest.c +src/htmlurl.c +src/htmlwidget.c +src/htmlexts.c +src/htmltokens.c +" + for i in $vars; do + case $i in + \$*) + # allow $-var names + PKG_SOURCES="$PKG_SOURCES $i" + PKG_OBJECTS="$PKG_OBJECTS $i" + ;; + *) + # check for existence - allows for generic/win/unix VPATH + # To add more dirs here (like 'src'), you have to update VPATH + # in Makefile.in as well + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + as_fn_error $? "could not find source file '$i'" "$LINENO" 5 + fi + PKG_SOURCES="$PKG_SOURCES $i" + # this assumes it is in a VPATH dir +# i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" + fi + PKG_OBJECTS="$PKG_OBJECTS $j" + ;; + esac + done + + + + + vars="" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + as_fn_error $? "could not find header file '${srcdir}/$i'" "$LINENO" 5 + fi + PKG_HEADERS="$PKG_HEADERS $i" + done + + + + vars="-I./src" + for i in $vars; do + PKG_INCLUDES="$PKG_INCLUDES $i" + done + + + + vars="" + for i in $vars; do + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then + # Convert foo.lib to -lfoo for GCC. No-op if not *.lib + i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'` + fi + PKG_LIBS="$PKG_LIBS $i" + done + + + + PKG_CFLAGS="$PKG_CFLAGS -DUSE_INTERP_RESULT" + + + + vars="" + for i in $vars; do + # check for existence - allows for generic/win/unix VPATH + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + as_fn_error $? "could not find stub source file '$i'" "$LINENO" 5 + fi + PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" + fi + PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" + done + + + + + vars="" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + as_fn_error $? "could not find tcl source file '${srcdir}/$i'" "$LINENO" 5 + fi + PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" + done + + + +#-------------------------------------------------------------------- +# __CHANGE__ +# +# You can add more files to clean if your extension creates any extra +# files by extending CLEANFILES. +# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure +# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. +# +# A few miscellaneous platform-specific items: +# TEA_ADD_* any platform specific compiler/build info here. +#-------------------------------------------------------------------- + +CLEANFILES="$CLEANFILES src/makeheaders" +if test "${TEA_PLATFORM}" = "windows" ; then + # Ensure no empty if clauses + : + #TEA_ADD_SOURCES([win/winFile.c]) + #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) +else + # Ensure no empty else clauses + : + #TEA_ADD_SOURCES([unix/unixFile.c]) + #TEA_ADD_LIBS([-lsuperfly]) +fi + +#-------------------------------------------------------------------- +# __CHANGE__ +# Choose which headers you need. Extension authors should try very +# hard to only rely on the Tcl public header files. Internal headers +# contain private data structures and are subject to change without +# notice. +# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG +#-------------------------------------------------------------------- + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl public headers" >&5 +$as_echo_n "checking for Tcl public headers... " >&6; } + + +# Check whether --with-tclinclude was given. +if test "${with_tclinclude+set}" = set; then : + withval=$with_tclinclude; with_tclinclude=${withval} +fi + + + if ${ac_cv_c_tclh+:} false; then : + $as_echo_n "(cached) " >&6 +else + + # Use the value from --with-tclinclude, if it was given + + if test x"${with_tclinclude}" != x ; then + if test -f "${with_tclinclude}/tcl.h" ; then + ac_cv_c_tclh=${with_tclinclude} + else + as_fn_error $? "${with_tclinclude} directory does not contain tcl.h" "$LINENO" 5 + fi + else + list="" + if test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use + # the framework's Headers directory + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" + ;; + esac + fi + + # Look in the source dir only if Tcl is not installed, + # and in that situation, look there before installed locations. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" + fi + + # Check order: pkg --prefix location, Tcl's --prefix location, + # relative to directory of tclConfig.sh. + + eval "temp_includedir=${includedir}" + list="$list \ + `ls -d ${temp_includedir} 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" + if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then + list="$list /usr/local/include /usr/include" + if test x"${TCL_INCLUDE_SPEC}" != x ; then + d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` + list="$list `ls -d ${d} 2>/dev/null`" + fi + fi + for i in $list ; do + if test -f "$i/tcl.h" ; then + ac_cv_c_tclh=$i + break + fi + done + fi + +fi + + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tclh}" = x ; then + as_fn_error $? "tcl.h not found. Please specify its location with --with-tclinclude" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tclh}" >&5 +$as_echo "${ac_cv_c_tclh}" >&6; } + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` + + TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + + +#TEA_PRIVATE_TCL_HEADERS + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tk public headers" >&5 +$as_echo_n "checking for Tk public headers... " >&6; } + + +# Check whether --with-tkinclude was given. +if test "${with_tkinclude+set}" = set; then : + withval=$with_tkinclude; with_tkinclude=${withval} +fi + + + if ${ac_cv_c_tkh+:} false; then : + $as_echo_n "(cached) " >&6 +else + + # Use the value from --with-tkinclude, if it was given + + if test x"${with_tkinclude}" != x ; then + if test -f "${with_tkinclude}/tk.h" ; then + ac_cv_c_tkh=${with_tkinclude} + else + as_fn_error $? "${with_tkinclude} directory does not contain tk.h" "$LINENO" 5 + fi + else + list="" + if test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use + # the framework's Headers directory. + case ${TK_DEFS} in + *TK_FRAMEWORK*) + list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`" + ;; + esac + fi + + # Look in the source dir only if Tk is not installed, + # and in that situation, look there before installed locations. + if test -f "${TK_BIN_DIR}/Makefile" ; then + list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`" + fi + + # Check order: pkg --prefix location, Tk's --prefix location, + # relative to directory of tkConfig.sh, Tcl's --prefix location, + # relative to directory of tclConfig.sh. + + eval "temp_includedir=${includedir}" + list="$list \ + `ls -d ${temp_includedir} 2>/dev/null` \ + `ls -d ${TK_PREFIX}/include 2>/dev/null` \ + `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" + if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then + list="$list /usr/local/include /usr/include" + if test x"${TK_INCLUDE_SPEC}" != x ; then + d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'` + list="$list `ls -d ${d} 2>/dev/null`" + fi + fi + for i in $list ; do + if test -f "$i/tk.h" ; then + ac_cv_c_tkh=$i + break + fi + done + fi + +fi + + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tkh}" = x ; then + as_fn_error $? "tk.h not found. Please specify its location with --with-tkinclude" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tkh}" >&5 +$as_echo "${ac_cv_c_tkh}" >&6; } + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}` + + TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + + + if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then + # On Windows and Aqua, we need the X compat headers + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11 header files" >&5 +$as_echo_n "checking for X11 header files... " >&6; } + if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then + INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`" + TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${INCLUDE_DIR_NATIVE}" >&5 +$as_echo "${INCLUDE_DIR_NATIVE}" >&6; } + fi + +#TEA_PRIVATE_TK_HEADERS + + if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 +$as_echo_n "checking for X... " >&6; } + + +# Check whether --with-x was given. +if test "${with_x+set}" = set; then : + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : + $as_echo_n "(cached) " >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /usr/lib64 | /lib | /lib64) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R7/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R7 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R7/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R7 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <X11/Xlib.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # We can compile using X headers with no special include directory. +ac_x_includes= +else + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <X11/Xlib.h> +int +main () +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + LIBS=$ac_save_LIBS +for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no";; #( + *) + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 +$as_echo "$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 +$as_echo "libraries $x_libraries, headers $x_includes" >&6; } +fi + + not_really_there="" + if test "$no_x" = ""; then + if test "$x_includes" = ""; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <X11/Xlib.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + not_really_there="yes" +fi +rm -f conftest.err conftest.i conftest.$ac_ext + else + if test ! -r $x_includes/X11/Xlib.h; then + not_really_there="yes" + fi + fi + fi + if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11 header files" >&5 +$as_echo_n "checking for X11 header files... " >&6; } + found_xincludes="no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <X11/Xlib.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + found_xincludes="yes" +else + found_xincludes="no" +fi +rm -f conftest.err conftest.i conftest.$ac_ext + if test "$found_xincludes" = "no"; then + dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" + for i in $dirs ; do + if test -r $i/X11/Xlib.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $i" >&5 +$as_echo "$i" >&6; } + XINCLUDES=" -I$i" + found_xincludes="yes" + break + fi + done + fi + else + if test "$x_includes" != ""; then + XINCLUDES="-I$x_includes" + found_xincludes="yes" + fi + fi + if test "$found_xincludes" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: couldn't find any!" >&5 +$as_echo "couldn't find any!" >&6; } + fi + + if test "$no_x" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11 libraries" >&5 +$as_echo_n "checking for X11 libraries... " >&6; } + XLIBSW=nope + dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" + for i in $dirs ; do + if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $i" >&5 +$as_echo "$i" >&6; } + XLIBSW="-L$i -lX11" + x_libraries="$i" + break + fi + done + else + if test "$x_libraries" = ""; then + XLIBSW=-lX11 + else + XLIBSW="-L$x_libraries -lX11" + fi + fi + if test "$XLIBSW" = nope ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XCreateWindow in -lXwindow" >&5 +$as_echo_n "checking for XCreateWindow in -lXwindow... " >&6; } +if ${ac_cv_lib_Xwindow_XCreateWindow+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXwindow $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XCreateWindow (); +int +main () +{ +return XCreateWindow (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_Xwindow_XCreateWindow=yes +else + ac_cv_lib_Xwindow_XCreateWindow=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xwindow_XCreateWindow" >&5 +$as_echo "$ac_cv_lib_Xwindow_XCreateWindow" >&6; } +if test "x$ac_cv_lib_Xwindow_XCreateWindow" = xyes; then : + XLIBSW=-lXwindow +fi + + fi + if test "$XLIBSW" = nope ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find any! Using -lX11." >&5 +$as_echo "could not find any! Using -lX11." >&6; } + XLIBSW=-lX11 + fi + # TEA specific: + if test x"${XLIBSW}" != x ; then + PKG_LIBS="${PKG_LIBS} ${XLIBSW}" + fi + + fi + + +#-------------------------------------------------------------------- +# Check whether --enable-threads or --disable-threads was given. +# This auto-enables if Tcl was compiled threaded. +#-------------------------------------------------------------------- + + + # Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then : + enableval=$enable_threads; tcl_ok=$enableval +else + tcl_ok=yes +fi + + + if test "${enable_threads+set}" = set; then + enableval="$enable_threads" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then + TCL_THREADS=1 + + if test "${TEA_PLATFORM}" != "windows" ; then + # We are always OK on Windows, so check what this platform wants: + + # USE_THREAD_ALLOC tells us to try the special thread-based + # allocator that significantly reduces lock contention + +$as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h + + +$as_echo "#define _REENTRANT 1" >>confdefs.h + + if test "`uname -s`" = "SunOS" ; then + +$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + fi + +$as_echo "#define _THREAD_SAFE 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 +$as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_init (); +int +main () +{ +return pthread_mutex_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_mutex_init=yes +else + ac_cv_lib_pthread_pthread_mutex_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } +if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "no"; then + # Check a little harder for __pthread_mutex_init in the same + # library, as some systems hide it there until pthread.h is + # defined. We could alternatively do an AC_TRY_COMPILE with + # pthread.h, but that will work with libpthread really doesn't + # exist, like AIX 4.2. [Bug: 4359] + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5 +$as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; } +if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __pthread_mutex_init (); +int +main () +{ +return __pthread_mutex_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread___pthread_mutex_init=yes +else + ac_cv_lib_pthread___pthread_mutex_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 +$as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; } +if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthread" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5 +$as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; } +if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthreads $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_init (); +int +main () +{ +return pthread_mutex_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthreads_pthread_mutex_init=yes +else + ac_cv_lib_pthreads_pthread_mutex_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 +$as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } +if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthreads" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5 +$as_echo_n "checking for pthread_mutex_init in -lc... " >&6; } +if ${ac_cv_lib_c_pthread_mutex_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_init (); +int +main () +{ +return pthread_mutex_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_c_pthread_mutex_init=yes +else + ac_cv_lib_c_pthread_mutex_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5 +$as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; } +if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5 +$as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; } +if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc_r $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_init (); +int +main () +{ +return pthread_mutex_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_c_r_pthread_mutex_init=yes +else + ac_cv_lib_c_r_pthread_mutex_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 +$as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; } +if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -pthread" + else + TCL_THREADS=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&5 +$as_echo "$as_me: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&2;} + fi + fi + fi + fi + fi + else + TCL_THREADS=0 + fi + # Do checking message here to not mess up interleaved configure output + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5 +$as_echo_n "checking for building with threads... " >&6; } + if test "${TCL_THREADS}" = 1; then + +$as_echo "#define TCL_THREADS 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5 +$as_echo "yes (default)" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + # TCL_THREADS sanity checking. See if our request for building with + # threads is the same as the way Tcl was built. If not, warn the user. + case ${TCL_DEFS} in + *THREADS=1*) + if test "${TCL_THREADS}" = "0"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: + Building ${PACKAGE_NAME} without threads enabled, but building against Tcl + that IS thread-enabled. It is recommended to use --enable-threads." >&5 +$as_echo "$as_me: WARNING: + Building ${PACKAGE_NAME} without threads enabled, but building against Tcl + that IS thread-enabled. It is recommended to use --enable-threads." >&2;} + fi + ;; + *) + if test "${TCL_THREADS}" = "1"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: + --enable-threads requested, but building against a Tcl that is NOT + thread-enabled. This is an OK configuration that will also run in + a thread-enabled core." >&5 +$as_echo "$as_me: WARNING: + --enable-threads requested, but building against a Tcl that is NOT + thread-enabled. This is an OK configuration that will also run in + a thread-enabled core." >&2;} + fi + ;; + esac + + + +#-------------------------------------------------------------------- +# The statement below defines a collection of symbols related to +# building as a shared library instead of a static library. +#-------------------------------------------------------------------- + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5 +$as_echo_n "checking how to build libraries... " >&6; } + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; tcl_ok=$enableval +else + tcl_ok=yes +fi + + + if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5 +$as_echo "shared" >&6; } + SHARED_BUILD=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5 +$as_echo "static" >&6; } + SHARED_BUILD=0 + +$as_echo "#define STATIC_BUILD 1" >>confdefs.h + + fi + + + +#-------------------------------------------------------------------- +# This macro figures out what flags to use with the compiler/linker +# when building shared/static debug/optimized objects. This information +# can be taken from the tclConfig.sh file, but this figures it all out. +#-------------------------------------------------------------------- + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + + + + # Step 0.a: Enable 64 bit support? + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5 +$as_echo_n "checking if 64bit support is requested... " >&6; } + # Check whether --enable-64bit was given. +if test "${enable_64bit+set}" = set; then : + enableval=$enable_64bit; do64bit=$enableval +else + do64bit=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5 +$as_echo "$do64bit" >&6; } + + # Step 0.b: Enable Solaris 64 bit VIS support? + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5 +$as_echo_n "checking if 64bit Sparc VIS support is requested... " >&6; } + # Check whether --enable-64bit-vis was given. +if test "${enable_64bit_vis+set}" = set; then : + enableval=$enable_64bit_vis; do64bitVIS=$enableval +else + do64bitVIS=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5 +$as_echo "$do64bitVIS" >&6; } + # Force 64bit on with VIS + if test "$do64bitVIS" = "yes"; then : + do64bit=yes +fi + + # Step 0.c: Check if visibility support is available. Do this here so + # that platform specific alternatives can be used below if this fails. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5 +$as_echo_n "checking if compiler supports visibility \"hidden\"... " >&6; } +if ${tcl_cv_cc_visibility_hidden+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + extern __attribute__((__visibility__("hidden"))) void f(void); + void f(void) {} +int +main () +{ +f(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_cc_visibility_hidden=yes +else + tcl_cv_cc_visibility_hidden=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5 +$as_echo "$tcl_cv_cc_visibility_hidden" >&6; } + if test $tcl_cv_cc_visibility_hidden = yes; then : + + +$as_echo "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h + + +$as_echo "#define HAVE_HIDDEN 1" >>confdefs.h + + +fi + + # Step 0.d: Disable -rpath support? + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5 +$as_echo_n "checking if rpath support is requested... " >&6; } + # Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; doRpath=$enableval +else + doRpath=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5 +$as_echo "$doRpath" >&6; } + + # TEA specific: Cross-compiling options for Windows/CE builds? + + if test "${TEA_PLATFORM}" = windows; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Windows/CE build is requested" >&5 +$as_echo_n "checking if Windows/CE build is requested... " >&6; } + # Check whether --enable-wince was given. +if test "${enable_wince+set}" = set; then : + enableval=$enable_wince; doWince=$enableval +else + doWince=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doWince" >&5 +$as_echo "$doWince" >&6; } + +fi + + # Set the variable "system" to hold the name and version number + # for the system. + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5 +$as_echo_n "checking system version... " >&6; } +if ${tcl_cv_sys_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + + # TEA specific: + if test "${TEA_PLATFORM}" = "windows" ; then + tcl_cv_sys_version=windows + else + tcl_cv_sys_version=`uname -s`-`uname -r` + if test "$?" -ne 0 ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 +$as_echo "$as_me: WARNING: can't find uname command" >&2;} + tcl_cv_sys_version=unknown + else + if test "`uname -s`" = "AIX" ; then + tcl_cv_sys_version=AIX-`uname -v`.`uname -r` + fi + fi + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 +$as_echo "$tcl_cv_sys_version" >&6; } + system=$tcl_cv_sys_version + + + # Require ranlib early so we can override it in special cases below. + + + + # Set configuration options based on system name and version. + # This is similar to Tcl's unix/tcl.m4 except that we've added a + # "windows" case and removed some core-only vars. + + do64bit_ok=no + # default to '{$LIBS}' and set to "" on per-platform necessary basis + SHLIB_LD_LIBS='${LIBS}' + # When ld needs options to work in 64-bit mode, put them in + # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] + # is disabled by the user. [Bug 1016796] + LDFLAGS_ARCH="" + UNSHARED_LIB_SUFFIX="" + # TEA specific: use PACKAGE_VERSION instead of VERSION + TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' + ECHO_VERSION='`echo ${PACKAGE_VERSION}`' + TCL_LIB_VERSIONS_OK=ok + CFLAGS_DEBUG=-g + if test "$GCC" = yes; then : + + CFLAGS_OPTIMIZE=-O2 + CFLAGS_WARNING="-Wall" + +else + + CFLAGS_OPTIMIZE=-O + CFLAGS_WARNING="" + +fi + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + + STLIB_LD='${AR} cr' + LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" + if test "x$SHLIB_VERSION" = x; then : + SHLIB_VERSION="1.0" +fi + case $system in + # TEA specific: + windows) + # This is a 2-stage check to make sure we have the 64-bit SDK + # We have to know where the SDK is installed. + # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs + # MACHINE is IX86 for LINK, but this is used by the manifest, + # which requires x86|amd64|ia64. + MACHINE="X86" + if test "$do64bit" != "no" ; then + if test "x${MSSDK}x" = "xx" ; then + MSSDK="C:/Progra~1/Microsoft Platform SDK" + fi + MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'` + PATH64="" + case "$do64bit" in + amd64|x64|yes) + MACHINE="AMD64" ; # default to AMD64 64-bit build + PATH64="${MSSDK}/Bin/Win64/x86/AMD64" + ;; + ia64) + MACHINE="IA64" + PATH64="${MSSDK}/Bin/Win64" + ;; + esac + if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&5 +$as_echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ensure latest Platform SDK is installed" >&5 +$as_echo "$as_me: WARNING: Ensure latest Platform SDK is installed" >&2;} + do64bit="no" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using 64-bit $MACHINE mode" >&5 +$as_echo " Using 64-bit $MACHINE mode" >&6; } + do64bit_ok="yes" + fi + fi + + if test "$doWince" != "no" ; then + if test "$do64bit" != "no" ; then + as_fn_error $? "Windows/CE and 64-bit builds incompatible" "$LINENO" 5 + fi + if test "$GCC" = "yes" ; then + as_fn_error $? "Windows/CE and GCC builds incompatible" "$LINENO" 5 + fi + + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-celib + + if test x"${no_celib}" = x ; then + # we reset no_celib in case something fails here + no_celib=true + +# Check whether --with-celib was given. +if test "${with_celib+set}" = set; then : + withval=$with_celib; with_celibconfig=${withval} +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Windows/CE celib directory" >&5 +$as_echo_n "checking for Windows/CE celib directory... " >&6; } + if ${ac_cv_c_celibconfig+:} false; then : + $as_echo_n "(cached) " >&6 +else + + # First check to see if --with-celibconfig was specified. + if test x"${with_celibconfig}" != x ; then + if test -d "${with_celibconfig}/inc" ; then + ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)` + else + as_fn_error $? "${with_celibconfig} directory doesn't contain inc directory" "$LINENO" 5 + fi + fi + + # then check for a celib library + if test x"${ac_cv_c_celibconfig}" = x ; then + for i in \ + ../celib-palm-3.0 \ + ../celib \ + ../../celib-palm-3.0 \ + ../../celib \ + `ls -dr ../celib-*3.[0-9]* 2>/dev/null` \ + ${srcdir}/../celib-palm-3.0 \ + ${srcdir}/../celib \ + `ls -dr ${srcdir}/../celib-*3.[0-9]* 2>/dev/null` \ + ; do + if test -d "$i/inc" ; then + ac_cv_c_celibconfig=`(cd $i; pwd)` + break + fi + done + fi + +fi + + if test x"${ac_cv_c_celibconfig}" = x ; then + as_fn_error $? "Cannot find celib support library directory" "$LINENO" 5 + else + no_celib= + CELIB_DIR=${ac_cv_c_celibconfig} + CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found $CELIB_DIR" >&5 +$as_echo "found $CELIB_DIR" >&6; } + fi + fi + + # Set defaults for common evc4/PPC2003 setup + # Currently Tcl requires 300+, possibly 420+ for sockets + CEVERSION=420; # could be 211 300 301 400 420 ... + TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ... + ARCH=ARM; # could be ARM MIPS X86EM ... + PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002" + if test "$doWince" != "yes"; then + # If !yes then the user specified something + # Reset ARCH to allow user to skip specifying it + ARCH= + eval `echo $doWince | awk -F, '{ \ + if (length($1)) { printf "CEVERSION=\"%s\"\n", $1; \ + if ($1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \ + if (length($2)) { printf "TARGETCPU=\"%s\"\n", toupper($2) }; \ + if (length($3)) { printf "ARCH=\"%s\"\n", toupper($3) }; \ + if (length($4)) { printf "PLATFORM=\"%s\"\n", $4 }; \ + }'` + if test "x${ARCH}" = "x" ; then + ARCH=$TARGETCPU; + fi + fi + OSVERSION=WCE$CEVERSION; + if test "x${WCEROOT}" = "x" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0" + if test ! -d "${WCEROOT}" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded Tools" + fi + fi + if test "x${SDKROOT}" = "x" ; then + SDKROOT="C:/Program Files/Windows CE Tools" + if test ! -d "${SDKROOT}" ; then + SDKROOT="C:/Windows CE Tools" + fi + fi + WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'` + SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'` + if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \ + -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then + as_fn_error $? "could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" "$LINENO" 5 + doWince="no" + else + # We could PATH_NOSPACE these, but that's not important, + # as long as we quote them when used. + CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include" + if test -d "${CEINCLUDE}/${TARGETCPU}" ; then + CEINCLUDE="${CEINCLUDE}/${TARGETCPU}" + fi + CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" + fi + fi + + if test "$GCC" != "yes" ; then + if test "${SHARED_BUILD}" = "0" ; then + runtime=-MT + else + runtime=-MD + fi + + if test "$do64bit" != "no" ; then + # All this magic is necessary for the Win64 SDK RC1 - hobbs + CC="\"${PATH64}/cl.exe\"" + CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\"" + RC="\"${MSSDK}/bin/rc.exe\"" + lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\"" + LINKBIN="\"${PATH64}/link.exe\"" + CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + # Avoid 'unresolved external symbol __security_cookie' + # errors, c.f. http://support.microsoft.com/?id=894573 + + vars="bufferoverflowU.lib" + for i in $vars; do + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then + # Convert foo.lib to -lfoo for GCC. No-op if not *.lib + i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'` + fi + PKG_LIBS="$PKG_LIBS $i" + done + + + elif test "$doWince" != "no" ; then + CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin" + if test "${TARGETCPU}" = "X86"; then + CC="\"${CEBINROOT}/cl.exe\"" + else + CC="\"${CEBINROOT}/cl${ARCH}.exe\"" + fi + CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\"" + RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" + arch=`echo ${ARCH} | awk '{print tolower($0)}'` + defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS" + if test "${SHARED_BUILD}" = "1" ; then + # Static CE builds require static celib as well + defs="${defs} _DLL" + fi + for i in $defs ; do + +cat >>confdefs.h <<_ACEOF +#define $i 1 +_ACEOF + + done + +cat >>confdefs.h <<_ACEOF +#define _WIN32_WCE $CEVERSION +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define UNDER_CE $CEVERSION +_ACEOF + + CFLAGS_DEBUG="-nologo -Zi -Od" + CFLAGS_OPTIMIZE="-nologo -Ox" + lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'` + lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" + LINKBIN="\"${CEBINROOT}/link.exe\"" + + else + RC="rc" + lflags="-nologo" + LINKBIN="link" + CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + fi + fi + + if test "$GCC" = "yes"; then + # mingw gcc mode + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. +set dummy ${ac_tool_prefix}windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RC"; then + ac_cv_prog_RC="$RC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RC="${ac_tool_prefix}windres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RC=$ac_cv_prog_RC +if test -n "$RC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RC" >&5 +$as_echo "$RC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RC"; then + ac_ct_RC=$RC + # Extract the first word of "windres", so it can be a program name with args. +set dummy windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RC"; then + ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RC="windres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RC=$ac_cv_prog_ac_ct_RC +if test -n "$ac_ct_RC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5 +$as_echo "$ac_ct_RC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RC" = x; then + RC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RC=$ac_ct_RC + fi +else + RC="$ac_cv_prog_RC" +fi + + CFLAGS_DEBUG="-g" + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + SHLIB_LD='${CC} -shared' + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" + LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5 +$as_echo_n "checking for cross-compile version of gcc... " >&6; } +if ${ac_cv_cross+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #ifdef __WIN32__ + #error cross-compiler + #endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_cross=yes +else + ac_cv_cross=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5 +$as_echo "$ac_cv_cross" >&6; } + if test "$ac_cv_cross" = "yes"; then + case "$do64bit" in + amd64|x64|yes) + CC="x86_64-w64-mingw32-gcc" + LD="x86_64-w64-mingw32-ld" + AR="x86_64-w64-mingw32-ar" + RANLIB="x86_64-w64-mingw32-ranlib" + RC="x86_64-w64-mingw32-windres" + ;; + *) + CC="i686-w64-mingw32-gcc" + LD="i686-w64-mingw32-ld" + AR="i686-w64-mingw32-ar" + RANLIB="i686-w64-mingw32-ranlib" + RC="i686-w64-mingw32-windres" + ;; + esac + fi + + else + SHLIB_LD="${LINKBIN} -dll ${lflags}" + # link -lib only works when -lib is the first arg + STLIB_LD="${LINKBIN} -lib ${lflags}" + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' + PATHTYPE=-w + # For information on what debugtype is most useful, see: + # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp + # and also + # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx + # This essentially turns it all on. + LDFLAGS_DEBUG="-debug -debugtype:cv" + LDFLAGS_OPTIMIZE="-release" + if test "$doWince" != "no" ; then + LDFLAGS_CONSOLE="-link ${lflags}" + LDFLAGS_WINDOW=${LDFLAGS_CONSOLE} + else + LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" + LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" + fi + fi + + SHLIB_SUFFIX=".dll" + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' + + TCL_LIB_VERSIONS_OK=nodots + ;; + AIX-*) + if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"; then : + + # AIX requires the _r compiler when gcc isn't being used + case "${CC}" in + *_r|*_r\ *) + # ok ... + ;; + *) + # Make sure only first arg gets _r + CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5 +$as_echo "Using $CC for compiling with threads" >&6; } + +fi + LIBS="$LIBS -lc" + SHLIB_CFLAGS="" + SHLIB_SUFFIX=".so" + + LD_LIBRARY_PATH_VAR="LIBPATH" + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = yes; then : + + if test "$GCC" = yes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS -q64" + LDFLAGS_ARCH="-q64" + RANLIB="${RANLIB} -X64" + AR="${AR} -X64" + SHLIB_LD_FLAGS="-b64" + +fi + +fi + + if test "`uname -m`" = ia64; then : + + # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + if test "$GCC" = yes; then : + + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + +else + + CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' + +fi + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + +else + + if test "$GCC" = yes; then : + + SHLIB_LD='${CC} -shared -Wl,-bexpall' + +else + + SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" + LDFLAGS="$LDFLAGS -brtl" + +fi + SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" + CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +fi + ;; + BeOS*) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -nostart' + SHLIB_SUFFIX=".so" + + #----------------------------------------------------------- + # Check for inet_ntoa in -lbind, for BeOS (which also needs + # -lsocket, even if the network functions are in -lnet which + # is always linked to, for compatibility. + #----------------------------------------------------------- + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5 +$as_echo_n "checking for inet_ntoa in -lbind... " >&6; } +if ${ac_cv_lib_bind_inet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbind $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inet_ntoa (); +int +main () +{ +return inet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bind_inet_ntoa=yes +else + ac_cv_lib_bind_inet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5 +$as_echo "$ac_cv_lib_bind_inet_ntoa" >&6; } +if test "x$ac_cv_lib_bind_inet_ntoa" = xyes; then : + LIBS="$LIBS -lbind -lsocket" +fi + + ;; + BSD/OS-4.*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + CYGWIN_*) + SHLIB_CFLAGS="" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".dll" + EXEEXT=".exe" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + Haiku*) + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}' + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5 +$as_echo_n "checking for inet_ntoa in -lnetwork... " >&6; } +if ${ac_cv_lib_network_inet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnetwork $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inet_ntoa (); +int +main () +{ +return inet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_network_inet_ntoa=yes +else + ac_cv_lib_network_inet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5 +$as_echo "$ac_cv_lib_network_inet_ntoa" >&6; } +if test "x$ac_cv_lib_network_inet_ntoa" = xyes; then : + LIBS="$LIBS -lnetwork" +fi + + ;; + HP-UX-*.11.*) + # Use updated header definitions where possible + +$as_echo "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h + + # TEA specific: Needed by Tcl, but not most extensions + #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) + #LIBS="$LIBS -lxnet" # Use the XOPEN network library + + if test "`uname -m`" = ia64; then : + + SHLIB_SUFFIX=".so" + # Use newer C++ library for C++ extensions + #if test "$GCC" != "yes" ; then + # CPPFLAGS="-AA" + #fi + +else + + SHLIB_SUFFIX=".sl" + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + tcl_ok=yes +else + tcl_ok=no +fi + + if test "$tcl_ok" = yes; then : + + LDFLAGS="$LDFLAGS -Wl,-E" + CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' + LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' + LD_LIBRARY_PATH_VAR="SHLIB_PATH" + +fi + if test "$GCC" = yes; then : + + SHLIB_LD='${CC} -shared' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +else + + CFLAGS="$CFLAGS -z" + # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc + #CFLAGS="$CFLAGS +DAportable" + SHLIB_CFLAGS="+z" + SHLIB_LD="ld -b" + +fi + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = "yes"; then : + + if test "$GCC" = yes; then : + + case `${CC} -dumpmachine` in + hppa64*) + # 64-bit gcc in use. Fix flags for GNU ld. + do64bit_ok=yes + SHLIB_LD='${CC} -shared' + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} + ;; + esac + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS +DD64" + LDFLAGS_ARCH="+DD64" + +fi + +fi ;; + IRIX-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + if test "$GCC" = yes; then : + + CFLAGS="$CFLAGS -mabi=n32" + LDFLAGS="$LDFLAGS -mabi=n32" + +else + + case $system in + IRIX-6.3) + # Use to build 6.2 compatible binaries on 6.3. + CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" + ;; + *) + CFLAGS="$CFLAGS -n32" + ;; + esac + LDFLAGS="$LDFLAGS -n32" + +fi + ;; + IRIX64-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + + # Check to enable 64-bit flags for compiler/linker + + if test "$do64bit" = yes; then : + + if test "$GCC" = yes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} + +else + + do64bit_ok=yes + SHLIB_LD="ld -64 -shared -rdata_shared" + CFLAGS="$CFLAGS -64" + LDFLAGS_ARCH="-64" + +fi + +fi + ;; + Linux*|GNU*|NetBSD-Debian) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + + # TEA specific: + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}' + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "`uname -m`" = "alpha"; then : + CFLAGS="$CFLAGS -mieee" +fi + if test $do64bit = yes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5 +$as_echo_n "checking if compiler accepts -m64 flag... " >&6; } +if ${tcl_cv_cc_m64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -m64" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_cc_m64=yes +else + tcl_cv_cc_m64=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5 +$as_echo "$tcl_cv_cc_m64" >&6; } + if test $tcl_cv_cc_m64 = yes; then : + + CFLAGS="$CFLAGS -m64" + do64bit_ok=yes + +fi + +fi + + # The combo of gcc + glibc has a bug related to inlining of + # functions like strtod(). The -fno-builtin flag should address + # this problem but it does not work. The -fno-inline flag is kind + # of overkill but it works. Disable inlining only when one of the + # files in compat/*.c is being linked in. + + if test x"${USE_COMPAT}" != x; then : + CFLAGS="$CFLAGS -fno-inline" +fi + ;; + Lynx*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + CFLAGS_OPTIMIZE=-02 + SHLIB_LD='${CC} -shared' + LD_FLAGS="-Wl,--export-dynamic" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + ;; + OpenBSD-*) + arch=`arch -s` + case "$arch" in + vax) + SHLIB_SUFFIX="" + SHARED_LIB_SUFFIX="" + LDFLAGS="" + ;; + *) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' + LDFLAGS="-Wl,-export-dynamic" + ;; + esac + case "$arch" in + vax) + CFLAGS_OPTIMIZE="-O1" + ;; + *) + CFLAGS_OPTIMIZE="-O2" + ;; + esac + if test "${TCL_THREADS}" = "1"; then : + + # On OpenBSD: Compile with -pthread + # Don't link with -lpthread + LIBS=`echo $LIBS | sed s/-lpthread//` + CFLAGS="$CFLAGS -pthread" + +fi + # OpenBSD doesn't do version numbers with dots. + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + NetBSD-*) + # NetBSD has ELF and can use 'cc -shared' to build shared libs + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "${TCL_THREADS}" = "1"; then : + + # The -pthread needs to go in the CFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + +fi + ;; + FreeBSD-*) + # This configuration from FreeBSD Ports. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="${CC} -shared" + TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$@" + SHLIB_SUFFIX=".so" + LDFLAGS="" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' +fi + if test "${TCL_THREADS}" = "1"; then : + + # The -pthread needs to go in the LDFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LDFLAGS="$LDFLAGS $PTHREAD_LIBS" +fi + # Version numbers are dot-stripped by system policy. + TCL_TRIM_DOTS=`echo ${PACKAGE_VERSION} | tr -d .` + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1' + TCL_LIB_VERSIONS_OK=nodots + ;; + Darwin-*) + CFLAGS_OPTIMIZE="-Os" + SHLIB_CFLAGS="-fno-common" + # To avoid discrepancies between what headers configure sees during + # preprocessing tests and compiling tests, move any -isysroot and + # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: + CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`" + CFLAGS="`echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`" + if test $do64bit = yes; then : + + case `arch` in + ppc) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5 +$as_echo_n "checking if compiler accepts -arch ppc64 flag... " >&6; } +if ${tcl_cv_cc_arch_ppc64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_cc_arch_ppc64=yes +else + tcl_cv_cc_arch_ppc64=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5 +$as_echo "$tcl_cv_cc_arch_ppc64" >&6; } + if test $tcl_cv_cc_arch_ppc64 = yes; then : + + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + do64bit_ok=yes + +fi;; + i386) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5 +$as_echo_n "checking if compiler accepts -arch x86_64 flag... " >&6; } +if ${tcl_cv_cc_arch_x86_64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch x86_64" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_cc_arch_x86_64=yes +else + tcl_cv_cc_arch_x86_64=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS=$hold_cflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5 +$as_echo "$tcl_cv_cc_arch_x86_64" >&6; } + if test $tcl_cv_cc_arch_x86_64 = yes; then : + + CFLAGS="$CFLAGS -arch x86_64" + do64bit_ok=yes + +fi;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5 +$as_echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};; + esac + +else + + # Check for combined 32-bit and 64-bit fat build + if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ + && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then : + + fat_32_64=yes +fi + +fi + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5 +$as_echo_n "checking if ld accepts -single_module flag... " >&6; } +if ${tcl_cv_ld_single_module+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_ld_single_module=yes +else + tcl_cv_ld_single_module=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5 +$as_echo "$tcl_cv_ld_single_module" >&6; } + if test $tcl_cv_ld_single_module = yes; then : + + SHLIB_LD="${SHLIB_LD} -Wl,-single_module" + +fi + # TEA specific: link shlib with current and compatibility version flags + vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([0-9]\{1,5\}\)\(\(\.[0-9]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` + SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" + SHLIB_SUFFIX=".dylib" + # Don't use -prebind when building for Mac OS X 10.4 or later only: + if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \ + "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then : + + LDFLAGS="$LDFLAGS -prebind" +fi + LDFLAGS="$LDFLAGS -headerpad_max_install_names" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5 +$as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; } +if ${tcl_cv_ld_search_paths_first+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_ld_search_paths_first=yes +else + tcl_cv_ld_search_paths_first=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5 +$as_echo "$tcl_cv_ld_search_paths_first" >&6; } + if test $tcl_cv_ld_search_paths_first = yes; then : + + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + +fi + if test "$tcl_cv_cc_visibility_hidden" != yes; then : + + +$as_echo "#define MODULE_SCOPE __private_extern__" >>confdefs.h + + tcl_cv_cc_visibility_hidden=yes + +fi + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" + # TEA specific: for combined 32 & 64 bit fat builds of Tk + # extensions, verify that 64-bit build is possible. + if test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"; then : + + if test "${TEA_WINDOWINGSYSTEM}" = x11; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit X11" >&5 +$as_echo_n "checking for 64-bit X11... " >&6; } +if ${tcl_cv_lib_x11_64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" + LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <X11/Xlib.h> +int +main () +{ +XrmInitialize(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_lib_x11_64=yes +else + tcl_cv_lib_x11_64=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_x11_64" >&5 +$as_echo "$tcl_cv_lib_x11_64" >&6; } + +fi + if test "${TEA_WINDOWINGSYSTEM}" = aqua; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit Tk" >&5 +$as_echo_n "checking for 64-bit Tk... " >&6; } +if ${tcl_cv_lib_tk_64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" + LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <tk.h> +int +main () +{ +Tk_InitStubs(NULL, "", 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_lib_tk_64=yes +else + tcl_cv_lib_tk_64=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_tk_64" >&5 +$as_echo "$tcl_cv_lib_tk_64" >&6; } + +fi + # remove 64-bit arch flags from CFLAGS et al. if configuration + # does not support 64-bit. + if test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: Removing 64-bit architectures from compiler & linker flags" >&5 +$as_echo "$as_me: Removing 64-bit architectures from compiler & linker flags" >&6;} + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' + done +fi + +fi + ;; + OS/390-*) + CFLAGS_OPTIMIZE="" # Optimizer is buggy + +$as_echo "#define _OE_SOCKETS 1" >>confdefs.h + + ;; + OSF1-V*) + # Digital OSF/1 + SHLIB_CFLAGS="" + if test "$SHARED_BUILD" = 1; then : + + SHLIB_LD='ld -shared -expect_unresolved "*"' + +else + + SHLIB_LD='ld -non_shared -expect_unresolved "*"' + +fi + SHLIB_SUFFIX=".so" + if test $doRpath = yes; then : + + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' +fi + if test "$GCC" = yes; then : + CFLAGS="$CFLAGS -mieee" +else + + CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" +fi + # see pthread_intro(3) for pthread support on osf1, k.furukawa + if test "${TCL_THREADS}" = 1; then : + + CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" + CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" + LIBS=`echo $LIBS | sed s/-lpthreads//` + if test "$GCC" = yes; then : + + LIBS="$LIBS -lpthread -lmach -lexc" + +else + + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + +fi + +fi + ;; + QNX-6*) + # QNX RTP + # This may work for all QNX, but it was only reported for v6. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="ld -Bshareable -x" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SCO_SV-3.2*) + if test "$GCC" = yes; then : + + SHLIB_CFLAGS="-fPIC -melf" + LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" + +else + + SHLIB_CFLAGS="-Kpic -belf" + LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" + +fi + SHLIB_LD="ld -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SunOS-5.[0-6]) + # Careful to not let 5.10+ fall into this case + + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + +$as_echo "#define _REENTRANT 1" >>confdefs.h + + +$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + + SHLIB_CFLAGS="-KPIC" + SHLIB_SUFFIX=".so" + if test "$GCC" = yes; then : + + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +else + + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + +fi + ;; + SunOS-5*) + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + +$as_echo "#define _REENTRANT 1" >>confdefs.h + + +$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + + SHLIB_CFLAGS="-KPIC" + + # Check to enable 64-bit flags for compiler/linker + if test "$do64bit" = yes; then : + + arch=`isainfo` + if test "$arch" = "sparcv9 sparc"; then : + + if test "$GCC" = yes; then : + + if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;} + +else + + do64bit_ok=yes + CFLAGS="$CFLAGS -m64 -mcpu=v9" + LDFLAGS="$LDFLAGS -m64 -mcpu=v9" + SHLIB_CFLAGS="-fPIC" + +fi + +else + + do64bit_ok=yes + if test "$do64bitVIS" = yes; then : + + CFLAGS="$CFLAGS -xarch=v9a" + LDFLAGS_ARCH="-xarch=v9a" + +else + + CFLAGS="$CFLAGS -xarch=v9" + LDFLAGS_ARCH="-xarch=v9" + +fi + # Solaris 64 uses this as well + #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" + +fi + +else + if test "$arch" = "amd64 i386"; then : + + if test "$GCC" = yes; then : + + case $system in + SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) + do64bit_ok=yes + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};; + esac + +else + + do64bit_ok=yes + case $system in + SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + CFLAGS="$CFLAGS -xarch=amd64" + LDFLAGS="$LDFLAGS -xarch=amd64";; + esac + +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5 +$as_echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} +fi +fi + +fi + + SHLIB_SUFFIX=".so" + if test "$GCC" = yes; then : + + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + if test "$do64bit_ok" = yes; then : + + if test "$arch" = "sparcv9 sparc"; then : + + # We need to specify -static-libgcc or we need to + # add the path to the sparv9 libgcc. + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" + # for finding sparcv9 libgcc, get the regular libgcc + # path, remove so name and append 'sparcv9' + #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." + #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" + +else + if test "$arch" = "amd64 i386"; then : + + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" + +fi +fi + +fi + +else + + case $system in + SunOS-5.[1-9][0-9]*) + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; + *) + SHLIB_LD='/usr/ccs/bin/ld -G -z text';; + esac + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + +fi + ;; + UNIX_SV* | UnixWare-5*) + SHLIB_CFLAGS="-KPIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers + # that don't grok the -Bexport option. Test that it does. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5 +$as_echo_n "checking for ld accepts -Bexport flag... " >&6; } +if ${tcl_cv_ld_Bexport+:} false; then : + $as_echo_n "(cached) " >&6 +else + + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-Bexport" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tcl_cv_ld_Bexport=yes +else + tcl_cv_ld_Bexport=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$hold_ldflags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5 +$as_echo "$tcl_cv_ld_Bexport" >&6; } + if test $tcl_cv_ld_Bexport = yes; then : + + LDFLAGS="$LDFLAGS -Wl,-Bexport" + +fi + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + esac + + if test "$do64bit" = yes -a "$do64bit_ok" = no; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 +$as_echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} + +fi + + + + # Add in the arch flags late to ensure it wasn't removed. + # Not necessary in TEA, but this is aligned with core + LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" + + # If we're running gcc, then change the C flags for compiling shared + # libraries to the right flags for gcc, instead of those for the + # standard manufacturer compiler. + + if test "$GCC" = yes; then : + + case $system in + AIX-*) ;; + BSD/OS*) ;; + CYGWIN_*|MINGW32_*) ;; + IRIX*) ;; + NetBSD-*|FreeBSD-*|OpenBSD-*) ;; + Darwin-*) ;; + SCO_SV-3.2*) ;; + windows) ;; + *) SHLIB_CFLAGS="-fPIC" ;; + esac +fi + + if test "$tcl_cv_cc_visibility_hidden" != yes; then : + + +$as_echo "#define MODULE_SCOPE extern" >>confdefs.h + + +fi + + if test "$SHARED_LIB_SUFFIX" = ""; then : + + # TEA specific: use PACKAGE_VERSION instead of VERSION + SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' +fi + if test "$UNSHARED_LIB_SUFFIX" = ""; then : + + # TEA specific: use PACKAGE_VERSION instead of VERSION + UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' +fi + + if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5 +$as_echo_n "checking for SEH support in compiler... " >&6; } +if ${tcl_cv_seh+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + tcl_cv_seh=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef WIN32_LEAN_AND_MEAN + + int main(int argc, char** argv) { + int a, b = 0; + __try { + a = 666 / b; + } + __except (EXCEPTION_EXECUTE_HANDLER) { + return 0; + } + return 1; + } + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + tcl_cv_seh=yes +else + tcl_cv_seh=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5 +$as_echo "$tcl_cv_seh" >&6; } + if test "$tcl_cv_seh" = "no" ; then + +$as_echo "#define HAVE_NO_SEH 1" >>confdefs.h + + fi + + # + # Check to see if the excpt.h include file provided contains the + # definition for EXCEPTION_DISPOSITION; if not, which is the case + # with Cygwin's version as of 2002-04-10, define it to be int, + # sufficient for getting the current code to work. + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5 +$as_echo_n "checking for EXCEPTION_DISPOSITION support in include files... " >&6; } +if ${tcl_cv_eh_disposition+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# undef WIN32_LEAN_AND_MEAN + +int +main () +{ + + EXCEPTION_DISPOSITION x; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_eh_disposition=yes +else + tcl_cv_eh_disposition=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5 +$as_echo "$tcl_cv_eh_disposition" >&6; } + if test "$tcl_cv_eh_disposition" = "no" ; then + +$as_echo "#define EXCEPTION_DISPOSITION int" >>confdefs.h + + fi + + # Check to see if winnt.h defines CHAR, SHORT, and LONG + # even if VOID has already been #defined. The win32api + # used by mingw and cygwin is known to do this. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for winnt.h that ignores VOID define" >&5 +$as_echo_n "checking for winnt.h that ignores VOID define... " >&6; } +if ${tcl_cv_winnt_ignore_void+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define VOID void +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef WIN32_LEAN_AND_MEAN + +int +main () +{ + + CHAR c; + SHORT s; + LONG l; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_winnt_ignore_void=yes +else + tcl_cv_winnt_ignore_void=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_winnt_ignore_void" >&5 +$as_echo "$tcl_cv_winnt_ignore_void" >&6; } + if test "$tcl_cv_winnt_ignore_void" = "yes" ; then + +$as_echo "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h + + fi + fi + + # See if the compiler supports casting to a union type. + # This is used to stop gcc from printing a compiler + # warning when initializing a union member. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5 +$as_echo_n "checking for cast to union support... " >&6; } +if ${tcl_cv_cast_to_union+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + union foo { int i; double d; }; + union foo f = (union foo) (int) 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_cast_to_union=yes +else + tcl_cv_cast_to_union=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5 +$as_echo "$tcl_cv_cast_to_union" >&6; } + if test "$tcl_cv_cast_to_union" = "yes"; then + +$as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h + + fi + + + + + + + + + + + + + + # These must be called after we do the basic CFLAGS checks and + # verify any possible 64-bit or similar switches are necessary + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5 +$as_echo_n "checking for required early compiler flags... " >&6; } + tcl_flags="" + + if ${tcl_cv_flag__isoc99_source+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +int +main () +{ +char *p = (char *)strtoll; char *q = (char *)strtoull; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__isoc99_source=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _ISOC99_SOURCE 1 +#include <stdlib.h> +int +main () +{ +char *p = (char *)strtoll; char *q = (char *)strtoull; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__isoc99_source=yes +else + tcl_cv_flag__isoc99_source=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then + +$as_echo "#define _ISOC99_SOURCE 1" >>confdefs.h + + tcl_flags="$tcl_flags _ISOC99_SOURCE" + fi + + + if ${tcl_cv_flag__largefile64_source+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +struct stat64 buf; int i = stat64("/", &buf); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__largefile64_source=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGEFILE64_SOURCE 1 +#include <sys/stat.h> +int +main () +{ +struct stat64 buf; int i = stat64("/", &buf); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__largefile64_source=yes +else + tcl_cv_flag__largefile64_source=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__largefile64_source}" = "xyes" ; then + +$as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h + + tcl_flags="$tcl_flags _LARGEFILE64_SOURCE" + fi + + + if ${tcl_cv_flag__largefile_source64+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +char *p = (char *)open64; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__largefile_source64=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGEFILE_SOURCE64 1 +#include <sys/stat.h> +int +main () +{ +char *p = (char *)open64; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_flag__largefile_source64=yes +else + tcl_cv_flag__largefile_source64=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then + +$as_echo "#define _LARGEFILE_SOURCE64 1" >>confdefs.h + + tcl_flags="$tcl_flags _LARGEFILE_SOURCE64" + fi + + if test "x${tcl_flags}" = "x" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5 +$as_echo "${tcl_flags}" >&6; } + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type" >&5 +$as_echo_n "checking for 64-bit integer type... " >&6; } + if ${tcl_cv_type_64bit+:} false; then : + $as_echo_n "(cached) " >&6 +else + + tcl_cv_type_64bit=none + # See if the compiler knows natively about __int64 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +__int64 value = (__int64) 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_type_64bit=__int64 +else + tcl_type_64bit="long long" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + # See if we should use long anyway Note that we substitute in the + # type that is our current guess for a 64-bit type inside this check + # program, so it should be modified only carefully... + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +switch (0) { + case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; + } + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_type_64bit=${tcl_type_64bit} +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "${tcl_cv_type_64bit}" = none ; then + +$as_echo "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: using long" >&5 +$as_echo "using long" >&6; } + elif test "${tcl_cv_type_64bit}" = "__int64" \ + -a "${TEA_PLATFORM}" = "windows" ; then + # TEA specific: We actually want to use the default tcl.h checks in + # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* + { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Tcl header defaults" >&5 +$as_echo "using Tcl header defaults" >&6; } + else + +cat >>confdefs.h <<_ACEOF +#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit} +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}" >&5 +$as_echo "${tcl_cv_type_64bit}" >&6; } + + # Now check for auxiliary declarations + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5 +$as_echo_n "checking for struct dirent64... " >&6; } +if ${tcl_cv_struct_dirent64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> +#include <dirent.h> +int +main () +{ +struct dirent64 p; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_struct_dirent64=yes +else + tcl_cv_struct_dirent64=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5 +$as_echo "$tcl_cv_struct_dirent64" >&6; } + if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then + +$as_echo "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5 +$as_echo_n "checking for struct stat64... " >&6; } +if ${tcl_cv_struct_stat64+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +struct stat64 p; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_struct_stat64=yes +else + tcl_cv_struct_stat64=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5 +$as_echo "$tcl_cv_struct_stat64" >&6; } + if test "x${tcl_cv_struct_stat64}" = "xyes" ; then + +$as_echo "#define HAVE_STRUCT_STAT64 1" >>confdefs.h + + fi + + for ac_func in open64 lseek64 +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5 +$as_echo_n "checking for off64_t... " >&6; } + if ${tcl_cv_type_off64_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> +int +main () +{ +off64_t offset; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tcl_cv_type_off64_t=yes +else + tcl_cv_type_off64_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + if test "x${tcl_cv_type_off64_t}" = "xyes" && \ + test "x${ac_cv_func_lseek64}" = "xyes" && \ + test "x${ac_cv_func_open64}" = "xyes" ; then + +$as_echo "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + fi + + + +#-------------------------------------------------------------------- +# Set the default compiler switches based on the --enable-symbols option. +#-------------------------------------------------------------------- + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5 +$as_echo_n "checking for build with symbols... " >&6; } + # Check whether --enable-symbols was given. +if test "${enable_symbols+set}" = set; then : + enableval=$enable_symbols; tcl_ok=$enableval +else + tcl_ok=no +fi + + DBGX="" + if test "$tcl_ok" = "no"; then + CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" + LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else + CFLAGS_DEFAULT="${CFLAGS_DEBUG}" + LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" + if test "$tcl_ok" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5 +$as_echo "yes (standard debugging)" >&6; } + fi + fi + # TEA specific: + if test "${TEA_PLATFORM}" != "windows" ; then + LDFLAGS_DEFAULT="${LDFLAGS}" + fi + + + + + if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then + +$as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h + + fi + + if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then + if test "$tcl_ok" = "all"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem debugging" >&5 +$as_echo "enabled symbols mem debugging" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5 +$as_echo "enabled $tcl_ok debugging" >&6; } + fi + fi + + +#-------------------------------------------------------------------- +# Everyone should be linking against the Tcl stub library. If you +# can't for some reason, remove this definition. If you aren't using +# stubs, you also need to modify the SHLIB_LD_LIBS setting below to +# link against the non-stubbed Tcl library. Add Tk too if necessary. +#-------------------------------------------------------------------- + + +$as_echo "#define USE_TCL_STUBS 1" >>confdefs.h + + +$as_echo "#define USE_TK_STUBS 1" >>confdefs.h + + +#-------------------------------------------------------------------- +# This macro generates a line to use when building a library. It +# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, +# and TEA_LOAD_TCLCONFIG macros above. +#-------------------------------------------------------------------- + + + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then + MAKE_STATIC_LIB="\${STLIB_LD} -out:\$@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\$@ \$(PKG_OBJECTS)" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined(_MSC_VER) && _MSC_VER >= 1400 +print("manifest needed") +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "manifest needed" >/dev/null 2>&1; then : + + # Could do a CHECK_PROG for mt, but should always be with MSVC8+ + VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;2 ; fi" + VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;1 ; fi" + MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" + + CLEANFILES="$CLEANFILES *.manifest" + + +fi +rm -f conftest* + + MAKE_STUB_LIB="\${STLIB_LD} -out:\$@ \$(PKG_STUB_OBJECTS)" + else + MAKE_STATIC_LIB="\${STLIB_LD} \$@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} -o \$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" + MAKE_STUB_LIB="\${STLIB_LD} \$@ \$(PKG_STUB_OBJECTS)" + fi + + if test "${SHARED_BUILD}" = "1" ; then + MAKE_LIB="${MAKE_SHARED_LIB} " + else + MAKE_LIB="${MAKE_STATIC_LIB} " + fi + + #-------------------------------------------------------------------- + # Shared libraries and static libraries have different names. + # Use the double eval to make sure any variables in the suffix is + # substituted. (@@@ Might not be necessary anymore) + #-------------------------------------------------------------------- + + if test "${TEA_PLATFORM}" = "windows" ; then + if test "${SHARED_BUILD}" = "1" ; then + # We force the unresolved linking of symbols that are really in + # the private libraries of Tcl and Tk. + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" + fi + eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + else + eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + if test "$GCC" = "yes"; then + PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} + fi + # These aren't needed on Windows (either MSVC or gcc) + RANLIB=: + RANLIB_STUB=: + else + RANLIB_STUB="${RANLIB}" + if test "${SHARED_BUILD}" = "1" ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" + fi + eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + RANLIB=: + else + eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + fi + + # These are escaped so that only CFLAGS is picked up at configure time. + # The other values will be substituted at make time. + CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" + if test "${SHARED_BUILD}" = "1" ; then + CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" + fi + + + + + + + + + + +#-------------------------------------------------------------------- +# Determine the name of the tclsh and/or wish executables in the +# Tcl and Tk build directories or the location they were installed +# into. These paths are used to support running test cases only, +# the Makefile should not be making use of these paths to generate +# a pkgIndex.tcl file or anything else at extension build time. +#-------------------------------------------------------------------- + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 +$as_echo_n "checking for tclsh... " >&6; } + if test -f "${TCL_BIN_DIR}/Makefile" ; then + # tclConfig.sh is in Tcl build directory + if test "${TEA_PLATFORM}" = "windows"; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + else + TCLSH_PROG="${TCL_BIN_DIR}/tclsh" + fi + else + # tclConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + else + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}" + fi + list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${TCLSH_PROG}" ; then + REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}" >&5 +$as_echo "${TCLSH_PROG}" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wish" >&5 +$as_echo_n "checking for wish... " >&6; } + if test -f "${TK_BIN_DIR}/Makefile" ; then + # tkConfig.sh is in Tk build directory + if test "${TEA_PLATFORM}" = "windows"; then + WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" + else + WISH_PROG="${TK_BIN_DIR}/wish" + fi + else + # tkConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" + else + WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}" + fi + list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TK_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TK_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${WISH_PROG}" ; then + REAL_TK_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${WISH_PROG}" >&5 +$as_echo "${WISH_PROG}" >&6; } + + + +#-------------------------------------------------------------------- +# Finally, substitute all of the various values into the Makefile. +# You may alternatively have a special pkgIndex.tcl.in or other files +# which require substituting th AC variables in. Include these here. +#-------------------------------------------------------------------- + +ac_config_files="$ac_config_files Makefile pkgIndex.tcl" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +:mline +/\\$/{ + N + s,\\\n,, + b mline +} +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS="" + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by tkhtml1 $as_me 1.0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +tkhtml1 config.status 1.0 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "pkgIndex.tcl") CONFIG_FILES="$CONFIG_FILES pkgIndex.tcl" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/tkhtml1/configure.in b/tkhtml1/configure.in new file mode 100755 index 0000000..1f9e504 --- /dev/null +++ b/tkhtml1/configure.in @@ -0,0 +1,201 @@ +#!/bin/bash -norc +dnl This file is an input file used by the GNU "autoconf" program to +dnl generate the file "configure", which is run during Tcl installation +dnl to configure the system for the local environment. + +#----------------------------------------------------------------------- +# Sample configure.in for Tcl Extensions. The only places you should +# need to modify this file are marked by the string __CHANGE__ +#----------------------------------------------------------------------- + +#----------------------------------------------------------------------- +# __CHANGE__ +# Set your package name and version numbers here. +# +# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION +# set as provided. These will also be added as -D defs in your Makefile +# so you can encode the package version directly into the source files. +# This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME> +# so that we create the export library with the dll. +#----------------------------------------------------------------------- + +AC_INIT([tkhtml1], [1.0]) + +#-------------------------------------------------------------------- +# Call TEA_INIT as the first TEA_ macro to set up initial vars. +# This will define a ${TEA_PLATFORM} variable == "unix" or "windows" +# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. +#-------------------------------------------------------------------- + +TEA_INIT([3.9]) + +AC_CONFIG_AUX_DIR(tclconfig) + +#-------------------------------------------------------------------- +# Load the tclConfig.sh file +#-------------------------------------------------------------------- + +TEA_PATH_TCLCONFIG +TEA_LOAD_TCLCONFIG + +#-------------------------------------------------------------------- +# Load the tkConfig.sh file if necessary (Tk extension) +#-------------------------------------------------------------------- + +TEA_PATH_TKCONFIG +TEA_LOAD_TKCONFIG + +#----------------------------------------------------------------------- +# Handle the --prefix=... option by defaulting to what Tcl gave. +# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. +#----------------------------------------------------------------------- + +TEA_PREFIX + +#----------------------------------------------------------------------- +# Standard compiler checks. +# This sets up CC by using the CC env var, or looks for gcc otherwise. +# This also calls AC_PROG_CC and a few others to create the basic setup +# necessary to compile executables. +#----------------------------------------------------------------------- + +TEA_SETUP_COMPILER + +#----------------------------------------------------------------------- +# __CHANGE__ +# Specify the C source files to compile in TEA_ADD_SOURCES, +# public headers that need to be installed in TEA_ADD_HEADERS, +# stub library C source files to compile in TEA_ADD_STUB_SOURCES, +# and runtime Tcl library files in TEA_ADD_TCL_SOURCES. +# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS +# and PKG_TCL_SOURCES. +#----------------------------------------------------------------------- + +TEA_ADD_SOURCES([ +src/htmlcmd.c +src/htmldraw.c +src/htmlform.c +src/htmlimage.c +src/htmlindex.c +src/htmllayout.c +src/htmlparse.c +src/htmlsizer.c +src/htmltable.c +src/htmltest.c +src/htmlurl.c +src/htmlwidget.c +src/htmlexts.c +src/htmltokens.c +]) +TEA_ADD_HEADERS([]) +TEA_ADD_INCLUDES([-I./src]) +TEA_ADD_LIBS([]) +TEA_ADD_CFLAGS([-DUSE_INTERP_RESULT]) +TEA_ADD_STUB_SOURCES([]) +TEA_ADD_TCL_SOURCES([]) + +#-------------------------------------------------------------------- +# __CHANGE__ +# +# You can add more files to clean if your extension creates any extra +# files by extending CLEANFILES. +# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure +# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. +# +# A few miscellaneous platform-specific items: +# TEA_ADD_* any platform specific compiler/build info here. +#-------------------------------------------------------------------- + +CLEANFILES="$CLEANFILES src/makeheaders" +if test "${TEA_PLATFORM}" = "windows" ; then + # Ensure no empty if clauses + : + #TEA_ADD_SOURCES([win/winFile.c]) + #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) +else + # Ensure no empty else clauses + : + #TEA_ADD_SOURCES([unix/unixFile.c]) + #TEA_ADD_LIBS([-lsuperfly]) +fi + +#-------------------------------------------------------------------- +# __CHANGE__ +# Choose which headers you need. Extension authors should try very +# hard to only rely on the Tcl public header files. Internal headers +# contain private data structures and are subject to change without +# notice. +# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG +#-------------------------------------------------------------------- + +TEA_PUBLIC_TCL_HEADERS +#TEA_PRIVATE_TCL_HEADERS + +TEA_PUBLIC_TK_HEADERS +#TEA_PRIVATE_TK_HEADERS +TEA_PATH_X + +#-------------------------------------------------------------------- +# Check whether --enable-threads or --disable-threads was given. +# This auto-enables if Tcl was compiled threaded. +#-------------------------------------------------------------------- + +TEA_ENABLE_THREADS + +#-------------------------------------------------------------------- +# The statement below defines a collection of symbols related to +# building as a shared library instead of a static library. +#-------------------------------------------------------------------- + +TEA_ENABLE_SHARED + +#-------------------------------------------------------------------- +# This macro figures out what flags to use with the compiler/linker +# when building shared/static debug/optimized objects. This information +# can be taken from the tclConfig.sh file, but this figures it all out. +#-------------------------------------------------------------------- + +TEA_CONFIG_CFLAGS + +#-------------------------------------------------------------------- +# Set the default compiler switches based on the --enable-symbols option. +#-------------------------------------------------------------------- + +TEA_ENABLE_SYMBOLS + +#-------------------------------------------------------------------- +# Everyone should be linking against the Tcl stub library. If you +# can't for some reason, remove this definition. If you aren't using +# stubs, you also need to modify the SHLIB_LD_LIBS setting below to +# link against the non-stubbed Tcl library. Add Tk too if necessary. +#-------------------------------------------------------------------- + +AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) +AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) + +#-------------------------------------------------------------------- +# This macro generates a line to use when building a library. It +# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, +# and TEA_LOAD_TCLCONFIG macros above. +#-------------------------------------------------------------------- + +TEA_MAKE_LIB + +#-------------------------------------------------------------------- +# Determine the name of the tclsh and/or wish executables in the +# Tcl and Tk build directories or the location they were installed +# into. These paths are used to support running test cases only, +# the Makefile should not be making use of these paths to generate +# a pkgIndex.tcl file or anything else at extension build time. +#-------------------------------------------------------------------- + +TEA_PROG_TCLSH +TEA_PROG_WISH + +#-------------------------------------------------------------------- +# Finally, substitute all of the various values into the Makefile. +# You may alternatively have a special pkgIndex.tcl.in or other files +# which require substituting th AC variables in. Include these here. +#-------------------------------------------------------------------- + +AC_OUTPUT([Makefile pkgIndex.tcl]) diff --git a/tkhtml1/doc/COPYING b/tkhtml1/doc/COPYING new file mode 100644 index 0000000..e77696a --- /dev/null +++ b/tkhtml1/doc/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/tkhtml1/doc/COPYRIGHT b/tkhtml1/doc/COPYRIGHT new file mode 100644 index 0000000..f42114b --- /dev/null +++ b/tkhtml1/doc/COPYRIGHT @@ -0,0 +1,25 @@ +# +# Smithsonian Astrophysical Observatory, Cambridge, MA, USA +# This code has been modified under the terms listed below and is made +# available under the same terms. +# +# Copyright (C) 1997,1998 D. Richard Hipp +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# +# Author contact information: +# drh@acm.org +# http://www.hwaci.com/drh/ diff --git a/tkhtml1/doc/README b/tkhtml1/doc/README new file mode 100644 index 0000000..8f3613a --- /dev/null +++ b/tkhtml1/doc/README @@ -0,0 +1,15 @@ +This directory contains all source code files for the TkHtml +widget. TkHtml renders HTML for Tcl/Tk 8.0 and later. + + COPYRIGHT Text of the GNU Public License, under which this + software is distributed. + + + COMPILE.txt Instructions on how to compile TkHtml. + + doc Other documentation about TkHtml. + + src All of the source code. + + tools Source code to tools that are used to build the widget + but which do not become part of the widget. diff --git a/tkhtml1/doc/notes1.txt b/tkhtml1/doc/notes1.txt new file mode 100644 index 0000000..120f33f --- /dev/null +++ b/tkhtml1/doc/notes1.txt @@ -0,0 +1,52 @@ +The HTML widget uses lots of TCL callback routines. But a TCL +callback can do nasty things. For example, a TCL callback +could delete the HTML widget that invoked the callback. Or +it could delete the TCL interpreter in which the HTML widget +is running. So we have to call HtmlLock() before invoking +a TCL callback and check to make sure the widget was not +deleted before using any fields in the widget structure after +the callback runs. + +The following routines can call TCL callbacks, either directly +or indirectly: + + HtmlTokenizerAppend() + HtmlParseCmd() + HtmlWidgetCommand() + HtmlGetImage() + HtmlAddStyle() + HtmlParseCmd()... + HtmlSizer() + HtmlLayout() + HtmlRedrawCallback() + GetLinkColor() + HtmlAddStyle()... + HtmlCallResolver() + HtmlGetImage()... + HtmlResolveCmd() + HtmlWidgetCommand() + HtmlRedrawCallback()... + HtmlGetFont() + DrawSelectionBackground() + HtmlBlockDraw()... + HtmlBlockDraw() + HtmlRedrawCallback() + FindIndexInBlock() + DecodeBaseIndex() + HtmlGetIndex() + HtmlIndexCmd() + HtmlWidgetCommand()... + HtmlSelectionSetCmd() + HtmlWidgetCommand()... + HtmlInsertCmd() + HtmlWidgetCommand()... + Paragraph() + DoBreakMarkup() + HtmlLayoutBlock() + HtmlLayout()... + HtmlTableLayout() + DoBreakMarkup()... + HtmlDeleteControls() + HtmlClear() + HtmlWidgetCommand()... + HtmlDestroyWidget() diff --git a/tkhtml1/doc/simple.make b/tkhtml1/doc/simple.make new file mode 100644 index 0000000..cd99dc6 --- /dev/null +++ b/tkhtml1/doc/simple.make @@ -0,0 +1,80 @@ +#! /bin/sh +# +# Trying to generate a loadable module for Tcl/Tk8.1.1 on +# WindowsNT using Cygwin20 cross-compiler running under +# RedHat6.0. + +# Step -1: +# Make a copy of winsock.h into winsock2.h. "Winsock2.h" is needed by +# tclWinPort.h. tclWinPort.h is included by tclStubLib.c in step 3. +# + +# Step 0: +# Make sure the cross-compiler tools are on PATH and remove +# old files. +# +PATH=$PATH:/opt/cygwin20/bin +rm -f simple.o stublib.o simple.dll + +# Step 1: +# Generate the C source code into "simple.c" +# +cat >simple.c <<\END +#include <tcl.h> + +int Simple_Init(Tcl_Interp *interp){ + Tcl_InitStubs(interp,"8.1",0); + Tk_InitStubs(interp,"8.1",0); + return TCL_OK; +} +END + +# Step 2: +# Compile the C source code yielding simple.o +# +i586-cygwin32-gcc \ + -I/home/drh/tcltk/tcl8.1.1/generic \ + -mno-cygwin \ + -DUSE_TCL_STUBS=1 \ + -c simple.c + +# Step 3: +# Compile the Stub libraries yielding tclstub.o and tkstub.o +# +i586-cygwin32-gcc \ + -I/home/drh/tcltk/tcl8.1.1/generic \ + -I/home/drh/tcltk/tcl8.1.1/win \ + -mno-cygwin \ + -o tclstub.o \ + -c /home/drh/tcltk/tcl8.1.1/generic/tclStubLib.c +i586-cygwin32-gcc \ + -I/home/drh/tcltk/tcl8.1.1/generic \ + -I/home/drh/tcltk/tcl8.1.1/win \ + -I/home/drh/tcltk/tk8.1.1/generic \ + -I/home/drh/tcltk/tk8.1.1/win \ + -I/home/drh/tcltk/tk8.1.1/xlib \ + -mno-cygwin \ + -o tkstub.o \ + -c /home/drh/tcltk/tk8.1.1/generic/tkStubLib.c + +# Step 4: +# Generate the DEF file +# +cat >simple.def <<\END +EXPORTS +Simple_Init +END + +# Step 5: +# Use dllwrap to build the DLL. Note: tclstub81.lib is copied out +# of the binary tk8.1 distribution from Scriptics. +# +i586-cygwin32-dllwrap \ + --def simple.def \ + -v \ + --driver-name i586-cygwin32-gcc \ + --dlltool-name i586-cygwin32-dlltool \ + --as i586-cygwin32-as \ + --dllname simple.dll \ + --target i386-mingw32 -mno-cygwin \ + simple.o tclstub.o tkstub.o diff --git a/tkhtml1/doc/spec.html b/tkhtml1/doc/spec.html new file mode 100644 index 0000000..cc88b52 --- /dev/null +++ b/tkhtml1/doc/spec.html @@ -0,0 +1,677 @@ +<html> +<!-- + Specifications for the Tk HTML Widget + $Revision$ + Copyright (C) 1997, 1998, 1999 D. Richard Hipp + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Author Contact Information: + drh@acm.org + http://www.hwaci.com/drh/ + + @(#) $Id$ +--> +<head> +<title>Interface Specification For The HTML Widget</title> +</head> +<body bgcolor=white> +<h1>Interface Specification For The HTML Widget</h1> + +<p>This is a draft interface specification for the Tk HTML +widget currently under development. +Since it is still a draft, it is subject to change. +Eventually, the interface will stabilize and this interface +specification will morph into a manual page.</p> + +<h2>Configuration Options</h2> + +<table cellspacing=10> +<tr><td valign=top><tt>-appletcommand</tt></td> +<td> + <p>This option specifies the name of the Tcl procedure to invoke when the + <tt><applet>...</applet></tt> tag sequence is seen. The html + widget will append two arguments to the procedure before calling it. + The first argument is the name of a widget that the callback should + create to hold the applet. + The second argument is + a list of name/value pairs which are the arguments to + the <tt><applet></tt> tag.</p> + + <p>The text between <tt><applet></tt> and <tt></applet></tt> + is normally suppressed. + However, if the <tt>-appletcommand</tt> option is set to the empty string, + the <tt><applet></tt> tag is ignored and all text between + <tt><applet></tt> and <tt></applet></tt> is displayed + normally.</p> + + <p>"<embed>" is treated as an alias for + "<applet></applet>".</p> +</td></tr> + +<tr><td valign=top><tt>-background</tt></td> +<td> + <p>The background color for the widget.</p> + + <p>Note that the <tt><body bgcolor=...></tt> HTML tag does not + automatically cause the widget to change its background color. If + you want the background color to change in response to this HTML tag, + then your Tcl script should intercept + the <tt><body></tt> tag using the + ``<tt>token handler</tt>'' widget command (described below) and + change the background color manually.</p> +</td></tr> + +<tr><td valign=top><tt>-base</tt></td> +<td> + <p>The base URI for the current document. This should be set to + the URI that was used to retrieve the document before parsing + begins.</p> +</td></tr> + +<tr><td valign=top><tt>-bd</tt><td>An alias for <tt>-borderwidth</tt> + +<tr><td valign=top><tt>-bg</tt><td>An alias for <tt>-background</tt> + +<tr><td valign=top><tt>-borderwidth</tt></td> +<td> + <p>The width of the 3-D border drawn around the parameter of the widget, in + pixels.</p> +</td></tr> + +<tr><td valign=top><tt>-cursor</tt></td> +<td> + <p>The cursor displayed when the pointer is positioned over the HTML widget. + If {}, the cursor reverts to its default shape.</p> +</td></tr> + +<tr><td valign=top><tt>-exportselection</tt></td> +</tr> + +<tr><td valign=top><tt>-fontcommand</tt></td> +<td> + <p>The name of a TCL procedure that is used to convert HTML font names + into TCL font names. A default built-in procedure is used if the value + of this option is {}.</p> + + <p>When the HTML widget needs a new font, it calls this procedure with + two arguments. This first argument is the font size expressed as an + integer between 1 and 7. The standard size is 4. The second argument + is a set of between 0 and 3 keywords drawn from the following set: + "bold", "italic", and "fixed". If the "bold" keyword is present in + the second argument, the font returned should be bold. If the "italic" + keyword is present, the font should be italic. If the "fixed" keyword + is present, the font should be fixed-width. The TCL procedure should + return the name of the TCL font that the HTML widget will use to render + the given HTML font. If the TCL procedure returns an empty string, + then the built-in default procedure is used to determine the font.</p> + + <p>Examples: This is {4 {}}. <tt>This is {4 fixed}</tt>. + <small>This is {3 {}}</small>. <large><tt><bold>This is {5 {fixed bold}} + </bold></tt></large></p> +</td></tr> + + +<tr><td valign=top><tt>-fg</tt></td> +<td>An alias for <tt>-foreground</tt>.</td> +</tr> + +<tr><td valign=top><tt>-foreground</tt></td> +<td> + The default foreground color in which HTML text is rendered. + The HTML can override this using the <tt>color=...</tt> attribute + on various HTML tags. +</td></tr> + +<tr><td valign=top> +<code>-formcommand <var>string</var></code> +</td><td> +Declares a handler for everything to do with forms within a document. +Arguments will be appended to <var>string</var> and the result evaluated +during parsing (for form creation) and when the widget is cleared (for +form cleanup). The first argument is a token for +identifying a form. The second argument selects the action to perform. +The remaining arguments depend on the action, as follows. + +<dl><dt><code><var>string token</var> form <var>URL method attrs</var></code> +<dd>The handler should begin taking notes for form <var>token</var>, +especially the (resolved) <var>URL</var> of the action and the +<var>method</var> to be applied. The raw attributes of the FORM element +are in the pairlist <var>attrs</var>. + +<dt><code><var>string token</var> flush</code> +<dd>When the document is cleared, the widget will destroy all the windows +it requested. This handler should clean up anything else +it created for that form. + +<dt><code><var>string token</var> input <var>path attrs</var></code> +<dd>The handler should create a window named <var>path</var> +appropriate for the element described by the <var>attrs</var>. +The widget will map the window into its rendering appropriately. +<p>It is not an error for the handler to return without creating such a window +(it's natural in the case of type=hidden); the widget simply +ignores the element in that case. +The attributes are the raw values in the HTML, with one exception; +a <code>src</code> will be resolved before the handler is called. + +<dt><code><var>string token</var> textarea <var>path attrs initial</var></code> +<dd>The handler should create a window (a single Text, or a Frame with Text +and Scrollbars, or whatever) appropriate for a <textarea> and +initialise it to the <var>initial</var> string. + +<dt><code><var>string token</var> select <var>path attrs choices initial</var></code> +<dd><em><select> is quite a complicated case...</em> +The handler should create a window +appropriate for a <select> of the given attributes and +present the list of <var>choices</var>. Each choice is a pair, the +value and its label. <var>initial</var> is a list of values initially +selected. <em>This approach is somewhat questionable but should do +most of the time.</em> +</dl> + +Caution: Be very careful to avoid confusing HTML variables with TCL +variables. It may be tempting to use the <code>name</code> attribute +fairly directly to link +together related widgets, but it will likely cause incorrect +behaviours. Also be careful to observe the order in which the elements are +created; this determines the order in which they must be submitted. +A default form handler with the correct bahaviour written in TCL will be +bundled with the widget. +<p>The attribute names will be downcased within <var>attrs</var>. +</td></tr> + +<tr><td valign=top><tt>-framecommand</tt><td> +The script specified by this option is invoked when the HTML parser +encounters a <tt><frameset>...</frameset></tt> tag sequence. +The arguments to the script are TBD. +If the value of the option is the empty string, then the text within +the <tt><noframe>...</noframe></tt> tag sequence is displayed. + +<tr><td valign=top><tt>-height</tt><td> +Specifies the height of the area into which HTML is rendered. +This value plus twice the <tt>-padx</tt>, <tt>-borderwidth</tt> and +<tt>-highlightthickness</tt> values is the total height of the widget. + +<tr><td valign=top><tt>-highlightbackground</tt><td> + +<tr><td valign=top><tt>-highlightcolor</tt><td> + +<tr><td valign=top><tt>-highlightthickness</tt><td> + +<tr><td valign=top><tt>-hyperlinkcommand</tt></td> +<td> + The script specified by this option is invoked whenever the user + clicks on a hyperlink on the HTML page. Before invoking this + script, the URI for the hyperlink is appended. +</td></tr> + +<tr><td valign=top><tt>-imagecommand</tt></td> +<td> + When a ``<tt><img src=...></tt>'' tag is encountered, the + HTML widget invokes the script specified by this option in order to + get the name of a Tk image object to display the HTML image. + Before invoking the script, the following arguments are appended: + <ol> + <li>The value of the <tt>src=...</tt> parameter after have been + processed by the resolver. + <li>The value of the <tt>width=...</tt> parameter. + <li>The value of the <tt>height=...</tt> parameter. + <li>A list containing the names and values of all parameters. + </ol> + If the name returned by this script is the empty string, or if the + script is an empty string, then the HTML widget displays the + <tt>alt=...</tt> text of the <tt><img></tt> tag instead of + an image. +</td></tr> + +<tr><td valign=top><tt>-isvisitedcommand</tt><td> +When the HTML widget encounters a hyperlink +(``<tt><a href=...></tt>'') it invokes the script specified +by this option in order to determine whether or not the hyperlink +has been visited. +This information is needed to determine what color to use to display +the hyperlink. + +<tr><td valign=top><tt>-padx</tt><td> +The amount of extra space to insert between the 3-D border and the +left and right sides of the document text. + +<tr><td valign=top><tt>-pady</tt><td> +The amount of extra space to insert between the 3-D border and the top +and bottom of the document text. + +<tr><td valign=top><tt>-relief</tt><td> +The relief used to draw the 3-D border. + +<tr><td valign=top><tt>-resolvercommand</tt></td> +<td> + <p>The name of a TCL command used to resolve URIs. If blank, a built-in + resolver is used. If a TCL command is specified but it returns + an empty string, the built-in resolver is used then too. + The build-in resolver is based on the algorithm + in section 5.2 of RFC 2396. </p> + + <p>Multiple URIs are appended to the TCL command before it is executed. + The first URI is the BASE URI of the document (the URL that specified + by the -base configuration option and updated according to any prior + <BASE> markup). Zero or more additional URIs are + appended to this base. The result of the script should be the resolution + of the whole series or URIs.</p> +</td></tr> + +<tr><td valign=top><tt>-rulerelief</tt></td> +<td> + <p>Determines the appearance of the Horizontal Rule (<HR>) markup. + The default is "sunken". This can also be "raised" or "flat". If + "flat", then the <HR> is drawn using a solid line in the current + foreground color. "groove" and "ridge" are the same as "flat".</p> +</td></tr> + +<tr><td valign=top><tt>-scriptcommand</tt></td> +<td> + <p>Whenever <SCRIPT>...</SCRIPT> markup is encountered in + the input HTML, the attributes of the <SCRIPT> markup and + the body of the script are appended to this string and the result + is executed as a TCL command. If this options is the empty string, + then the script is ignored. +</td></tr> + +<tr><td valign=top><tt>-selectioncolor</tt><td> +The background color used when drawing the selection. The +foreground color for the selection is the same as the regular +foreground color. + +<tr><td valign=top><tt>-tablerelief</tt></td> +<td> + <p>Determines the appearance of the borders around tables. + The default is "raised". This can also be "sunken" or "flat". If + "flat", then the borders is drawn using solid lines in the current + foreground color. "groove" and "ridge" are the same as "flat".</p> +</td></tr> + +<tr><td valign=top><tt>-takefocus</tt><td> + +<tr><td valign=top><tt>-unvisitedcolor</tt><td> +The foreground color used to draw hyperlinks that have not been visited. + +<tr><td valign=top><tt>-underlinehyperlinks</tt><td> +Set to TRUE to cause hyperlinks to be drawn using an underlined font. + +<tr><td valign=top><tt>-visitedcolor</tt><td> +The foreground color used to draw hyperlinks that have been visited. + +<tr><td valign=top><tt>-width</tt><td> +The width of the document text. +This value does not include space allocated for +<tt>-highlightthickness</tt>, <tt>-borderwiddth</tt> or +<tt>-padx</tt>. + +<tr><td valign=top><tt>-xscrollcommand</tt><td> + +<tr><td valign=top><tt>-yscrollcommand</tt><td> + +</table> + +<h2>Indices</h2> + +Internally, the HTML widget stores the HTML document as a list of +tokens. +Each token is either +<ul> +<li>a contiguous sequence of non-space characters (Text), +<li>a contiguous sequence of spaces, tabs or newlines (Space), +<li>or an HTML markup tag (such as ``<tt><em></tt>''.) +</ul> +Tokens are identified by number. +The first token is ``1'', the second is ``2'' and so forth. +So in its simplest form, an index is just an integer greater than 0. +<p> +Within a single Text or Space token, individual characters are +also identified by number, though the counting starts with 0 instead +of 1. +The character number is connected to the token number by a period. +So, for example, the 4th character in the 9th token would be +``9.3''. +<p> +Two integers separated by a dot is called the <em>connonical</em> form +of an index. +Other index forms are available, including: + +<table cellspacing=10> +<tr><td valign=top>end<td> +The keyword ``end'' means one character past +the last character of the last token. +<tr><td valign=top>@X,Y<td> +The character located at screen coordinates X,Y. +<tr><td valign=top>*.last<td> +The second integer can be replaced by the keyword ``last'' to mean the +last character in the token. +<tr><td valign=top>sel.first<td> +This is the first character that is part of the selection. +<tr><td valign=top>sel.last<td> +This is the last character that is part of the selection. +<tr><td valign=top>ins<td> +The character immediately following the insertion cursor. +</table> + +<h2>Commands</h2> + +<dl> +<dt><b>html</b> <i>window</i> ?<i>options ...</i>?</dt><p> +<dd> + Create a new HTML widget instance named <i>windows</i> +</dd> +<p> +<dt><b>html</b> <b>reformat</b> <i>from to text</i><p> +<dd> +Convert text from one encoding to another. The text is given +in the <i>text</i> argument. The current encoding of the text +is specified by the <i>from</i> argument. This command returns +the same text in the <i>to</i> encoding. +<p> +<i>From</i> and <i>to</i> may be any of the following values: +<p> +<table cellspacing=10> +<tr><td valign=top>plain</td> +<td> + Ordinary text with no characters escaped. +</td></tr> +<tr><td valign=top>http</td> +<td> + The text is encoded in a form suitable for use with the HTTP + protocol. Spaces are converted to "+". Special characters + and escaped as "%aa" where "a" is a hexadecimal digit. A special + character is anything other than an alphanumeric or one of these: + ".", "$", "-", or "_". +</td></tr> +<tr><td valign=top>url</td> +<td> + The text is encoded in a form suitable for use as a URI. + Spaces are converted to "+". Special characters + and escaped as "%aa" where "a" is a hexadecimal digit. A special + character is anything other than an alphanumeric or one of these: + ".", "$", "-", "_", or "/". +</td></tr> +<tr><td valign=top>html</td> +<td> + The text is encoded in a form suitable for use within HTML. + "&" is encoded as "&amp;", "<" is encoded as "&lt;" and so + forth. +</td></tr> +</table> +<p> +This command is intended to be useful to the TCL procedures that implement +callbacks for the HTML widget. +</dd> +<p> +<dt><b>html</b> <b>uri join</b> <i>scheme authority path query fragment</i><p> +<dd> +This command takes the five main components of a URI and joins them together +into a complete URI. Special characters in any component are escaped. +</dd> +<p> +<dt><b>html</b> <b>uri split</b> <i>uri</i><p> +<dd> +This command takes a single URI and splits it into its five major +components: scheme, authorithy, path, query and fragement. The command +returns a list where each component is an element of the list. +Components missing from the URI are represented as empty elements in +the list. +</dd> + +</dl> + +<h2>Widget Commands</h2> + +<dl> + +<dt><i>WIDGET</i>  <tt>cget</tt> <i>config-option</i><p> +<dd> +Return the value of a configuration option. Works just like any +other Tk widget. +<p> + +<dt><i>WIDGET</i>  <tt>clear</tt><p> +<dd> +Remove all tokens and text from the HTML widget. +The parser is reset to its initial state. +This routine should be called to changes pages. +<p> + +<dt><i>WIDGET</i>  <tt>configure</tt> ?<i>args...</i>?<p> +<dd> +The standard Tk configuration command. +<p> + +<dt><i>WIDGET</i>  <tt>href</tt>  <i>X  Y</i><p> +<dd>If the coordinates <i>X Y</i> define a point above a hyperlink, +then this command will return the target URL for that hyperlink. +The URL will be resolved using the -resolvercommand before it +is returned. +<p> + +<dt><i>WIDGET</i>  <tt>index</tt>  <i>INDEX  ?COUNT  UNITS?</i></p> +<dd> +Translates <i>INDEX</i> into its connonical form. +The connonical form of an index is two integers separated by a period. +<p> +The optional 3rd and 4th arguments specify a displacement from <i>INDEX</i> +to the value of the index returned. +<i>COUNT</i> can be any integer value, including a negative number. +<i>UNITS</i> must be either ``<tt>char</tt>'' or ``<tt>line</tt>''. +<p> + +<dt><i>WIDGET</i>  <tt>insert</tt>  <i>INDEX</i><p> +<dd> +Causes the insertion cursor (a flashing vertical bar) to be positioned +immediately before the character specified by <i>INDEX</i>. +<p> + +<dt><i>WIDGET</i>  <tt>names</tt><p> +<dd> +This command causes the widget to scan the entire text of the document +looking for tags of the form ``<tt><a name=...></tt>''. +It returns a list of values of the <tt>name=...</tt> fields. +<p> +The vertical position of the document can be moved to any of these names +using the ``<i>WIDGET</i> <tt>yview</tt> <i>NAME</i>'' command described +below. +<p> + +<dt><i>WIDGET</i>  <tt>parse</tt>  <i>HTML-TEXT</i><p> +<dd>Adds the given HTML text to the end of any text previously received +through the <tt>parse</tt> command and parses as much of the text as +possible into tokens. +Afterwards, the display is updated to show the new tokens, if they are +visible.<p> + +<dt><i>WIDGET</i> <tt>resolver</tt> ?<i>uri ...</i>?<p> +<dd>The resolver specified by the -resolvercommand option + is called with the + base URI of the document followed + by the remaining arguments to this commant. The result of this + command is the result of the -resolvercommand script.<p> + +<dt><i>WIDGET</i>  <tt>selection</tt>  <i>subcommand args...</i><p> +<dd>The selection widget command is used to control the selection.<p> + <dl> + <dt><i>WIDGET</i>  <tt>selection clear</tt><p> + <dd>Clear the current selection. No text will be selected after this + command executes.<p> + + <dt><i>WIDGET</i>  <tt>selection set</tt>  <i>START  END</i><p> + <dd>Change the selection to be all text contained within the given + indices.<p> + </dl> + <p> + +<dt><i>WIDGET</i>  <tt>text</tt>  <i>subcommand args...</i><p> +<dd>There are several token commands. They all have the common +property that they directly manipulate the text that is displayed. +These commands (none of which are currently implemented) can be used +to build an WYSIWYG editor for HTML.<p> + <dl> + <dt><i>WIDGET</i> <tt>text ascii</tt>  <i>INDEX-1  INDEX-2</i><p> + <dd><p> + Returns plain ASCII text that represents all characters between + <i>INDEX-1</i> and <i>INDEX-2</i>. Formatting tags are omitted. + The <i>INDEX-1</i> character is included by <i>INDEX-2</i> is omitted. + <p> + + <dt><i>WIDGET</i> <tt>text delete</tt>  <i>INDEX-1  INDEX-2</i><p> + <dd><p> + All text from <i>INDEX-1</i> up to, but not including <i>INDEX-2</i> is + removed and the display is updated accordingly. + <p> + + <dt><i>WIDGET</i> <tt>text html</tt>  <i>INDEX-1  INDEX-2</i><p> + <dd><p> + Returns HTML text that represents all characters and formatting tags + between <i>INDEX-1</i> and <i>INDEX-2</i>. + The <i>INDEX-1</i> character is included by <i>INDEX-2</i> is omitted. + <p> + + <dt><i>WIDGET</i> <tt>text insert</tt>  <i>INDEX  TEXT</i><p> + <dd><p> + Inserts one or more characters immediately before the character whose + index is given. + <p> + </dl> + + +<dt><i>WIDGET</i>  <tt>token</tt>  <i>subcommand args...</i><p> +<dd>There are several token commands. They all have the common + property that they involve the list of tokens into which the + HTML is parsed.<p> + Some of the following subcommands make use of indices. The + character number of these indices is ignored since these commands + deal only with whole tokens. + <p> + <dl> + <dt><i>WIDGET</i> <tt>token append</tt> + <i>TAG ARGUMENTS</i><p> + <dd> + The command causes a token to be appended to the current list of + tokens in the HTML widget. This command is typically used within + a token handler. + <p> + + + <dt><i>WIDGET</i> <tt>token delete</tt> + <i>INDEX  ?INDEX-2?</i><p> + <dd> + Deletes the single token indentified by the index. If a second index is + given, the range of tokens from the first to the second index inclusive + is deleted. + <p> + + <dt><i>WIDGET</i> <tt>token find</tt> + <i>TAG</i><p> + <dd> + Locates all tokens with the given <i>TAG</i> and returns them all + as a list. + Each element of the returned list is a sublist containing the index + for the token and the arguments for the token. + <p> + + <dt><i>WIDGET</i> <tt>token get</tt> + <i>INDEX  ?INDEX-2?</i><p> + <dd> + Returns a list of tokens in the range of <i>INDEX</i> through + <i>INDEX-2</i>. + Each element of the list consists of the token tag followed by + the token arguments. + <p> + + <dt><i>WIDGET</i> <tt>token handler</tt> + <i>TAG ?SCRIPT?</i><p> + <dd> + This command allows special processing to occur for selected tokens + in the HTML input stream. + The <i>TAG</i> argument is either ``Text'' or ``Space'' or the name + of an HTML tag (ex: ``H3'' or ``/A''). + If a non-empty script is specified for a particular tag, then when + instances of that tag are encountered by the parser, the parser calls the + corresponding script instead of appending the token to the end of the + token list. Before calling the script, three arguments are appended: + <ol> + <li>The token number. + <li>The tag. (ex: <tt>H3</tt>) + <li>A list of name/value pairs describing all arguments to the tag. + </ol> + An empty handler script causes the default processing to occur for + the tag. If the script argument is omitted all together, then + the current value of the token handler for the given tag is returned. + <p> + Only one handler may be defined for each token type. If a new + handler is specified for a token type that previously had a different + handler defined, then the old handler is overwritten by the new. + <p> + + <dt><i>WIDGET</i> <tt>token insert</tt> + <i>INDEX  TAG  ARGUMENTS</i><p> + <dd> + Inserts a single token given by <i>TAG</i> and <i>ARGUMENTS</i> into + the token list immediately before <i>INDEX</i>. + <p> + </dl> + +<p> + +<dt><i>WIDGET</i> <tt>xview</tt> <i>args...</i><p> +<dd>Used to control horizontal scrolling.<p> + <dl> + <dt><i>WIDGET</i>  <tt>xview</tt><p> + <dd>Returns a list containing two elements. The elements are a fractions + between 0.0 and 1.0 that define the position of the left and right + edges of + the visible part of the document as a fraction of the whole.<p> + <dt><i>WIDGET</i>  <tt>xview moveto</tt>  <i>FRACTION</i><p> + <dd>Adjusts the horizontal position of the document so that + <i>FRACTION</i> of the horizontal span of the document is off-screen + to the left.<p> + <dt><i>WIDGET</i>  <tt>xview scroll</i>  <i>NUMBER  WHAT</i><p> + <dd> + Shifts the view in the window left or right according to + <i>NUMBER</i> and <i>WHAT</i>.   <i>NUMBER</i> is an integer + and <i>WHAT</i> is either <tt>units</tt> or <tt>pages</tt>.<p> + </dl> + +<dt><i>WIDGET</i>  <tt>yview</tt> <i>args...</i><p> +<dd>Used to control the vertical position of the document.<p> + <dl> + <dt><i>WIDGET</i>  <tt>yview</tt><p> + <dd>Returns a list containing two elements. The elements are a fractions + between 0.0 and 1.0 that define the position of the top and bottom + edges of + the visible part of the document as a fraction of the whole.<p> + <dt><i>WIDGET</i>  <tt>yview</tt>  <i>NAME</i><p> + <dd>Adjusts the vertical position of the document so that the tag + ``<tt><a name=</tt><i>NAME</i><tt>></tt>'' is on screen, + and preferably near the top of the screen.<p> + <dt><i>WIDGET</i>  <tt>yview moveto</tt>  <i>FRACTION</i><p> + <dd>Adjusts the horizontal position of the document so that + <i>FRACTION</i> of the vertical span of the document is off-screen + above the visible region.<p> + <dt><i>WIDGET</i>  <tt>xview scroll</i> <i>NUMBER WHAT</i><p> + <dd> + Shifts the view in the window up or down according to + <i>NUMBER</i> and <i>WHAT</i>.   <i>NUMBER</i> is an integer + and <i>WHAT</i> is either <tt>units</tt> or <tt>pages</tt>.<p> + </dl> + +</dl> +</body> +</html> diff --git a/tkhtml1/doc/webpage/mkwebpage.tcl b/tkhtml1/doc/webpage/mkwebpage.tcl new file mode 100644 index 0000000..de1d25d --- /dev/null +++ b/tkhtml1/doc/webpage/mkwebpage.tcl @@ -0,0 +1,195 @@ +#!/usr/bin/tclsh +# +# Construct the web page for tkhtml +# +# @(#) $Id$ +# + +set p [open publish.sh w] +puts $p "#!/bin/sh" +puts $p "#" + +set SendList {} + +set f [open index.html w] +puts $f { +<html> +<head> +<title>An HTML Widget for Tcl/Tk</title> +</head> +<body bgcolor=white> +<h1 align=center>An HTML Widget For Tcl/Tk</h1> +} +puts $f "<p align=center><i>Last update: [clock format [clock seconds]]</i></p>" +puts $f { +<p>"Tkhtml" is a Tcl/Tk widget that displays HTML. Tkhtml +is implemented in C. It is a true widget, not a metawidget implemented +using the Text or Canvas widgets of the Tcl/Tk core. Implementing +Tkhtml in C gives it a number of advantages:</p> + +<p> +<ul> +<li> It runs fast and uses little memory.</li> +<li> It supports smooth scrolling.</li> +<li> It supports text wrap-around on images and tables.</li> +<li> It has a full implementation of tables. Complex pages (such as + <a href="http://www.scriptics.com/">http://www.scriptics.com/</a>) + are displayed correctly.</li> +<li> Supports forms. </li> +<li> It supports the <APPLET>, <SCRIPT> and <EMBED>. + (Partially. Full support is pending.) </li> +<li> Support for frames is planned. </li> +</ul> +</p> + +<p>Tkhtml can be used with Tcl/Tk8.0 or later. +The shared libraries use the new stubs mechanism, so you +should be able to load Tkhtml with any version of "wish" beginning +with 8.0.6.</p> + +<p>At the moment, there is not a lot of software that uses this +widget. Tkhtml is not an application in and of itself. It is only +a tool. But applications are being built around tkhtml. Check back +later for new developments.</p> + +<h2>Mailing List!</h2> + +<p><font color=red><b><i>New!</i></b></font> + A mailing list has been started for users of tkhtml. + Sign up if you want to recieve notifications of updates or + ask questions about using tkhtml.</p> + +<form method=GET action="http://www.egroups.com/subscribe"> +<input type=hidden name="listname" value="tkhtml"> +<input type=hidden name="SubmitAction" value="Subscribe"> +<p>Enter your e-mail address below and click the button to + sign up for the tkhtml mailing list:</p> + +<p> +<table cellspacing=10> +<tr><td valign=center> +<input type=text name="emailaddr" value="your e-mail" size=21> +</td><td valign=center> +<input type=image border=0 alt="Click here to join tkhtml" + name="Click here to join tkhtml" SRC="http://www.egroups.com/oems/default/languages/english/images/subscriptionBoxButton.gif"> +</td></tr> +</table> +</p> + +<p>You can also view the + <a href="http://www.egroups.com/group/tkhtml/">archives</a> + for the mailing list. To post to this mailing list, send a + message to <a href="mailto:tkhtml@eGroups.com">tkhtml@eGroups.com</a>. + The mailing list is hosted by + <a href="http://www.egroups.com/">eGroups.com</A> +</p> +</form> + + +<h2>You Can Help!</h2> + +<p>If you would like to help, please consider +contributing in the following ways:</p> + +<p> +<ul> +<li> Try out tkhtml on your computer and report bugs to + <a href="mailto:drh@acm.org">drh@acm.org</a>. </li> +<li> Fix bugs and send in patches. (Write access to the + CVS repository may be granted to anyone who is serious + about this.)</li> +<li> Make suggestions for new features. </li> +<li> Write applications that use tkhtml. </li> +<li> Improve the documentation. </li> +</ul> +</p> + +<p>Any help you can provide is appreciated.</p> + +<h2>Getting The Widget</h2> + +<p>Visit the <a href="download.html">download</a> page for a list of +files available for immediate download.</p> + +<p>You can now also obtain the latest tkhtml sources via anonymous CVS. +To access the anonymous CVS server, first install CVS on your system. +(See <a href="http://www.cyclic.com/">http://www.cyclic.com/</a> for +additional information.) Then login as follows:</p> + +<blockquote><pre> +cvs -d :pserver:cvs@xoli.dyn.dhs.org:/home/cvs/cvsroot login +</pre></blockquote> + +<p>You will be prompted for a password. Use "<tt>cvs</tt>". After +you get logged in successfully, you can check out the source tree +like this:</p> + +<blockquote><pre> +cvs -d :pserver:cvs@xoli.dyn.dhs.org:/home/cvs/cvsroot checkout htmlwidget +</pre></blockquote> + +<p>This command creates a directory named "<tt>htmlwidget</tt>" and +fills it with the latest version of the sources.</p> + +</body> +</html> +} +close $f +lappend SendList index.html + +set f [open download.html w] +puts $f { +<html> +<head> +<title>TkHtml Download Page</title> +</head> +<body bgcolor=white> +<h1 align=center>TkHtml Download Page</h1> +} +puts $f "<p align=center><i>Last update: [clock format [clock seconds]]</i></p>" +puts $f { + +<p>The files shown below are available for download. For the very +latest sources, visit the anonymous CVS server. Instructions for +reaching the anonymous CVS server are on the tkhtml +<a href="index.html">homepage</a>.</p> + +<ul> +} +foreach {file desc} { + tkhtml.tar.gz {A tarball containing all the latest source code} + hv.tcl.gz {The "Html Viewer" example application} + spec.html {A raw specification of how the tkhtml widget works} + tkhtml.so.gz {Shared library suitable for use on Linux} + tkhtml.dll.zip {A DLL suitable for use on Windows95/98/NT/2K} +} { + if {![file readable $file]} continue + lappend SendList $file + puts $f "<li><p><a href=\"$file\">$file</a><br>" + puts $f "Description: $desc<br>" + puts $f "Size: [file size $file] bytes<br>" + puts $f "Last modified: [clock format [file mtime $file]]" + switch -glob -- $file { + *.zip - + *.gz {set access zcat} + default {set access cat} + } + if {![catch {exec $access $file | ident | grep {$Id: }} ident]} { + puts $f "<br>Version information:" + puts $f "<pre>\n$ident</pre>" + } + puts $f "</p></li>\n" +} +puts $f { +</ul> + +<p><a href="index.html">Back</a> to the tkhtml home page</p> + +</body> +</html> +} +close $f +lappend SendList download.html + +puts $p "scp [lsort $SendList] hwaci@oak.he.net:public_html/sw/tkhtml" +close $p diff --git a/tkhtml1/pkgIndex.tcl.in b/tkhtml1/pkgIndex.tcl.in new file mode 100755 index 0000000..d7566b4 --- /dev/null +++ b/tkhtml1/pkgIndex.tcl.in @@ -0,0 +1,5 @@ +# +# Tcl package index file +# +package ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ \ + [list load [file join $dir @PKG_LIB_FILE@] @PACKAGE_NAME@] diff --git a/tkhtml1/src/html.h b/tkhtml1/src/html.h new file mode 100644 index 0000000..b43da47 --- /dev/null +++ b/tkhtml1/src/html.h @@ -0,0 +1,1010 @@ +/* +** Structures and typedefs used by the HTML widget +** $Revision$ +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ + +/* +** Debug must be turned on for testing to work. +*/ +#define DEBUG 1 + +/* +** Sanity checking macros. +*/ +#ifdef DEBUG +#define HtmlAssert(X) \ + if(!(X)){ \ + fprintf(stderr,"Assertion failed on line %d of %s\n",__LINE__,__FILE__); \ + } +#define HtmlCantHappen \ + fprintf(stderr,"Can't happen on line %d of %s\n",__LINE__,__FILE__); +#else +#define HtmlAssert(X) +#define HtmlCantHappen +#endif + +/* +** The TRACE macro is used to print internal information about the +** HTML layout engine during testing and debugging. The amount of +** information printed is governed by a global variable named +** HtmlTraceMask. If bits in the first argument to the TRACE macro +** match any bits in HtmlTraceMask variable, then the trace message +** is printed. +** +** All of this is completely disabled, of course, if the DEBUG macro +** is not defined. +*/ +#ifdef DEBUG +# define TRACE_INDENT printf("%*s",HtmlDepth-3,"") +# define TRACE(Flag, Args) \ + if( (Flag)&HtmlTraceMask ){ \ + TRACE_INDENT; printf Args; fflush(stdout); \ + } +# define TRACE_PUSH(Flag) if( (Flag)&HtmlTraceMask ){ HtmlDepth+=3; } +# define TRACE_POP(Flag) if( (Flag)&HtmlTraceMask ){ HtmlDepth-=3; } +#else +# define TRACE_INDENT +# define TRACE(Flag, Args) +# define TRACE_PUSH(Flag) +# define TRACE_POP(Flag) +#endif + +/* +** Bitmasks for the HtmlTraceMask global variable +*/ +#define HtmlTrace_Table1 0x00000001 +#define HtmlTrace_Table2 0x00000002 +#define HtmlTrace_Table3 0x00000004 +#define HtmlTrace_Table4 0x00000008 +#define HtmlTrace_Table5 0x00000010 +#define HtmlTrace_Table6 0x00000020 +#define HtmlTrace_GetLine 0x00000100 +#define HtmlTrace_GetLine2 0x00000200 +#define HtmlTrace_FixLine 0x00000400 +#define HtmlTrace_BreakMarkup 0x00001000 +#define HtmlTrace_Style 0x00002000 +#define HtmlTrace_Input1 0x00004000 + + +/* +** Macros to allocate and free memory. +*/ +#define HtmlAlloc(A) ((void*)Tcl_Alloc(A)) +#define HtmlFree(A) Tcl_Free((char*)(A)) +#define HtmlRealloc(A,B) ((void*)Tcl_Realloc((A),(B))) + +/* +** Various data types. This code is designed to run on a modern +** cached architecture where the CPU runs a lot faster than the +** memory bus. Hence we try to pack as much data into as small a space +** as possible so that it is more likely to fit in cache. The +** extra CPU instruction or two needed to unpack the data is not +** normally an issue since we expect the speed of the memory bus +** to be the limiting factor. +*/ +typedef unsigned char Html_u8; /* 8-bit unsigned integer */ +typedef short Html_16; /* 16-bit signed integer */ +typedef unsigned short Html_u16; /* 16-bit unsigned integer */ +typedef int Html_32; /* 32-bit signed integer */ + +/* +** An instance of the following structure is used to record style +** information on each Html element. +*/ +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +} + +/* +** We allow 8 different font families: Normal, Bold, Italic and +** Bold-Italic in either variable or constant width. +** Within each family there can be up to 7 font sizes from 1 +** (the smallest) up to 7 (the largest). Hence, the widget can use +** a maximum of 56 fonts. The ".font" field of the style is an integer +** between 0 and 55 which indicates which font to use. +*/ +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define NormalFont(X) (X) +#define BoldFont(X) ((X)+N_FONT_SIZE) +#define ItalicFont(X) ((X)+2*N_FONT_SIZE) +#define CWFont(X) ((X)+4*N_FONT_SIZE) +#define FontSize(X) ((X)%N_FONT_SIZE) +#define FontFamily(X) (((X)/N_FONT_SIZE)*N_FONT_SIZE) +#define FONT_Any -1 +#define FONT_Default 3 +#define FontSwitch(Size, Bold, Italic, Cw) \ + ((Size)+(Bold+(Italic)*2+(Cw)*4)*N_FONT_SIZE) + +/* +** Macros for manipulating the fontValid bitmap of an HtmlWidget structure. +*/ +#define FontIsValid(H,I) (((H)->fontValid[(I)>>3] & (1<<((I)&3)))!=0) +#define FontSetValid(H,I) ((H)->fontValid[(I)>>3] |= (1<<((I)&3))) +#define FontClearValid(H,I) ((H)->fontValid[(I)>>3] &= ~(1<<((I)&3))) + +/* +** Information about available colors. +** +** The widget will use at most N_COLOR colors. 4 of these colors +** are predefined. The rest are user selectable by options to +** various markups. (Ex: <font color=red>) +** +** All colors are stored in the apColor[] array of the main widget +** structure. The ".color" field of the HtmlStyle is an integer +** between 0 and N_COLOR-1 which indicates which of these colors +** to use. +*/ +#define N_COLOR 16 /* Total number of colors */ +#define COLOR_Normal 0 /* Index for normal color (black) */ +#define COLOR_Unvisited 1 /* Index for unvisited hyperlinks */ +#define COLOR_Visited 2 /* Color for visited hyperlinks */ +#define COLOR_Selection 3 /* Background color for the selection */ +#define COLOR_Background 4 /* Default background color */ +#define N_PREDEFINED_COLOR 5 /* Number of predefined colors */ + +/* +** The "align" field of the style determines how text is justified +** horizontally. ALIGN_None means that the alignment is not specified. +** (It should probably default to ALIGN_Left in this case.) +*/ +#define ALIGN_Left 1 +#define ALIGN_Right 2 +#define ALIGN_Center 3 +#define ALIGN_None 0 + +/* +** Possible value of the "flags" field of HtmlStyle are shown below. +** +** STY_Preformatted If set, the current text occurred within +** <pre>..</pre> +** +** STY_StrikeThru Draw a solid line thru the middle of this text. +** +** STY_Underline This text should drawn with an underline. +** +** STY_NoBreak This text occurs within <nobr>..</nobr> +** +** STY_Anchor This text occurs within <a href=X>..</a>. +** +** STY_DT This text occurs within <dt>..</dt>. +** +** STY_Invisible This text should not appear in the main HTML +** window. (For example, it might be within +** <title>..</title> or <marquee>..</marquee>.) +*/ +#define STY_Preformatted 0x001 +#define STY_StrikeThru 0x002 +#define STY_Underline 0x004 +#define STY_NoBreak 0x008 +#define STY_Anchor 0x010 +#define STY_DT 0x020 +#define STY_Invisible 0x040 +#define STY_FontMask (STY_StrikeThru|STY_Underline) + +/* +** The first thing done with input HTML text is to parse it into +** HtmlElements. All sizing and layout is done using these elements, +** so this is a very important structure. +** +** Elements are designed so that the common ones (Text and Space) +** require as little storage as possible, in order to increase +** the chance of memory cache hits. (Turns out I didn't do a +** very good job of this. This widget is a pig for memory. But +** the speed is good, so I'm not going to change it right now...) +** +** Some elements require more memory than Text and Space (ex: <IMG>). +** An HtmlElement is therefore represented as a union of many other +** structures all of different sizes. That way we can have a pointer +** to a generic element without having to worry about how big that +** element is. The ".base.type" field (which is found in all elements) +** will tell us what type of element we are dealing with. +** +** NOTE: This trick will only work on compilers that align all elements +** of a union to the lowest memory address in that union. This is true +** for every C compiler I've ever seen, but isn't guarenteed for ANSI-C. +*/ +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; + +/* +** Every element contains at least this much information: +*/ +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; + +/* +** Bitmasks for the "flags" field of the HtmlBaseElement +*/ +#define HTML_Visible 0x01 /* This element produces "ink" */ +#define HTML_NewLine 0x02 /* type==Html_Space and ends with newline */ +#define HTML_Selected 0x04 /* Some or all of this Html_Block is selected */ + /* Used by Html_Block elements only. */ + +/* +** Each text element holds additional information as show here. Notice +** that extra space is allocated so that zText[] will be large enough +** to hold the complete text of the element. X and y coordinates are +** relative to the virtual canvas. The y coordinate refers to the +** baseline. +*/ +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; + +/* +** Each space element is represented like this: +*/ +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; + +/* +** Most markup uses this structure. Some markup extends this structure +** with additional information, but most use it as a base, at the very +** least. +** +** If the markup doesn't have arguments (the "count" field of +** HtmlBaseElement is 0) then the extra "argv" field of this structure +** is not allocated and should not be used. +*/ +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; + +/* Each <td> or <th> markup is represented by an instance of the +** following structure. +** +** Drawing for a cell is a sunken 3D border with the border width given +** by the borderWidth field in the associated <table> structure. +*/ +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; + +/* +** The maximum number of columns allowed in a table. Any columns beyond +** this number are ignored. +*/ +#define HTML_MAX_COLUMNS 40 + +/* +** This structure is used for each <table> element. +** +** In the minW[] and maxW[] arrays, the [0] element is the overall +** minimum and maximum width, including cell padding, spacing and +** the "hspace". All other elements are the minimum and maximum +** width for the contents of individual cells without any spacing or +** padding. +*/ +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; + +/* This structure is used for </table>, </td>, <tr>, </tr> +** and </th> elements. It points back to the <table> element +** that began the table. It is also used by </a> to point back +** to the original <a>. I'll probably think of other uses before +** all is said and done... +*/ +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; + +/* +** An instance of the following structure is used to represent +** each <LI> markup. +*/ +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; + +/* +** The .type field of an HtmlLi or HtmlListStart structure can take on +** any of the following values to indicate what type of bullet to draw. +** The value in HtmlLi will take precedence over the value in HtmlListStart +** if the two values differ. +*/ +#define LI_TYPE_Undefined 0 /* If in HtmlLi, use the HtmlListStart value */ +#define LI_TYPE_Bullet1 1 /* A solid circle */ +#define LI_TYPE_Bullet2 2 /* A hollow circle */ +#define LI_TYPE_Bullet3 3 /* A hollow square */ +#define LI_TYPE_Enum_1 4 /* Arabic numbers */ +#define LI_TYPE_Enum_A 5 /* A, B, C, ... */ +#define LI_TYPE_Enum_a 6 /* a, b, c, ... */ +#define LI_TYPE_Enum_I 7 /* Capitalized roman numerals */ +#define LI_TYPE_Enum_i 8 /* Lower-case roman numerals */ + +/* +** An instance of this structure is used for <UL> or <OL> +** markup. +*/ +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; + +/* +** Information about each image on the HTML widget is held in an +** instance of the following structure. A pointer to this structure +** is the clientData for the image change callback. All image structures +** are held on a list attached to the main widget structure. +** +** This structure is NOT an element. The <IMG> element is represented +** by an HtmlImageMarkup structure below. There is one HtmlImageMarkup +** for each <IMG> in the source HTML. There is one of these structures +** for each unique image loaded. (If two <IMG> specify the same image, +** there are still two HtmlImageMarkup structures but only one +** HtmlImage structure that is shared between them.) +*/ +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; + +/* Each <img> markup is represented by an instance of the +** following structure. +** +** If pImage==0, then we use the alternative text in zAlt. +*/ +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; + +/* +** Allowed alignments for images. These represent the allowed arguments +** to the "align=" field of the <IMG> markup. +*/ +#define IMAGE_ALIGN_Bottom 0 +#define IMAGE_ALIGN_Middle 1 +#define IMAGE_ALIGN_Top 2 +#define IMAGE_ALIGN_TextTop 3 +#define IMAGE_ALIGN_AbsMiddle 4 +#define IMAGE_ALIGN_AbsBottom 5 +#define IMAGE_ALIGN_Left 6 +#define IMAGE_ALIGN_Right 7 + +/* +** All kinds of form markup, including <INPUT>, <TEXTAREA> and <SELECT> +** are represented by instances of the following structure. +** +** (later...) We also use this for the <APPLET> markup. That way, +** the window we create for an <APPLET> responds to the HtmlMapControls() +** and HtmlUnmapControls() function calls. For an <APPLET>, the +** pForm field is NULL. (Later still...) <EMBED> works just like +** <APPLET> so it uses this structure too. +*/ +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; + +/* +** An input control can be one of the following types. See the +** comment about <APPLET> on the HtmlInput structure insight into +** INPUT_TYPE_Applet. +*/ +#define INPUT_TYPE_Unknown 0 +#define INPUT_TYPE_Checkbox 1 +#define INPUT_TYPE_File 2 +#define INPUT_TYPE_Hidden 3 +#define INPUT_TYPE_Image 4 +#define INPUT_TYPE_Password 5 +#define INPUT_TYPE_Radio 6 +#define INPUT_TYPE_Reset 7 +#define INPUT_TYPE_Select 8 +#define INPUT_TYPE_Submit 9 +#define INPUT_TYPE_Text 10 +#define INPUT_TYPE_TextArea 11 +#define INPUT_TYPE_Applet 12 + +/* +** There can be multiple <FORM> entries on a single HTML page. +** Each one must be given a unique number for identification purposes, +** and so we can generate unique state variable names for radiobuttons, +** checkbuttons, and entry boxes. +*/ +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; + +/* +** Information used by a <HR> markup +*/ +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; + +/* +** Information used by a <A> markup +*/ +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; + +/* +** Information about the <SCRIPT> markup. The parser treats <SCRIPT> +** specially. All text between <SCRIPT> and </SCRIPT> is captured and +** is pointed to by the zScript field of this structure. +** +** Note that zScript is not null-terminated. Instead, zScript just +** points to a spot in the zText field of the HtmlWidget structure. +** The nScript field determines how long the script is. +*/ +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +} + +/* +** A block is a single unit of display information. This can be +** one or more text elements, or the border of table, or an +** image, etc. +** +** Blocks are used to improve display speed and to improve the +** speed of linear searchs through the token list. A single +** block will typically contain enough information to display +** a dozen or more Text and Space elements all with a single +** call to Tk_DrawChars(). The blocks are linked together on +** their own list, so we can search them much faster then elements +** (since there are fewer of them.) +** +** Of course, you can construct pathological HTML that has as +** many Blocks as it has normal tokens. But you haven't lost +** anything. Using blocks just speeds things up in the common +** case. +** +** Much of the information needed for display is held in the +** original HtmlElement structures. "base.pNext" points to the first +** structure in the list which can be used to find the "style" +** "x" and "y". +** +** If n==0, then "base.pNext" might point to a special HtmlElement that +** defines some other kind of drawing, like <LI> or <IMG> or <INPUT>. +*/ +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; + +/* +** Linux doesn't have a stricmp() function. +*/ +#ifndef HAVE_STRICMP +# define stricmp strcasecmp +# define strnicmp strncasecmp +#endif + +/* +** A stack of these structures is used to keep track of nested font and +** style changes. This allows us to easily revert to the previous style +** when we encounter and end-tag like </em> or </h3>. +** +** This stack is used to keep track of the current style while walking +** the list of elements. After all elements have been assigned a style, +** the information in this stack is no longer used. +*/ +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +} + +/* +** A stack of the following structures is used to remember the +** left and right margins within a layout context. +*/ +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; + +/* +** How much space (in pixels) used for a single level of indentation due +** to a <UL> or <DL> or <BLOCKQUOTE>, etc. +*/ +#define HTML_INDENT 36 + +/* +** A layout context holds all state information used by the layout +** engine. +*/ +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; + +/* +** With 28 different fonts and 16 colors, we could in principle have +** as many as 448 different GCs. But in practice, a single page of +** HTML will typically have much less than this. So we won't try to +** keep all GCs on hand. Instead, We'll keep around the most recently +** used GCs and allocate new ones as necessary. +** +** The following structure is used to build a cache of GCs in the +** main widget structure. +*/ +#define N_CACHE_GC 16 +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; + +/* +** An HtmlIndex is a reference to a particular character within a +** particular Text or Space token. +*/ +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; + +/* +** A single instance of the following structure (together with various +** other structures to which this structure points) contains complete +** state information for a single HTML widget. The clientData for +** the widget command is a pointer to this structure. +** +** The HTML widget is really a mega-widget. It consists of two nested +** windows. The outer window (tkwin) contains the focus highlight border, +** the 3D border and the padding between the border and the text. All +** text that results from the HTML is drawn into the clipping window +** (clipwin). The clipping window is a child of the main +** window and has the name "x". We have to use a clipping window so +** that subwindows required by <FORM> will be clipped properly and won't +** overlap with the borders. +** +** Two primary coordinate systems are used in this widget. +** +** Window coordinates In this system, (0,0) is the upper left-hand +** corner of the clipping window. This coordinates +** apply only to objects which is visible on screen. +** +** Virtual canvas The virtual canvas is an imaginary canvas holding +** the entire document. Typically, part of the +** virtual canvas will show thru the clipping +** window to become visible. The mapping from +** window to virtual canvas coordinates is +** governed by the "xOffset" and "yOffset" fields +** of the widget structure. +** +** +*/ +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +} + +/* + * Flag bits "flags" field of the Html widget: + * + * REDRAW_PENDING A DoWhenIdle handler has already been queued to + * call HtmlRedrawCallback() function. + * + * GOT_FOCUS This widget currently has input focus. + * + * HSCROLL Horizontal scrollbar position needs to be + * recomputed. + * + * VSCROLL Vertical scrollbar position needs to be + * recomputed. + * + * RELAYOUT We need to reposition every element on the + * virtual canvas. (This happens, for example, + * when the size of the widget changes and we + * need to recompute the line breaks.) + * + * RESIZE_ELEMENTS We need to recompute the size of every element. + * This happens, for example, when the fonts + * change. + * + * REDRAW_FOCUS We need to repaint the focus highlight border. + * + * REDRAW_TEXT Everything in the clipping window needs to be redrawn. + * + * REDRAW_BORDER Everything outside the clipping window needs + * to be redrawn. + * + * RESIZE_CLIPWIN The size and position of the clipping window + * needs to be adjusted using Tk_MoveResizeWindow(). + * + * STYLER_RUNNING There is a call to HtmlAddStyle() in process. + * Used to prevent a recursive call to HtmlAddStyle(). + * + * INSERT_FLASHING True if there is a timer callback pending that will + * toggle the state of the insertion cursor. + * + * REDRAW_IMAGES One or more HtmlImageMarkup structures have + * their redrawNeeded flag set. + */ + +#define REDRAW_PENDING 0x000001 +#define GOT_FOCUS 0x000002 +#define HSCROLL 0x000004 +#define VSCROLL 0x000008 +#define RELAYOUT 0x000010 +#define RESIZE_ELEMENTS 0x000020 +#define REDRAW_FOCUS 0x000040 +#define REDRAW_TEXT 0x000080 +#define REDRAW_BORDER 0x000100 +#define EXTEND_LAYOUT 0x000200 +#define RESIZE_CLIPWIN 0x000400 +#define STYLER_RUNNING 0x000800 +#define INSERT_FLASHING 0x001000 +#define REDRAW_IMAGES 0x002000 + +/* +** Macros to set, clear or test bits of the "flags" field. +*/ +#define HtmlHasFlag(A,F) (((A)->flags&(F))==(F)) +#define HtmlHasAnyFlag(A,F) (((A)->flags&(F))!=0) +#define HtmlSetFlag(A,F) ((A)->flags|=(F)) +#define HtmlClearFlag(A,F) ((A)->flags&=~(F)) + +/* +** No coordinate is every as big as this number +*/ +#define LARGE_NUMBER 100000000 + +/* +** Default values for configuration options +*/ +#define DEF_HTML_BG_COLOR DEF_FRAME_BG_COLOR +#define DEF_HTML_BG_MONO DEF_FRAME_BG_MONO +#define DEF_HTML_BORDER_WIDTH "2" +#define DEF_HTML_CALLBACK "" +#define DEF_HTML_CURSOR DEF_FRAME_CURSOR +#define DEF_HTML_EXPORT_SEL "yes" +#define DEF_HTML_FG DEF_BUTTON_FG +#define DEF_HTML_HEIGHT "400" +#define DEF_HTML_HIGHLIGHT_BG DEF_BUTTON_HIGHLIGHT_BG +#define DEF_HTML_HIGHLIGHT DEF_BUTTON_HIGHLIGHT +#define DEF_HTML_HIGHLIGHT_WIDTH "0" +#define DEF_HTML_INSERT_OFF_TIME "300" +#define DEF_HTML_INSERT_ON_TIME "600" +#define DEF_HTML_PADX "5" +#define DEF_HTML_PADY "5" +#define DEF_HTML_RELIEF "raised" +#define DEF_HTML_SCROLL_COMMAND "" +#define DEF_HTML_SELECTION_COLOR "skyblue" +#define DEF_HTML_TAKE_FOCUS "0" +#define DEF_HTML_UNVISITED "blue1" +#define DEF_HTML_VISITED "blue3" +#define DEF_HTML_WIDTH "600" + +#ifdef NAVIGATOR_TABLES + +#define DEF_HTML_TABLE_BORDER "0" +#define DEF_HTML_TABLE_CELLPADDING "2" +#define DEF_HTML_TABLE_CELLSPACING "5" +#define DEF_HTML_TABLE_BORDER_LIGHT_COLOR "gray80" +#define DEF_HTML_TABLE_BORDER_DARK_COLOR "gray40" + +#endif /* NAVIGATOR_TABLES */ diff --git a/tkhtml1/src/htmlcmd.c b/tkhtml1/src/htmlcmd.c new file mode 100644 index 0000000..c95d080 --- /dev/null +++ b/tkhtml1/src/htmlcmd.c @@ -0,0 +1,727 @@ +/* +** Routines to implement the HTML widget commands +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <tk.h> +#include <stdlib.h> +#include <string.h> +#include "htmlcmd.h" + +/* +** WIDGET resolve ?URI ...? +** +** Call the TCL command specified by the -resolvercommand option +** to resolve the URL. +*/ +int HtmlResolveCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + return HtmlCallResolver(htmlPtr, (char**)argv+2); +} + +/* +** WIDGET cget CONFIG-OPTION +** +** Retrieve the value of a configuration option +*/ +int HtmlCgetCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + TestPoint(0); + return Tk_ConfigureValue(interp, htmlPtr->tkwin, HtmlConfigSpec(), + (char *) htmlPtr, argv[2], 0); +} + +/* +** WIDGET clear +** +** Erase all HTML from this widget and clear the screen. This is +** typically done before loading a new document. +*/ +int HtmlClearCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + HtmlClear(htmlPtr); + htmlPtr->flags |= REDRAW_TEXT | VSCROLL | HSCROLL; + HtmlScheduleRedraw(htmlPtr); + TestPoint(0); + return TCL_OK; +} + +/* +** WIDGET configure ?OPTIONS? +** +** The standard Tk configure command. +*/ +int HtmlConfigCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + if (argc == 2) { + TestPoint(0); + return Tk_ConfigureInfo(interp, htmlPtr->tkwin, HtmlConfigSpec(), + (char *) htmlPtr, (char *) NULL, 0); + } else if (argc == 3) { + TestPoint(0); + return Tk_ConfigureInfo(interp, htmlPtr->tkwin, HtmlConfigSpec(), + (char *) htmlPtr, argv[2], 0); + } else { + TestPoint(0); + return ConfigureHtmlWidget(interp, htmlPtr, argc-2, argv+2, + TK_CONFIG_ARGV_ONLY, 0); + } +} + +/* +** WIDGET href X Y +** +** Returns the URL on the hyperlink that is beneath the position X,Y. +** Returns {} if there is no hyperlink beneath X,Y. +*/ +int HtmlHrefCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + int x, y; + char *z; + + if( Tcl_GetInt(interp, argv[2], &x) != TCL_OK + || Tcl_GetInt(interp, argv[3], &y) != TCL_OK + ){ + TestPoint(0); + return TCL_ERROR; + } + z = HtmlGetHref(htmlPtr, x + htmlPtr->xOffset, y + htmlPtr->yOffset); + if( z ){ + HtmlLock(htmlPtr); + z = HtmlResolveUri(htmlPtr, z); + if( !HtmlUnlock(htmlPtr) ){ + Tcl_SetResult(interp, z, TCL_DYNAMIC); + } + } + return TCL_OK; +} + +/* +** WIDGET names +** +** Returns a list of names associated with <a name=...> tags. +*/ +int HtmlNamesCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + HtmlElement *p; + char *z; + TestPoint(0); + for(p=htmlPtr->pFirst; p; p=p->pNext){ + if( p->base.type!=Html_A ) continue; + z = HtmlMarkupArg(p,"name",0); + if( z ){ + Tcl_AppendElement(interp,z); + }else{ + z = HtmlMarkupArg(p,"id",0); + if( z ){ + Tcl_AppendElement(interp,z); + } + } + } + return TCL_OK; +} + +/* +** WIDGET parse HTML +** +** Appends the given HTML text to the end of any HTML text that may have +** been inserted by prior calls to this command. Then it runs the +** tokenizer, parser and layout engine as far as possible with the +** text that is available. The display is updated appropriately. +*/ +int HtmlParseCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + HtmlElement *endPtr; + endPtr = htmlPtr->pLast; + HtmlLock(htmlPtr); + HtmlTokenizerAppend(htmlPtr, argv[2]); + if( HtmlIsDead(htmlPtr) ){ + return TCL_OK; + } + if( endPtr ){ + if( endPtr->pNext ){ + HtmlAddStyle(htmlPtr, endPtr->pNext); + } + }else if( htmlPtr->pFirst ){ + htmlPtr->paraAlignment = ALIGN_None; + htmlPtr->rowAlignment = ALIGN_None; + htmlPtr->anchorFlags = 0; + htmlPtr->inDt = 0; + htmlPtr->anchorStart = 0; + htmlPtr->formStart = 0; + htmlPtr->innerList = 0; + HtmlAddStyle(htmlPtr, htmlPtr->pFirst); + TestPoint(0); + } + if( !HtmlUnlock(htmlPtr) ){ + htmlPtr->flags |= EXTEND_LAYOUT; + HtmlScheduleRedraw(htmlPtr); + TestPoint(0); + } + return TCL_OK; +} + +/* +** WIDGET xview ?SCROLL-OPTIONS...? +** +** Implements horizontal scrolling in the usual Tk way. +*/ +int HtmlXviewCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + if( argc==2 ){ + HtmlComputeHorizontalPosition(htmlPtr,(char*)Tcl_GetStringResult(interp)); + TestPoint(0); + }else{ + int count; + double fraction; + int maxX = htmlPtr->maxX; + int w = HtmlUsableWidth(htmlPtr); + int offset = htmlPtr->xOffset; + int type = Tk_GetScrollInfo(interp,argc,(const char**)argv,&fraction,&count); + switch( type ){ + case TK_SCROLL_ERROR: + TestPoint(0); + return TCL_ERROR; + case TK_SCROLL_MOVETO: + offset = fraction * maxX; + TestPoint(0); + break; + case TK_SCROLL_PAGES: + offset += (count * w * 9)/10; + TestPoint(0); + break; + case TK_SCROLL_UNITS: + offset += (count * w)/10; + TestPoint(0); + break; + } + if( offset + w > maxX ){ + offset = maxX - w; + TestPoint(0); + }else{ + TestPoint(0); + } + if( offset < 0 ){ + offset = 0; + TestPoint(0); + }else{ + TestPoint(0); + } + HtmlHorizontalScroll(htmlPtr, offset); + } + return TCL_OK; +} + +/* +** WIDGET yview ?SCROLL-OPTIONS...? +** +** Implements vertical scrolling in the usual Tk way, but with one +** enhancement. If the argument is a single word, the widget looks +** for a <a name=...> tag with that word as the "name" and scrolls +** to the position of that tag. +*/ +int HtmlYviewCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + if( argc==2 ){ + HtmlComputeVerticalPosition(htmlPtr,(char*)Tcl_GetStringResult(interp)); + TestPoint(0); + }else if( argc==3 ){ + char *z; + HtmlElement *p; + for(p=htmlPtr->pFirst; p; p=p->pNext){ + if( p->base.type!=Html_A ) continue; + z = HtmlMarkupArg(p,"name",0); + if( z==0 ){ + TestPoint(0); + continue; + } + if( strcmp(z,argv[2])!=0 ){ + TestPoint(0); + continue; + } + HtmlVerticalScroll(htmlPtr, p->anchor.y); + TestPoint(0); + break; + } + } else if( argc==4 && !strncmp(argv[2],"text",4)) { + HtmlElement *p; + int i; + + HtmlLock(htmlPtr); + if( HtmlGetIndex(htmlPtr, argv[3], &p, &i)!=0 ){ + if( !HtmlUnlock(htmlPtr) ){ + Tcl_AppendResult(interp,"malformed index: \"", argv[3], "\"", 0); + } + TestPoint(0); + return TCL_ERROR; + } + if( !HtmlUnlock(htmlPtr) && p ){ + if( p->base.type==Html_Text ) { + int offset = p->text.y-20; + if (offset<0) + offset = 0; + HtmlVerticalScroll(htmlPtr, offset); + } + TestPoint(0); + } + } + else{ + int count; + double fraction; + int maxY = htmlPtr->maxY; + int h = HtmlUsableHeight(htmlPtr); + int offset = htmlPtr->yOffset; + int type = Tk_GetScrollInfo(interp,argc,(const char**)argv,&fraction,&count); + switch( type ){ + case TK_SCROLL_ERROR: + TestPoint(0); + return TCL_ERROR; + case TK_SCROLL_MOVETO: + offset = fraction * maxY; + TestPoint(0); + break; + case TK_SCROLL_PAGES: + offset += (count * h * 9)/10; + TestPoint(0); + break; + case TK_SCROLL_UNITS: + offset += (count * h)/10; + TestPoint(0); + break; + } + if( offset + h > maxY ){ + offset = maxY - h; + TestPoint(0); + }else{ + TestPoint(0); + } + if( offset < 0 ){ + offset = 0; + TestPoint(0); + }else{ + TestPoint(0); + } + HtmlVerticalScroll(htmlPtr, offset); + } + return TCL_OK; +} + +/* +** WIDGET token handler TAG ?SCRIPT? +*/ +int HtmlTokenHandlerCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + int type = HtmlNameToType(argv[3]); + if( type==Html_Unknown ){ + Tcl_AppendResult(interp,"unknown tag: \"", argv[3], "\"", 0); + return TCL_ERROR; + } + if( argc==4 ){ + if( htmlPtr->zHandler[type]!=0 ){ + Tcl_SetResult(interp,htmlPtr->zHandler[type],NULL); + } + }else{ + if( htmlPtr->zHandler[type]!=0 ){ + HtmlFree(htmlPtr->zHandler[type]); + } + htmlPtr->zHandler[type] = HtmlAlloc( strlen(argv[4]) + 1 ); + if( htmlPtr->zHandler[type] ){ + strcpy(htmlPtr->zHandler[type],argv[4]); + } + } + return TCL_OK; +} + +/* +** WIDGET index INDEX +*/ +int HtmlIndexCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + HtmlElement *p; + int i; + + HtmlLock(htmlPtr); + if( HtmlGetIndex(htmlPtr, argv[2], &p, &i)!=0 ){ + if( !HtmlUnlock(htmlPtr) ){ + Tcl_AppendResult(interp,"malformed index: \"", argv[2], "\"", 0); + } + TestPoint(0); + return TCL_ERROR; + } + if( !HtmlUnlock(htmlPtr) && p ){ + sprintf((char*)Tcl_GetStringResult(interp), "%d.%d", HtmlTokenNumber(p), i); + TestPoint(0); + }else{ + TestPoint(0); + } + return TCL_OK; +} + +/* The pSelStartBlock and pSelEndBlock values have been changed. +** This routine's job is to loop over all HtmlBlocks and either +** set or clear the HTML_Selected bits in the .base.flags field +** as appropriate. For every HtmlBlock where the bit changes, +** mark that block for redrawing. +*/ +static void UpdateSelection(HtmlWidget *htmlPtr){ + int selected = 0; + HtmlIndex tempIndex; + HtmlBlock *pTempBlock; + int temp; + HtmlBlock *p; + + for(p=htmlPtr->firstBlock; p; p=p->pNext){ + if( p==htmlPtr->pSelStartBlock ){ + selected = 1; + HtmlRedrawBlock(htmlPtr, p); + TestPoint(0); + }else if( !selected && p==htmlPtr->pSelEndBlock ){ + selected = 1; + tempIndex = htmlPtr->selBegin; + htmlPtr->selBegin = htmlPtr->selEnd; + htmlPtr->selEnd = tempIndex; + pTempBlock = htmlPtr->pSelStartBlock; + htmlPtr->pSelStartBlock = htmlPtr->pSelEndBlock; + htmlPtr->pSelEndBlock = pTempBlock; + temp = htmlPtr->selStartIndex; + htmlPtr->selStartIndex = htmlPtr->selEndIndex; + htmlPtr->selEndIndex = temp; + HtmlRedrawBlock(htmlPtr, p); + TestPoint(0); + }else{ + TestPoint(0); + } + if( p->base.flags & HTML_Selected ){ + if( !selected ){ + p->base.flags &= ~HTML_Selected; + HtmlRedrawBlock(htmlPtr,p); + TestPoint(0); + }else{ + TestPoint(0); + } + }else{ + if( selected ){ + p->base.flags |= HTML_Selected; + HtmlRedrawBlock(htmlPtr,p); + TestPoint(0); + }else{ + TestPoint(0); + } + } + if( p==htmlPtr->pSelEndBlock ){ + selected = 0; + HtmlRedrawBlock(htmlPtr, p); + TestPoint(0); + }else{ + TestPoint(0); + } + } +} + +/* Given the selection end-points in htmlPtr->selBegin +** and htmlPtr->selEnd, recompute pSelBeginBlock and +** pSelEndBlock, then call UpdateSelection to update the +** display. +** +** This routine should be called whenever the selection +** changes or whenever the set of HtmlBlock structures +** change. +*/ +void HtmlUpdateSelection(HtmlWidget *htmlPtr, int forceUpdate){ + HtmlBlock *pBlock; + int index; + int needUpdate = forceUpdate; + int temp; + + if( htmlPtr->selEnd.p==0 ){ + htmlPtr->selBegin.p = 0; + TestPoint(0); + }else{ + TestPoint(0); + } + HtmlIndexToBlockIndex(htmlPtr, htmlPtr->selBegin, &pBlock, &index); + if( needUpdate || pBlock != htmlPtr->pSelStartBlock ){ + needUpdate = 1; + HtmlRedrawBlock(htmlPtr, htmlPtr->pSelStartBlock); + htmlPtr->pSelStartBlock = pBlock; + htmlPtr->selStartIndex = index; + TestPoint(0); + }else if( index != htmlPtr->selStartIndex ){ + HtmlRedrawBlock(htmlPtr, pBlock); + htmlPtr->selStartIndex = index; + TestPoint(0); + }else{ + TestPoint(0); + } + if( htmlPtr->selBegin.p==0 ){ + htmlPtr->selEnd.p = 0; + TestPoint(0); + }else{ + TestPoint(0); + } + HtmlIndexToBlockIndex(htmlPtr, htmlPtr->selEnd, &pBlock, &index); + if( needUpdate || pBlock != htmlPtr->pSelEndBlock ){ + needUpdate = 1; + HtmlRedrawBlock(htmlPtr, htmlPtr->pSelEndBlock); + htmlPtr->pSelEndBlock = pBlock; + htmlPtr->selEndIndex = index; + TestPoint(0); + }else if( index != htmlPtr->selEndIndex ){ + HtmlRedrawBlock(htmlPtr, pBlock); + htmlPtr->selEndIndex = index; + TestPoint(0); + }else{ + TestPoint(0); + } + if( htmlPtr->pSelStartBlock + && htmlPtr->pSelStartBlock==htmlPtr->pSelEndBlock + && htmlPtr->selStartIndex > htmlPtr->selEndIndex + ){ + temp = htmlPtr->selStartIndex; + htmlPtr->selStartIndex = htmlPtr->selEndIndex; + htmlPtr->selEndIndex = temp; + TestPoint(0); + }else{ + TestPoint(0); + } + if( needUpdate ){ + UpdateSelection(htmlPtr); + TestPoint(0); + }else{ + TestPoint(0); + } +} + +/* +** WIDGET selection set INDEX INDEX +*/ +int HtmlSelectionSetCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + HtmlIndex selBegin, selEnd; + + HtmlLock(htmlPtr); + if( HtmlGetIndex(htmlPtr, argv[3], &selBegin.p, &selBegin.i) ){ + if( !HtmlUnlock(htmlPtr) ){ + Tcl_AppendResult(interp,"malformed index: \"", argv[3], "\"", 0); + } + TestPoint(0); + return TCL_ERROR; + } + if( HtmlIsDead(htmlPtr) ) return TCL_OK; + if( HtmlGetIndex(htmlPtr, argv[4], &selEnd.p, &selEnd.i) ){ + if( !HtmlUnlock(htmlPtr) ){ + Tcl_AppendResult(interp,"malformed index: \"", argv[4], "\"", 0); + } + TestPoint(0); + return TCL_ERROR; + } + if( HtmlUnlock(htmlPtr) ) return TCL_OK; + htmlPtr->selBegin = selBegin; + htmlPtr->selEnd = selEnd; + HtmlUpdateSelection(htmlPtr,0); + TestPoint(0); + return TCL_OK; +} + +/* +** WIDGET selection clear +*/ +int HtmlSelectionClearCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + htmlPtr->pSelStartBlock = 0; + htmlPtr->pSelEndBlock = 0; + htmlPtr->selBegin.p = 0; + htmlPtr->selEnd.p = 0; + UpdateSelection(htmlPtr); + TestPoint(0); + return TCL_OK; +} + +/* +** Recompute the position of the insertion cursor based on the +** position in htmlPtr->ins. +*/ +void HtmlUpdateInsert(HtmlWidget *htmlPtr){ + HtmlIndexToBlockIndex(htmlPtr, htmlPtr->ins, + &htmlPtr->pInsBlock, &htmlPtr->insIndex); + HtmlRedrawBlock(htmlPtr, htmlPtr->pInsBlock); + if( htmlPtr->insTimer==0 ){ + htmlPtr->insStatus = 0; + HtmlFlashCursor(htmlPtr); + TestPoint(0); + }else{ + TestPoint(0); + } +} + +/* +** WIDGET insert INDEX +*/ +int HtmlInsertCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + HtmlIndex ins; + if( argv[2][0]==0 ){ + HtmlRedrawBlock(htmlPtr, htmlPtr->pInsBlock); + htmlPtr->insStatus = 0; + htmlPtr->pInsBlock = 0; + htmlPtr->ins.p = 0; + TestPoint(0); + }else{ + HtmlLock(htmlPtr); + if( HtmlGetIndex(htmlPtr, argv[2], &ins.p, &ins.i) ){ + if( !HtmlUnlock(htmlPtr) ){ + Tcl_AppendResult(interp,"malformed index: \"", argv[2], "\"", 0); + } + TestPoint(0); + return TCL_ERROR; + } + if( HtmlUnlock(htmlPtr) ) return TCL_OK; + HtmlRedrawBlock(htmlPtr, htmlPtr->pInsBlock); + htmlPtr->ins = ins; + HtmlUpdateInsert(htmlPtr); + TestPoint(0); + } + return TCL_OK; +} + +/* +** WIDGET token list START END +*/ +int HtmlTokenListCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + HtmlElement *pStart, *pEnd; + int i; + + if( HtmlGetIndex(htmlPtr, argv[3], &pStart, &i)!=0 ){ + Tcl_AppendResult(interp,"malformed index: \"", argv[3], "\"", 0); + return TCL_ERROR; + } + if( HtmlGetIndex(htmlPtr, argv[4], &pEnd, &i)!=0 ){ + Tcl_AppendResult(interp,"malformed index: \"", argv[4], "\"", 0); + return TCL_ERROR; + } + if( pStart ){ + HtmlTclizeList(interp,pStart,pEnd ? pEnd->base.pNext : 0); + } + return TCL_OK; +} + +#ifdef DEBUG +/* +** WIDGET debug dump START END +*/ +int HtmlDebugDumpCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + HtmlElement *pStart, *pEnd; + int i; + + if( HtmlGetIndex(htmlPtr, argv[3], &pStart, &i)!=0 ){ + Tcl_AppendResult(interp,"malformed index: \"", argv[3], "\"", 0); + return TCL_ERROR; + } + if( HtmlGetIndex(htmlPtr, argv[4], &pEnd, &i)!=0 ){ + Tcl_AppendResult(interp,"malformed index: \"", argv[4], "\"", 0); + return TCL_ERROR; + } + if( pStart ){ + HtmlPrintList(pStart,pEnd ? pEnd->base.pNext : 0); + } + return TCL_OK; +} + +/* +** WIDGET debug testpt FILENAME +*/ +int HtmlDebugTestPtCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + HtmlTestPointDump(argv[3]); + return TCL_OK; +} +#endif diff --git a/tkhtml1/src/htmlcmd.h b/tkhtml1/src/htmlcmd.h new file mode 100644 index 0000000..2b7930a --- /dev/null +++ b/tkhtml1/src/htmlcmd.h @@ -0,0 +1,497 @@ +/* This file was automatically generated. Do not edit! */ +void HtmlTestPointDump(const char *filename); +typedef struct HtmlWidget HtmlWidget; +#define DEBUG 1 +#if defined(DEBUG) +int HtmlDebugTestPtCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +#endif +typedef union HtmlElement HtmlElement; +#if defined(DEBUG) +void HtmlPrintList(HtmlElement *p,HtmlElement *pEnd); +int HtmlDebugDumpCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +#endif +void HtmlTclizeList(Tcl_Interp *interp,HtmlElement *p,HtmlElement *pEnd); +int HtmlTokenListCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlInsertCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +void HtmlFlashCursor(ClientData clientData); +void HtmlUpdateInsert(HtmlWidget *htmlPtr); +int HtmlSelectionClearCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlSelectionSetCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +typedef struct HtmlBlock HtmlBlock; +void HtmlIndexToBlockIndex(HtmlWidget *htmlPtr,HtmlIndex sIndex,HtmlBlock **ppBlock,int *piIndex); +void HtmlUpdateSelection(HtmlWidget *htmlPtr,int forceUpdate); +#define HTML_Selected 0x04 /* Some or all of this Html_Block is selected */ +void HtmlRedrawBlock(HtmlWidget *htmlPtr,HtmlBlock *p); +typedef struct HtmlBaseElement HtmlBaseElement; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +typedef unsigned char Html_u8; +typedef short Html_16; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +typedef unsigned short Html_u16; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +int HtmlTokenNumber(HtmlElement *p); +int HtmlIndexCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +#define HtmlAlloc(A) ((void*)Tcl_Alloc(A)) +#define HtmlFree(A) Tcl_Free((char*)(A)) +#define Html_Unknown 3 +int HtmlNameToType(const char *zType); +int HtmlTokenHandlerCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlUsableHeight(HtmlWidget *htmlPtr); +#define Html_Text 1 +int HtmlGetIndex(HtmlWidget *htmlPtr,const char *zIndex,HtmlElement **ppToken,int *pIndex); +void HtmlVerticalScroll(HtmlWidget *htmlPtr,int yOffset); +void HtmlComputeVerticalPosition(HtmlWidget *htmlPtr,char *buf); +int HtmlYviewCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +void HtmlHorizontalScroll(HtmlWidget *htmlPtr,int xOffset); +int HtmlUsableWidth(HtmlWidget *htmlPtr); +void HtmlComputeHorizontalPosition(HtmlWidget *htmlPtr,char *buf); +int HtmlXviewCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +#define EXTEND_LAYOUT 0x000200 +#define ALIGN_None 0 +void HtmlAddStyle(HtmlWidget *htmlPtr,HtmlElement *p); +int HtmlIsDead(HtmlWidget *htmlPtr); +void HtmlTokenizerAppend(HtmlWidget *htmlPtr,const char *zText); +int HtmlParseCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +char *HtmlMarkupArg(HtmlElement *p,const char *tag,char *zDefault); +#define Html_A 5 +typedef struct HtmlTextElement HtmlTextElement; +typedef int Html_32; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlMarkupElement HtmlMarkupElement; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +typedef struct HtmlImage HtmlImage; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +typedef struct HtmlScript HtmlScript; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +int HtmlNamesCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlUnlock(HtmlWidget *htmlPtr); +char *HtmlResolveUri(HtmlWidget *htmlPtr,char *zUri); +void HtmlLock(HtmlWidget *htmlPtr); +char *HtmlGetHref(HtmlWidget *htmlPtr,int x,int y); +int HtmlHrefCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int ConfigureHtmlWidget(Tcl_Interp *interp,HtmlWidget *htmlPtr,int argc,const char **argv,int flags,int realign); +int HtmlConfigCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +void HtmlScheduleRedraw(HtmlWidget *htmlPtr); +#define HSCROLL 0x000004 +#define VSCROLL 0x000008 +#define REDRAW_TEXT 0x000080 +void HtmlClear(HtmlWidget *htmlPtr); +int HtmlClearCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +Tk_ConfigSpec *HtmlConfigSpec(void); +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +int HtmlCgetCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlCallResolver(HtmlWidget *htmlPtr,char **azSeries); +#define Html_TypeCount 151 +typedef struct HtmlStyleStack HtmlStyleStack; +typedef struct HtmlLayoutContext HtmlLayoutContext; +typedef struct HtmlMargin HtmlMargin; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +int HtmlResolveCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/htmldraw.c b/tkhtml1/src/htmldraw.c new file mode 100644 index 0000000..42f2f80 --- /dev/null +++ b/tkhtml1/src/htmldraw.c @@ -0,0 +1,877 @@ +/* +** Routines used to render HTML onto the screen for the Tk HTML widget. +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <tk.h> +#include <string.h> +#include <stdlib.h> +#include "htmldraw.h" +/* +#ifdef USE_TK_STUBS +# include <tkIntXlibDecls.h> +#endif +*/ +#define USE_TK_DRAWCHARS 1 + +/* +** Allocate a new HtmlBlock structure. +*/ +static HtmlBlock *AllocBlock(void){ + HtmlBlock *pNew; + + pNew = HtmlAlloc( sizeof(HtmlBlock) ); + if( pNew ){ + memset(pNew, 0, sizeof(*pNew)); + pNew->base.type = Html_Block; + } + return pNew; +} + +/* +** Free an HtmlBlock structure. Assume that it is already unlinked +** from the element list and the block list. +*/ +static void FreeBlock(HtmlBlock *pBlock){ + if( pBlock ){ + if( pBlock->z ){ + HtmlFree(pBlock->z); + } + HtmlFree(pBlock); + } +} + +/* +** Destroy the given Block after first unlinking it from the +** element list. Note that this unlinks the block from the +** element list only -- not from the block list. +*/ +static void UnlinkAndFreeBlock(HtmlWidget *htmlPtr, HtmlBlock *pBlock){ + if( pBlock->base.pNext ){ + pBlock->base.pNext->base.pPrev = pBlock->base.pPrev; + TestPoint(0); + }else{ + htmlPtr->pLast = pBlock->base.pPrev; + TestPoint(0); + } + if( pBlock->base.pPrev ){ + pBlock->base.pPrev->base.pNext = pBlock->base.pNext; + TestPoint(0); + }else{ + htmlPtr->pFirst = pBlock->base.pNext; + TestPoint(0); + } + pBlock->base.pPrev = pBlock->base.pNext = 0; + FreeBlock(pBlock); +} + +/* +** Append a block to the block list and insert the block into the +** element list immediately prior to the element given. +*/ +static void AppendBlock( + HtmlWidget *htmlPtr, /* The HTML widget */ + HtmlElement *pToken, /* The token that comes after pBlock */ + HtmlBlock *pBlock /* The block to be appended */ +){ + pBlock->base.pPrev = pToken->base.pPrev; + pBlock->base.pNext = pToken; + pBlock->pPrev = htmlPtr->lastBlock; + pBlock->pNext = 0; + if( htmlPtr->lastBlock ){ + htmlPtr->lastBlock->pNext = pBlock; + TestPoint(0); + }else{ + htmlPtr->firstBlock = pBlock; + TestPoint(0); + } + htmlPtr->lastBlock = pBlock; + if( pToken->base.pPrev ){ + pToken->base.pPrev->base.pNext = (HtmlElement*)pBlock; + TestPoint(0); + }else{ + htmlPtr->pFirst = (HtmlElement*)pBlock; + TestPoint(0); + } + pToken->base.pPrev = (HtmlElement*)pBlock; +} + +/* +** Print an ordered list index into the given buffer. Use numbering +** like this: +** +** A B C ... Y Z AA BB CC ... ZZ +** +** Revert to decimal for indices greater than 52. +*/ +static void GetLetterIndex(char *zBuf, int index, int isUpper){ + int seed; + if( index<1 || index>52 ){ + sprintf(zBuf,"%d",index); + TestPoint(0); + return; + } + if( isUpper ){ + seed = 'A'; + TestPoint(0); + }else{ + seed = 'a'; + TestPoint(0); + } + index--; + if( index<26 ){ + zBuf[0] = seed + index; + zBuf[1] = 0; + TestPoint(0); + }else{ + index -= 26; + zBuf[0] = seed + index; + zBuf[1] = seed + index; + zBuf[2] = 0; + TestPoint(0); + } + strcat(zBuf,"."); +} + +/* +** Print an ordered list index into the given buffer. Use roman +** numerals. For indices greater than a few thousand, revert to +** decimal. +*/ +static void GetRomanIndex(char *zBuf, int index, int isUpper){ + int i = 0; + int j; + static struct { + int value; + char *name; + } values[] = { + { 1000, "m" }, + { 999, "im" }, + { 990, "xm" }, + { 900, "cm" }, + { 500, "d" }, + { 499, "id" }, + { 490, "xd" }, + { 400, "cd" }, + { 100, "c" }, + { 99, "ic" }, + { 90, "xc" }, + { 50, "l" }, + { 49, "il" }, + { 40, "xl" }, + { 10, "x" }, + { 9, "ix" }, + { 5, "v" }, + { 4, "iv" }, + { 1, "i" }, + }; + if( index<1 || index>=5000 ){ + sprintf(zBuf,"%d",index); + TestPoint(0); + return; + } + for(j=0; index>0 && j<sizeof(values)/sizeof(values[0]); j++){ + int k; + while( index >= values[j].value ){ + for(k=0; values[j].name[k]; k++){ + zBuf[i++] = values[j].name[k]; + TestPoint(0); + } + index -= values[j].value; + TestPoint(0); + } + } + zBuf[i] = 0; + if( isUpper ){ + for(i=0; zBuf[i]; i++){ + zBuf[i] += 'A' - 'a'; + TestPoint(0); + } + }else{ + TestPoint(0); + } + strcat(zBuf,"."); +} + +/* Draw the selection background for the given block +*/ +static void DrawSelectionBackground( + HtmlWidget *htmlPtr, /* The HTML widget */ + HtmlBlock *pBlock, /* The block whose background is drawn */ + Drawable drawable, /* Draw the background on this drawable */ + int x, int y /* Virtual coords of top-left of drawable */ +){ + int xLeft, xRight; /* Left and right bounds of box to draw */ + int yTop, yBottom; /* Top and bottom of box */ + HtmlElement *p = 0; /* First element of the block */ + Tk_Font font; /* Font */ + GC gc; /* GC for drawing */ + XRectangle xrec; /* Size of a filled rectangle to be drawn */ + + if( pBlock==0 || (pBlock->base.flags & HTML_Selected)==0 ){ + TestPoint(0); + return; + } + xLeft = pBlock->left - x; + if( pBlock==htmlPtr->pSelStartBlock && htmlPtr->selStartIndex>0 ){ + if( htmlPtr->selStartIndex >= pBlock->n ){ TestPoint(0); return; } + p = pBlock->base.pNext; + font = HtmlGetFont(htmlPtr, p->base.style.font); + if( font==0 ) return; + if( p->base.type==Html_Text ){ + xLeft = p->text.x - x + Tk_TextWidth(font, pBlock->z, + htmlPtr->selStartIndex); + } + } + xRight = pBlock->right - x; + if( pBlock==htmlPtr->pSelEndBlock && htmlPtr->selEndIndex<pBlock->n ){ + if( p==0 ){ + p = pBlock->base.pNext; + font = HtmlGetFont(htmlPtr, p->base.style.font); + if( font==0 ) return; + } + if( p->base.type==Html_Text ){ + xRight = p->text.x - x + Tk_TextWidth(font, pBlock->z, + htmlPtr->selEndIndex); + } + } + yTop = pBlock->top - y; + yBottom = pBlock->bottom - y; + gc = HtmlGetGC(htmlPtr, COLOR_Selection, FONT_Any); + xrec.x = xLeft; + xrec.y = yTop; + xrec.width = xRight - xLeft; + xrec.height = yBottom - yTop; + XFillRectangles(htmlPtr->display, drawable, gc, &xrec, 1); +} + +/* +** Draw a rectangle. The rectangle will have a 3-D appearance if +** flat==0 and a flat appearance if flat==1. +** +** We don't use Tk_Draw3DRectangle() because it doesn't work well +** when the background color is close to pure white or pure black. +*/ +static void HtmlDrawRect( + HtmlWidget *htmlPtr, /* The HTML widget */ + Drawable drawable, /* Draw it here */ + HtmlElement *src, /* Element associated with drawing */ + int x, int y, int w, int h, /* Coordinates of the rectangle */ + int depth, /* Width of the relief, or the flat line */ + int relief /* The relief. TK_RELIEF_FLAT omits 3d */ +){ + if( depth>0 ){ + int i; + GC gcLight, gcDark; + XRectangle xrec[1]; + if( relief!=TK_RELIEF_FLAT ){ + int iLight, iDark; + iLight = HtmlGetLightShadowColor(htmlPtr, src->base.style.bgcolor); + gcLight = HtmlGetGC(htmlPtr, iLight, FONT_Any); + iDark = HtmlGetDarkShadowColor(htmlPtr, src->base.style.bgcolor); + gcDark = HtmlGetGC(htmlPtr, iDark, FONT_Any); + if( relief==TK_RELIEF_SUNKEN ){ + GC gcTemp = gcLight; + gcLight = gcDark; + gcDark = gcTemp; + } + }else{ + gcLight = HtmlGetGC(htmlPtr, src->base.style.color, FONT_Any); + gcDark = gcLight; + } + xrec[0].x = x; + xrec[0].y = y; + xrec[0].width = depth; + xrec[0].height = h; + XFillRectangles(htmlPtr->display, drawable, gcLight, xrec, 1); + xrec[0].x = x+w-depth; + XFillRectangles(htmlPtr->display, drawable, gcDark, xrec, 1); + for(i=0; i<depth && i<h/2; i++){ + XDrawLine(htmlPtr->display, drawable, gcLight, x+i, y+i, x+w-i-1, y+i); + XDrawLine(htmlPtr->display, drawable, gcDark, x+i, y+h-i-1, + x+w-i-1, y+h-i-1); + } + } + if( h>depth*2 && w>depth*2 ){ + GC gcBg; + XRectangle xrec[1]; + gcBg = HtmlGetGC(htmlPtr, src->base.style.bgcolor, FONT_Any); + xrec[0].x = x + depth; + xrec[0].y = y + depth; + xrec[0].width = w - depth*2; + xrec[0].height = h - depth*2; + XFillRectangles(htmlPtr->display, drawable, gcBg, xrec, 1); + } +} + +/* +** Display a single HtmlBlock. This is where all the drawing +** happens. +*/ +void HtmlBlockDraw( + HtmlWidget *htmlPtr, /* The main HTML widget */ + HtmlBlock *pBlock, /* Block which needs to be drawn */ + Drawable drawable, /* Draw the line on this */ + int drawableLeft, /* Virtual coordinate of left edge of drawable */ + int drawableTop, /* Virtual coordinate of top edge of drawable */ + int drawableWidth, /* Width of the drawable */ + int drawableHeight /* Height of the drawable */ +){ + Tk_Font font; /* Font to use to render text */ + GC gc; /* A graphics context */ + HtmlElement *src; /* HtmlElement holding style information */ + HtmlElement *pTable; /* The table (when drawing part of a table) */ + int x, y; /* Where to draw */ + + if( pBlock==0 ){ TestPoint(0); return; } + src = pBlock->base.pNext; + while( src && (src->base.flags & HTML_Visible)==0 ){ + src = src->base.pNext; + TestPoint(0); + } + if( src==0 ){ TestPoint(0); return; } + if( pBlock->n>0 ){ + /* We must be dealing with plain old text */ + if( src->base.type==Html_Text ){ + x = src->text.x; + y = src->text.y; + TestPoint(0); + }else{ + CANT_HAPPEN; + return; + } + if( pBlock->base.flags & HTML_Selected ){ + HtmlLock(htmlPtr); + DrawSelectionBackground(htmlPtr, pBlock, drawable, + drawableLeft, drawableTop); + if( HtmlUnlock(htmlPtr) ) return; + } + gc = HtmlGetGC(htmlPtr, src->base.style.color, src->base.style.font); + font = HtmlGetFont(htmlPtr, src->base.style.font); + if( font==0 ) return; + Tk_DrawChars(htmlPtr->display, + drawable, + gc, font, + pBlock->z, pBlock->n, + x - drawableLeft, y - drawableTop); + if( src->base.style.flags & STY_Underline ){ + Tk_UnderlineChars(htmlPtr->display, drawable, gc, font, pBlock->z, + x - drawableLeft, y-drawableTop, 0, pBlock->n); + } + if( src->base.style.flags & STY_StrikeThru ){ + XRectangle xrec; + xrec.x = pBlock->left - drawableLeft; + xrec.y = (pBlock->top + pBlock->bottom)/2 - drawableTop; + xrec.width = pBlock->right - pBlock->left; + xrec.height = 1 + (pBlock->bottom - pBlock->top > 15); + XFillRectangles(htmlPtr->display, drawable, gc, &xrec, 1); + } + if( pBlock==htmlPtr->pInsBlock && htmlPtr->insStatus>0 ){ + int x; + XRectangle xrec; + if( htmlPtr->insIndex < pBlock->n ){ + x = src->text.x - drawableLeft; + x += Tk_TextWidth(font, pBlock->z, htmlPtr->insIndex); + }else{ + x = pBlock->right - drawableLeft; + } + if( x>0 ){ TestPoint(0); x--; } + xrec.x = x; + xrec.y = pBlock->top - drawableTop; + xrec.width = 2; + xrec.height = pBlock->bottom - pBlock->top; + XFillRectangles(htmlPtr->display, drawable, gc, &xrec, 1); + } + }else{ + /* We are dealing with a single HtmlElement which contains something + ** other than plain text. */ + int top=0; + int btm=0; + int cntr; + int cnt, w; + char zBuf[30]; + switch( src->base.type ){ + case Html_LI: + x = src->li.x; + y = src->li.y; + cntr = (top+btm)/2; + switch( src->li.type ){ + case LI_TYPE_Enum_1: + sprintf(zBuf,"%d.",src->li.cnt); + TestPoint(0); + break; + case LI_TYPE_Enum_A: + GetLetterIndex(zBuf,src->li.cnt,1); + TestPoint(0); + break; + case LI_TYPE_Enum_a: + GetLetterIndex(zBuf,src->li.cnt,0); + TestPoint(0); + break; + case LI_TYPE_Enum_I: + GetRomanIndex(zBuf,src->li.cnt,1); + TestPoint(0); + break; + case LI_TYPE_Enum_i: + GetRomanIndex(zBuf,src->li.cnt,0); + TestPoint(0); + break; + default: + zBuf[0] = 0; + TestPoint(0); + break; + } + gc = HtmlGetGC(htmlPtr, src->base.style.color, src->base.style.font); + switch( src->li.type ){ + case LI_TYPE_Undefined: + case LI_TYPE_Bullet1: + XFillArc(htmlPtr->display, + drawable, + gc, + x - 7 - drawableLeft, y - 8 - drawableTop, 7, 7, + 0, 360*64); + TestPoint(0); + break; + + case LI_TYPE_Bullet2: + XDrawArc(htmlPtr->display, + drawable, + gc, + x - 7 - drawableLeft, y - 8 - drawableTop, 7, 7, + 0, 360*64); + TestPoint(0); + break; + + case LI_TYPE_Bullet3: + XDrawRectangle(htmlPtr->display, + drawable, + gc, + x - 7 - drawableLeft, y - 8 - drawableTop, 7, 7); + TestPoint(0); + break; + + case LI_TYPE_Enum_1: + case LI_TYPE_Enum_A: + case LI_TYPE_Enum_a: + case LI_TYPE_Enum_I: + case LI_TYPE_Enum_i: + cnt = strlen(zBuf); + font = HtmlGetFont(htmlPtr, src->base.style.font); + if( font==0 ) return; + w = Tk_TextWidth(font, zBuf, cnt); + Tk_DrawChars(htmlPtr->display, + drawable, + gc, font, + zBuf, cnt, + x - w - drawableLeft, y - drawableTop); + TestPoint(0); + break; + } + break; + case Html_HR: { + int relief = htmlPtr->ruleRelief; + switch( relief ){ + case TK_RELIEF_RAISED: + case TK_RELIEF_SUNKEN: + break; + default: + relief = TK_RELIEF_FLAT; + break; + } + HtmlDrawRect(htmlPtr, drawable, src, + src->hr.x - drawableLeft, + src->hr.y - drawableTop, + src->hr.w, + src->hr.h, + 1, relief); + break; + } + case Html_TABLE: { + int relief = htmlPtr->tableRelief; + switch( relief ){ + case TK_RELIEF_RAISED: + case TK_RELIEF_SUNKEN: + break; + default: + relief = TK_RELIEF_FLAT; + break; + } + HtmlDrawRect(htmlPtr, drawable, src, + src->table.x - drawableLeft, + src->table.y - drawableTop, + src->table.w, + src->table.h, + src->table.borderWidth, + relief); + break; + } + case Html_TH: + case Html_TD: { + int depth, relief; + pTable = src->cell.pTable; + depth = pTable && pTable->table.borderWidth>0; + switch( htmlPtr->tableRelief ){ + case TK_RELIEF_RAISED: relief = TK_RELIEF_SUNKEN; break; + case TK_RELIEF_SUNKEN: relief = TK_RELIEF_RAISED; break; + default: relief = TK_RELIEF_FLAT; break; + } + HtmlDrawRect(htmlPtr, drawable, src, + src->cell.x - drawableLeft, + src->cell.y - drawableTop, + src->cell.w, + src->cell.h, + depth, + relief); + break; + } + case Html_IMG: + if( src->image.pImage ){ + HtmlDrawImage(src, drawable, drawableLeft, drawableTop, + drawableLeft + drawableWidth, + drawableTop + drawableHeight); + }else if( src->image.zAlt ){ + gc = HtmlGetGC(htmlPtr, src->base.style.color, src->base.style.font); + font = HtmlGetFont(htmlPtr, src->base.style.font); + if( font==0 ) return; + Tk_DrawChars(htmlPtr->display, + drawable, + gc, font, + src->image.zAlt, strlen(src->image.zAlt), + src->image.x - drawableLeft, + src->image.y - drawableTop); + TestPoint(0); + } + break; + default: + TestPoint(0); + break; + } + } +} + +/* +** Draw all or part of an image. +*/ +void HtmlDrawImage( + HtmlElement *pElem, /* The <IMG> to be drawn */ + Drawable drawable, /* Draw it here */ + int drawableLeft, /* left edge of the drawable */ + int drawableTop, /* Virtual canvas coordinate for top of drawable */ + int drawableRight, /* right edge of the drawable */ + int drawableBottom /* bottom edge of the drawable */ +){ + int imageTop; /* virtual canvas coordinate for top of image */ + int x, y; /* where to place image on the drawable */ + int imageX, imageY; /* \__ Subset of image that fits */ + int imageW, imageH; /* / on the drawable */ + + imageTop = pElem->image.y - pElem->image.ascent; + y = imageTop - drawableTop; + if( imageTop + pElem->image.h > drawableBottom ){ + imageH = drawableBottom - imageTop; + TestPoint(0); + }else{ + imageH = pElem->image.h; + TestPoint(0); + } + if( y<0 ){ + imageY = -y; + imageH += y; + y = 0; + TestPoint(0); + }else{ + imageY = 0; + TestPoint(0); + } + x = pElem->image.x - drawableLeft; + if( pElem->image.x + pElem->image.w > drawableRight ){ + imageW = drawableRight - pElem->image.x; + TestPoint(0); + }else{ + imageW = pElem->image.w; + TestPoint(0); + } + if( x<0 ){ + imageX = -x; + imageW += x; + x = 0; + TestPoint(0); + }else{ + imageX = 0; + TestPoint(0); + } + Tk_RedrawImage(pElem->image.pImage->image, imageX, imageY, imageW, imageH, + drawable, x, y); + pElem->image.redrawNeeded = 0; +} + +/* +** Recompute the following fields of the given block structure: +** +** base.count The number of elements described by this +** block structure. +** +** n The number of characters of text output +** associated with this block. If the block +** renders something other than text (ex: <IMG>) +** then set n to 0. +** +** z Pointer to malloced memory containing the +** text associated with this block. NULL if +** n is 0. +** +** Return a pointer to the first HtmlElement not covered by the +** block. +*/ +static HtmlElement *FillOutBlock(HtmlWidget *htmlPtr, HtmlBlock *p){ + HtmlElement *pElem; + int go; + int n; + int x, y; + int i; + HtmlStyle style; + int firstSelected; /* First selected character in this block */ + int lastSelected; /* Last selected character in this block */ + char zBuf[400]; + + /* + ** Reset n and z + */ + if( p->n ){ + p->n = 0; + } + if( p->z ){ + HtmlFree(p->z); + } + firstSelected = 1000000; + lastSelected = -1; + + /* + ** Skip over HtmlElements that aren't directly displayed. + */ + pElem = p->base.pNext; + p->base.count = 0; + while( pElem && (pElem->base.flags & HTML_Visible)==0 ){ + HtmlElement *pNext = pElem->pNext; + if( pElem->base.type==Html_Block ){ + UnlinkAndFreeBlock(htmlPtr, &pElem->block); + TestPoint(0); + }else{ + p->base.count++; + TestPoint(0); + } + pElem = pNext; + } + if( pElem==0 ){ TestPoint(0); return 0; } + + /* + ** Handle "special" elements. + */ + if( pElem->base.type!=Html_Text ){ + switch( pElem->base.type ){ + case Html_HR: + p->top = pElem->hr.y - pElem->hr.h; + p->bottom = pElem->hr.y; + p->left = pElem->hr.x; + p->right = pElem->hr.x + pElem->hr.w; + TestPoint(0); + break; + case Html_LI: + p->top = pElem->li.y - pElem->li.ascent; + p->bottom = pElem->li.y + pElem->li.descent; + p->left = pElem->li.x - 10; + p->right = pElem->li.x + 10; + TestPoint(0); + break; + case Html_TD: + case Html_TH: + p->top = pElem->cell.y; + p->bottom = pElem->cell.y + pElem->cell.h; + p->left = pElem->cell.x; + p->right = pElem->cell.x + pElem->cell.w; + TestPoint(0); + break; + case Html_TABLE: + p->top = pElem->table.y; + p->bottom = pElem->table.y + pElem->table.h; + p->left = pElem->table.x; + p->right = pElem->table.x + pElem->table.w; + TestPoint(0); + break; + case Html_IMG: + p->top = pElem->image.y - pElem->image.ascent; + p->bottom = pElem->image.y + pElem->image.descent; + p->left = pElem->image.x; + p->right = pElem->image.x + pElem->image.w; + TestPoint(0); + break; + } + p->base.count++; + TestPoint(0); + return pElem->pNext; + } + + /* + ** If we get this far, we must be dealing with text. + */ + n = 0; + x = pElem->text.x; + y = pElem->text.y; + p->top = y - pElem->text.ascent; + p->bottom = y + pElem->text.descent; + p->left = x; + style = pElem->base.style; + go = 1; + while( pElem ){ + HtmlElement *pNext = pElem->pNext; + switch( pElem->base.type ){ + case Html_Text: + if( pElem->base.style.flags & STY_Invisible ){ + TestPoint(0); + break; + } + if( pElem->text.spaceWidth <=0 ){ + CANT_HAPPEN; + break; + } + if( y != pElem->text.y + || style.font != pElem->base.style.font + || style.color != pElem->base.style.color + || (style.flags & STY_FontMask) + != (pElem->base.style.flags & STY_FontMask) + ){ + go = 0; + TestPoint(0); + }else{ + int sw = pElem->text.spaceWidth; + int nSpace = (pElem->text.x - x) / sw; + if( nSpace * sw + x != pElem->text.x ){ + go = 0; + TestPoint(0); + }else if( n + nSpace + pElem->base.count >= sizeof(zBuf) ){ + go = 0; + TestPoint(0); + }else{ + for(i=0; i<nSpace; i++){ + zBuf[n++] = ' '; + TestPoint(0); + } + strcpy(&zBuf[n], pElem->text.zText); + n += pElem->base.count; + x = pElem->text.x + pElem->text.w; + } + } + break; + + case Html_Space: + if( pElem->base.style.font != style.font ){ + pElem = pElem->pNext; + go = 0; + }else if( (style.flags & STY_Preformatted)!=0 + && (pElem->base.flags & HTML_NewLine)!=0 ){ + pElem = pElem->pNext; + go = 0; + } + break; + + case Html_Block: + UnlinkAndFreeBlock(htmlPtr,&pElem->block); + break; + + case Html_A: + case Html_EndA: + go = 0; + break; + + default: + if( pElem->base.flags & HTML_Visible ) go = 0; + TestPoint(0); + break; + } + if( go==0 ) break; + p->base.count++; + pElem = pNext; + } + p->right = x; + + while( n>0 && zBuf[n-1]==' ' ){ TestPoint(0); n--; } + p->z = HtmlAlloc( n ); + strncpy(p->z, zBuf, n); + p->n = n; + return pElem; +} + +/* +** Scan ahead looking for a place to put a block. Return a pointer +** to the element which should come immediately after the block. +** +** if pCnt!=0, then put the number of elements skipped in *pCnt. +*/ +static HtmlElement *FindStartOfNextBlock( + HtmlWidget *htmlPtr, /* The HTML widget */ + HtmlElement *p, /* First candid for the start of a block */ + int *pCnt /* Write number of elements skipped here */ +){ + int cnt = 0; + + while( p && (p->base.flags & HTML_Visible)==0 ){ + HtmlElement *pNext = p->pNext; + if( p->base.type==Html_Block ){ + UnlinkAndFreeBlock(htmlPtr, &p->block); + }else{ + cnt++; + } + p = pNext; + } + if( pCnt ){ *pCnt = cnt; } + return p; +} + + +/* +** Add additional blocks to the block list in order to cover +** all elements on the element list. +** +** If any old blocks are found on the element list, they must +** be left over from a prior rendering. Unlink and delete them. +*/ +void HtmlFormBlocks(HtmlWidget *htmlPtr){ + HtmlElement *pElem; + + if( htmlPtr->lastBlock ){ + pElem = FillOutBlock(htmlPtr, htmlPtr->lastBlock); + }else{ + pElem = htmlPtr->pFirst; + } + while( pElem ){ + int cnt; + pElem = FindStartOfNextBlock(htmlPtr, pElem, &cnt); + if( pElem ){ + HtmlBlock *pNew = AllocBlock(); + if( htmlPtr->lastBlock ){ + htmlPtr->lastBlock->base.count += cnt; + } + AppendBlock(htmlPtr, pElem, pNew); + pElem = FillOutBlock(htmlPtr, pNew); + } + } +} diff --git a/tkhtml1/src/htmldraw.h b/tkhtml1/src/htmldraw.h new file mode 100644 index 0000000..6768dd3 --- /dev/null +++ b/tkhtml1/src/htmldraw.h @@ -0,0 +1,482 @@ +/* This file was automatically generated. Do not edit! */ +typedef struct HtmlWidget HtmlWidget; +void HtmlFormBlocks(HtmlWidget *htmlPtr); +#define Html_EndA 6 +#define Html_A 5 +#define HTML_NewLine 0x02 /* type==Html_Space and ends with newline */ +#define STY_Preformatted 0x001 +#define Html_Space 2 +#define STY_StrikeThru 0x002 +#define STY_Underline 0x004 +#define STY_FontMask (STY_StrikeThru|STY_Underline) +#define STY_Invisible 0x040 +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +typedef union HtmlElement HtmlElement; +void HtmlDrawImage(HtmlElement *pElem,Drawable drawable,int drawableLeft,int drawableTop,int drawableRight,int drawableBottom); +#define Html_IMG 76 +#define Html_TD 131 +#define Html_TH 135 +#define Html_TABLE 129 +#define Html_HR 70 +#define LI_TYPE_Bullet3 3 /* A hollow square */ +#define LI_TYPE_Bullet2 2 /* A hollow circle */ +#define LI_TYPE_Bullet1 1 /* A solid circle */ +#define LI_TYPE_Undefined 0 /* If in HtmlLi, use the HtmlListStart value */ +#define LI_TYPE_Enum_i 8 /* Lower-case roman numerals */ +#define LI_TYPE_Enum_I 7 /* Capitalized roman numerals */ +#define LI_TYPE_Enum_a 6 /* a, b, c, ... */ +#define LI_TYPE_Enum_A 5 /* A, B, C, ... */ +#define LI_TYPE_Enum_1 4 /* Arabic numbers */ +#define Html_LI 81 +int HtmlUnlock(HtmlWidget *htmlPtr); +void HtmlLock(HtmlWidget *htmlPtr); +void HtmlTPCantHappen(const char *zFile,int line); +#if defined(COVERAGE_TEST) +# define CANT_HAPPEN HtmlTPCantHappen(__FILE__,__LINE__) +#endif +#if !(defined(COVERAGE_TEST)) +# define CANT_HAPPEN +#endif +#define HTML_Visible 0x01 /* This element produces "ink" */ +typedef struct HtmlBlock HtmlBlock; +void HtmlBlockDraw(HtmlWidget *htmlPtr,HtmlBlock *pBlock,Drawable drawable,int drawableLeft,int drawableTop,int drawableWidth,int drawableHeight); +int HtmlGetDarkShadowColor(HtmlWidget *htmlPtr,int iBgColor); +int HtmlGetLightShadowColor(HtmlWidget *htmlPtr,int iBgColor); +#define FONT_Any -1 +#define COLOR_Selection 3 /* Background color for the selection */ +GC HtmlGetGC(HtmlWidget *htmlPtr,int color,int font); +#define Html_Text 1 +Tk_Font HtmlGetFont(HtmlWidget *htmlPtr,int iFont); +#define HTML_Selected 0x04 /* Some or all of this Html_Block is selected */ +typedef struct HtmlBaseElement HtmlBaseElement; +typedef unsigned char Html_u8; +typedef short Html_16; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +typedef struct HtmlTextElement HtmlTextElement; +typedef int Html_32; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlMarkupElement HtmlMarkupElement; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +typedef unsigned short Html_u16; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +typedef struct HtmlImage HtmlImage; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +typedef struct HtmlScript HtmlScript; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +#define Html_TypeCount 151 +typedef struct HtmlStyleStack HtmlStyleStack; +typedef struct HtmlLayoutContext HtmlLayoutContext; +typedef struct HtmlMargin HtmlMargin; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +#define HtmlFree(A) Tcl_Free((char*)(A)) +#define Html_Block 4 +#define HtmlAlloc(A) ((void*)Tcl_Alloc(A)) +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/htmlexts.c b/tkhtml1/src/htmlexts.c new file mode 100644 index 0000000..9496972 --- /dev/null +++ b/tkhtml1/src/htmlexts.c @@ -0,0 +1,110 @@ +/* +** The extra routines for the HTML widget for Tcl/Tk +** +** Copyright (C) 1997-2000 Peter MacDonald and BrowseX Systems Inc. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** peter@browsex.com +** http://browsex.com +*/ + +#include <tk.h> +#include <string.h> +#include <stdlib.h> +#include "htmlexts.h" + +void HtmlTclizeAscii(Tcl_Interp *interp, HtmlIndex *s, HtmlIndex *e); + +/* +** WIDGET text ascii START END +*/ +int HtmlTextAsciiCmd( + HtmlWidget *htmlPtr, /* The HTML widget */ + Tcl_Interp *interp, /* The interpreter */ + int argc, /* Number of arguments */ + const char **argv /* List of all arguments */ +){ + HtmlIndex iStart, iEnd; + char *cb, *ce; + if (argc<=3) cb="begin"; else cb=(char*)argv[3]; + if (argc<=4) ce=cb; else ce=(char*)argv[4]; + + if( HtmlGetIndex(htmlPtr, cb, &iStart.p, &iStart.i)!=0 ){ + Tcl_AppendResult(interp,"malformed index: \"", cb, "\"", 0); + return TCL_ERROR; + } + if( HtmlGetIndex(htmlPtr, ce, &iEnd.p, &iEnd.i)!=0 ){ + Tcl_AppendResult(interp,"malformed index: \"", ce, "\"", 0); + return TCL_ERROR; + } + if (iEnd.p && iStart.p) { + if ((!iEnd.i) && (!strchr(ce,'.'))) { + iEnd.p=iEnd.p->pNext; + } + HtmlTclizeAscii(interp,&iStart,&iEnd); + } + return TCL_OK; +} + +/* +** Return all tokens between the two elements as a Text. +*/ +void HtmlTclizeAscii(Tcl_Interp *interp, HtmlIndex *s, HtmlIndex *e){ + int j, nsub=0; + HtmlElement* p=s->p; + Tcl_DString str; + if (p && p->base.type==Html_Text) { + nsub=s->i; + } + Tcl_DStringInit(&str); + while( p) { + switch( p->base.type ){ + case Html_Block: + break; + case Html_Text: + j=strlen(p->text.zText); + if (j<nsub) nsub=j; + if (p==e->p) { + j= (e->i-nsub+1); + } + Tcl_DStringAppend(&str, p->text.zText+nsub,j-nsub); + nsub=0; + break; + case Html_Space: + for (j=0; j< p->base.count; j++) { + if (nsub-->0) continue; + Tcl_DStringAppend(&str, " ", 1); + } + if ((p->base.flags & HTML_NewLine)!=0) + Tcl_DStringAppend(&str, "\n",1); + nsub=0; + break; + case Html_P: + case Html_BR: + Tcl_DStringAppend(&str, "\n",1); + break; + case Html_Unknown: + break; + default: + break; + } + if (p==e->p) break; + p = p->pNext; + } + Tcl_DStringResult(interp, &str); +} diff --git a/tkhtml1/src/htmlexts.h b/tkhtml1/src/htmlexts.h new file mode 100644 index 0000000..e94edde --- /dev/null +++ b/tkhtml1/src/htmlexts.h @@ -0,0 +1,438 @@ +/* This file was automatically generated. Do not edit! */ +#define Html_Unknown 3 +#define Html_BR 24 +#define Html_P 104 +#define HTML_NewLine 0x02 /* type==Html_Space and ends with newline */ +#define Html_Space 2 +#define Html_Block 4 +#define Html_Text 1 +typedef union HtmlElement HtmlElement; +typedef struct HtmlBaseElement HtmlBaseElement; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +typedef unsigned char Html_u8; +typedef short Html_16; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +typedef struct HtmlTextElement HtmlTextElement; +typedef int Html_32; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlMarkupElement HtmlMarkupElement; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +typedef unsigned short Html_u16; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +typedef struct HtmlImage HtmlImage; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +typedef struct HtmlWidget HtmlWidget; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +typedef struct HtmlScript HtmlScript; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +typedef struct HtmlBlock HtmlBlock; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +int HtmlGetIndex(HtmlWidget *htmlPtr,const char *zIndex,HtmlElement **ppToken,int *pIndex); +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +#define Html_TypeCount 151 +typedef struct HtmlStyleStack HtmlStyleStack; +typedef struct HtmlLayoutContext HtmlLayoutContext; +typedef struct HtmlMargin HtmlMargin; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +int HtmlTextAsciiCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +void HtmlTclizeAscii(Tcl_Interp *interp,HtmlIndex *s,HtmlIndex *e); +void HtmlTclizeAscii(Tcl_Interp *interp,HtmlIndex *s,HtmlIndex *e); +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/htmlform.c b/tkhtml1/src/htmlform.c new file mode 100644 index 0000000..210ae62 --- /dev/null +++ b/tkhtml1/src/htmlform.c @@ -0,0 +1,606 @@ +/* +** Routines used for processing HTML makeup for forms. +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <tk.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include "htmlform.h" + +/* +** Unmap any input control that is currently mapped. +*/ +void HtmlUnmapControls(HtmlWidget *htmlPtr){ + HtmlElement *p; + + for(p=htmlPtr->firstInput; p; p=p->input.pNext){ + if( p->input.tkwin!=0 && Tk_IsMapped(p->input.tkwin) ){ + Tk_UnmapWindow(p->input.tkwin); + } + } +} + +/* +** Map any control that should be visible according to the +** current scroll position. At the same time, if any controls that +** should not be visible are mapped, unmap them. After this routine +** finishes, all <INPUT> controls should be in their proper places +** regardless of where they might have been before. +** +** Return the number of controls that are currently visible. +*/ +int HtmlMapControls(HtmlWidget *htmlPtr){ + HtmlElement *p; /* For looping over all controls */ + int x, y, w, h; /* Part of the virtual canvas that is visible */ + int cnt = 0; /* Number of visible controls */ + + x = htmlPtr->xOffset; + y = htmlPtr->yOffset; + w = Tk_Width(htmlPtr->clipwin); + h = Tk_Height(htmlPtr->clipwin); + for(p=htmlPtr->firstInput; p; p=p->input.pNext){ + if( p->input.tkwin==0 ) continue; + if( p->input.y < y+h + && p->input.y + p->input.h > y + && p->input.x < x+w + && p->input.x + p->input.w > x + ){ + /* The control should be visible. Make is so if it isn't already */ + Tk_MoveResizeWindow(p->input.tkwin, + p->input.x - x, p->input.y - y, + p->input.w, p->input.h); + if( !Tk_IsMapped(p->input.tkwin) ){ + Tk_MapWindow(p->input.tkwin); + } + cnt++; + }else{ + /* This control should not be visible. Unmap it. */ + if( Tk_IsMapped(p->input.tkwin) ){ + Tk_UnmapWindow(p->input.tkwin); + } + } + } + return cnt; +} + +/* +** Delete all input controls. This happens when the HTML widget +** is cleared. +** +** When the TCL "exit" command is invoked, the order of operations +** here is very touchy. +*/ +void HtmlDeleteControls(HtmlWidget *htmlPtr){ + HtmlElement *p; /* For looping over all controls */ + Tcl_Interp *interp; /* The interpreter */ + + interp = htmlPtr->interp; + p = htmlPtr->firstInput; + htmlPtr->firstInput = 0; + htmlPtr->lastInput = 0; + htmlPtr->nInput = 0; + if( p==0 || htmlPtr->tkwin==0 ) return; + HtmlLock(htmlPtr); + for(; p; p=p->input.pNext){ + if( p->input.pForm && p->input.pForm->form.id>0 + && htmlPtr->zFormCommand && htmlPtr->zFormCommand[0] + && !Tcl_InterpDeleted(interp) && htmlPtr->clipwin ){ + Tcl_DString cmd; + int result; + char zBuf[60]; + Tcl_DStringInit(&cmd); + Tcl_DStringAppend(&cmd, htmlPtr->zFormCommand, -1); + sprintf(zBuf," %d flush", p->input.pForm->form.id); + Tcl_DStringAppend(&cmd, zBuf, -1); + result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd)); + Tcl_DStringFree(&cmd); + if( !Tcl_InterpDeleted(interp) ){ + if( result != TCL_OK ){ + Tcl_AddErrorInfo(htmlPtr->interp, + "\n (-formcommand flush callback executed by html widget)"); + Tcl_BackgroundError(htmlPtr->interp); + TestPoint(0); + } + Tcl_ResetResult(htmlPtr->interp); + } + p->input.pForm->form.id = 0; + } + if( p->input.tkwin ){ + if( htmlPtr->clipwin!=0 ) Tk_DestroyWindow(p->input.tkwin); + p->input.tkwin = 0; + } + p->input.sized = 0; + } + HtmlUnlock(htmlPtr); +} + +/* +** Return an appropriate type value for the given <INPUT> markup. +*/ +static int InputType(HtmlElement *p){ + int type = INPUT_TYPE_Unknown; + char *z; + int i; + static struct { + char *zName; + int type; + } types[] = { + { "checkbox", INPUT_TYPE_Checkbox }, + { "file", INPUT_TYPE_File }, + { "hidden", INPUT_TYPE_Hidden }, + { "image", INPUT_TYPE_Image }, + { "password", INPUT_TYPE_Password }, + { "radio", INPUT_TYPE_Radio }, + { "reset", INPUT_TYPE_Reset }, + { "submit", INPUT_TYPE_Submit }, + { "text", INPUT_TYPE_Text }, + }; + + switch( p->base.type ){ + case Html_INPUT: + z = HtmlMarkupArg(p, "type", "text"); + if( z==0 ){ TestPoint(0); break; } + for(i=0; i<sizeof(types)/sizeof(types[0]); i++){ + if( stricmp(types[i].zName,z)==0 ){ + type = types[i].type; + TestPoint(0); + break; + } + TestPoint(0); + } + break; + case Html_SELECT: + type = INPUT_TYPE_Select; + TestPoint(0); + break; + case Html_TEXTAREA: + type = INPUT_TYPE_TextArea; + TestPoint(0); + break; + case Html_APPLET: + case Html_IFRAME: + case Html_EMBED: + type = INPUT_TYPE_Applet; + TestPoint(0); + break; + default: + CANT_HAPPEN; + break; + } + return type; +} + +/* +** Create the window name for a child widget. Space to hold the name +** is obtained from HtmlAlloc() and must be freed by the calling function. +*/ +static char *MakeWindowName( + HtmlWidget *htmlPtr, /* The HTML widget */ + HtmlElement *pElem /* The input that needs a child widget */ +){ + int n; + char *zBuf; + + n = strlen(Tk_PathName(htmlPtr->clipwin)); + zBuf = HtmlAlloc( n + 20 ); + sprintf(zBuf,"%s.x%d",Tk_PathName(htmlPtr->clipwin), pElem->input.cnt); + return zBuf; +} + +/* +** A Input element is the input. Mark this element as being +** empty. It has no widget and doesn't appear on the screen. +** +** This is called for HIDDEN inputs or when the -formcommand +** callback doesn't create the widget. +*/ +static void EmptyInput(HtmlElement *pElem){ + pElem->input.tkwin = 0; + pElem->input.w = 0; + pElem->input.h = 0; + pElem->base.flags &= !HTML_Visible; + pElem->base.style.flags |= STY_Invisible; + pElem->input.sized = 1; +} + +/* +** This routine is called when one of the child windows for a form +** wants to change its size. +*/ +static void HtmlInputRequestProc(ClientData clientData, Tk_Window tkwin){ + HtmlElement *pElem = (HtmlElement*)clientData; + if( pElem->base.type!=Html_INPUT ){ CANT_HAPPEN; return; } + if( pElem->input.tkwin!=tkwin ){ CANT_HAPPEN; return; } + pElem->input.w = Tk_ReqWidth(tkwin); + pElem->input.h = Tk_ReqHeight(tkwin); + if( pElem->input.htmlPtr && pElem->input.htmlPtr->tkwin!=0 ){ + pElem->input.htmlPtr->flags |= RELAYOUT; + HtmlScheduleRedraw(pElem->input.htmlPtr); + } +} + +/* +** This routine is called when another entity takes over geometry +** management for a widget corresponding to an input element. +*/ +static void HtmlInputLostSlaveProc(ClientData clientData, Tk_Window tkwin){ + HtmlElement *pElem = (HtmlElement*)clientData; + if( pElem->base.type!=Html_INPUT ){ CANT_HAPPEN; return; } + if( pElem->input.tkwin!=tkwin ){ CANT_HAPPEN; return; } + EmptyInput(pElem); + if( pElem->input.htmlPtr && pElem->input.htmlPtr->tkwin!=0 ){ + pElem->input.htmlPtr->flags |= RELAYOUT; + HtmlScheduleRedraw(pElem->input.htmlPtr); + } +} + +/* +** This routine catches DestroyNotify events on a INPUT window so +** that we will know the window is been deleted. +*/ +static void HtmlInputEventProc(ClientData clientData, XEvent *eventPtr){ + HtmlElement *pElem = (HtmlElement*)clientData; + /* if( pElem->base.type!=Html_INPUT ){ CANT_HAPPEN; return; } */ + if( eventPtr->type==DestroyNotify ){ + EmptyInput(pElem); + if( pElem->input.htmlPtr && pElem->input.htmlPtr->tkwin!=0 ){ + pElem->input.htmlPtr->flags |= RELAYOUT; + HtmlScheduleRedraw(pElem->input.htmlPtr); + } + } +} + +/* +** The geometry manager for the HTML widget +*/ +static Tk_GeomMgr htmlGeomType = { + "html", /* Name */ + HtmlInputRequestProc, /* Called when widget changes size */ + HtmlInputLostSlaveProc, /* Called when someone else takes over management */ +}; + +/* +** zWin is the name of a child widget that is used to implement an +** input element. Query Tk for information about this widget (such +** as its size) and put that information in the pElem structure +** that represents the input. +*/ +static void SizeAndLink(HtmlWidget *htmlPtr, char *zWin, HtmlElement *pElem){ + pElem->input.tkwin = Tk_NameToWindow(htmlPtr->interp, zWin, htmlPtr->clipwin); + if( pElem->input.tkwin==0 ){ + Tcl_ResetResult(htmlPtr->interp); + EmptyInput(pElem); + }else if( pElem->input.type==INPUT_TYPE_Hidden ){ + pElem->input.w = 0; + pElem->input.h = 0; + pElem->base.flags &= !HTML_Visible; + pElem->base.style.flags |= STY_Invisible; + }else{ + pElem->input.w = Tk_ReqWidth(pElem->input.tkwin); + pElem->input.h = Tk_ReqHeight(pElem->input.tkwin); + pElem->base.flags |= HTML_Visible; + pElem->input.htmlPtr = htmlPtr; + Tk_ManageGeometry(pElem->input.tkwin, &htmlGeomType, pElem); + Tk_CreateEventHandler(pElem->input.tkwin, StructureNotifyMask, + HtmlInputEventProc, pElem); + } + pElem->input.pNext = 0; + if( htmlPtr->firstInput==0 ){ + htmlPtr->firstInput = pElem; + }else{ + htmlPtr->lastInput->input.pNext = pElem; + } + htmlPtr->lastInput = pElem; + pElem->input.sized = 1; +} + +/* Append all text and space tokens between pStart and pEnd to +** the given Tcl_DString. +*/ +static void HtmlAppendText( + Tcl_DString *str, /* Append the text here */ + HtmlElement *pFirst, /* The first token */ + HtmlElement *pEnd /* The last token */ +){ + while( pFirst && pFirst!=pEnd ){ + switch( pFirst->base.type ){ + case Html_Text: { + Tcl_DStringAppend(str, pFirst->text.zText, -1); + break; + } + case Html_Space: { + if( pFirst->base.flags & HTML_NewLine ){ + Tcl_DStringAppend(str, "\n", 1); + }else{ + int cnt; + static char zSpaces[] = " "; + cnt = pFirst->base.count; + while( cnt>sizeof(zSpaces)-1 ){ + Tcl_DStringAppend(str, zSpaces, sizeof(zSpaces)-1); + cnt -= sizeof(zSpaces)-1; + } + if( cnt>0 ){ + Tcl_DStringAppend(str, zSpaces, cnt); + } + } + break; + } + default: + /* Do nothing */ + break; + } + pFirst = pFirst->pNext; + } +} + +/* +** The "p" argument points to a <select>. This routine scans all +** subsequent elements (up to the next </select>) looking for +** <option> tags. For each option tag, it appends three elements +** to the "str" DString: +** +** * 1 or 0 to indicated whether or not the element is +** selected. +** +** * The value returned if this element is selected. +** +** * The text displayed for this element. +*/ +static void AddSelectOptions( + Tcl_DString *str, /* Add text here */ + HtmlElement *p, /* The <SELECT> markup */ + HtmlElement *pEnd /* The </SELECT> markup */ +){ + while( p && p!=pEnd && p->base.type!=Html_EndSELECT ){ + if( p->base.type==Html_OPTION ){ + char *zValue; + Tcl_DStringStartSublist(str); + if( HtmlMarkupArg(p, "selected", 0)==0 ){ + Tcl_DStringAppend(str, "0 ", 2); + }else{ + Tcl_DStringAppend(str, "1 ", 2); + } + zValue = HtmlMarkupArg(p, "value", ""); + Tcl_DStringAppendElement(str, zValue); + Tcl_DStringStartSublist(str); + p = p->pNext; + while( p && p!=pEnd && p->base.type!=Html_EndOPTION + && p->base.type!=Html_OPTION && p->base.type!=Html_EndSELECT ){ + if( p->base.type==Html_Text ){ + Tcl_DStringAppend(str, p->text.zText, -1); + }else if( p->base.type==Html_Space ){ + Tcl_DStringAppend(str, " ", 1); + } + p = p->pNext; + } + Tcl_DStringEndSublist(str); + Tcl_DStringEndSublist(str); + }else{ + p = p->pNext; + } + } +} + +/* +** This routine implements the Sizer() function for <INPUT>, +** <SELECT> and <TEXTAREA> markup. +** +** A side effect of sizing these markups is that widgets are +** created to represent the corresponding input controls. +** +** The function normally returns 0. But if it is dealing with +** a <SELECT> or <TEXTAREA> that is incomplete, 1 is returned. +** In that case, the sizer will be called again at some point in +** the future when more information is available. +*/ +int HtmlControlSize(HtmlWidget *htmlPtr, HtmlElement *pElem){ + char *zWin; /* Name of child widget that implements this input */ + int incomplete = 0; /* True if data is incomplete */ + Tcl_DString cmd; /* The complete -formcommand callback */ + + if( pElem->input.sized ) return 0; + pElem->input.type = InputType(pElem); + switch( pElem->input.type ){ + case INPUT_TYPE_Checkbox: + case INPUT_TYPE_Hidden: + case INPUT_TYPE_Image: + case INPUT_TYPE_Radio: + case INPUT_TYPE_Reset: + case INPUT_TYPE_Submit: + case INPUT_TYPE_Text: + case INPUT_TYPE_Password: + case INPUT_TYPE_File: { + int result; + char zToken[50]; + + if( pElem->input.pForm==0 || htmlPtr->zFormCommand==0 + || htmlPtr->zFormCommand[0]==0 ){ + EmptyInput(pElem); + break; + } + Tcl_DStringInit(&cmd); + Tcl_DStringAppend(&cmd, htmlPtr->zFormCommand, -1); + sprintf(zToken," %d input ",pElem->input.pForm->form.id); + Tcl_DStringAppend(&cmd, zToken, -1); + pElem->input.cnt = ++htmlPtr->nInput; + zWin = MakeWindowName(htmlPtr, pElem); + Tcl_DStringAppend(&cmd, zWin, -1); + Tcl_DStringStartSublist(&cmd); + HtmlAppendArglist(&cmd, pElem); + Tcl_DStringEndSublist(&cmd); + HtmlLock(htmlPtr); + result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd)); + Tcl_DStringFree(&cmd); + if( !HtmlUnlock(htmlPtr) ){ + SizeAndLink(htmlPtr, zWin, pElem); + } + HtmlFree(zWin); + break; + } + case INPUT_TYPE_Select: { + int result; + char zToken[50]; + + if( pElem->input.pForm==0 || htmlPtr->zFormCommand==0 + || htmlPtr->zFormCommand[0]==0 ){ + EmptyInput(pElem); + break; + } + Tcl_DStringInit(&cmd); + Tcl_DStringAppend(&cmd, htmlPtr->zFormCommand, -1); + sprintf(zToken," %d select ",pElem->input.pForm->form.id); + Tcl_DStringAppend(&cmd, zToken, -1); + pElem->input.cnt = ++htmlPtr->nInput; + zWin = MakeWindowName(htmlPtr, pElem); + Tcl_DStringAppend(&cmd, zWin, -1); + Tcl_DStringStartSublist(&cmd); + HtmlAppendArglist(&cmd, pElem); + Tcl_DStringEndSublist(&cmd); + Tcl_DStringStartSublist(&cmd); + AddSelectOptions(&cmd, pElem, pElem->input.pEnd); + Tcl_DStringEndSublist(&cmd); + HtmlLock(htmlPtr); + result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd)); + Tcl_DStringFree(&cmd); + if( !HtmlUnlock(htmlPtr) ){ + SizeAndLink(htmlPtr, zWin, pElem); + } + HtmlFree(zWin); + break; + } + case INPUT_TYPE_TextArea: { + int result; + char zToken[50]; + + if( pElem->input.pForm==0 || htmlPtr->zFormCommand==0 + || htmlPtr->zFormCommand[0]==0 ){ + EmptyInput(pElem); + break; + } + Tcl_DStringInit(&cmd); + Tcl_DStringAppend(&cmd, htmlPtr->zFormCommand, -1); + sprintf(zToken," %d textarea ",pElem->input.pForm->form.id); + Tcl_DStringAppend(&cmd, zToken, -1); + pElem->input.cnt = ++htmlPtr->nInput; + zWin = MakeWindowName(htmlPtr, pElem); + Tcl_DStringAppend(&cmd, zWin, -1); + Tcl_DStringStartSublist(&cmd); + HtmlAppendArglist(&cmd, pElem); + Tcl_DStringEndSublist(&cmd); + Tcl_DStringStartSublist(&cmd); + HtmlAppendText(&cmd, pElem, pElem->input.pEnd); + Tcl_DStringEndSublist(&cmd); + HtmlLock(htmlPtr); + result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd)); + Tcl_DStringFree(&cmd); + if( !HtmlUnlock(htmlPtr) ){ + SizeAndLink(htmlPtr, zWin, pElem); + } + HtmlFree(zWin); + break; + } + case INPUT_TYPE_Applet: { + int result; + + if( htmlPtr->zAppletCommand==0 || htmlPtr->zAppletCommand[0]==0 ){ + EmptyInput(pElem); + break; + } + Tcl_DStringInit(&cmd); + Tcl_DStringAppend(&cmd, htmlPtr->zAppletCommand, -1); + Tcl_DStringAppend(&cmd, " ", 1); + pElem->input.cnt = ++htmlPtr->nInput; + zWin = MakeWindowName(htmlPtr, pElem); + Tcl_DStringAppend(&cmd, zWin, -1); + Tcl_DStringStartSublist(&cmd); + HtmlAppendArglist(&cmd, pElem); + Tcl_DStringEndSublist(&cmd); + HtmlLock(htmlPtr); + result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd)); + Tcl_DStringFree(&cmd); + if( !HtmlUnlock(htmlPtr) ){ + SizeAndLink(htmlPtr, zWin, pElem); + } + HtmlFree(zWin); + break; + } + default: { + CANT_HAPPEN; + pElem->base.flags &= ~HTML_Visible; + pElem->base.style.flags |= STY_Invisible; + pElem->input.tkwin = 0; + break; + } + } + return incomplete; +} + +#if 0 +/* +** The following array determines which characters can be put directly +** in a query string and which must be escaped. +*/ +static char needEscape[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, +}; +#define NeedToEscape(C) ((C)>0 && (C)<127 && needEscape[(int)(C)]) + +/* +** Append to the given DString, an encoded version of the given +** text. +*/ +static void EncodeText(Tcl_DString *str, char *z){ + int i; + while( *z ){ + for(i=0; z[i] && !NeedToEscape(z[i]); i++){ TestPoint(0); } + if( i>0 ){ TestPoint(0); Tcl_DStringAppend(str, z, i); } + z += i; + while( *z && NeedToEscape(*z) ){ + if( *z==' ' ){ + Tcl_DStringAppend(str,"+",1); + TestPoint(0); + }else if( *z=='\n' ){ + Tcl_DStringAppend(str, "%0D%0A", 6); + TestPoint(0); + }else if( *z=='\r' ){ + /* Ignore it... */ + TestPoint(0); + }else{ + char zBuf[5]; + sprintf(zBuf,"%%%02X",0xff & *z); + Tcl_DStringAppend(str, zBuf, 3); + TestPoint(0); + } + z++; + } + } +} +#endif diff --git a/tkhtml1/src/htmlform.h b/tkhtml1/src/htmlform.h new file mode 100644 index 0000000..c6b1671 --- /dev/null +++ b/tkhtml1/src/htmlform.h @@ -0,0 +1,483 @@ +/* This file was automatically generated. Do not edit! */ +#define HtmlFree(A) Tcl_Free((char*)(A)) +typedef union HtmlElement HtmlElement; +void HtmlAppendArglist(Tcl_DString *str,HtmlElement *pElem); +typedef struct HtmlWidget HtmlWidget; +int HtmlControlSize(HtmlWidget *htmlPtr,HtmlElement *pElem); +#define Html_EndOPTION 103 +#define Html_OPTION 102 +#define Html_EndSELECT 117 +#define HTML_NewLine 0x02 /* type==Html_Space and ends with newline */ +#define Html_Space 2 +#define Html_Text 1 +void HtmlScheduleRedraw(HtmlWidget *htmlPtr); +#define RELAYOUT 0x000010 +#define STY_Invisible 0x040 +#define HTML_Visible 0x01 /* This element produces "ink" */ +#define HtmlAlloc(A) ((void*)Tcl_Alloc(A)) +void HtmlTPCantHappen(const char *zFile,int line); +#if defined(COVERAGE_TEST) +# define CANT_HAPPEN HtmlTPCantHappen(__FILE__,__LINE__) +#endif +#if !(defined(COVERAGE_TEST)) +# define CANT_HAPPEN +#endif +#define INPUT_TYPE_Applet 12 +#define Html_EMBED 49 +#define Html_IFRAME 75 +#define Html_APPLET 9 +#define INPUT_TYPE_TextArea 11 +#define Html_TEXTAREA 133 +#define INPUT_TYPE_Select 8 +#define Html_SELECT 116 +#if !defined(HAVE_STRICMP) +# define stricmp strcasecmp +#endif +char *HtmlMarkupArg(HtmlElement *p,const char *tag,char *zDefault); +#define Html_INPUT 77 +#define INPUT_TYPE_Text 10 +#define INPUT_TYPE_Submit 9 +#define INPUT_TYPE_Reset 7 +#define INPUT_TYPE_Radio 6 +#define INPUT_TYPE_Password 5 +#define INPUT_TYPE_Image 4 +#define INPUT_TYPE_Hidden 3 +#define INPUT_TYPE_File 2 +#define INPUT_TYPE_Checkbox 1 +#define INPUT_TYPE_Unknown 0 +int HtmlUnlock(HtmlWidget *htmlPtr); +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +void HtmlLock(HtmlWidget *htmlPtr); +void HtmlDeleteControls(HtmlWidget *htmlPtr); +int HtmlMapControls(HtmlWidget *htmlPtr); +typedef struct HtmlBaseElement HtmlBaseElement; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +typedef unsigned char Html_u8; +typedef short Html_16; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +typedef struct HtmlTextElement HtmlTextElement; +typedef int Html_32; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlMarkupElement HtmlMarkupElement; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +typedef unsigned short Html_u16; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +typedef struct HtmlImage HtmlImage; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +typedef struct HtmlScript HtmlScript; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +typedef struct HtmlBlock HtmlBlock; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +#define Html_TypeCount 151 +typedef struct HtmlStyleStack HtmlStyleStack; +typedef struct HtmlLayoutContext HtmlLayoutContext; +typedef struct HtmlMargin HtmlMargin; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +void HtmlUnmapControls(HtmlWidget *htmlPtr); +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/htmlimage.c b/tkhtml1/src/htmlimage.c new file mode 100644 index 0000000..962ac5c --- /dev/null +++ b/tkhtml1/src/htmlimage.c @@ -0,0 +1,225 @@ +/* +** Routines used for processing <IMG> markup +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <tk.h> +#include <string.h> +#include <stdlib.h> +#include "htmlimage.h" + +/* +** Find the alignment for an image +*/ +int HtmlGetImageAlignment(HtmlElement *p){ + char *z; + int i; + int result; + + static struct { + char *zName; + int iValue; + } aligns[] = { + { "bottom", IMAGE_ALIGN_Bottom }, + { "baseline", IMAGE_ALIGN_Bottom }, + { "middle", IMAGE_ALIGN_Middle }, + { "top", IMAGE_ALIGN_Top }, + { "absbottom", IMAGE_ALIGN_AbsBottom }, + { "absmiddle", IMAGE_ALIGN_AbsMiddle }, + { "texttop", IMAGE_ALIGN_TextTop }, + { "left", IMAGE_ALIGN_Left }, + { "right", IMAGE_ALIGN_Right }, + }; + + z = HtmlMarkupArg(p, "align", 0); + result = IMAGE_ALIGN_Bottom; + if( z ){ + for(i=0; i<sizeof(aligns)/sizeof(aligns[0]); i++){ + if( stricmp(aligns[i].zName,z)==0 ){ + result = aligns[i].iValue; + TestPoint(0); + break; + }else{ + TestPoint(0); + } + } + }else{ + TestPoint(0); + } + return result; +} + +/* +** This routine is called when an image changes. If the size of the +** images changes, then we need to completely redo the layout. If +** only the appearance changes, then this works like an expose event. +*/ +static void ImageChangeProc( + ClientData clientData, /* Pointer to an HtmlImage structure */ + int x, /* Left edge of region that changed */ + int y, /* Top edge of region that changed */ + int w, /* Width of region that changes. Maybe 0 */ + int h, /* Height of region that changed. Maybe 0 */ + int newWidth, /* New width of the image */ + int newHeight /* New height of the image */ +){ + HtmlImage *pImage; + HtmlWidget *htmlPtr; + HtmlElement *pElem; + + pImage = (HtmlImage*)clientData; + htmlPtr = pImage->htmlPtr; + if( pImage->w!=newWidth || pImage->h!=newHeight ){ + /* We have to completely redo the layout after adjusting the size + ** of the images */ + for(pElem = pImage->pList; pElem; pElem = pElem->image.pNext){ + pElem->image.w = newWidth; + pElem->image.h = newHeight; + TestPoint(0); + } + htmlPtr->flags |= RELAYOUT; + pImage->w = newWidth; + pImage->h = newHeight; + HtmlRedrawEverything(htmlPtr); + }else{ + for(pElem = pImage->pList; pElem; pElem = pElem->image.pNext){ + pElem->image.redrawNeeded = 1; + } + htmlPtr->flags |= REDRAW_IMAGES; + HtmlScheduleRedraw(htmlPtr); + } +} + +/* +** Append all the arguments of the given markup to the given +** DString. +** +** Example: If the markup is <IMG SRC=image.gif ALT="hello!"> +** then the following text is appended to the DString: +** +** "src image.gif alt hello!" +** +** Notice how all attribute names are converted to lower case. +** This conversion happens in the parser. +*/ +void HtmlAppendArglist(Tcl_DString *str, HtmlElement *pElem){ + int i; + for(i=0; i+1<pElem->base.count; i+=2){ + char *z = pElem->markup.argv[i+1]; + Tcl_DStringAppendElement(str, pElem->markup.argv[i]); + Tcl_DStringAppendElement(str, z); + } +} + +/* +** Given an <IMG> markup, find or create an appropriate HtmlImage +** structure and return a pointer to that structure. NULL might +** be returned. +** +** This routine may invoke a callback procedure which could delete +** the HTML widget. Use HtmlLock() if necessary to preserve the +** widget structure. +*/ +HtmlImage *HtmlGetImage(HtmlWidget *htmlPtr, HtmlElement *p){ + char *zWidth; + char *zHeight; + char *zSrc; + char *zImageName; + HtmlImage *pImage; + int result; + Tcl_DString cmd; + int lenSrc, lenW, lenH; /* Lengths of various strings */ + + if( p->base.type!=Html_IMG ){ CANT_HAPPEN; return 0; } + if( htmlPtr->zGetImage==0 || htmlPtr->zGetImage[0]==0 ){ + TestPoint(0); + return 0; + } + zSrc = HtmlMarkupArg(p, "src", 0); + if( zSrc==0 ){ + return 0; + } + HtmlLock(htmlPtr); + zSrc = HtmlResolveUri(htmlPtr, zSrc); + if( HtmlUnlock(htmlPtr) || zSrc==0 ) return 0; + zWidth = HtmlMarkupArg(p, "width", ""); + zHeight = HtmlMarkupArg(p, "height", ""); + for(pImage=htmlPtr->imageList; pImage; pImage=pImage->pNext){ + if( strcmp(pImage->zUrl,zSrc)==0 + && strcmp(pImage->zWidth, zWidth)==0 + && strcmp(pImage->zHeight, zHeight)==0 ){ + HtmlFree(zSrc); + return pImage; + } + } + Tcl_DStringInit(&cmd); + Tcl_DStringAppend(&cmd, htmlPtr->zGetImage, -1); + Tcl_DStringAppendElement(&cmd,zSrc); + Tcl_DStringAppendElement(&cmd,zWidth); + Tcl_DStringAppendElement(&cmd,zHeight); + Tcl_DStringStartSublist(&cmd); + HtmlAppendArglist(&cmd, p); + Tcl_DStringEndSublist(&cmd); + HtmlLock(htmlPtr); + result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd)); + Tcl_DStringFree(&cmd); + if( HtmlUnlock(htmlPtr) ){ + HtmlFree(zSrc); + } + zImageName = (char*)Tcl_GetStringResult(htmlPtr->interp); + lenSrc = strlen(zSrc); + lenW = strlen(zWidth); + lenH = strlen(zHeight); + pImage = HtmlAlloc( sizeof(HtmlImage) + lenSrc + lenW + lenH + 3 ); + memset(pImage,0,sizeof(HtmlImage)); + pImage->htmlPtr = htmlPtr; + pImage->zUrl = (char*)&pImage[1]; + strcpy(pImage->zUrl,zSrc); + HtmlFree(zSrc); + pImage->zWidth = &pImage->zUrl[lenSrc+1]; + strcpy(pImage->zWidth, zWidth); + pImage->zHeight = &pImage->zWidth[lenW+1]; + strcpy(pImage->zHeight, zHeight); + pImage->w = 0; + pImage->h = 0; + if( result==TCL_OK ){ + pImage->image = Tk_GetImage(htmlPtr->interp, htmlPtr->clipwin, + zImageName, ImageChangeProc, pImage); + TestPoint(0); + }else{ + Tcl_AddErrorInfo(htmlPtr->interp, + "\n (\"-imagecommand\" command executed by html widget)"); + Tcl_BackgroundError(htmlPtr->interp); + pImage->image = 0; + TestPoint(0); + } + if( pImage->image==0 ){ + HtmlFree((char*)pImage); + TestPoint(0); + return 0; + } + pImage->pNext = htmlPtr->imageList; + htmlPtr->imageList = pImage; + TestPoint(0); + Tcl_ResetResult(htmlPtr->interp); + return pImage; +} diff --git a/tkhtml1/src/htmlimage.h b/tkhtml1/src/htmlimage.h new file mode 100644 index 0000000..bbb5703 --- /dev/null +++ b/tkhtml1/src/htmlimage.h @@ -0,0 +1,466 @@ +/* This file was automatically generated. Do not edit! */ +#define HtmlAlloc(A) ((void*)Tcl_Alloc(A)) +#define HtmlFree(A) Tcl_Free((char*)(A)) +typedef struct HtmlWidget HtmlWidget; +int HtmlUnlock(HtmlWidget *htmlPtr); +char *HtmlResolveUri(HtmlWidget *htmlPtr,char *zUri); +void HtmlLock(HtmlWidget *htmlPtr); +void HtmlTPCantHappen(const char *zFile,int line); +#if defined(COVERAGE_TEST) +# define CANT_HAPPEN HtmlTPCantHappen(__FILE__,__LINE__) +#endif +#if !(defined(COVERAGE_TEST)) +# define CANT_HAPPEN +#endif +#define Html_IMG 76 +typedef struct HtmlImage HtmlImage; +typedef union HtmlElement HtmlElement; +HtmlImage *HtmlGetImage(HtmlWidget *htmlPtr,HtmlElement *p); +void HtmlAppendArglist(Tcl_DString *str,HtmlElement *pElem); +void HtmlScheduleRedraw(HtmlWidget *htmlPtr); +#define REDRAW_IMAGES 0x002000 +void HtmlRedrawEverything(HtmlWidget *htmlPtr); +#define RELAYOUT 0x000010 +typedef struct HtmlBlock HtmlBlock; +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +typedef short Html_16; +typedef struct HtmlScript HtmlScript; +#define Html_TypeCount 151 +typedef struct HtmlStyleStack HtmlStyleStack; +typedef struct HtmlLayoutContext HtmlLayoutContext; +typedef struct HtmlMargin HtmlMargin; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +typedef unsigned char Html_u8; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +typedef int Html_32; +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +#if !defined(HAVE_STRICMP) +# define stricmp strcasecmp +#endif +char *HtmlMarkupArg(HtmlElement *p,const char *tag,char *zDefault); +#define IMAGE_ALIGN_Right 7 +#define IMAGE_ALIGN_Left 6 +#define IMAGE_ALIGN_TextTop 3 +#define IMAGE_ALIGN_AbsMiddle 4 +#define IMAGE_ALIGN_AbsBottom 5 +#define IMAGE_ALIGN_Top 2 +#define IMAGE_ALIGN_Middle 1 +#define IMAGE_ALIGN_Bottom 0 +typedef struct HtmlBaseElement HtmlBaseElement; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +typedef struct HtmlTextElement HtmlTextElement; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlMarkupElement HtmlMarkupElement; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +typedef unsigned short Html_u16; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +int HtmlGetImageAlignment(HtmlElement *p); +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/htmlindex.c b/tkhtml1/src/htmlindex.c new file mode 100644 index 0000000..7b488a1 --- /dev/null +++ b/tkhtml1/src/htmlindex.c @@ -0,0 +1,505 @@ +/* +** Routines that deal with indexes +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <ctype.h> +#include <tk.h> +#include <string.h> +#include "htmlindex.h" + +/* +** Return a pointer to the Nth HtmlElement in the list. If there +** is no Nth element, return 0 if flag==0 and return either the first +** or last element (whichever is closest) if flag!=0 +*/ +HtmlElement *HtmlTokenByIndex(HtmlWidget *htmlPtr, int N, int flag){ + HtmlElement *p; + int n; + + if( N > htmlPtr->nToken/2 ){ + /* Start at the end and work back toward the beginning */ + for(p=htmlPtr->pLast, n=htmlPtr->nToken; p; p=p->base.pPrev){ + if( p->base.type!=Html_Block ){ + if( n==N ){ TestPoint(0); break; } + n--; + TestPoint(0); + }else{ + TestPoint(0); + } + } + }else{ + /* Start at the beginning and work forward */ + for(p=htmlPtr->pFirst; p; p = p->base.pNext){ + if( p->base.type!=Html_Block ){ + N--; + if( N<=0 ){ TestPoint(0); break; } + }else{ + TestPoint(0); + } + } + } + return p; +} + +/* +** Return the token number for the given HtmlElement +*/ +int HtmlTokenNumber(HtmlElement *p){ + int n = 0; + + while( p ){ + if( p->base.type!=Html_Block ){ + TestPoint(0); + n++; + }else{ + TestPoint(0); + } + p = p->base.pPrev; + } + return n; +} + +/* +** Find the maximum index for the given token +*/ +static void maxIndex(HtmlElement *p, int *pIndex){ + if( p==0 ){ + *pIndex = 0; + TestPoint(0); + }else{ + switch( p->base.type ){ + case Html_Text: + *pIndex = p->base.count-1; + TestPoint(0); + break; + case Html_Space: + if( p->base.style.flags & STY_Preformatted ){ + *pIndex = p->base.count-1; + TestPoint(0); + }else{ + *pIndex = 0; + TestPoint(0); + } + break; + default: + *pIndex = 0; + TestPoint(0); + break; + } + } +} + +/* +** Given a Block and an x coordinate, find the Index of the character +** that is closest to the given x coordinate. +** +** The x-coordinate might specify a point to the left of the block, +** in which case the procedure returns the first token and a character +** index of 0. Or the x-coordinate might specify a point to the right +** of the block, in which case the last token is returned with an index +** equal to its last character. +*/ +static void FindIndexInBlock( + HtmlWidget *htmlPtr, /* The widget */ + HtmlBlock *pBlock, /* The block */ + int x, /* The x coordinate */ + HtmlElement **ppToken, /* Write the closest token here */ + int *pIndex /* Write the charater index in ppToken here */ +){ + HtmlElement *p; + Tk_Font font; + int len; + int n; + + p = pBlock->base.pNext; + HtmlLock(htmlPtr); + font = HtmlGetFont(htmlPtr, p->base.style.font); + if( HtmlUnlock(htmlPtr) ){ + *ppToken = p; + *pIndex = 0; + return; + } + if( x <= pBlock->left ){ + *ppToken = p; + *pIndex = 0; + TestPoint(0); + return; + }else if( x>= pBlock->right ){ + *ppToken = p; + *pIndex = 0; + while( p && p->base.type!=Html_Block ){ + *ppToken = p; + p = p->base.pNext; + TestPoint(0); + } + p = *ppToken; + if( p && p->base.type==Html_Text ){ + *pIndex = p->base.count - 1; + TestPoint(0); + }else{ + TestPoint(0); + } + return; + } + if( pBlock->n==0 ){ + *ppToken = p; + *pIndex = 0; + TestPoint(0); + }else{ + TestPoint(0); + } + n = Tk_MeasureChars(font, pBlock->z, pBlock->n, x - pBlock->left, 0, &len); + *pIndex = 0; + *ppToken = 0; + while( p && n>=0 ){ + switch( p->base.type ){ + case Html_Text: + if( n<p->base.count ){ + *pIndex = n; + TestPoint(0); + }else{ + *pIndex = p->base.count - 1; + TestPoint(0); + } + *ppToken = p; + n -= p->base.count; + break; + case Html_Space: + if( p->base.style.flags & STY_Preformatted ){ + if( n<p->base.count ){ + *pIndex = n; + TestPoint(0); + }else{ + *pIndex = p->base.count - 1; + TestPoint(0); + } + *ppToken = p; + n -= p->base.count; + }else{ + *pIndex = 0; + *ppToken = p; + n--; + TestPoint(0); + } + break; + default: + TestPoint(0); + break; + } + if( p ){ + p = p->base.pNext; + TestPoint(0); + }else{ + TestPoint(0); + } + } +} + +/* +** Convert an Element-based index into a Block-based index. +** +** In other words, given a pointer to an element and an index +** of a particular character within that element, compute a +** pointer to the HtmlBlock used to display that character and +** the index in the HtmlBlock of the character. +*/ +void HtmlIndexToBlockIndex( + HtmlWidget *htmlPtr, /* The widget */ + HtmlIndex sIndex, /* The index to be translated */ + HtmlBlock **ppBlock, /* Write the corresponding block here */ + int *piIndex /* Write the block index here */ +){ + int n = sIndex.i; + HtmlElement *p; + + if( sIndex.p==0 ){ + *ppBlock = 0; + *piIndex = 0; + TestPoint(0); + return; + } + p = sIndex.p->base.pPrev; + while( p && p->base.type!=Html_Block ){ + switch( p->base.type ){ + case Html_Text: + n += p->base.count; + TestPoint(0); + break; + case Html_Space: + if( p->base.style.flags & STY_Preformatted ){ + n += p->base.count; + TestPoint(0); + }else{ + n++; + TestPoint(0); + } + break; + default: + TestPoint(0); + break; + } + p = p->base.pPrev; + } + if( p ){ + *ppBlock = &p->block; + *piIndex = n; + TestPoint(0); + return; + } + for(p=sIndex.p; p && p->base.type!=Html_Block; p=p->base.pNext){ + TestPoint(0); + } + *ppBlock = &p->block; + *piIndex = 0; +} + + + +/* +** Given a base index name (without any modifiers) return a pointer +** to the token described, and the character within that token. +** +** Valid input forms include: +** +** N.M Token number N (with numbering starting at 1) and +** character number M (with numbering starting at 0). +** +** end The end of all text +** +** N.last Last character of token number N. +** +** sel.first First character of the selection. +** +** sel.last Last character of the selection. +** +** ins The character holding the insertion cursor. +** +** @X,Y The character a location X,Y of the clipping window. +** +** Zero is returned if we are successful and non-zero if there is +** any kind of error. +** +** If the given token doesn't exist (for example if there are only 10 +** tokens and 11.5 is requested) then *ppToken is left pointing to NULL. +** But the function still returns 0 for success. +*/ +static int DecodeBaseIndex( + HtmlWidget *htmlPtr, /* The HTML widget we are dealing with */ + const char *zBase, /* The base index string */ + HtmlElement **ppToken, /* Write the pointer to the token here */ + int *pIndex /* Write the character offset here */ +){ + int x, y; + int n; + int i; + HtmlElement *p; + HtmlBlock *pBlock; + HtmlBlock *pNearby; + int dist = 1000000; + int rc = 0; + + while( isspace(*zBase) ){ TestPoint(0); zBase++; } + switch( *zBase ){ + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + n = sscanf(zBase,"%d.%d",&x,&y); + if( n>0 ){ + p = *ppToken = HtmlTokenByIndex(htmlPtr, x, 0); + TestPoint(0); + }else{ + TestPoint(0); + } + if( n==2 ){ + *pIndex = y; + TestPoint(0); + }else{ + for(i=1; isdigit(zBase[i]); i++){ TestPoint(0); } + if( zBase[i]==0 ){ + *pIndex = 0; + TestPoint(0); + }else if( strcmp(&zBase[i],".last")==0 ){ + maxIndex(p,pIndex); + TestPoint(0); + }else{ + rc = 1; + TestPoint(0); + } + } + break; + case 'e': + if( strcmp(zBase,"end")==0 ){ + p = *ppToken = htmlPtr->pLast; + maxIndex(p,pIndex); + TestPoint(0); + }else{ + rc = 1; + TestPoint(0); + } + break; + case 's': + if( strcmp(zBase,"sel.first")==0 ){ + *ppToken = htmlPtr->selBegin.p; + *pIndex = htmlPtr->selBegin.i; + TestPoint(0); + }else if( strcmp(zBase,"sel.last")==0 ){ + *ppToken = htmlPtr->selEnd.p; + *pIndex = htmlPtr->selEnd.i; + TestPoint(0); + }else{ + rc = 1; + TestPoint(0); + } + break; + case 'i': + if( strcmp(zBase,"insert")==0 ){ + *ppToken = htmlPtr->ins.p; + *pIndex = htmlPtr->ins.i; + TestPoint(0); + }else{ + rc = 1; + TestPoint(0); + } + break; + case '@': + n = sscanf(zBase,"@%d,%d",&x,&y); + if( n!=2 ){ + rc = 1; + TestPoint(0); + break; + } + x += htmlPtr->xOffset; + y += htmlPtr->yOffset; + pNearby = 0; + *ppToken = htmlPtr->pLast; + *pIndex = 0; + for(pBlock=htmlPtr->firstBlock; pBlock; pBlock=pBlock->pNext){ + int dotest; + if( pBlock->n==0 ){ + switch( pBlock->base.pNext->base.type ){ + case Html_LI: + case Html_IMG: + case Html_INPUT: + case Html_TEXTAREA: + case Html_SELECT: + dotest = 1; + TestPoint(0); + break; + default: + dotest = 0; + TestPoint(0); + break; + } + }else{ + dotest = 1; + TestPoint(0); + } + if (dotest){ + if( pBlock->top <= y && pBlock->bottom >= y ){ + if( pBlock->left > x ){ + if( pBlock->left - x < dist ){ + dist = pBlock->left - x; + pNearby = pBlock; + TestPoint(0); + }else{ + TestPoint(0); + } + }else if( pBlock->right < x ){ + if( x - pBlock->right < dist ){ + dist = x - pBlock->right; + pNearby = pBlock; + TestPoint(0); + }else{ + TestPoint(0); + } + }else{ + HtmlLock(htmlPtr); + FindIndexInBlock(htmlPtr, pBlock, x, ppToken, pIndex); + if( HtmlUnlock(htmlPtr) ) return 1; + TestPoint(0); + break; + } + }else{ + int distY; + int distX; + + if( pBlock->bottom < y ){ + distY = y - pBlock->bottom; + TestPoint(0); + }else{ + distY = pBlock->top - y; + TestPoint(0); + } + if( pBlock->left > x ){ + distX = pBlock->left - x; + TestPoint(0); + }else if( pBlock->right < x ){ + distX = x - pBlock->right; + TestPoint(0); + }else{ + distX = 0; + TestPoint(0); + } + if( distX + 4*distY < dist ){ + dist = distX + 4*distY; + pNearby = pBlock; + TestPoint(0); + }else{ + TestPoint(0); + } + } + } + } + if( pBlock==0 ){ + if( pNearby ){ + HtmlLock(htmlPtr); + FindIndexInBlock(htmlPtr, pNearby, x, ppToken, pIndex); + if( HtmlUnlock(htmlPtr) ) return 1; + TestPoint(0); + }else{ + TestPoint(0); + } + }else{ + TestPoint(0); + } + break; + default: + rc = 1; + TestPoint(0); + break; + } + return rc; +} + +/* +** This routine decodes a complete index specification. A complete +** index consists of the base specification followed by modifiers. +*/ +int HtmlGetIndex( + HtmlWidget *htmlPtr, /* The widget */ + const char *zIndex, /* Complete text of the index spec */ + HtmlElement **ppToken, /* Write the pointer to the token here */ + int *pIndex /* Write the character offset here */ +){ + TestPoint(0); + return DecodeBaseIndex(htmlPtr, zIndex, ppToken, pIndex); +} diff --git a/tkhtml1/src/htmlindex.h b/tkhtml1/src/htmlindex.h new file mode 100644 index 0000000..37a5fee --- /dev/null +++ b/tkhtml1/src/htmlindex.h @@ -0,0 +1,450 @@ +/* This file was automatically generated. Do not edit! */ +typedef struct HtmlWidget HtmlWidget; +typedef union HtmlElement HtmlElement; +int HtmlGetIndex(HtmlWidget *htmlPtr,const char *zIndex,HtmlElement **ppToken,int *pIndex); +#define Html_SELECT 116 +#define Html_TEXTAREA 133 +#define Html_INPUT 77 +#define Html_IMG 76 +#define Html_LI 81 +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +typedef struct HtmlBlock HtmlBlock; +void HtmlIndexToBlockIndex(HtmlWidget *htmlPtr,HtmlIndex sIndex,HtmlBlock **ppBlock,int *piIndex); +int HtmlUnlock(HtmlWidget *htmlPtr); +Tk_Font HtmlGetFont(HtmlWidget *htmlPtr,int iFont); +void HtmlLock(HtmlWidget *htmlPtr); +typedef struct HtmlBaseElement HtmlBaseElement; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +typedef unsigned char Html_u8; +typedef short Html_16; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +typedef unsigned short Html_u16; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +#define STY_Preformatted 0x001 +#define Html_Space 2 +#define Html_Text 1 +int HtmlTokenNumber(HtmlElement *p); +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +#define Html_Block 4 +typedef struct HtmlScript HtmlScript; +#define Html_TypeCount 151 +typedef struct HtmlStyleStack HtmlStyleStack; +typedef struct HtmlLayoutContext HtmlLayoutContext; +typedef struct HtmlMargin HtmlMargin; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +typedef struct HtmlImage HtmlImage; +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +HtmlElement *HtmlTokenByIndex(HtmlWidget *htmlPtr,int N,int flag); +typedef struct HtmlTextElement HtmlTextElement; +typedef int Html_32; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlMarkupElement HtmlMarkupElement; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/htmllayout.c b/tkhtml1/src/htmllayout.c new file mode 100644 index 0000000..e511e53 --- /dev/null +++ b/tkhtml1/src/htmllayout.c @@ -0,0 +1,1170 @@ +/* +** This file contains the code used to position elements of the +** HTML file on the screen. +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <tk.h> +#include <stdlib.h> +#include <string.h> +#include "htmllayout.h" + + +/* +** Push a new margin onto the given margin stack. +** +** If the "bottom" parameter is non-negative, then this margin will +** automatically expire for all text that is placed below the y-coordinate +** given by "bottom". This feature is used for <IMG ALIGN=left> +** and <IMG ALIGN=right> kinds of markup. It allows text to flow around +** an image. +** +** If "bottom" is negative, then the margin stays in force until +** it is explicitly canceled by a call to HtmlPopMargin(). +*/ +void HtmlPushMargin( + HtmlMargin **ppMargin, /* The margin stack onto which to push */ + int indent, /* The indentation for the new margin */ + int bottom, /* The margin expires at this Y coordinate */ + int tag /* Markup that will cancel this margin */ +){ + HtmlMargin *pNew = HtmlAlloc( sizeof(HtmlMargin) ); + pNew->pNext = *ppMargin; + if( pNew->pNext ){ + pNew->indent = indent + pNew->pNext->indent; + TestPoint(0); + }else{ + pNew->indent = indent; + TestPoint(0); + } + pNew->bottom = bottom; + pNew->tag = tag; + *ppMargin = pNew; +} + +/* +** Pop one margin off of the given margin stack. +*/ +static void HtmlPopOneMargin(HtmlMargin **ppMargin){ + if( *ppMargin ){ + HtmlMargin *pOld = *ppMargin; + *ppMargin = pOld->pNext; + HtmlFree(pOld); + } +} + +/* +** Pop as many margins as necessary until the margin that was +** created with "tag" is popped off. Update the layout context +** to move past obsticles, if necessary. +** +** If there are some margins on the stack that contain non-negative +** bottom fields, that means there are some obsticles that we have +** not yet cleared. If these margins get popped off the stack, +** then we have to be careful to advance the pLC->bottom value so +** that the next line of text will clear the obsticle. +*/ +static void HtmlPopMargin( + HtmlMargin **ppMargin, /* The margin stack to be popped */ + int tag, /* The tag we want to pop */ + HtmlLayoutContext *pLC /* Update this layout context */ +){ + int bottom = -1; + int oldTag; + HtmlMargin *pM; + + for(pM=*ppMargin; pM && pM->tag!=tag; pM=pM->pNext){} + if( pM==0 ){ + /* No matching margin is found. Do nothing. */ + return; + } + while( (pM=*ppMargin)!=0 ){ + if( pM->bottom>bottom ){ + bottom = pM->bottom; + } + oldTag = pM->tag; + HtmlPopOneMargin(ppMargin); + if( oldTag==tag ) break; + } + if( pLC && pLC->bottom<bottom ){ + pLC->headRoom += bottom - pLC->bottom; + pLC->bottom = bottom; + } +} + +/* +** Pop all expired margins from the stack. +** +** An expired margin is one with a non-negative bottom parameter +** that is less than the value "y". "y" is the Y-coordinate of +** the top edge the next line of text to by positioned. What this +** function does is check to see if we have cleared any obsticles +** (an obsticle is an <IMG ALIGN=left> or <IMG ALIGN=right>) and +** expands the margins if we have. +*/ +static void PopExpiredMargins(HtmlMargin **ppMarginStack, int y){ + while( *ppMarginStack && (**ppMarginStack).bottom>=0 && + (**ppMarginStack).bottom <= y ){ + HtmlPopOneMargin(ppMarginStack); + } +} + +/* +** Clear a margin stack to reclaim memory. This routine just blindly +** pops everything off the stack. Typically used when the screen is +** cleared or the widget is deleted, etc. +*/ +void HtmlClearMarginStack(HtmlMargin **ppMargin){ + while( *ppMargin ){ + HtmlPopOneMargin(ppMargin); + } +} + +/* +** This routine gathers as many tokens as will fit on one line. +** +** The candidate tokens begin with pStart and go thru the end of +** the list or to pEnd, whichever comes first. The first token +** at the start of the next line is returned. NULL is returned if +** we exhaust data. +** +** "width" is the maximum allowed width of the line. The actual +** width is returned in *actualWidth. The actual width does not +** include any trailing spaces. Sometimes the actual width will +** be greater than the maximum width. This will happen, for example, +** for text enclosed in <pre>..</pre> that has lines longer than +** the width of the page. +** +** If the list begins with text, at least one token is returned, +** even if that one token is longer than the allowed line length. +** But if the list begins with some kind of break markup (possibly +** preceded by white space) then the returned list may be empty. +** +** The "x" coordinates of all elements are set assuming that the line +** begins at 0. The calling routine should adjust these coordinates +** to position the line horizontally. (The FixLine() procedure does +** this.) Note that the "x" coordinate of <li> elements will be negative. +** Text within <dt>..</dt> might also have a negative "x" coordinate. +** But in no case will the x coordinate every be less than "minX". +*/ +static HtmlElement *GetLine( + HtmlLayoutContext *pLC, /* The complete layout context. */ + HtmlElement *pStart, /* First token on new line */ + HtmlElement *pEnd, /* End of line. Might be NULL */ + int width, /* How much space is on this line */ + int minX, /* The minimum value of the X coordinate */ + int *actualWidth /* Return space actually required */ +){ + int x; /* Current X coordinate */ + int spaceWanted = 0; /* Add this much space before next token */ + HtmlElement *p; /* For looping over tokens */ + HtmlElement *lastBreak = 0; /* Last line-break opportunity */ + int isEmpty = 1; /* True if link contains nothing */ + int origin; /* Initial value of "x" */ + + *actualWidth = 0; + p = pStart; + while( p && p!=pEnd && (p->base.style.flags & STY_Invisible)!=0 ){ + p = p->pNext; + } + if( p && p->base.style.flags & STY_DT ){ + origin = -HTML_INDENT; + }else{ + origin = 0; + } + x = origin; + if( x<minX ){ x = minX; } + if( p && p!=pEnd && p->base.type==Html_LI ){ + p->li.x = x - HTML_INDENT/3; + if( p->li.x - (HTML_INDENT*2)/3<minX ){ + x += minX - p->li.x + (HTML_INDENT*2)/3; + p->li.x = minX + (HTML_INDENT*2)/3; + } + isEmpty = 0; + *actualWidth = 1; + p = p->pNext; + while( p && (p->base.type==Html_Space || p->base.type==Html_P) ){ + p = p->pNext; + } + } + for(; p && p!=pEnd; p=p->pNext){ + if( p->base.style.flags & STY_Invisible ){ + continue; + } + switch( p->base.type ){ + case Html_Text: + p->text.x = x + spaceWanted; + if( (p->base.style.flags & STY_Preformatted) == 0 ){ + if( lastBreak && x + spaceWanted + p->text.w > width ){ + TestPoint(0); + return lastBreak; + } + } + TRACE(HtmlTrace_GetLine2, ("Place token %s at x=%d w=%d\n", + HtmlTokenName(p), p->text.x, p->text.w)); + x += p->text.w + spaceWanted; + isEmpty = 0; + spaceWanted = 0; + break; + + case Html_Space: + if( p->base.style.flags & STY_Preformatted ){ + if( p->base.flags & HTML_NewLine ){ + *actualWidth = x<=0 ? 1 : x; + TestPoint(0); + return p->pNext; + } + x += p->space.w * p->base.count; + TestPoint(0); + }else{ + int w; + if( (p->base.style.flags & STY_NoBreak)==0 ){ + lastBreak = p->pNext; + *actualWidth = x<=0 && !isEmpty ? 1 : x; + } + w = p->space.w; + if( spaceWanted < w && x>origin ){ + spaceWanted = w; + } + } + break; + + case Html_IMG: + switch( p->image.align ){ + case IMAGE_ALIGN_Left: + case IMAGE_ALIGN_Right: + *actualWidth = x<=0 && !isEmpty ? 1 : x; + return p; + default: + break; + } + p->image.x = x + spaceWanted; + if( (p->base.style.flags & STY_Preformatted) == 0 ){ + if( lastBreak && x + spaceWanted + p->image.w > width ){ + TestPoint(0); + return lastBreak; + } + } + TRACE(HtmlTrace_GetLine2, ("Place in-line image %s at x=%d w=%d\n", + HtmlTokenName(p), p->image.x, p->image.w)); + x += p->image.w + spaceWanted; + if( (p->base.style.flags & STY_NoBreak)==0 ){ + lastBreak = p->pNext; + *actualWidth = x<=0 && !isEmpty ? 1 : x; + } + spaceWanted = 0; + isEmpty = 0; + break; + + case Html_APPLET: + case Html_EMBED: + case Html_INPUT: + case Html_SELECT: + case Html_TEXTAREA: + p->input.x = x + spaceWanted + p->input.padLeft; + if( (p->base.style.flags & STY_Preformatted) == 0 ){ + if( lastBreak && x + spaceWanted + p->input.w > width ){ + TestPoint(0); + return lastBreak; + } + } + TRACE(HtmlTrace_GetLine2, ("Place token %s at x=%d w=%d\n", + HtmlTokenName(p), p->input.x, p->input.w)); + x = p->input.x + p->input.w; + if( (p->base.style.flags & STY_NoBreak)==0 ){ + lastBreak = p->pNext; + *actualWidth = x<=0 && !isEmpty ? 1 : x; + } + spaceWanted = 0; + isEmpty = 0; + break; + + case Html_EndTEXTAREA: + if( p->ref.pOther ){ + /* HtmlResetTextarea(pLC->htmlPtr, p->ref.pOther); */ + } + break; + + case Html_DD: + if( p->ref.pOther==0 ) break; + if( p->ref.pOther->list.compact==0 || x + spaceWanted >= 0 ){ + *actualWidth = x<=0 && !isEmpty ? 1 : x; + return p; + } + x = 0; + spaceWanted = 0; + break; + + case Html_WBR: + *actualWidth = x<=0 && !isEmpty ? 1 : x; + if( x + spaceWanted >= width ){ + return p->pNext; + }else{ + lastBreak = p->pNext; + } + break; + + case Html_ADDRESS: + case Html_EndADDRESS: + case Html_BLOCKQUOTE: + case Html_EndBLOCKQUOTE: + case Html_BODY: + case Html_EndBODY: + case Html_BR: + case Html_CAPTION: + case Html_EndCAPTION: + case Html_CENTER: + case Html_EndCENTER: + case Html_EndDD: + case Html_DIV: + case Html_EndDIV: + case Html_DL: + case Html_EndDL: + case Html_DT: + case Html_H1: + case Html_EndH1: + case Html_H2: + case Html_EndH2: + case Html_H3: + case Html_EndH3: + case Html_H4: + case Html_EndH4: + case Html_H5: + case Html_EndH5: + case Html_H6: + case Html_EndH6: + case Html_EndHTML: + case Html_HR: + case Html_LI: + case Html_LISTING: + case Html_EndLISTING: + case Html_MENU: + case Html_EndMENU: + case Html_OL: + case Html_EndOL: + case Html_P: + case Html_EndP: + case Html_PRE: + case Html_EndPRE: + case Html_TABLE: + case Html_EndTABLE: + case Html_TD: + case Html_EndTD: + case Html_TH: + case Html_EndTH: + case Html_TR: + case Html_EndTR: + case Html_UL: + case Html_EndUL: + *actualWidth = x<=0 && !isEmpty ? 1 : x; + return p; + + default: + break; + } + } + *actualWidth = x<=0 && !isEmpty ? 1 : x; + return p; +} + +/* +** Set the y coordinate for every anchor in the given list +*/ +static void FixAnchors(HtmlElement *p, HtmlElement *pEnd, int y){ + while( p && p!=pEnd ){ + if( p->base.type==Html_A ){ + p->anchor.y = y; + } + p = p->pNext; + } +} + +/* +** This routine computes the X and Y coordinates for all elements of +** a line that has been gathered using GetLine() above. It also figures +** the ascent and descent for in-line images. +** +** The value returned is the Y coordinate of the bottom edge of the +** new line. The X coordinates are computed by adding the left margin +** plus any extra space needed for centering or right-justification. +*/ +static int FixLine( + HtmlElement *pStart, /* Start of tokens for this line */ + HtmlElement *pEnd, /* First token past end of this line. Maybe NULL */ + int bottom, /* Put the top of this line here */ + int width, /* This is the space available to the line */ + int actualWidth, /* This is the actual width needed by the line */ + int leftMargin, /* The current left margin */ + int *maxX /* Write maximum X coordinate of ink here */ +){ + int dx; /* Amount by which to increase all X coordinates */ + int maxAscent; /* Maximum height above baseline */ + int maxTextAscent; /* Maximum height above baseline for text */ + int maxDescent; /* Maximum depth below baseline */ + int ascent, descent; /* Computed ascent and descent for one element */ + HtmlElement *p; /* For looping */ + int y; /* Y coordinate of the baseline */ + int dy2center; /* Distance from baseline to text font center */ + int max = 0; + + if( actualWidth>0 ){ + for(p=pStart; p && p!=pEnd && p->base.type!=Html_Text; p=p->pNext){} + if( p==pEnd || p==0 ) p = pStart; + if( p->base.style.align == ALIGN_Center ){ + dx = leftMargin + (width - actualWidth)/2; + }else if( p->base.style.align == ALIGN_Right ){ + dx = leftMargin + (width - actualWidth); + }else{ + dx = leftMargin; + } + if( dx<0 ) dx = 0; + maxAscent = maxTextAscent = 0; + for(p=pStart; p && p!=pEnd; p=p->pNext){ + int ss; + if( p->base.style.flags & STY_Invisible ){ + continue; + } + switch( p->base.type ){ + case Html_Text: + p->text.x += dx; + max = p->text.x + p->text.w; + ss = p->base.style.subscript; + if( ss > 0 ){ + int ascent = p->text.ascent; + int delta = (ascent + p->text.descent)*ss/2; + ascent += delta; + p->text.y = -delta; + if( ascent > maxAscent ){ TestPoint(0); maxAscent = ascent; } + if( ascent > maxTextAscent ){ TestPoint(0); maxTextAscent = ascent;} + }else if( ss < 0 ){ + int descent = p->text.descent; + int delta = (descent + p->text.ascent)*(-ss)/2; + descent += delta; + p->text.y = delta; + }else{ + p->text.y = 0; + if( p->text.ascent > maxAscent ){ + maxAscent = p->text.ascent; + } + if( p->text.ascent > maxTextAscent ){ + maxTextAscent = p->text.ascent; + } + } + break; + case Html_Space: + if( p->space.ascent > maxAscent ){ + maxAscent = p->space.ascent; + } + break; + case Html_LI: + p->li.x += dx; + if( p->li.x > max ){ + max = p->li.x; + } + break; + case Html_IMG: + p->image.x += dx; + max = p->image.x + p->image.w; + switch( p->image.align ){ + case IMAGE_ALIGN_Middle: + p->image.descent = p->image.h/2; + p->image.ascent = p->image.h - p->image.descent; + if( p->image.ascent > maxAscent ){ + maxAscent = p->image.ascent; + } + break; + case IMAGE_ALIGN_AbsMiddle: + dy2center = (p->image.textDescent - p->image.textAscent)/2; + p->image.descent = p->image.h/2 + dy2center; + p->image.ascent = p->image.h - p->image.descent; + if( p->image.ascent > maxAscent ){ + maxAscent = p->image.ascent; + } + break; + case IMAGE_ALIGN_Bottom: + p->image.descent = 0; + p->image.ascent = p->image.h; + if( p->image.ascent > maxAscent ){ + maxAscent = p->image.ascent; + } + break; + case IMAGE_ALIGN_AbsBottom: + p->image.descent = p->image.textDescent; + p->image.ascent = p->image.h - p->image.descent; + if( p->image.ascent > maxAscent ){ + maxAscent = p->image.ascent; + } + break; + default: + TestPoint(0); + break; + } + break; + case Html_TEXTAREA: + case Html_INPUT: + case Html_SELECT: + case Html_EMBED: + case Html_APPLET: + p->input.x += dx; + max = p->input.x + p->input.w; + dy2center = (p->input.textDescent - p->input.textAscent)/2; + p->input.y = dy2center - p->input.h/2; + ascent = -p->input.y; + if( ascent > maxAscent ){ + maxAscent = ascent; + } + break; + default: + /* Shouldn't happen */ + break; + } + } + *maxX = max; + y = maxAscent + bottom; + maxDescent = 0; + for(p=pStart; p && p!=pEnd; p=p->pNext){ + if( p->base.style.flags & STY_Invisible ){ + TestPoint(0); + continue; + } + switch( p->base.type ){ + case Html_Text: + p->text.y += y; + if( p->text.descent > maxDescent ){ + maxDescent = p->text.descent; + } + break; + case Html_LI: + p->li.y = y; + if( p->li.descent > maxDescent ){ + maxDescent = p->li.descent; + } + break; + case Html_IMG: + p->image.y = y; + switch( p->image.align ){ + case IMAGE_ALIGN_Top: + p->image.ascent = maxAscent; + p->image.descent = p->image.h - maxAscent; + TestPoint(0); + break; + case IMAGE_ALIGN_TextTop: + p->image.ascent = maxTextAscent; + p->image.descent = p->image.h - maxTextAscent; + TestPoint(0); + break; + default: + TestPoint(0); + break; + } + if( p->image.descent > maxDescent ){ + maxDescent = p->image.descent; + } + break; + case Html_INPUT: + case Html_SELECT: + case Html_TEXTAREA: + case Html_APPLET: + case Html_EMBED: + descent = p->input.y + p->input.h; + p->input.y += y; + if( descent > maxDescent ){ + maxDescent = descent; + } + break; + default: + /* Shouldn't happen */ + break; + } + } + TRACE(HtmlTrace_FixLine, + ("Setting baseline to %d. bottom=%d ascent=%d descent=%d dx=%d\n", + y, bottom, maxAscent, maxDescent, dx)); + }else{ + maxDescent = 0; + y = bottom; + } + return y + maxDescent; +} + +/* +** Increase the headroom to create a paragraph break at the current token +*/ +static void Paragraph( + HtmlLayoutContext *pLC, + HtmlElement *p +){ + int headroom; + + if( p==0 ){ TestPoint(0); return; } + if( p->base.type==Html_Text ){ + headroom = p->text.ascent + p->text.descent; + TestPoint(0); + }else if( p->pNext && p->pNext->base.type==Html_Text ){ + headroom = p->pNext->text.ascent + p->pNext->text.descent; + TestPoint(0); + }else{ + Tk_FontMetrics fontMetrics; + Tk_Font font; + font = HtmlGetFont(pLC->htmlPtr, p->base.style.font); + if( font==0 ) return; + Tk_GetFontMetrics(font, &fontMetrics); + headroom = fontMetrics.descent + fontMetrics.ascent; + TestPoint(0); + } + if( pLC->headRoom < headroom && pLC->bottom > pLC->top ){ + pLC->headRoom = headroom; + } +} + +/* +** Compute the current margins for layout. Three values are returned: +** +** *pY The top edge of the area in which we can put ink. This +** takes into account any requested headroom. +** +** *pX The left edge of the inkable area. The takes into account +** any margin requests active at vertical position specified +** in pLC->bottom. +** +** *pW The width of the inkable area. This takes into account +** an margin requests that are active at the vertical position +** pLC->bottom. +** +*/ +void HtmlComputeMargins( + HtmlLayoutContext *pLC, /* The current layout context */ + int *pX, /* Put the left edge here */ + int *pY, /* Put the top edge here */ + int *pW /* Put the width here */ +){ + int x, y, w; + + y = pLC->bottom + pLC->headRoom; + PopExpiredMargins(&pLC->leftMargin, pLC->bottom); + PopExpiredMargins(&pLC->rightMargin, pLC->bottom); + w = pLC->pageWidth - pLC->right; + if( pLC->leftMargin ){ + x = pLC->leftMargin->indent + pLC->left; + TestPoint(0); + }else{ + x = pLC->left; + TestPoint(0); + } + w -= x; + if( pLC->rightMargin ){ + w -= pLC->rightMargin->indent; + TestPoint(0); + }else{ + TestPoint(0); + } + *pX = x; + *pY = y; + *pW = w; +} + + +/* +** Clear a wrap-around obstacle. The second option determines the +** precise behavior. +** +** CLEAR_Left Clear all obstacles on the left. +** +** CLEAR_Right Clear all obstacles on the right. +** +** CLEAR_Both Clear all obstacles on both sides. +** +** CLEAR_First Clear only the first obsticle on either side. +*/ +#define CLEAR_Left 0 +#define CLEAR_Right 1 +#define CLEAR_Both 2 +#define CLEAR_First 3 +static void ClearObstacle(HtmlLayoutContext *pLC, int mode){ + int newBottom = pLC->bottom; + + PopExpiredMargins(&pLC->leftMargin, pLC->bottom); + PopExpiredMargins(&pLC->rightMargin, pLC->bottom); + switch( mode ){ + case CLEAR_Both: + ClearObstacle(pLC,CLEAR_Left); + ClearObstacle(pLC,CLEAR_Right); + TestPoint(0); + break; + + case CLEAR_Left: + while( pLC->leftMargin && pLC->leftMargin->bottom>=0 ){ + newBottom = pLC->leftMargin->bottom; + HtmlPopOneMargin(&pLC->leftMargin); + TestPoint(0); + } + if( newBottom > pLC->bottom + pLC->headRoom ){ + pLC->headRoom = 0; + TestPoint(0); + }else{ + pLC->headRoom = newBottom - pLC->bottom; + TestPoint(0); + } + pLC->bottom = newBottom; + PopExpiredMargins(&pLC->rightMargin, pLC->bottom); + break; + + case CLEAR_Right: + while( pLC->rightMargin && pLC->rightMargin->bottom>=0 ){ + newBottom = pLC->rightMargin->bottom; + HtmlPopOneMargin(&pLC->rightMargin); + TestPoint(0); + } + if( newBottom > pLC->bottom + pLC->headRoom ){ + pLC->headRoom = 0; + TestPoint(0); + }else{ + pLC->headRoom = newBottom - pLC->bottom; + TestPoint(0); + } + pLC->bottom = newBottom; + PopExpiredMargins(&pLC->leftMargin, pLC->bottom); + break; + + case CLEAR_First: + if( pLC->leftMargin && pLC->leftMargin->bottom>=0 ){ + if( pLC->rightMargin + && pLC->rightMargin->bottom < pLC->leftMargin->bottom + ){ + newBottom = pLC->rightMargin->bottom; + HtmlPopOneMargin(&pLC->rightMargin); + TestPoint(0); + }else{ + newBottom = pLC->leftMargin->bottom; + HtmlPopOneMargin(&pLC->leftMargin); + TestPoint(0); + } + }else if( pLC->rightMargin && pLC->rightMargin->bottom>=0 ){ + newBottom = pLC->rightMargin->bottom; + HtmlPopOneMargin(&pLC->rightMargin); + TestPoint(0); + }else{ + TestPoint(0); + } + if( newBottom > pLC->bottom + pLC->headRoom ){ + pLC->headRoom = 0; + TestPoint(0); + }else{ + pLC->headRoom = newBottom - pLC->bottom; + TestPoint(0); + } + pLC->bottom = newBottom; + break; + } +} + +/* +** Break markup is any kind of markup that might force a line-break. This +** routine handles a single element of break markup and returns a pointer +** to the first element past that markup. If p doesn't point to break +** markup, then p is returned. If p is an incomplete table (a <TABLE> +** that lacks a </TABLE>), then NULL is returned. +*/ +static HtmlElement *DoBreakMarkup( + HtmlLayoutContext *pLC, + HtmlElement *p +){ + HtmlElement *pNext = p->pNext; + char *z; + int x, y, w; + + switch( p->base.type ){ + case Html_A: + p->anchor.y = pLC->bottom; + TestPoint(0); + break; + + case Html_BLOCKQUOTE: + HtmlPushMargin(&pLC->leftMargin, HTML_INDENT, -1, Html_EndBLOCKQUOTE); + HtmlPushMargin(&pLC->rightMargin, HTML_INDENT, -1, Html_EndBLOCKQUOTE); + Paragraph(pLC, p); + TestPoint(0); + break; + case Html_EndBLOCKQUOTE: + HtmlPopMargin(&pLC->leftMargin, Html_EndBLOCKQUOTE, pLC); + HtmlPopMargin(&pLC->rightMargin, Html_EndBLOCKQUOTE, pLC); + Paragraph(pLC, p); + TestPoint(0); + break; + + case Html_IMG: + switch( p->image.align ){ + case IMAGE_ALIGN_Left: + HtmlComputeMargins(pLC, &x, &y, &w); + p->image.x = x; + p->image.y = y; + p->image.ascent = 0; + p->image.descent = p->image.h; + HtmlPushMargin(&pLC->leftMargin, p->image.w + 2, y + p->image.h, 0); + SETMAX( pLC->maxY, y + p->image.h ); + SETMAX( pLC->maxX, x + p->image.w ); + break; + case IMAGE_ALIGN_Right: + HtmlComputeMargins(pLC, &x, &y, &w); + p->image.x = x + w - p->image.w; + p->image.y = y; + p->image.ascent = 0; + p->image.descent = p->image.h; + HtmlPushMargin(&pLC->rightMargin, p->image.w + 2, y + p->image.h, 0); + SETMAX( pLC->maxY, y + p->image.h ); + SETMAX( pLC->maxX, x + p->image.w ); + break; + default: + TestPoint(0); + pNext = p; + break; + } + break; + + + case Html_PRE: + /* Skip space tokens thru the next newline. */ + while( pNext->base.type==Html_Space ){ + HtmlElement *pThis = pNext; + pNext = pNext->pNext; + if( pThis->base.flags & HTML_NewLine ){ TestPoint(0); break; } + } + Paragraph(pLC,p); + break; + + case Html_UL: + case Html_MENU: + case Html_DIR: + case Html_OL: + if( p->list.compact==0 ){ + Paragraph(pLC,p); + } + HtmlPushMargin(&pLC->leftMargin, HTML_INDENT, -1, p->base.type+1); + break; + + case Html_EndOL: + case Html_EndUL: + case Html_EndMENU: + case Html_EndDIR: + if( p->ref.pOther ){ + HtmlPopMargin(&pLC->leftMargin, p->base.type, pLC); + if( !p->ref.pOther->list.compact ){ + Paragraph(pLC,p); + } + } + break; + + case Html_DL: + Paragraph(pLC,p); + HtmlPushMargin(&pLC->leftMargin, HTML_INDENT, -1, Html_EndDL); + TestPoint(0); + break; + + case Html_EndDL: + HtmlPopMargin(&pLC->leftMargin, Html_EndDL, pLC); + Paragraph(pLC,p); + TestPoint(0); + break; + + case Html_HR: { + int zl, wd; + + p->hr.is3D = HtmlMarkupArg(p, "noshade", 0)==0; + z = HtmlMarkupArg(p, "size", 0); + if( z ){ + p->hr.h = atoi(z); + }else{ + p->hr.h = 0; + } + if( p->hr.h<1 ){ + int relief = pLC->htmlPtr->ruleRelief; + if( p->hr.is3D + && (relief==TK_RELIEF_SUNKEN || relief==TK_RELIEF_RAISED) ){ + p->hr.h = 3; + }else{ + p->hr.h = 2; + } + } + HtmlComputeMargins(pLC, &x, &y, &w); + p->hr.y = y; + y += p->hr.h + 1; + p->hr.x = x; + z = HtmlMarkupArg(p, "width", "100%"); + zl = strlen(z); + if( zl>0 && z[zl-1]=='%' ){ + wd = (atoi(z)*w)/100; + }else{ + wd = atoi(z); + } + if( wd>w ) wd = w; + p->hr.w = wd; + switch( p->base.style.align ){ + case ALIGN_Center: + case ALIGN_None: + p->hr.x += (w - wd)/2; + TestPoint(0); + break; + case ALIGN_Right: + p->hr.x += (w - wd); + TestPoint(0); + break; + default: + TestPoint(0); + break; + } + SETMAX( pLC->maxY, y); + SETMAX( pLC->maxX, wd + p->hr.x ); + pLC->bottom = y; + pLC->headRoom = 0; + break; + } + + case Html_ADDRESS: + case Html_EndADDRESS: + case Html_CENTER: + case Html_EndCENTER: + case Html_DIV: + case Html_EndDIV: + case Html_H1: + case Html_EndH1: + case Html_H2: + case Html_EndH2: + case Html_H3: + case Html_EndH3: + case Html_H4: + case Html_EndH4: + case Html_H5: + case Html_EndH5: + case Html_H6: + case Html_EndH6: + case Html_P: + case Html_EndP: + case Html_EndPRE: + Paragraph(pLC, p); + TestPoint(0); + break; + + case Html_TABLE: + pNext = HtmlTableLayout(pLC, p); + TestPoint(0); + break; + + case Html_BR: + z = HtmlMarkupArg(p, "clear",0); + if( z ){ + if( stricmp(z,"left")==0 ){ + ClearObstacle(pLC, CLEAR_Left); + TestPoint(0); + }else if( stricmp(z,"right")==0 ){ + ClearObstacle(pLC, CLEAR_Right); + TestPoint(0); + }else{ + ClearObstacle(pLC, CLEAR_Both); + TestPoint(0); + } + }else{ + TestPoint(0); + } + break; + + /* All of the following tags need to be handed to the GetLine() routine */ + case Html_Text: + case Html_Space: + case Html_LI: + case Html_INPUT: + case Html_SELECT: + case Html_TEXTAREA: + case Html_APPLET: + case Html_EMBED: + pNext = p; + TestPoint(0); + break; + + default: + TestPoint(0); + break; + } + return pNext; +} + +/* +** Return TRUE (non-zero) if we are currently wrapping text around +** one or more images. +*/ +static int InWrapAround(HtmlLayoutContext *pLC){ + if( pLC->leftMargin && pLC->leftMargin->bottom >= 0 ){ + TestPoint(0); + return 1; + } + if( pLC->rightMargin && pLC->rightMargin->bottom >= 0 ){ + TestPoint(0); + return 1; + } + TestPoint(0); + return 0; +} + +/* +** Move past obsticles until a linewidth of reqWidth is obtained, +** or until all obsticles are cleared. +*/ +void HtmlWidenLine( + HtmlLayoutContext *pLC, /* The layout context */ + int reqWidth, /* Requested line width */ + int *pX, int *pY, int *pW /* The margins. See HtmllComputeMargins() */ +){ + HtmlComputeMargins(pLC, pX, pY, pW); + if( *pW<reqWidth && InWrapAround(pLC) ){ + ClearObstacle(pLC, CLEAR_First); + HtmlComputeMargins(pLC, pX, pY, pW); + } +} + +#ifdef TABLE_TRIM_BLANK +int HtmlLineWasBlank = 0; +#endif /* TABLE_TRIM_BLANK */ + +/* +** Do as much layout as possible on the block of text defined by +** the HtmlLayoutContext. +*/ +void HtmlLayoutBlock(HtmlLayoutContext *pLC){ + HtmlElement *p, *pNext; + + for(p=pLC->pStart; p && p!=pLC->pEnd; p=pNext){ + int lineWidth; + int actualWidth; + int y = 0; + int leftMargin; + int maxX = 0; + + /* Do as much break markup as we can. */ + while( p && p!=pLC->pEnd ){ + HtmlLock(pLC->htmlPtr); + pNext = DoBreakMarkup(pLC, p); + if( HtmlUnlock(pLC->htmlPtr) ) return; + if( pNext==p ){ TestPoint(0); break; } + if( pNext ){ + TRACE(HtmlTrace_BreakMarkup, + ("Processed token %s as break markup\n", HtmlTokenName(p))); + pLC->pStart = p; + } + p = pNext; + TestPoint(0); + } + if( p==0 || p==pLC->pEnd ){ TestPoint(0); break; } + +#ifdef TABLE_TRIM_BLANK + HtmlLineWasBlank = 0; +#endif /* TABLE_TRIM_BLANK */ + + /* We might try several times to layout a single line... */ + while( 1 ){ + + /* Compute margins */ + HtmlComputeMargins(pLC, &leftMargin, &y, &lineWidth); + + /* Layout a single line of text */ + pNext = GetLine(pLC, p, pLC->pEnd, lineWidth, pLC->left-leftMargin, + &actualWidth); + TRACE(HtmlTrace_GetLine, + ("GetLine page=%d left=%d right=%d available=%d used=%d\n", + pLC->pageWidth, pLC->left, pLC->right, lineWidth, actualWidth)); + FixAnchors(p,pNext,pLC->bottom); + + /* Move down and repeat the layout if we exceeded the available + ** line length and it is possible to increase the line length by + ** moving past some obsticle. + */ + if( actualWidth > lineWidth && InWrapAround(pLC) ){ + ClearObstacle(pLC, CLEAR_First); + TestPoint(0); + continue; + } + + /* Lock the line into place and exit the loop */ + y = FixLine(p, pNext, y, lineWidth, actualWidth, leftMargin, &maxX); + TestPoint(0); + break; + } + +#ifdef TABLE_TRIM_BLANK + /* + * I noticed that a newline following break markup would result + * in a blank line being drawn. So if an "empty" line was found + * I subtract any whitespace caused by break markup. + */ + if (actualWidth <= 0) + { + HtmlLineWasBlank = 1; + } +#endif /* TABLE_TRIM_BLANK */ + + /* If a line was completed, advance to the next line */ + if( pNext && actualWidth>0 && y > pLC->bottom ){ + pLC->bottom = y; + pLC->headRoom = 0; + pLC->pStart = pNext; + } + if( y > pLC->maxY ){ + pLC->maxY = y; + } + if( maxX > pLC->maxX ){ + pLC->maxX = maxX; + } + } +} + +/* +** Advance the layout as far as possible +*/ +void HtmlLayout(HtmlWidget *htmlPtr){ + HtmlLayoutContext *pLC; + int btm; + + if( htmlPtr->pFirst==0 ) return; + HtmlLock(htmlPtr); + HtmlSizer(htmlPtr); + if( HtmlUnlock(htmlPtr) ) return; + pLC = &htmlPtr->layoutContext; + pLC->htmlPtr = htmlPtr; + pLC->pageWidth = htmlPtr->realWidth - 2*(htmlPtr->inset + htmlPtr->padx); + pLC->left = 0; + pLC->right = 0; + pLC->pStart = htmlPtr->nextPlaced; + if( pLC->pStart==0 ){ + pLC->pStart = htmlPtr->pFirst; + } + if( pLC->pStart ){ + pLC->maxX = htmlPtr->maxX; + pLC->maxY = htmlPtr->maxY; + btm = pLC->bottom; + HtmlLock(htmlPtr); + HtmlLayoutBlock(pLC); + if( HtmlUnlock(htmlPtr) ) return; + htmlPtr->maxX = pLC->maxX; + htmlPtr->maxY = pLC->maxY; + htmlPtr->nextPlaced = pLC->pStart; + htmlPtr->flags |= HSCROLL | VSCROLL; + HtmlRedrawText(htmlPtr, btm); + } +} diff --git a/tkhtml1/src/htmllayout.h b/tkhtml1/src/htmllayout.h new file mode 100644 index 0000000..bf4ce59 --- /dev/null +++ b/tkhtml1/src/htmllayout.h @@ -0,0 +1,564 @@ +/* This file was automatically generated. Do not edit! */ +typedef struct HtmlWidget HtmlWidget; +void HtmlRedrawText(HtmlWidget *htmlPtr,int y); +#define VSCROLL 0x000008 +#define HSCROLL 0x000004 +void HtmlSizer(HtmlWidget *htmlPtr); +typedef union HtmlElement HtmlElement; +typedef struct HtmlBlock HtmlBlock; +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +typedef short Html_16; +typedef struct HtmlScript HtmlScript; +#define Html_TypeCount 151 +typedef struct HtmlStyleStack HtmlStyleStack; +typedef struct HtmlLayoutContext HtmlLayoutContext; +typedef struct HtmlMargin HtmlMargin; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +typedef unsigned char Html_u8; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +typedef struct HtmlImage HtmlImage; +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +void HtmlLayout(HtmlWidget *htmlPtr); +#define HtmlTrace_GetLine 0x00000100 +#define HtmlTrace_BreakMarkup 0x00001000 +int HtmlUnlock(HtmlWidget *htmlPtr); +void HtmlLock(HtmlWidget *htmlPtr); +void HtmlLayoutBlock(HtmlLayoutContext *pLC); +#if defined(TABLE_TRIM_BLANK) +extern int HtmlLineWasBlank; +#endif +void HtmlWidenLine(HtmlLayoutContext *pLC,int reqWidth,int *pX,int *pY,int *pW); +#if !defined(HAVE_STRICMP) +# define stricmp strcasecmp +#endif +HtmlElement *HtmlTableLayout(HtmlLayoutContext *pLC,HtmlElement *pTable); +#define ALIGN_None 0 +char *HtmlMarkupArg(HtmlElement *p,const char *tag,char *zDefault); +#define Html_EndDIR 40 +#define Html_DIR 39 +#define SETMAX(A,B) if( (A)<(B) ){ (A) = (B); } +void HtmlComputeMargins(HtmlLayoutContext *pLC,int *pX,int *pY,int *pW); +Tk_Font HtmlGetFont(HtmlWidget *htmlPtr,int iFont); +#define HtmlTrace_FixLine 0x00000400 +#define IMAGE_ALIGN_TextTop 3 +#define IMAGE_ALIGN_Top 2 +#define IMAGE_ALIGN_AbsBottom 5 +#define IMAGE_ALIGN_Bottom 0 +#define IMAGE_ALIGN_AbsMiddle 4 +#define IMAGE_ALIGN_Middle 1 +#define ALIGN_Right 2 +#define ALIGN_Center 3 +#define Html_A 5 +#define Html_EndUL 146 +#define Html_UL 145 +#define Html_EndTR 140 +#define Html_TR 139 +#define Html_EndTH 136 +#define Html_TH 135 +#define Html_EndTD 132 +#define Html_TD 131 +#define Html_EndTABLE 130 +#define Html_TABLE 129 +#define Html_EndPRE 110 +#define Html_PRE 109 +#define Html_EndP 105 +#define Html_EndOL 101 +#define Html_OL 100 +#define Html_EndMENU 91 +#define Html_MENU 90 +#define Html_EndLISTING 85 +#define Html_LISTING 84 +#define Html_HR 70 +#define Html_EndHTML 72 +#define Html_EndH6 69 +#define Html_H6 68 +#define Html_EndH5 67 +#define Html_H5 66 +#define Html_EndH4 65 +#define Html_H4 64 +#define Html_EndH3 63 +#define Html_H3 62 +#define Html_EndH2 61 +#define Html_H2 60 +#define Html_EndH1 59 +#define Html_H1 58 +#define Html_DT 45 +#define Html_EndDL 44 +#define Html_DL 43 +#define Html_EndDIV 42 +#define Html_DIV 41 +#define Html_EndDD 36 +#define Html_EndCENTER 28 +#define Html_CENTER 27 +#define Html_EndCAPTION 26 +#define Html_CAPTION 25 +#define Html_BR 24 +#define Html_EndBODY 23 +#define Html_BODY 22 +#define Html_EndBLOCKQUOTE 21 +#define Html_BLOCKQUOTE 20 +#define Html_EndADDRESS 8 +#define Html_ADDRESS 7 +#define Html_WBR 149 +#define Html_DD 35 +#define Html_EndTEXTAREA 134 +#define Html_TEXTAREA 133 +#define Html_SELECT 116 +#define Html_INPUT 77 +#define Html_EMBED 49 +#define Html_APPLET 9 +#define IMAGE_ALIGN_Right 7 +#define IMAGE_ALIGN_Left 6 +#define Html_IMG 76 +#define STY_NoBreak 0x008 +#define HTML_NewLine 0x02 /* type==Html_Space and ends with newline */ +char *HtmlTokenName(HtmlElement *p); +#define HtmlTrace_GetLine2 0x00000200 +extern int HtmlTraceMask; +#define DEBUG 1 +#if defined(DEBUG) +extern int HtmlDepth; +# define TRACE_INDENT printf("%*s",HtmlDepth-3,"") +#endif +#if !(defined(DEBUG)) +# define TRACE_INDENT +#endif +#if defined(DEBUG) +# define TRACE(Flag, Args) \ + if( (Flag)&HtmlTraceMask ){ \ + TRACE_INDENT; printf Args; fflush(stdout); \ + } +#endif +#if !(defined(DEBUG)) +# define TRACE(Flag, Args) +#endif +#define STY_Preformatted 0x001 +#define Html_Text 1 +#define Html_P 104 +#define Html_Space 2 +#define Html_LI 81 +#define HTML_INDENT 36 +#define STY_DT 0x020 +#define STY_Invisible 0x040 +typedef struct HtmlBaseElement HtmlBaseElement; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +typedef struct HtmlTextElement HtmlTextElement; +typedef int Html_32; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlMarkupElement HtmlMarkupElement; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +typedef unsigned short Html_u16; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +void HtmlClearMarginStack(HtmlMargin **ppMargin); +#define HtmlFree(A) Tcl_Free((char*)(A)) +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +#define HtmlAlloc(A) ((void*)Tcl_Alloc(A)) +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; +void HtmlPushMargin(HtmlMargin **ppMargin,int indent,int bottom,int tag); +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; diff --git a/tkhtml1/src/htmlparse.c b/tkhtml1/src/htmlparse.c new file mode 100644 index 0000000..4511005 --- /dev/null +++ b/tkhtml1/src/htmlparse.c @@ -0,0 +1,1181 @@ +/* +** A tokenizer that converts raw HTML into a linked list of HTML elements. +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <tk.h> +#include "htmlparse.h" + +/****************** Begin Escape Sequence Translator *************/ +/* +** The next section of code implements routines used to translate +** the '&' escape sequences of SGML to individual characters. +** Examples: +** +** & & +** < < +** > > +** nonbreakable space +*/ + +/* Each escape sequence is recorded as an instance of the following +** structure +*/ +struct sgEsc { + char *zName; /* The name of this escape sequence. ex: "amp" */ + char value[8]; /* The value for this sequence. ex: "&" */ + struct sgEsc *pNext; /* Next sequence with the same hash on zName */ +}; + +/* The following is a table of all escape sequences. Add new sequences +** by adding entries to this table. +*/ +static struct sgEsc esc_sequences[] = { + { "quot", "\"", 0 }, + { "amp", "&", 0 }, + { "lt", "<", 0 }, + { "gt", ">", 0 }, + { "nbsp", " ", 0 }, + { "iexcl", "\241", 0 }, + { "cent", "\242", 0 }, + { "pound", "\243", 0 }, + { "curren", "\244", 0 }, + { "yen", "\245", 0 }, + { "brvbar", "\246", 0 }, + { "sect", "\247", 0 }, + { "uml", "\250", 0 }, + { "copy", "\251", 0 }, + { "ordf", "\252", 0 }, + { "laquo", "\253", 0 }, + { "not", "\254", 0 }, + { "shy", "\255", 0 }, + { "reg", "\256", 0 }, + { "macr", "\257", 0 }, + { "deg", "\260", 0 }, + { "plusmn", "\261", 0 }, + { "sup2", "\262", 0 }, + { "sup3", "\263", 0 }, + { "acute", "\264", 0 }, + { "micro", "\265", 0 }, + { "para", "\266", 0 }, + { "middot", "\267", 0 }, + { "cedil", "\270", 0 }, + { "sup1", "\271", 0 }, + { "ordm", "\272", 0 }, + { "raquo", "\273", 0 }, + { "frac14", "\274", 0 }, + { "frac12", "\275", 0 }, + { "frac34", "\276", 0 }, + { "iquest", "\277", 0 }, + { "Agrave", "\300", 0 }, + { "Aacute", "\301", 0 }, + { "Acirc", "\302", 0 }, + { "Atilde", "\303", 0 }, + { "Auml", "\304", 0 }, + { "Aring", "\305", 0 }, + { "AElig", "\306", 0 }, + { "Ccedil", "\307", 0 }, + { "Egrave", "\310", 0 }, + { "Eacute", "\311", 0 }, + { "Ecirc", "\312", 0 }, + { "Euml", "\313", 0 }, + { "Igrave", "\314", 0 }, + { "Iacute", "\315", 0 }, + { "Icirc", "\316", 0 }, + { "Iuml", "\317", 0 }, + { "ETH", "\320", 0 }, + { "Ntilde", "\321", 0 }, + { "Ograve", "\322", 0 }, + { "Oacute", "\323", 0 }, + { "Ocirc", "\324", 0 }, + { "Otilde", "\325", 0 }, + { "Ouml", "\326", 0 }, + { "times", "\327", 0 }, + { "Oslash", "\330", 0 }, + { "Ugrave", "\331", 0 }, + { "Uacute", "\332", 0 }, + { "Ucirc", "\333", 0 }, + { "Uuml", "\334", 0 }, + { "Yacute", "\335", 0 }, + { "THORN", "\336", 0 }, + { "szlig", "\337", 0 }, + { "agrave", "\340", 0 }, + { "aacute", "\341", 0 }, + { "acirc", "\342", 0 }, + { "atilde", "\343", 0 }, + { "auml", "\344", 0 }, + { "aring", "\345", 0 }, + { "aelig", "\346", 0 }, + { "ccedil", "\347", 0 }, + { "egrave", "\350", 0 }, + { "eacute", "\351", 0 }, + { "ecirc", "\352", 0 }, + { "euml", "\353", 0 }, + { "igrave", "\354", 0 }, + { "iacute", "\355", 0 }, + { "icirc", "\356", 0 }, + { "iuml", "\357", 0 }, + { "eth", "\360", 0 }, + { "ntilde", "\361", 0 }, + { "ograve", "\362", 0 }, + { "oacute", "\363", 0 }, + { "ocirc", "\364", 0 }, + { "otilde", "\365", 0 }, + { "ouml", "\366", 0 }, + { "divide", "\367", 0 }, + { "oslash", "\370", 0 }, + { "ugrave", "\371", 0 }, + { "uacute", "\372", 0 }, + { "ucirc", "\373", 0 }, + { "uuml", "\374", 0 }, + { "yacute", "\375", 0 }, + { "thorn", "\376", 0 }, + { "yuml", "\377", 0 }, +}; + +/* The size of the handler hash table. For best results this should +** be a prime number which is about the same size as the number of +** escape sequences known to the system. */ +#define ESC_HASH_SIZE (sizeof(esc_sequences)/sizeof(esc_sequences[0])+7) + +/* The hash table +** +** If the name of an escape sequences hashes to the value H, then +** apEscHash[H] will point to a linked list of Esc structures, one of +** which will be the Esc structure for that escape sequence. +*/ +static struct sgEsc *apEscHash[ESC_HASH_SIZE]; + +/* Hash a escape sequence name. The value returned is an integer +** between 0 and ESC_HASH_SIZE-1, inclusive. +*/ +static int EscHash(const char *zName){ + int h = 0; /* The hash value to be returned */ + char c; /* The next character in the name being hashed */ + + while( (c=*zName)!=0 ){ + h = h<<5 ^ h ^ c; + zName++; + TestPoint(0); + } + if( h<0 ){ + h = -h; + TestPoint(0); + }else{ + TestPoint(0); + } + return h % ESC_HASH_SIZE; +} + +#ifdef TEST +/* +** Compute the longest and average collision chain length for the +** escape sequence hash table +*/ +static void EscHashStats(void){ + int i; + int sum = 0; + int max = 0; + int cnt; + int notempty = 0; + struct sgEsc *p; + + for(i=0; i<sizeof(esc_sequences)/sizeof(esc_sequences[0]); i++){ + cnt = 0; + p = apEscHash[i]; + if( p ) notempty++; + while( p ){ + cnt++; + p = p->pNext; + } + sum += cnt; + if( cnt>max ) max = cnt; + } + printf("Longest chain=%d avg=%g slots=%d empty=%d (%g%%)\n", + max,(double)sum/(double)notempty, i, i-notempty, + 100.0*(i-notempty)/(double)i); +} +#endif + +/* Initialize the escape sequence hash table +*/ +static void EscInit(void){ + int i; /* For looping thru the list of escape sequences */ + int h; /* The hash on a sequence */ + + for(i=0; i<sizeof(esc_sequences)/sizeof(esc_sequences[i]); i++){ +/* #ifdef TCL_UTF_MAX */ +#if 0 + { + int c = esc_sequences[i].value[0]; + Tcl_UniCharToUtf(c, esc_sequences[i].value); + } +#endif + h = EscHash(esc_sequences[i].zName); + esc_sequences[i].pNext = apEscHash[h]; + apEscHash[h] = &esc_sequences[i]; + TestPoint(0); + } +#ifdef TEST + EscHashStats(); +#endif +} + +/* +** This table translates the non-standard microsoft characters between +** 0x80 and 0x9f into plain ASCII so that the characters will be visible +** on Unix systems. Care is taken to translate the characters +** into values less than 0x80, to avoid UTF-8 problems. +*/ +#ifndef __WIN32__ +static char acMsChar[] = { + /* 0x80 */ 'C', + /* 0x81 */ ' ', + /* 0x82 */ ',', + /* 0x83 */ 'f', + /* 0x84 */ '"', + /* 0x85 */ '.', + /* 0x86 */ '*', + /* 0x87 */ '*', + /* 0x88 */ '^', + /* 0x89 */ '%', + /* 0x8a */ 'S', + /* 0x8b */ '<', + /* 0x8c */ 'O', + /* 0x8d */ ' ', + /* 0x8e */ 'Z', + /* 0x8f */ ' ', + /* 0x90 */ ' ', + /* 0x91 */ '\'', + /* 0x92 */ '\'', + /* 0x93 */ '"', + /* 0x94 */ '"', + /* 0x95 */ '*', + /* 0x96 */ '-', + /* 0x97 */ '-', + /* 0x98 */ '~', + /* 0x99 */ '@', + /* 0x9a */ 's', + /* 0x9b */ '>', + /* 0x9c */ 'o', + /* 0x9d */ ' ', + /* 0x9e */ 'z', + /* 0x9f */ 'Y', +}; +#endif + +/* Translate escape sequences in the string "z". "z" is overwritten +** with the translated sequence. +** +** Unrecognized escape sequences are unaltered. +** +** Example: +** +** input = "AT&T > MCI" +** output = "AT&T > MCI" +*/ +LOCAL void HtmlTranslateEscapes(char *z){ + int from; /* Read characters from this position in z[] */ + int to; /* Write characters into this position in z[] */ + int h; /* A hash on the escape sequence */ + struct sgEsc *p; /* For looping down the escape sequence collision chain */ + static int isInit = 0; /* True after initialization */ + + from = to = 0; + if( !isInit ){ + EscInit(); + isInit = 1; + } + while( z[from] ){ + if( z[from]=='&' ){ + if( z[from+1]=='#' ){ + int i = from + 2; + int v = 0; + while( isdigit(z[i]) ){ + v = v*10 + z[i] - '0'; + i++; + } + if( z[i]==';' ){ i++; } + + /* On Unix systems, translate the non-standard microsoft + ** characters in the range of 0x80 to 0x9f into something + ** we can see. + */ +#ifndef __WIN32__ + if( v>=0x80 && v<0xa0 ){ + v = acMsChar[v&0x1f]; + } +#endif + /* Put the character in the output stream in place of + ** the "�". How we do this depends on whether or + ** not we are using UTF-8. + */ +#ifdef TCL_UTF_MAX + { + int j, n; + char value[8]; + n = Tcl_UniCharToUtf(v,value); + for(j=0; j<n; j++){ + z[to++] = value[j]; + } + } +#else + z[to++] = v; +#endif + from = i; + }else{ + int i = from+1; + int c; + while( z[i] && isalnum(z[i]) ){ TestPoint(0); i++; } + c = z[i]; + z[i] = 0; + h = EscHash(&z[from+1]); + p = apEscHash[h]; + while( p && strcmp(p->zName,&z[from+1])!=0 ){ + p = p->pNext; + } + z[i] = c; + if( p ){ + int j; + for(j=0; p->value[j]; j++){ + z[to++] = p->value[j]; + } + from = i; + if( c==';' ){ + from++; + } + }else{ + z[to++] = z[from++]; + } + } + + /* On UNIX systems, look for the non-standard microsoft characters + ** between 0x80 and 0x9f and translate them into printable ASCII + ** codes. Separate algorithms are required to do this for plain + ** ascii and for utf-8. + */ +#ifndef __WIN32__ +#ifdef TCL_UTF_MAX + }else if( (z[from]&0x80)!=0 ){ + Tcl_UniChar c; + int n; + n = Tcl_UtfToUniChar(&z[from], &c); + if( c>=0x80 && c<0xa0 ){ + z[to++] = acMsChar[c & 0x1f]; + from += n; + }else{ + while( n-- ) z[to++] = z[from++]; + } +#else /* if !defined(TCL_UTF_MAX) */ + }else if( ((unsigned char)z[from])>=0x80 && ((unsigned char)z[from])<0xa0 ){ + z[to++] = acMsChar[z[from++]&0x1f]; +#endif /* TCL_UTF_MAX */ +#endif /* __WIN32__ */ + }else{ + z[to++] = z[from++]; + TestPoint(0); + } + } + z[to] = 0; +} +/******************* End Escape Sequence Translator ***************/ + +/******************* Begin HTML tokenizer code *******************/ +/* +** The following variable becomes TRUE when the markup hash table +** (stored in HtmlMarkupMap[]) is initialized. +*/ +static int isInit = 0; + +/* The hash table for HTML markup names. +** +** If an HTML markup name hashes to H, then apMap[H] will point to +** a linked list of sgMap structure, one of which will describe the +** the particular markup (if it exists.) +*/ +static HtmlTokenMap *apMap[HTML_MARKUP_HASH_SIZE]; + +/* Hash a markup name +** +** HTML markup is case insensitive, so this function will give the +** same hash regardless of the case of the markup name. +** +** The value returned is an integer between 0 and HTML_MARKUP_HASH_SIZE-1, +** inclusive. +*/ +static int HtmlHash(const char *zName){ + int h = 0; + char c; + while( (c=*zName)!=0 ){ + if( isupper(c) ){ + c = tolower(c); + } + h = h<<5 ^ h ^ c; + zName++; + } + if( h<0 ){ + h = -h; + } + return h % HTML_MARKUP_HASH_SIZE; +} + +#ifdef TEST +/* +** Compute the longest and average collision chain length for the +** markup hash table +*/ +static void HtmlHashStats(void){ + int i; + int sum = 0; + int max = 0; + int cnt; + int notempty = 0; + struct sgMap *p; + + for(i=0; i<HTML_MARKUP_COUNT; i++){ + cnt = 0; + p = apMap[i]; + if( p ) notempty++; + while( p ){ + cnt++; + p = p->pCollide; + } + sum += cnt; + if( cnt>max ) max = cnt; + + } + printf("longest chain=%d avg=%g slots=%d empty=%d (%g%%)\n", + max, (double)sum/(double)notempty, i, i-notempty, + 100.0*(i-notempty)/(double)i); +} +#endif + +/* Initialize the escape sequence hash table +*/ +static void HtmlHashInit(void){ + int i; /* For looping thru the list of markup names */ + int h; /* The hash on a markup name */ + + for(i=0; i<HTML_MARKUP_COUNT; i++){ + h = HtmlHash(HtmlMarkupMap[i].zName); + HtmlMarkupMap[i].pCollide = apMap[h]; + apMap[h] = &HtmlMarkupMap[i]; + } +#ifdef TEST + HtmlHashStats(); +#endif +} + +/* +** Append the given HtmlElement to the tokenizers list of elements +*/ +static void AppendElement(HtmlWidget *p, HtmlElement *pElem){ + pElem->base.pNext = 0; + pElem->base.pPrev = p->pLast; + if( p->pFirst==0 ){ + p->pFirst = pElem; + }else{ + p->pLast->base.pNext = pElem; + } + p->pLast = pElem; + p->nToken++; +} + +/* +** Compute the new column index following the given character. +*/ +static int NextColumn(int iCol, char c){ + switch( c ){ + case '\n': return 0; + case '\t': return (iCol | 7) + 1; + default: return iCol+1; + } + /* NOT REACHED */ +} + +/* +** Convert a string to all lower-case letters. +*/ +static void ToLower(char *z){ + while( *z ){ + if( isupper(*z) ) *z = tolower(*z); + z++; + } +} + +/* Process as much of the input HTML as possible. Construct new +** HtmlElement structures and appended them to the list. Return +** the number of characters actually processed. +** +** This routine may invoke a callback procedure which could delete +** the HTML widget. +** +** This routine is not reentrant for the same HTML widget. To +** prevent reentrancy (during a callback), the p->iCol field is +** set to a negative number. This is a flag to future invocations +** not to reentry this routine. The p->iCol field is restored +** before exiting, of course. +*/ +static int Tokenize( + HtmlWidget *p /* The HTML widget doing the parsing */ +){ + char *z; /* The input HTML text */ + int c; /* The next character of input */ + int n; /* Number of characters processed so far */ + int iCol; /* Column of input */ + int i, j; /* Loop counters */ + int h; /* Result from HtmlHash() */ + int nByte; /* Space allocated for a single HtmlElement */ + HtmlElement *pElem; /* A new HTML element */ + int selfClose; /* True for content free elements. Ex: <br/> */ + int argc; /* The number of arguments on a markup */ + HtmlTokenMap *pMap; /* For searching the markup name hash table */ + char *zBuf; /* For handing out buffer space */ +# define mxARG 200 /* Maximum number of parameters in a single markup */ + char *argv[mxARG]; /* Pointers to each markup argument. */ + int arglen[mxARG]; /* Length of each markup argument */ + + iCol = p->iCol; + n = p->nComplete; + z = p->zText; + if( iCol<0 ){ TestPoint(0); return n; } /* Prevents recursion */ + p->iCol = -1; + while( (c=z[n])!=0 ){ + if( p->pScript ){ + /* We are in the middle of <SCRIPT>...</SCRIPT>. Just look for + ** the </SCRIPT> markup. (later:) Treat <STYLE>...</STYLE> the + ** same way. */ + HtmlScript *pScript = p->pScript; + char *zEnd; + int nEnd; + if( pScript->markup.base.type==Html_SCRIPT ){ + zEnd = "</script>"; + nEnd = 9; + }else{ + zEnd = "</style>"; + nEnd = 8; + } + if( pScript->zScript==0 ){ + pScript->zScript = &z[n]; + pScript->nScript = 0; + } + for(i=n+pScript->nScript; z[i]; i++){ + if( z[i]=='<' && z[i+1]=='/' && strnicmp(&z[i],zEnd,nEnd)==0 ){ + pScript->nScript = i - n; + p->pScript = 0; + n = i+nEnd; + break; + } + } + if( p->pScript ){ + pScript->nScript = i - n; + } + continue; + }else if( isspace(c) ){ + /* White space */ + for(i=0; (c=z[n+i])!=0 && isspace(c) && c!='\n' && c!='\r'; i++){} + if( c=='\r' && z[n+i+1]=='\n' ){ i++; } + pElem = HtmlAlloc( sizeof(HtmlSpaceElement) ); + if( pElem==0 ){ goto incomplete; } + pElem->base.type = Html_Space; + if( c=='\n' || c=='\r' ){ + pElem->base.flags = HTML_NewLine; + pElem->base.count = 1; + i++; + iCol = 0; + TestPoint(0); + }else{ + int iColStart = iCol; + pElem->base.flags = 0; + for(j=0; j<i; j++){ + iCol = NextColumn(iCol, z[n+j]); + TestPoint(0); + } + pElem->base.count = iCol - iColStart; + } + AppendElement(p,pElem); + n += i; + }else if( c!='<' || p->iPlaintext!=0 || + (!isalpha(z[n+1]) && z[n+1]!='/' && z[n+1]!='!' && z[n+1]!='?') ){ + /* Ordinary text */ + for(i=1; (c=z[n+i])!=0 && !isspace(c) && c!='<'; i++){} + if( c==0 ){ TestPoint(0); goto incomplete; } + if( p->iPlaintext!=0 && z[n]=='<' ){ + switch( p->iPlaintext ){ + case Html_LISTING: + if( i>=10 && strnicmp(&z[n],"</listing>",10)==0 ){ + p->iPlaintext = 0; + goto doMarkup; + } + break; + case Html_XMP: + if( i>=6 && strnicmp(&z[n],"</xmp>",6)==0 ){ + p->iPlaintext = 0; + goto doMarkup; + } + break; + case Html_TEXTAREA: + if( i>=11 && strnicmp(&z[n],"</textarea>",11)==0 ){ + p->iPlaintext = 0; + goto doMarkup; + } + break; + default: + break; + } + } + nByte = sizeof(HtmlTextElement) + i; + pElem = HtmlAlloc( nByte ); + if( pElem==0 ){ goto incomplete; } + memset(pElem,0,nByte); + pElem->base.type = Html_Text; + sprintf(pElem->text.zText,"%.*s",i,&z[n]); + AppendElement(p,pElem); + if( p->iPlaintext==0 || p->iPlaintext==Html_TEXTAREA ){ + HtmlTranslateEscapes(pElem->text.zText); + } + pElem->base.count = strlen(pElem->text.zText); + n += i; + iCol += i; + }else if( strncmp(&z[n],"<!--",4)==0 ){ + /* An HTML comment. Just skip it. */ + for(i=4; z[n+i]; i++){ + if( z[n+i]=='-' && strncmp(&z[n+i],"-->",3)==0 ){ break; } + } + if( z[n+i]==0 ){ TestPoint(0); goto incomplete; } + for(j=0; j<i+3; j++){ + iCol = NextColumn(iCol, z[n+j]); + } + n += i + 3; + }else{ + /* Markup. + ** + ** First get the name of the markup + */ +doMarkup: + argc = 1; + argv[0] = &z[n+1]; + for(i=1; (c=z[n+i])!=0 && !isspace(c) && c!='>' && (i<2 || c!='/'); i++){} + arglen[0] = i - 1; + if( c==0 ){ goto incomplete; } + + /* + ** Now parse up the arguments + */ + while( isspace(z[n+i]) ){ i++; } + while( (c=z[n+i])!=0 && c!='>' && (c!='/' || z[n+i+1]!='>') ){ + if( argc>mxARG-3 ){ + argc = mxARG-3; + } + argv[argc] = &z[n+i]; + j = 0; + while( (c=z[n+i+j])!=0 && !isspace(c) && c!='>' + && c!='=' && (c!='/' || z[n+i+j+1]!='>') ){ + j++; + } + arglen[argc] = j; + if( c==0 ){ goto incomplete; } + i += j; + while( isspace(c) ){ + i++; + c = z[n+i]; + } + if( c==0 ){ goto incomplete; } + argc++; + if( c!='=' ){ + argv[argc] = ""; + arglen[argc] = 0; + argc++; + continue; + } + i++; + c = z[n+i]; + while( isspace(c) ){ + i++; + c = z[n+i]; + } + if( c==0 ){ goto incomplete; } + if( c=='\'' || c=='"' ){ + int cQuote = c; + i++; + argv[argc] = &z[n+i]; + for(j=0; (c=z[n+i+j])!=0 && c!=cQuote; j++){} + if( c==0 ){ goto incomplete; } + arglen[argc] = j; + i += j+1; + TestPoint(0); + }else{ + argv[argc] = &z[n+i]; + for(j=0; (c=z[n+i+j])!=0 && !isspace(c) && c!='>'; j++){} + if( c==0 ){ goto incomplete; } + arglen[argc] = j; + i += j; + } + argc++; + while( isspace(z[n+i]) ){ i++; } + } + if( c=='/' ){ + i++; + c = z[n+i]; + selfClose = 1; + }else{ + selfClose = 0; + } + if( c==0 ){ goto incomplete; } + for(j=0; j<i+1; j++){ + iCol = NextColumn(iCol, z[n+j]); + } + n += i + 1; + + /* Lookup the markup name in the hash table + */ + if( !isInit ){ + HtmlHashInit(); + isInit = 1; + } + c = argv[0][arglen[0]]; + argv[0][arglen[0]] = 0; + h = HtmlHash(argv[0]); + for(pMap = apMap[h]; pMap; pMap=pMap->pCollide){ + if( stricmp(pMap->zName,argv[0])==0 ){ break; } + TestPoint(0); + } + argv[0][arglen[0]] = c; + if( pMap==0 ){ continue; } /* Ignore unknown markup */ + +makeMarkupEntry: + /* Construct a HtmlMarkup entry for this markup. + */ + if( pMap->extra ){ + nByte = pMap->extra; + }else if( argc==1 ){ + nByte = sizeof(HtmlBaseElement); + }else{ + nByte = sizeof(HtmlMarkupElement); + } + if( argc>1 ){ + nByte += sizeof(char*) * argc; + for(j=1; j<argc; j++){ + nByte += arglen[j] + 1; + } + } + pElem = HtmlAlloc( nByte ); + if( pElem==0 ){ goto incomplete; } + memset(pElem,0,nByte); + pElem->base.type = pMap->type; + pElem->base.count = argc - 1; + if( argc>1 ){ + if( pMap->extra ){ + pElem->markup.argv = (char**)&((char*)pElem)[pMap->extra]; + }else{ + pElem->markup.argv = (char**)&((HtmlMarkupElement*)pElem)[1]; + } + zBuf = (char*)&pElem->markup.argv[argc]; + for(j=1; j<argc; j++){ + pElem->markup.argv[j-1] = zBuf; + zBuf += arglen[j] + 1; + sprintf(pElem->markup.argv[j-1],"%.*s",arglen[j],argv[j]); + HtmlTranslateEscapes(pElem->markup.argv[j-1]); + if( (j&1)==1 ){ + ToLower(pElem->markup.argv[j-1]); + } + } + pElem->markup.argv[argc-1] = 0; + } + + /* The new markup has now be constructed in pElem. But before + ** appending to the list, check to see if there is a special + ** handler for this markup type. + */ + if( p->zHandler[pMap->type] ){ + Tcl_DString str; + Tcl_DStringInit(&str); + Tcl_DStringAppend(&str, p->zHandler[pMap->type], -1); + Tcl_DStringAppendElement(&str, pMap->zName); + Tcl_DStringStartSublist(&str); + for(j=0; j<argc-1; j++){ + Tcl_DStringAppendElement(&str, pElem->markup.argv[j]); + } + Tcl_DStringEndSublist(&str); + HtmlFree(pElem); + HtmlLock(p); + Tcl_GlobalEval(p->interp, Tcl_DStringValue(&str)); + Tcl_DStringFree(&str); + if( HtmlUnlock(p) ){ return 0; } + + /* Tricky, tricky. The callback might have caused the p->zText + ** pointer to change, so renew our copy of that pointer. The + ** callback might also have cleared or destroyed the widget. + ** If so, abort this routine. + */ + z = p->zText; + if( z==0 || p->tkwin==0 ){ + n = 0; + iCol = 0; + goto incomplete; + } + continue; + } + + /* No special handler for this markup. Just append it to the + ** list of all tokens. + */ + AppendElement(p,pElem); + switch( pMap->type ){ + case Html_PLAINTEXT: + case Html_LISTING: + case Html_XMP: + case Html_TEXTAREA: + p->iPlaintext = pMap->type; + break; + case Html_STYLE: + case Html_SCRIPT: + p->pScript = (HtmlScript*)pElem; + break; + default: + break; + } + + /* If this is self-closing markup (ex: <br/> or <img/>) then + ** synthesize a closing token. + */ + if( selfClose && argv[0][0]!='/' + && strcmp(&pMap[1].zName[1],pMap->zName)==0 ){ + selfClose = 0; + pMap++; + argc = 1; + goto makeMarkupEntry; + } + } + } +incomplete: + p->iCol = iCol; + return n; +} +/************************** End HTML Tokenizer Code ***************************/ + +/* +** Append text to the tokenizer engine. +** +** This routine (actually the Tokenize() subroutine that is called +** by this routine) may invoke a callback procedure which could delete +** the HTML widget. +*/ +void HtmlTokenizerAppend(HtmlWidget *htmlPtr, const char *zText){ + int len = strlen(zText); + if( htmlPtr->nText==0 ){ + htmlPtr->nAlloc = len + 100; + htmlPtr->zText = HtmlAlloc( htmlPtr->nAlloc ); + TestPoint(0); + }else if( htmlPtr->nText + len >= htmlPtr->nAlloc ){ + htmlPtr->nAlloc += len + 100; + htmlPtr->zText = HtmlRealloc( htmlPtr->zText, htmlPtr->nAlloc ); + TestPoint(0); + } + if( htmlPtr->zText==0 ){ + htmlPtr->nText = 0; + UNTESTED; + return; + } + strcpy(&htmlPtr->zText[htmlPtr->nText], zText); + htmlPtr->nText += len; + htmlPtr->nComplete = Tokenize(htmlPtr); +} + +/* +** This routine takes a text representation of a token, converts +** it into an HtmlElement structure and inserts it immediately +** prior to pToken. If pToken==0, then the newly created HtmlElement +** is appended. +** +** This routine does nothing to resize, restyle, relayout or redisplay +** the HTML. That is the calling routines responsibility. +** +** Return 0 if successful. Return non-zero if zType is not a known +** markup name. +*/ +int HtmlInsertToken( + HtmlWidget *htmlPtr, /* The widget into which the token is inserted */ + HtmlElement *pToken, /* Insert before this. Append if pToken==0 */ + char *zType, /* Type of markup. Ex: "/a" or "table" */ + char *zArgs /* List of arguments */ +){ + HtmlTokenMap *pMap; /* For searching the markup name hash table */ + int h; /* The hash on zType */ + HtmlElement *pElem; /* The new element */ + int nByte; /* How many bytes to allocate */ + int i; /* Loop counter */ + + if( !isInit ){ + HtmlHashInit(); + isInit = 1; + TestPoint(0); + }else{ + TestPoint(0); + } + h = HtmlHash(zType); + for(pMap = apMap[h]; pMap; pMap=pMap->pCollide){ + if( stricmp(pMap->zName,zType)==0 ){ TestPoint(0); break; } + TestPoint(0); + } + if( pMap==0 ){ TestPoint(0); return 1; } + + if( zArgs==0 || *zArgs==0 ){ + /* Special case of no arguments. This is a lot easier... */ + nByte = pMap->extra ? pMap->extra : sizeof(HtmlBaseElement); + nByte += strlen(zType); + pElem = HtmlAlloc( nByte ); + if( pElem==0 ){ TestPoint(0); return 1; } + memset(pElem,0,nByte); + pElem->base.type = pMap->type; + TestPoint(0); + }else{ + /* The general case. There are arguments that need to be parsed + ** up. This is slower, but we gotta do it. + */ + int argc; + const char **argv; + char *zBuf; + + if( Tcl_SplitList(htmlPtr->interp, zArgs, &argc, (const char***)&argv)!=TCL_OK ){ + TestPoint(0); + return 1; + } + if( pMap->extra ){ + nByte = pMap->extra; + TestPoint(0); + }else{ + nByte = sizeof(HtmlMarkupElement); + TestPoint(0); + } + nByte += sizeof(char*)*(argc+1) + strlen(zArgs) + argc + 2; + pElem = HtmlAlloc( nByte ); + if( pElem==0 ){ + HtmlFree(argv); + TestPoint(0); + return 1; + } + memset(pElem,0,nByte); + pElem->base.type = pMap->type; + pElem->base.count = argc; + if( pMap->extra ){ + pElem->markup.argv = (char**)&((char*)pElem)[pMap->extra]; + TestPoint(0); + }else{ + pElem->markup.argv = (char**)&((HtmlMarkupElement*)pElem)[1]; + TestPoint(0); + } + zBuf = (char*)&pElem->markup.argv[argc]; + for(i=1; i<argc; i++){ + pElem->markup.argv[i-1] = zBuf; + zBuf += strlen(argv[i]) + 1; + strcpy(pElem->markup.argv[i-1],argv[i]); + TestPoint(0); + } + pElem->markup.argv[argc-1] = 0; + HtmlFree(argv); + TestPoint(0); + } + if( pToken ){ + pElem->base.pNext = pToken; + pElem->base.pPrev = pToken->base.pPrev; + if( pToken->base.pPrev ){ + pToken->base.pPrev->pNext = pElem; + TestPoint(0); + }else{ + htmlPtr->pFirst = pElem; + TestPoint(0); + } + pToken->base.pPrev = pElem; + htmlPtr->nToken++; + }else{ + AppendElement(htmlPtr,pElem); + TestPoint(0); + } + return 0; +} + +/* +** Convert a markup name into a type integer +*/ +int HtmlNameToType(const char *zType){ + HtmlTokenMap *pMap; /* For searching the markup name hash table */ + int h; /* The hash on zType */ + + if( !isInit ){ + HtmlHashInit(); + isInit = 1; + TestPoint(0); + }else{ + TestPoint(0); + } + h = HtmlHash(zType); + for(pMap = apMap[h]; pMap; pMap=pMap->pCollide){ + if( stricmp(pMap->zName,zType)==0 ){ TestPoint(0); break; } + TestPoint(0); + } + return pMap ? pMap->type : Html_Unknown; +} + +/* +** Convert a type into a symbolic name +*/ +const char *HtmlTypeToName(int type){ + if( type>=Html_A && type<=Html_EndXMP ){ + HtmlTokenMap *pMap = apMap[type - Html_A]; + TestPoint(0); + return pMap->zName; + }else{ + TestPoint(0); + return "???"; + } +} + +/* +** For debugging purposes, print information about a token +*/ +char *HtmlTokenName(HtmlElement *p){ +#ifdef DEBUG + static char zBuf[200]; + int j; + char *zName; + + if( p==0 ) return "NULL"; + switch( p->base.type ){ + case Html_Text: + sprintf(zBuf,"\"%.*s\"",p->base.count,p->text.zText); + break; + case Html_Space: + if( p->base.flags & HTML_NewLine ){ + sprintf(zBuf,"\"\\n\""); + }else{ + sprintf(zBuf,"\" \""); + } + break; + case Html_Block: + if( p->block.n>0 ){ + int n = p->block.n; + if( n>150 ) n = 150; + sprintf(zBuf,"<Block z=\"%.*s\">", n, p->block.z); + }else{ + sprintf(zBuf,"<Block>"); + } + break; + default: + if( p->base.type >= HtmlMarkupMap[0].type + && p->base.type <= HtmlMarkupMap[HTML_MARKUP_COUNT-1].type ){ + zName = HtmlMarkupMap[p->base.type - HtmlMarkupMap[0].type].zName; + }else{ + zName = "Unknown"; + } + sprintf(zBuf,"<%s",zName); + for(j=1; j<p->base.count; j += 2){ + sprintf(&zBuf[strlen(zBuf)]," %s=%s", + p->markup.argv[j-1],p->markup.argv[j]); + } + strcat(zBuf,">"); + break; + } + return zBuf; +#else + return 0; +#endif +} + +/* +** Return all tokens between the two elements as a Tcl list. +*/ +void HtmlTclizeList(Tcl_Interp *interp, HtmlElement *p, HtmlElement *pEnd){ + Tcl_DString str; + int i; + char *zName; + char zLine[100]; + + Tcl_DStringInit(&str); + while( p && p!=pEnd ){ + switch( p->base.type ){ + case Html_Block: + break; + case Html_Text: + Tcl_DStringStartSublist(&str); + Tcl_DStringAppendElement(&str,"Text"); + Tcl_DStringAppendElement(&str, p->text.zText); + Tcl_DStringEndSublist(&str); + break; + case Html_Space: + sprintf(zLine,"Space %d %d", + p->base.count, (p->base.flags & HTML_NewLine)!=0); + Tcl_DStringAppendElement(&str,zLine); + break; + case Html_Unknown: + Tcl_DStringAppendElement(&str,"Unknown"); + break; + default: + Tcl_DStringStartSublist(&str); + Tcl_DStringAppendElement(&str,"Markup"); + if( p->base.type >= HtmlMarkupMap[0].type + && p->base.type <= HtmlMarkupMap[HTML_MARKUP_COUNT-1].type ){ + zName = HtmlMarkupMap[p->base.type - HtmlMarkupMap[0].type].zName; + }else{ + zName = "Unknown"; + } + Tcl_DStringAppendElement(&str, zName); + for(i=0; i<p->base.count; i++){ + Tcl_DStringAppendElement(&str, p->markup.argv[i]); + } + Tcl_DStringEndSublist(&str); + break; + } + p = p->pNext; + } + Tcl_DStringResult(interp, &str); +} + +/* +** Print a list of tokens +*/ +#ifdef DEBUG +void HtmlPrintList(HtmlElement *p, HtmlElement *pEnd){ + while( p && p!=pEnd ){ + if( p->base.type==Html_Block ){ + char *z = p->block.z; + int n = p->block.n; + if( n==0 || z==0 ){ + n = 1; + z = ""; + } + printf("Block 0x%08x flags=%02x cnt=%d x=%d..%d y=%d..%d z=\"%.*s\"\n", + (int)p, p->base.flags, p->base.count, p->block.left, p->block.right, + p->block.top, p->block.bottom, n, z); + }else{ + printf("Token 0x%08x font=%2d color=%2d align=%d flags=0x%04x name=%s\n", + (int)p, p->base.style.font, p->base.style.color, + p->base.style.align, p->base.style.flags, HtmlTokenName(p)); + } + p = p->pNext; + } +} +#endif diff --git a/tkhtml1/src/htmlparse.h b/tkhtml1/src/htmlparse.h new file mode 100644 index 0000000..a5ae83f --- /dev/null +++ b/tkhtml1/src/htmlparse.h @@ -0,0 +1,487 @@ +/* This file was automatically generated. Do not edit! */ +typedef union HtmlElement HtmlElement; +#define DEBUG 1 +#if defined(DEBUG) +void HtmlPrintList(HtmlElement *p,HtmlElement *pEnd); +#endif +void HtmlTclizeList(Tcl_Interp *interp,HtmlElement *p,HtmlElement *pEnd); +#define Html_Block 4 +char *HtmlTokenName(HtmlElement *p); +#define Html_EndXMP 151 +#define Html_A 5 +const char *HtmlTypeToName(int type); +#define Html_Unknown 3 +int HtmlNameToType(const char *zType); +typedef struct HtmlWidget HtmlWidget; +int HtmlInsertToken(HtmlWidget *htmlPtr,HtmlElement *pToken,char *zType,char *zArgs); +void HtmlTPUntested(const char *zFile,int line); +#if defined(COVERAGE_TEST) +# define UNTESTED HtmlTPUntested(__FILE__,__LINE__) +#endif +#if !(defined(COVERAGE_TEST)) +# define UNTESTED +#endif +#define HtmlRealloc(A,B) ((void*)Tcl_Realloc((A),(B))) +void HtmlTokenizerAppend(HtmlWidget *htmlPtr,const char *zText); +#define Html_STYLE 124 +#define Html_PLAINTEXT 108 +int HtmlUnlock(HtmlWidget *htmlPtr); +void HtmlLock(HtmlWidget *htmlPtr); +#define HtmlFree(A) Tcl_Free((char*)(A)) +typedef struct HtmlMarkupElement HtmlMarkupElement; +typedef struct HtmlBaseElement HtmlBaseElement; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +typedef unsigned char Html_u8; +typedef short Html_16; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +#if !defined(HAVE_STRICMP) +# define stricmp strcasecmp +#endif +#define Html_Text 1 +typedef struct HtmlTextElement HtmlTextElement; +typedef int Html_32; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +#define Html_TEXTAREA 133 +#define Html_XMP 150 +#define Html_LISTING 84 +#define HTML_NewLine 0x02 /* type==Html_Space and ends with newline */ +#define Html_Space 2 +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +#define HtmlAlloc(A) ((void*)Tcl_Alloc(A)) +#if !defined(HAVE_STRICMP) +# define strnicmp strncasecmp +#endif +#define Html_SCRIPT 115 +typedef struct HtmlScript HtmlScript; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +typedef unsigned short Html_u16; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +typedef struct HtmlImage HtmlImage; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +typedef struct HtmlBlock HtmlBlock; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +#define Html_TypeCount 151 +typedef struct HtmlStyleStack HtmlStyleStack; +typedef struct HtmlLayoutContext HtmlLayoutContext; +typedef struct HtmlMargin HtmlMargin; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +typedef struct HtmlTokenMap HtmlTokenMap; +struct HtmlTokenMap { + char *zName; /* Name of a markup */ + Html_16 type; /* Markup type code */ + Html_16 extra; /* Extra space needed above HtmlBaseElement */ + HtmlTokenMap *pCollide; /* Hash table collision chain */ +}; +extern HtmlTokenMap HtmlMarkupMap[]; +#define HTML_MARKUP_COUNT 147 +#define HTML_MARKUP_HASH_SIZE 163 +#define LOCAL static +LOCAL void HtmlTranslateEscapes(char *z); +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/htmlsizer.c b/tkhtml1/src/htmlsizer.c new file mode 100644 index 0000000..68d8dc9 --- /dev/null +++ b/tkhtml1/src/htmlsizer.c @@ -0,0 +1,1176 @@ +/* +** Routines used to compute the style and size of individual elements. +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <tk.h> +#include <string.h> +#include <stdlib.h> +#include "htmlsizer.h" + +/* +** Get the current rendering style. In other words, get the style +** that is currently on the top of the style stack. +*/ +static HtmlStyle GetCurrentStyle(HtmlWidget *htmlPtr){ + HtmlStyle style; + if( htmlPtr->styleStack ){ + style = htmlPtr->styleStack->style; + }else{ + style.font = NormalFont(2); + style.color = COLOR_Normal; + style.bgcolor = COLOR_Background; + style.subscript = 0; + style.align = ALIGN_Left; + style.flags = 0; + } + return style; +} + +/* +** Push a new rendering style onto the stack. +*/ +static void PushStyleStack( + HtmlWidget *htmlPtr, /* Widget on which to push the style */ + int tag, /* Tag for this style. Normally the end-tag such + ** as </h3> or </em>. */ + HtmlStyle style /* The style to push */ +){ + HtmlStyleStack *p; + + p = HtmlAlloc(sizeof(*p)); + p->pNext = htmlPtr->styleStack; + p->type = tag; + p->style = style; + htmlPtr->styleStack = p; +} + +/* +** Pop a rendering style off of the stack. +** +** The top-most style on the stack should have a tag equal to "tag". +** If not, then we have an HTML coding error. Perhaps something +** like this: "Some text <em>Enphasized</i> more text". It is an +** interesting problem to figure out how to respond sanely to this +** kind of error. Our solution it to keep popping the stack until +** we find the correct tag, or until the stack is empty. +*/ +HtmlStyle HtmlPopStyleStack(HtmlWidget *htmlPtr, int tag){ + int type; + HtmlStyleStack *p; + static Html_u8 priority[Html_TypeCount+1]; + + if( priority[Html_TABLE]==0 ){ + int i; + for(i=0; i<=Html_TypeCount; i++) priority[i] = 1; + priority[Html_TD] = 2; + priority[Html_EndTD] = 2; + priority[Html_TH] = 2; + priority[Html_EndTH] = 2; + priority[Html_TR] = 3; + priority[Html_EndTR] = 3; + priority[Html_TABLE] = 4; + priority[Html_EndTABLE] = 4; + } + if( tag<=0 || tag>Html_TypeCount ){ + CANT_HAPPEN; + return GetCurrentStyle(htmlPtr); + } + while( (p=htmlPtr->styleStack)!=0 ){ + type = p->type; + if( type<=0 || type>Html_TypeCount ){ + CANT_HAPPEN; + return GetCurrentStyle(htmlPtr); + } + if( type!=tag && priority[type]>priority[tag] ){ + return GetCurrentStyle(htmlPtr); + } + htmlPtr->styleStack = p->pNext; + HtmlFree(p); + if( type==tag ){ break; } + } + return GetCurrentStyle(htmlPtr); +} + +/* +** Change the font size on the given style by the delta-amount given +*/ +static void ScaleFont(HtmlStyle *pStyle, int delta){ + int size = FontSize(pStyle->font) + delta; + if( size<0 ){ + delta -= size; + }else if( size>6 ){ + delta -= size-6; + } + pStyle->font += delta; +} + +/* +** Lookup an argument in the given markup with the name given. +** Return a pointer to its value, or the given default +** value if it doesn't appear. +*/ +char *HtmlMarkupArg(HtmlElement *p, const char *tag, char *zDefault){ + int i; + if( !HtmlIsMarkup(p) ){ TestPoint(0); return 0; } + for(i=0; i<p->base.count; i+=2){ + if( strcmp(p->markup.argv[i],tag)==0 ){ + return p->markup.argv[i+1]; + } + } + return zDefault; +} + +/* +** Return an alignment or justification flag associated with the +** given markup. The given default value is returned if no alignment is +** specified. +*/ +static int GetAlignment(HtmlElement *p, int dflt){ + char *z = HtmlMarkupArg(p,"align",0); + int rc = dflt; + if( z ){ + if( stricmp(z,"left")==0 ){ + rc = ALIGN_Left; + }else if( stricmp(z,"right")==0 ){ + rc = ALIGN_Right; + }else if( stricmp(z,"center")==0 ){ + rc = ALIGN_Center; + } + } + return rc; +} + +/* +** The "type" argument to the given element might describe the type +** for an ordered list. Return the corresponding LI_TYPE_* entry +** if this is the case, or the default value if it isn't. +*/ +static int GetOrderedListType(HtmlElement *p, int dflt){ + char *z; + + z = HtmlMarkupArg(p,"type",0); + if( z ){ + switch( *z ){ + case 'A': TestPoint(0); dflt = LI_TYPE_Enum_A; break; + case 'a': TestPoint(0); dflt = LI_TYPE_Enum_a; break; + case '1': TestPoint(0); dflt = LI_TYPE_Enum_1; break; + case 'I': TestPoint(0); dflt = LI_TYPE_Enum_I; break; + case 'i': TestPoint(0); dflt = LI_TYPE_Enum_i; break; + default: TestPoint(0); break; + } + }else{ + TestPoint(0); + } + return dflt; +} + +/* +** The "type" argument to the given element might describe a type +** for an unordered list. Return the corresponding LI_TYPE entry +** if this is the case, or the default value if it isn't. +*/ +static int GetUnorderedListType(HtmlElement *p, int dflt){ + char *z; + + z = HtmlMarkupArg(p,"type",0); + if( z ){ + if( stricmp(z,"disc")==0 ){ + dflt = LI_TYPE_Bullet1; + }else if( stricmp(z,"circle")==0 ){ + dflt = LI_TYPE_Bullet2; + }else if( stricmp(z,"square")==0 ){ + dflt = LI_TYPE_Bullet3; + } + } + return dflt; +} + +/* +** Add the STY_Invisible style to every token between pFirst and pLast. +*/ +static void MakeInvisible(HtmlElement *pFirst, HtmlElement *pLast){ + if( pFirst==0 ) return; + pFirst = pFirst->pNext; + while( pFirst && pFirst!=pLast ){ + pFirst->base.style.flags |= STY_Invisible; + pFirst=pFirst->pNext; + } +} + + + +/* +** For the markup <a href=XXX>, find out if the URL has been visited +** before or not. Return COLOR_Visited or COLOR_Unvisited, as +** appropriate. +** +** This routine may invoke a callback procedure which could delete +** the HTML widget. The calling function should call HtmlLock() +** if it needs the widget structure to be preserved. +*/ +static int GetLinkColor(HtmlWidget *htmlPtr, char *zURL){ + char *zCmd; + int result; + int isVisited; + + if( htmlPtr->tkwin==0 ){ + TestPoint(0); + return COLOR_Normal; + } + if( htmlPtr->zIsVisited==0 || htmlPtr->zIsVisited[0]==0 ){ + TestPoint(0); + return COLOR_Unvisited; + } + zCmd = HtmlAlloc( strlen(htmlPtr->zIsVisited) + strlen(zURL) + 10 ); + if( zCmd==0 ){ + TestPoint(0); + return COLOR_Unvisited; + } + sprintf(zCmd,"%s {%s}",htmlPtr->zIsVisited, zURL); + HtmlLock(htmlPtr); + result = Tcl_GlobalEval(htmlPtr->interp,zCmd); + HtmlFree(zCmd); + if( HtmlUnlock(htmlPtr) ){ + return COLOR_Unvisited; + } + if( result!=TCL_OK ){ + TestPoint(0); + goto errorOut; + } + result = Tcl_GetBoolean(htmlPtr->interp, Tcl_GetStringResult(htmlPtr->interp), &isVisited); + if( result!=TCL_OK ){ + TestPoint(0); + goto errorOut; + } + TestPoint(0); + return isVisited ? COLOR_Visited : COLOR_Unvisited; + + errorOut: + Tcl_AddErrorInfo(htmlPtr->interp, + "\n (\"-isvisitedcommand\" command executed by html widget)"); + Tcl_BackgroundError(htmlPtr->interp); + TestPoint(0); + return COLOR_Unvisited; +} + +/* +** This routine adds information to the input texts that doesn't change +** when the display is resized or when new fonts are selected, etc. +** Mostly this means adding style attributes. But other constant +** information (such as numbering on <li> and images used for <IMG>) +** is also obtained. The key is that this routine is only called +** once, where the sizer and layout routines can be called many times. +** +** This routine is called whenever the list of elements grows. The +** style stack is stored as part of the HTML widget so that we can +** always continue where we left off the last time. +** +** In addition to adding style, this routine will invoke callbacks +** needed to acquire information about a markup. The htmlPtr->zIsVisitied +** callback is called for each <a> and the htmlPtr->zGetImage is called +** for each <IMG> or for each <LI> that has a SRC= field. +** +** This routine may invoke a callback procedure which could delete +** the HTML widget. +** +** When a markup is inserted or deleted from the token list, the +** style routine must be completely rerun from the beginning. So +** what we said above, that this routine is only run once, is not +** strictly true. +*/ +void HtmlAddStyle(HtmlWidget *htmlPtr, HtmlElement *p){ + HtmlStyle style; /* Current style */ + int size; /* A new font size */ + int i; /* Loop counter */ + int paraAlign; /* Current paragraph alignment */ + int rowAlign; /* Current table row alignment */ + int anchorFlags; /* Flags associated with <a> tag */ + int inDt; /* True if within <dt>..</dt> */ + HtmlStyle nextStyle; /* Style for next token if useNextStyle==1 */ + int useNextStyle = 0; /* True if nextStyle is valid */ + char *z; /* A tag parameter's value */ + + /* The size of header fonts relative to the current font size */ + static int header_sizes[] = {+2, +1, 1, 1, -1, -1}; + + /* Don't allow recursion */ + if( htmlPtr->flags & STYLER_RUNNING ){ TestPoint(0); return; } + htmlPtr->flags |= STYLER_RUNNING; + + /* Load the style state out of the htmlPtr structure and into local + ** variables. This is purely a matter of convenience... */ + style = GetCurrentStyle(htmlPtr); + paraAlign = htmlPtr->paraAlignment; + rowAlign = htmlPtr->rowAlignment; + anchorFlags = htmlPtr->anchorFlags; + inDt = htmlPtr->inDt; + + /* Loop over tokens */ + while( p ){ + switch( p->base.type ){ + case Html_A: + if( htmlPtr->anchorStart ){ + style = HtmlPopStyleStack(htmlPtr, Html_EndA); + htmlPtr->anchorStart = 0; + anchorFlags = 0; + } + z = HtmlMarkupArg(p,"href",0); + if( z ){ + HtmlLock(htmlPtr); + style.color = GetLinkColor(htmlPtr, z); + if( htmlPtr->underlineLinks ){ + style.flags |= STY_Underline; + } + if( HtmlUnlock(htmlPtr) ) return; + anchorFlags |= STY_Anchor; + PushStyleStack(htmlPtr, Html_EndA, style); + htmlPtr->anchorStart = p; + } + break; + case Html_EndA: + if( htmlPtr->anchorStart ){ + p->ref.pOther = htmlPtr->anchorStart; + style = HtmlPopStyleStack(htmlPtr, Html_EndA); + htmlPtr->anchorStart = 0; + anchorFlags = 0; + } + break; + case Html_ADDRESS: + case Html_EndADDRESS: + case Html_BLOCKQUOTE: + case Html_EndBLOCKQUOTE: + paraAlign = ALIGN_None; + TestPoint(0); + break; + case Html_APPLET: + if( htmlPtr->zAppletCommand && *htmlPtr->zAppletCommand ){ + nextStyle = style; + nextStyle.flags |= STY_Invisible; + PushStyleStack(htmlPtr, Html_EndAPPLET, nextStyle); + useNextStyle = 1; + }else{ + PushStyleStack(htmlPtr, Html_EndAPPLET, style); + } + TestPoint(0); + break; + case Html_B: + style.font = BoldFont( FontSize(style.font) ); + PushStyleStack(htmlPtr, Html_EndB, style); + TestPoint(0); + break; + case Html_EndAPPLET: + case Html_EndB: + case Html_EndBIG: + case Html_EndCENTER: + case Html_EndCITE: + case Html_EndCODE: + case Html_EndCOMMENT: + case Html_EndEM: + case Html_EndFONT: + case Html_EndI: + case Html_EndKBD: + case Html_EndMARQUEE: + case Html_EndNOBR: + case Html_EndNOFRAME: + case Html_EndNOSCRIPT: + case Html_EndS: + case Html_EndSAMP: + case Html_EndSMALL: + case Html_EndSTRIKE: + case Html_EndSTRONG: + case Html_EndSUB: + case Html_EndSUP: + case Html_EndTITLE: + case Html_EndTT: + case Html_EndU: + case Html_EndVAR: + style = HtmlPopStyleStack(htmlPtr, p->base.type); + TestPoint(0); + break; + case Html_BASE: + z = HtmlMarkupArg(p,"href",0); + if( z ){ + HtmlLock(htmlPtr); + z = HtmlResolveUri(htmlPtr, z); + if( HtmlUnlock(htmlPtr) ) return; + if( z!=0 ){ + if( htmlPtr->zBaseHref ){ + HtmlFree(htmlPtr->zBaseHref); + } + htmlPtr->zBaseHref = z; + } + } + break; + case Html_EndDIV: + paraAlign = ALIGN_None; + style = HtmlPopStyleStack(htmlPtr, p->base.type); + TestPoint(0); + break; + case Html_EndBASEFONT: + style = HtmlPopStyleStack(htmlPtr, Html_EndBASEFONT); + style.font = FontFamily(style.font) + 2; + TestPoint(0); + break; + case Html_BIG: + ScaleFont(&style,1); + PushStyleStack(htmlPtr, Html_EndBIG, style); + TestPoint(0); + break; + case Html_CAPTION: + paraAlign = GetAlignment(p, paraAlign); + TestPoint(0); + break; + case Html_EndCAPTION: + paraAlign = ALIGN_None; + TestPoint(0); + break; + case Html_CENTER: + paraAlign = ALIGN_None; + style.align = ALIGN_Center; + PushStyleStack(htmlPtr, Html_EndCENTER, style); + TestPoint(0); + break; + case Html_CITE: + PushStyleStack(htmlPtr, Html_EndCITE, style); + TestPoint(0); + break; + case Html_CODE: + style.font = CWFont( FontSize(style.font) ); + PushStyleStack(htmlPtr, Html_EndCODE, style); + TestPoint(0); + break; + case Html_COMMENT: + style.flags |= STY_Invisible; + PushStyleStack(htmlPtr, Html_EndCOMMENT, style); + TestPoint(0); + break; + case Html_DD: + if( htmlPtr->innerList && htmlPtr->innerList->base.type==Html_DL ){ + p->ref.pOther = htmlPtr->innerList; + TestPoint(0); + }else{ + p->ref.pOther = 0; + TestPoint(0); + } + inDt = 0; + break; + case Html_DIR: + case Html_MENU: + case Html_UL: + p->list.pPrev = htmlPtr->innerList; + p->list.cnt = 0; + htmlPtr->innerList = p; + if( p->list.pPrev==0 ){ + p->list.type = LI_TYPE_Bullet1; + p->list.compact = HtmlMarkupArg(p,"compact",0)!=0; + TestPoint(0); + }else if( p->list.pPrev->list.pPrev==0 ){ + p->list.type = LI_TYPE_Bullet2; + p->list.compact = 1; + TestPoint(0); + }else{ + p->list.type = LI_TYPE_Bullet3; + p->list.compact = 1; + TestPoint(0); + } + p->list.type = GetUnorderedListType(p,p->list.type); + break; + case Html_EndDL: + inDt = 0; + TestPoint(0); + /* Fall thru into the next case */ + case Html_EndDIR: + case Html_EndMENU: + case Html_EndOL: + case Html_EndUL: + p->ref.pOther = htmlPtr->innerList; + if( htmlPtr->innerList ){ + htmlPtr->innerList = htmlPtr->innerList->list.pPrev; + TestPoint(0); + }else{ + TestPoint(0); + } + break; + case Html_DIV: + paraAlign = ALIGN_None; + style.align = GetAlignment(p, style.align); + PushStyleStack(htmlPtr, Html_EndDIV, style); + TestPoint(0); + break; + case Html_DT: + if( htmlPtr->innerList && htmlPtr->innerList->base.type==Html_DL ){ + p->ref.pOther = htmlPtr->innerList; + TestPoint(0); + }else{ + p->ref.pOther = 0; + TestPoint(0); + } + inDt = STY_DT; + break; + case Html_EndDD: + case Html_EndDT: + inDt = 0; + TestPoint(0); + break; + case Html_DL: + p->list.pPrev = htmlPtr->innerList; + p->list.cnt = 0; + htmlPtr->innerList = p; + p->list.compact = HtmlMarkupArg(p,"compact",0)!=0; + inDt = 0; + TestPoint(0); + break; + case Html_EM: + style.font = ItalicFont( FontSize(style.font) ); + PushStyleStack(htmlPtr, Html_EndEM, style); + TestPoint(0); + break; + case Html_EMBED: + break; + case Html_BASEFONT: + case Html_FONT: + z = HtmlMarkupArg(p,"size",0); + if( z ){ + if( *z=='-' ){ + size = FontSize(style.font) - atoi(&z[1]); + }else if( *z=='+' ){ + size = FontSize(style.font) + atoi(&z[1]); + }else{ + size = atoi(z); + } + if( size <= 0 ){ + size = 1; + } + if( size >= N_FONT_SIZE ){ + size = N_FONT_SIZE - 1; + } + style.font = FontFamily(style.font) + size - 1; + } + z = HtmlMarkupArg(p,"color",0); + if( z ){ + style.color = HtmlGetColorByName(htmlPtr, z); + } + PushStyleStack(htmlPtr, + p->base.type==Html_FONT ? Html_EndFONT : Html_EndBASEFONT, style); + break; + case Html_FORM: { + char *zUrl; + char *zMethod; + Tcl_DString cmd; /* -formcommand callback */ + int result; + char zToken[50]; + + htmlPtr->formStart = 0; + p->form.id = 0; + if( htmlPtr->zFormCommand==0 || htmlPtr->zFormCommand[0]==0 ){ + TestPoint(0); + break; + } + zUrl = HtmlMarkupArg(p,"action",0); + if( zUrl==0 ){ + TestPoint(0); + break; + } + HtmlLock(htmlPtr); + zUrl = HtmlResolveUri(htmlPtr, zUrl); + if( HtmlUnlock(htmlPtr) ) return; + if( zUrl==0 ) break; + zMethod = HtmlMarkupArg(p,"method","GET"); + sprintf(zToken," %d form ", ++htmlPtr->nForm); + Tcl_DStringInit(&cmd); + Tcl_DStringAppend(&cmd, htmlPtr->zFormCommand, -1); + Tcl_DStringAppend(&cmd, zToken, -1); + Tcl_DStringAppendElement(&cmd, zUrl); + HtmlFree(zUrl); + Tcl_DStringAppendElement(&cmd, zMethod); + Tcl_DStringStartSublist(&cmd); + HtmlAppendArglist(&cmd, p); + Tcl_DStringEndSublist(&cmd); + HtmlLock(htmlPtr); + result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd)); + Tcl_DStringFree(&cmd); + if( HtmlUnlock(htmlPtr) ) return; + if( result==TCL_OK ){ + htmlPtr->formStart = p; + p->form.id = htmlPtr->nForm; + } + Tcl_ResetResult(htmlPtr->interp); + break; + } + case Html_EndFORM: + p->ref.pOther = htmlPtr->formStart; + htmlPtr->formStart = 0; + TestPoint(0); + break; + case Html_H1: + case Html_H2: + case Html_H3: + case Html_H4: + case Html_H5: + case Html_H6: + paraAlign = ALIGN_None; + i = (p->base.type - Html_H1)/2 + 1; + if( i>=1 && i<=6 ){ + ScaleFont(&style,header_sizes[i-1]); + } + style.font = BoldFont( FontSize(style.font) ); + style.align = GetAlignment(p, style.align); + PushStyleStack(htmlPtr, Html_EndH1, style); + break; + case Html_EndH1: + case Html_EndH2: + case Html_EndH3: + case Html_EndH4: + case Html_EndH5: + case Html_EndH6: + paraAlign = ALIGN_None; + style = HtmlPopStyleStack(htmlPtr, Html_EndH1); + TestPoint(0); + break; + case Html_HR: + nextStyle = style; + style.align = GetAlignment(p, ALIGN_None); + useNextStyle = 1; + break; + case Html_I: + style.font = ItalicFont( FontSize(style.font) ); + PushStyleStack(htmlPtr, Html_EndI, style); + TestPoint(0); + break; + case Html_IMG: + HtmlLock(htmlPtr); + p->image.pImage = HtmlGetImage(htmlPtr, p); + if( HtmlUnlock(htmlPtr) ) return; + TestPoint(0); + break; + case Html_INPUT: + p->input.pForm = htmlPtr->formStart; + TestPoint(0); + break; + case Html_KBD: + style.font = CWFont( FontSize(style.font) ); + PushStyleStack(htmlPtr, Html_EndKBD, style); + TestPoint(0); + break; + case Html_LI: + if( htmlPtr->innerList ){ + p->li.type = htmlPtr->innerList->list.type; + if( htmlPtr->innerList->base.type==Html_OL ){ + z = HtmlMarkupArg(p, "value", 0); + if( z ){ + int n = atoi(z); + if( n>0 ){ + p->li.cnt = n; + htmlPtr->innerList->list.cnt = n+1; + TestPoint(0); + }else{ + TestPoint(0); + } + }else{ + p->li.cnt = htmlPtr->innerList->list.cnt++; + TestPoint(0); + } + p->li.type = GetOrderedListType(p,p->li.type); + }else{ + p->li.type = GetUnorderedListType(p,p->li.type); + TestPoint(0); + } + }else{ + p->base.flags &= ~HTML_Visible; + TestPoint(0); + } + break; + case Html_MARQUEE: + style.flags |= STY_Invisible; + PushStyleStack(htmlPtr, Html_EndMARQUEE, style); + TestPoint(0); + break; + case Html_NOBR: + style.flags |= STY_NoBreak; + PushStyleStack(htmlPtr, Html_EndNOBR, style); + TestPoint(0); + break; + case Html_NOFRAME: + if( htmlPtr->zFrameCommand && *htmlPtr->zFrameCommand ){ + nextStyle = style; + nextStyle.flags |= STY_Invisible; + PushStyleStack(htmlPtr, Html_EndNOFRAME, nextStyle); + useNextStyle = 1; + }else{ + PushStyleStack(htmlPtr, Html_EndNOFRAME, style); + } + TestPoint(0); + break; + case Html_NOSCRIPT: + if( htmlPtr->zScriptCommand && *htmlPtr->zScriptCommand ){ + nextStyle = style; + nextStyle.flags |= STY_Invisible; + PushStyleStack(htmlPtr, Html_EndNOSCRIPT, nextStyle); + useNextStyle = 1; + }else{ + PushStyleStack(htmlPtr, Html_EndNOSCRIPT, style); + } + TestPoint(0); + break; + case Html_OL: + p->list.pPrev = htmlPtr->innerList; + p->list.type = GetOrderedListType(p,LI_TYPE_Enum_1); + p->list.cnt = 1; + z = HtmlMarkupArg(p,"start",0); + if( z ){ + int n = atoi(z); + if( n>0 ){ + p->list.cnt = n; + TestPoint(0); + }else{ + TestPoint(0); + } + }else{ + TestPoint(0); + } + p->list.compact = htmlPtr->innerList!=0 || + HtmlMarkupArg(p,"compact",0)!=0; + htmlPtr->innerList = p; + break; + case Html_P: + paraAlign = GetAlignment(p, ALIGN_None); + TestPoint(0); + break; + case Html_EndP: + paraAlign = ALIGN_None; + TestPoint(0); + break; + case Html_PRE: + case Html_LISTING: + case Html_XMP: + case Html_PLAINTEXT: + paraAlign = ALIGN_None; + style.font = CWFont( FontSize(style.font) ); + style.flags |= STY_Preformatted; + PushStyleStack(htmlPtr, Html_EndPRE, style); + TestPoint(0); + break; + case Html_EndPRE: + case Html_EndLISTING: + case Html_EndXMP: + style = HtmlPopStyleStack(htmlPtr, Html_EndPRE); + TestPoint(0); + break; + case Html_S: + style.flags |= STY_StrikeThru; + PushStyleStack(htmlPtr, Html_EndS, style); + TestPoint(0); + break; + case Html_SCRIPT: + if( htmlPtr->zScriptCommand && *htmlPtr->zScriptCommand ){ + Tcl_DString cmd; + int result; + Tcl_DStringInit(&cmd); + Tcl_DStringAppend(&cmd, htmlPtr->zScriptCommand, -1); + Tcl_DStringStartSublist(&cmd); + HtmlAppendArglist(&cmd, p); + Tcl_DStringEndSublist(&cmd); + Tcl_DStringStartSublist(&cmd); + Tcl_DStringAppend(&cmd, p->script.zScript, p->script.nScript); + Tcl_DStringEndSublist(&cmd); + HtmlLock(htmlPtr); + result = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd)); + Tcl_DStringFree(&cmd); + if( HtmlUnlock(htmlPtr) ) return; + Tcl_ResetResult(htmlPtr->interp); + } + nextStyle = style; + style.flags |= STY_Invisible; + useNextStyle = 1; + break; + case Html_SELECT: + p->input.pForm = htmlPtr->formStart; + nextStyle.flags |= STY_Invisible; + useNextStyle = 1; + PushStyleStack(htmlPtr, Html_EndSELECT, style); + htmlPtr->formElemStart = p; + break; + case Html_EndSELECT: + style = HtmlPopStyleStack(htmlPtr, Html_EndSELECT); + if( htmlPtr->formElemStart + && htmlPtr->formElemStart->base.type==Html_SELECT ){ + p->ref.pOther = htmlPtr->formElemStart; + MakeInvisible(p->ref.pOther, p); + }else{ + p->ref.pOther = 0; + } + htmlPtr->formElemStart = 0; + break; + case Html_STRIKE: + style.flags |= STY_StrikeThru; + PushStyleStack(htmlPtr, Html_EndSTRIKE, style); + TestPoint(0); + break; + case Html_STYLE: + /* Ignore style sheets */ + break; + case Html_SAMP: + style.font = CWFont( FontSize(style.font) ); + PushStyleStack(htmlPtr, Html_EndSAMP, style); + TestPoint(0); + break; + case Html_SMALL: + ScaleFont(&style,-1); + PushStyleStack(htmlPtr, Html_EndSMALL, style); + TestPoint(0); + break; + case Html_STRONG: + style.font = BoldFont( FontSize(style.font) ); + PushStyleStack(htmlPtr, Html_EndSTRONG, style); + TestPoint(0); + break; + case Html_SUB: + ScaleFont(&style,-1); + if( style.subscript > -6 ){ + style.subscript--; + TestPoint(0); + }else{ + TestPoint(0); + } + PushStyleStack(htmlPtr, Html_EndSUB, style); + break; + case Html_SUP: + ScaleFont(&style,-1); + if( style.subscript < 6 ){ + style.subscript++; + TestPoint(0); + }else{ + TestPoint(0); + } + PushStyleStack(htmlPtr, Html_EndSUP, style); + break; + case Html_TABLE: + paraAlign = ALIGN_None; + nextStyle = style; + nextStyle.align = ALIGN_Left; + z = HtmlMarkupArg(p, "bgcolor", 0); + if( z ){ + nextStyle.bgcolor = HtmlGetColorByName(htmlPtr, z); + style.bgcolor = nextStyle.bgcolor; +/* }else{ + nextStyle.bgcolor = COLOR_Background; */ + } + PushStyleStack(htmlPtr, Html_EndTABLE, nextStyle); + useNextStyle = 1; + htmlPtr->inTd = 0; + htmlPtr->inTr = 0; + TestPoint(0); + break; + case Html_EndTABLE: + paraAlign = ALIGN_None; + if( htmlPtr->inTd ){ + style = HtmlPopStyleStack(htmlPtr, Html_EndTD); + htmlPtr->inTd = 0; + } + if( htmlPtr->inTr ){ + style = HtmlPopStyleStack(htmlPtr, Html_EndTR); + htmlPtr->inTr = 0; + } + style = HtmlPopStyleStack(htmlPtr, p->base.type); + TestPoint(0); + break; + case Html_TD: + if( htmlPtr->inTd ){ + style = HtmlPopStyleStack(htmlPtr, Html_EndTD); + } + htmlPtr->inTd = 1; + paraAlign = GetAlignment(p, rowAlign); + if( (z = HtmlMarkupArg(p, "bgcolor", 0))!=0 ){ + style.bgcolor = HtmlGetColorByName(htmlPtr, z); + } + PushStyleStack(htmlPtr, Html_EndTD, style); + TestPoint(0); + break; + case Html_TEXTAREA: + p->input.pForm = htmlPtr->formStart; + nextStyle = style; + nextStyle.flags |= STY_Invisible; + PushStyleStack(htmlPtr, Html_EndTEXTAREA, nextStyle); + htmlPtr->formElemStart = p; + useNextStyle = 1; + TestPoint(0); + break; + case Html_EndTEXTAREA: + style = HtmlPopStyleStack(htmlPtr, Html_EndTEXTAREA); + if( htmlPtr->formElemStart + && htmlPtr->formElemStart->base.type==Html_TEXTAREA ){ + p->ref.pOther = htmlPtr->formElemStart; + }else{ + p->ref.pOther = 0; + } + htmlPtr->formElemStart = 0; + break; + case Html_TH: + /* paraAlign = GetAlignment(p, rowAlign); */ + if( htmlPtr->inTd ){ + style = HtmlPopStyleStack(htmlPtr, Html_EndTD); + } + paraAlign = GetAlignment(p, ALIGN_Center); + style.font = BoldFont( FontSize(style.font) ); + if( (z = HtmlMarkupArg(p, "bgcolor", 0))!=0 ){ + style.bgcolor = HtmlGetColorByName(htmlPtr, z); + } + PushStyleStack(htmlPtr, Html_EndTD, style); + htmlPtr->inTd = 1; + TestPoint(0); + break; + case Html_TR: + if( htmlPtr->inTd ){ + style = HtmlPopStyleStack(htmlPtr, Html_EndTD); + htmlPtr->inTd = 0; + } + if( htmlPtr->inTr ){ + style = HtmlPopStyleStack(htmlPtr, Html_EndTR); + } + rowAlign = GetAlignment(p, ALIGN_None); + if( (z = HtmlMarkupArg(p, "bgcolor", 0))!=0 ){ + style.bgcolor = HtmlGetColorByName(htmlPtr, z); + } + PushStyleStack(htmlPtr, Html_EndTR, style); + htmlPtr->inTr = 1; + TestPoint(0); + break; + case Html_EndTR: + if( htmlPtr->inTd ){ + style = HtmlPopStyleStack(htmlPtr, Html_EndTD); + htmlPtr->inTd = 0; + } + style = HtmlPopStyleStack(htmlPtr, Html_EndTR); + htmlPtr->inTr = 0; + paraAlign = ALIGN_None; + rowAlign = ALIGN_None; + TestPoint(0); + break; + case Html_EndTD: + case Html_EndTH: + style = HtmlPopStyleStack(htmlPtr, Html_EndTD); + htmlPtr->inTd = 0; + paraAlign = ALIGN_None; + rowAlign = ALIGN_None; + TestPoint(0); + break; + case Html_TITLE: + style.flags |= STY_Invisible; + PushStyleStack(htmlPtr, Html_EndTITLE, style); + TestPoint(0); + break; + case Html_TT: + style.font = CWFont( FontSize(style.font) ); + PushStyleStack(htmlPtr, Html_EndTT, style); + TestPoint(0); + break; + case Html_U: + style.flags |= STY_Underline; + PushStyleStack(htmlPtr, Html_EndU, style); + break; + case Html_VAR: + style.font = ItalicFont( FontSize(style.font) ); + PushStyleStack(htmlPtr, Html_EndVAR, style); + TestPoint(0); + break; + default: + TestPoint(0); + break; + } + p->base.style = style; + p->base.style.flags |= anchorFlags | inDt; + if( paraAlign!=ALIGN_None ){ + p->base.style.align = paraAlign; + } + if( useNextStyle ){ + style = nextStyle; + useNextStyle = 0; + } + TRACE(HtmlTrace_Style, + ("Style of 0x%08x font=%02d color=%02d bg=%02d " + "align=%d flags=0x%04x token=%s\n", + (int)p, p->base.style.font, p->base.style.color, p->base.style.bgcolor, + p->base.style.align, p->base.style.flags, HtmlTokenName(p))); + p = p->pNext; + } + + /* Copy state information back into the htmlPtr structure for + ** safe keeping. */ + htmlPtr->paraAlignment = paraAlign; + htmlPtr->rowAlignment = rowAlign; + htmlPtr->anchorFlags = anchorFlags; + htmlPtr->inDt = inDt; + htmlPtr->flags &= ~STYLER_RUNNING; +} + +/* +** Compute the size of all elements in the widget. Assume that a +** style has already been assigned to all elements. +** +** Some of the elements might have already been sized. Refer to the +** htmlPtr->lastSized and only compute sizes for elements that follow +** this one. If htmlPtr->lastSized==0, then size everything. +** +** This routine only computes the sizes of individual elements. The +** size of aggregate elements (like tables) are computed separately. +** +** The HTML_Visible flag is also set on every element that results +** in ink on the page. +** +** This routine may invoke a callback procedure which could delete +** the HTML widget. +*/ +void HtmlSizer(HtmlWidget *htmlPtr){ + HtmlElement *p; + int iFont = -1; + Tk_Font font; + int spaceWidth = 0; + Tk_FontMetrics fontMetrics; + char *z; + int stop = 0; + + if( htmlPtr->pFirst==0 ){ TestPoint(0); return; } + if( htmlPtr->lastSized==0 ){ + p = htmlPtr->pFirst; + TestPoint(0); + }else{ + p = htmlPtr->lastSized->pNext; + TestPoint(0); + } + for(; !stop && p; p=p->pNext){ + if( p->base.style.flags & STY_Invisible ){ + p->base.flags &= ~HTML_Visible; + TestPoint(0); + continue; + } + if( iFont != p->base.style.font ){ + iFont = p->base.style.font; + HtmlLock(htmlPtr); + font = HtmlGetFont(htmlPtr, iFont); + if( HtmlUnlock(htmlPtr) ) break; + Tk_GetFontMetrics(font, &fontMetrics); + spaceWidth = 0; + } + switch( p->base.type ){ + case Html_Text: + p->text.w = Tk_TextWidth(font, p->text.zText, p->base.count); + p->base.flags |= HTML_Visible; + p->text.descent = fontMetrics.descent; + p->text.ascent = fontMetrics.ascent; + if( spaceWidth==0 ){ + spaceWidth = Tk_TextWidth(font, " ", 1); + TestPoint(0); + }else{ + TestPoint(0); + } + p->text.spaceWidth = spaceWidth; + break; + case Html_Space: + if( spaceWidth==0 ){ + spaceWidth = Tk_TextWidth(font, " ", 1); + } + p->space.w = spaceWidth; + p->space.descent = fontMetrics.descent; + p->space.ascent = fontMetrics.ascent; + p->base.flags &= ~HTML_Visible; + break; + case Html_TD: + case Html_TH: + z = HtmlMarkupArg(p, "rowspan","1"); + p->cell.rowspan = atoi(z); + z = HtmlMarkupArg(p, "colspan","1"); + p->cell.colspan = atoi(z); + p->base.flags |= HTML_Visible; + TestPoint(0); + break; + case Html_LI: + p->li.descent = fontMetrics.descent; + p->li.ascent = fontMetrics.ascent; + p->base.flags |= HTML_Visible; + TestPoint(0); + break; + case Html_IMG: + p->base.flags |= HTML_Visible; + p->image.redrawNeeded = 0; + p->image.textAscent = fontMetrics.ascent; + p->image.textDescent = fontMetrics.descent; + p->image.align = HtmlGetImageAlignment(p); + if( p->image.pImage==0 ){ + p->image.ascent = fontMetrics.ascent; + p->image.descent = fontMetrics.descent; + p->image.zAlt = HtmlMarkupArg(p, "alt", "<image>"); + p->image.w = Tk_TextWidth(font, p->image.zAlt, strlen(p->image.zAlt)); + }else{ + int w, h; + p->image.pNext = p->image.pImage->pList; + p->image.pImage->pList = p; + Tk_SizeOfImage(p->image.pImage->image, &w, &h); + p->image.h = h; + p->image.w = w; + p->image.ascent = h/2; + p->image.descent = h - p->image.ascent; + } + if( (z = HtmlMarkupArg(p, "width", 0))!=0 ){ + int w = atoi(z); + if( w>0 ) p->image.w = w; + } + if( (z = HtmlMarkupArg(p, "height", 0))!=0 ){ + int h = atoi(z); + if( h>0 ) p->image.h = h; + } + break; + case Html_HR: + case Html_TABLE: + p->base.flags |= HTML_Visible; + TestPoint(0); + break; + case Html_APPLET: + case Html_EMBED: + case Html_INPUT: + p->input.textAscent = fontMetrics.ascent; + p->input.textDescent = fontMetrics.descent; + stop = HtmlControlSize(htmlPtr, p); + break; + case Html_SELECT: + case Html_TEXTAREA: + p->input.textAscent = fontMetrics.ascent; + p->input.textDescent = fontMetrics.descent; + break; + case Html_EndSELECT: + case Html_EndTEXTAREA: + if( p->ref.pOther ){ + p->ref.pOther->input.pEnd = p; + stop = HtmlControlSize(htmlPtr, p->ref.pOther); + } + break; + default: + p->base.flags &= ~HTML_Visible; + break; + } + } + if( p ){ + htmlPtr->lastSized = p; + }else{ + htmlPtr->lastSized = htmlPtr->pLast; + } +} diff --git a/tkhtml1/src/htmlsizer.h b/tkhtml1/src/htmlsizer.h new file mode 100644 index 0000000..c14bcf3 --- /dev/null +++ b/tkhtml1/src/htmlsizer.h @@ -0,0 +1,635 @@ +/* This file was automatically generated. Do not edit! */ +typedef struct HtmlWidget HtmlWidget; +typedef union HtmlElement HtmlElement; +int HtmlControlSize(HtmlWidget *htmlPtr,HtmlElement *pElem); +int HtmlGetImageAlignment(HtmlElement *p); +#define Html_Space 2 +#define Html_Text 1 +Tk_Font HtmlGetFont(HtmlWidget *htmlPtr,int iFont); +void HtmlSizer(HtmlWidget *htmlPtr); +char *HtmlTokenName(HtmlElement *p); +#define HtmlTrace_Style 0x00002000 +extern int HtmlTraceMask; +#define DEBUG 1 +#if defined(DEBUG) +extern int HtmlDepth; +# define TRACE_INDENT printf("%*s",HtmlDepth-3,"") +#endif +#if !(defined(DEBUG)) +# define TRACE_INDENT +#endif +#if defined(DEBUG) +# define TRACE(Flag, Args) \ + if( (Flag)&HtmlTraceMask ){ \ + TRACE_INDENT; printf Args; fflush(stdout); \ + } +#endif +#if !(defined(DEBUG)) +# define TRACE(Flag, Args) +#endif +#define Html_VAR 147 +#define Html_U 143 +#define Html_TT 141 +#define Html_TITLE 137 +#define Html_EndTEXTAREA 134 +#define Html_TEXTAREA 133 +#define Html_SUP 127 +#define Html_SUB 125 +#define Html_STRONG 122 +#define Html_SMALL 118 +#define Html_SAMP 113 +#define Html_STYLE 124 +#define Html_STRIKE 120 +#define Html_EndSELECT 117 +#define Html_SELECT 116 +#define Html_SCRIPT 115 +#define STY_StrikeThru 0x002 +#define Html_S 111 +#define Html_EndXMP 151 +#define Html_EndLISTING 85 +#define Html_EndPRE 110 +#define STY_Preformatted 0x001 +#define Html_PLAINTEXT 108 +#define Html_XMP 150 +#define Html_LISTING 84 +#define Html_PRE 109 +#define Html_EndP 105 +#define Html_P 104 +#define Html_NOSCRIPT 98 +#define Html_NOFRAME 96 +#define STY_NoBreak 0x008 +#define Html_NOBR 94 +#define Html_MARQUEE 88 +#define HTML_Visible 0x01 /* This element produces "ink" */ +#define Html_OL 100 +#define Html_LI 81 +#define Html_KBD 79 +#define Html_INPUT 77 +typedef struct HtmlImage HtmlImage; +HtmlImage *HtmlGetImage(HtmlWidget *htmlPtr,HtmlElement *p); +#define Html_IMG 76 +#define Html_I 73 +#define Html_HR 70 +#define Html_EndH6 69 +#define Html_EndH5 67 +#define Html_EndH4 65 +#define Html_EndH3 63 +#define Html_EndH2 61 +#define Html_EndH1 59 +#define Html_H6 68 +#define Html_H5 66 +#define Html_H4 64 +#define Html_H3 62 +#define Html_H2 60 +#define Html_H1 58 +#define Html_EndFORM 53 +void HtmlAppendArglist(Tcl_DString *str,HtmlElement *pElem); +#define Html_FORM 52 +int HtmlGetColorByName(HtmlWidget *htmlPtr,char *zColor); +#define N_FONT_SIZE 7 +#define Html_FONT 50 +#define Html_BASEFONT 15 +#define Html_EMBED 49 +#define ItalicFont(X) ((X)+2*N_FONT_SIZE) +#define Html_EM 47 +#define Html_EndDT 46 +#define Html_EndDD 36 +#define STY_DT 0x020 +#define Html_DT 45 +#define Html_DIV 41 +#define Html_EndUL 146 +#define Html_EndOL 101 +#define Html_EndMENU 91 +#define Html_EndDIR 40 +#define Html_EndDL 44 +#define Html_UL 145 +#define Html_MENU 90 +#define Html_DIR 39 +#define Html_DL 43 +#define Html_DD 35 +#define Html_COMMENT 33 +#define CWFont(X) ((X)+4*N_FONT_SIZE) +#define Html_CODE 31 +#define Html_CITE 29 +#define Html_CENTER 27 +#define Html_EndCAPTION 26 +#define Html_CAPTION 25 +#define Html_BIG 18 +#define FontFamily(X) (((X)/N_FONT_SIZE)*N_FONT_SIZE) +#define Html_EndBASEFONT 16 +#define Html_EndDIV 42 +char *HtmlResolveUri(HtmlWidget *htmlPtr,char *zUri); +#define Html_BASE 14 +#define Html_EndVAR 148 +#define Html_EndU 144 +#define Html_EndTT 142 +#define Html_EndTITLE 138 +#define Html_EndSUP 128 +#define Html_EndSUB 126 +#define Html_EndSTRONG 123 +#define Html_EndSTRIKE 121 +#define Html_EndSMALL 119 +#define Html_EndSAMP 114 +#define Html_EndS 112 +#define Html_EndNOSCRIPT 99 +#define Html_EndNOFRAME 97 +#define Html_EndNOBR 95 +#define Html_EndMARQUEE 89 +#define Html_EndKBD 80 +#define Html_EndI 74 +#define Html_EndFONT 51 +#define Html_EndEM 48 +#define Html_EndCOMMENT 34 +#define Html_EndCODE 32 +#define Html_EndCITE 30 +#define Html_EndCENTER 28 +#define Html_EndBIG 19 +#define Html_EndB 13 +#define BoldFont(X) ((X)+N_FONT_SIZE) +#define Html_B 12 +#define Html_EndAPPLET 10 +#define Html_APPLET 9 +#define ALIGN_None 0 +#define Html_EndBLOCKQUOTE 21 +#define Html_BLOCKQUOTE 20 +#define Html_EndADDRESS 8 +#define Html_ADDRESS 7 +#define STY_Anchor 0x010 +#define STY_Underline 0x004 +#define Html_EndA 6 +#define Html_A 5 +#define STYLER_RUNNING 0x000800 +void HtmlAddStyle(HtmlWidget *htmlPtr,HtmlElement *p); +#define COLOR_Visited 2 /* Color for visited hyperlinks */ +int HtmlUnlock(HtmlWidget *htmlPtr); +void HtmlLock(HtmlWidget *htmlPtr); +#define COLOR_Unvisited 1 /* Index for unvisited hyperlinks */ +#define STY_Invisible 0x040 +#define LI_TYPE_Bullet3 3 /* A hollow square */ +#define LI_TYPE_Bullet2 2 /* A hollow circle */ +#define LI_TYPE_Bullet1 1 /* A solid circle */ +#define LI_TYPE_Enum_i 8 /* Lower-case roman numerals */ +#define LI_TYPE_Enum_I 7 /* Capitalized roman numerals */ +#define LI_TYPE_Enum_1 4 /* Arabic numbers */ +#define LI_TYPE_Enum_a 6 /* a, b, c, ... */ +#define LI_TYPE_Enum_A 5 /* A, B, C, ... */ +#define ALIGN_Center 3 +#define ALIGN_Right 2 +#if !defined(HAVE_STRICMP) +# define stricmp strcasecmp +#endif +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +#define Html_Block 4 +#define HtmlIsMarkup(X) ((X)->base.type>Html_Block) +typedef struct HtmlBaseElement HtmlBaseElement; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +typedef unsigned char Html_u8; +typedef short Html_16; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +typedef struct HtmlTextElement HtmlTextElement; +typedef int Html_32; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlMarkupElement HtmlMarkupElement; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +typedef unsigned short Html_u16; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +typedef struct HtmlScript HtmlScript; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +typedef struct HtmlBlock HtmlBlock; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +char *HtmlMarkupArg(HtmlElement *p,const char *tag,char *zDefault); +#define FontSize(X) ((X)%N_FONT_SIZE) +#define HtmlFree(A) Tcl_Free((char*)(A)) +void HtmlTPCantHappen(const char *zFile,int line); +#if defined(COVERAGE_TEST) +# define CANT_HAPPEN HtmlTPCantHappen(__FILE__,__LINE__) +#endif +#if !(defined(COVERAGE_TEST)) +# define CANT_HAPPEN +#endif +#define Html_EndTABLE 130 +#define Html_EndTR 140 +#define Html_TR 139 +#define Html_EndTH 136 +#define Html_TH 135 +#define Html_EndTD 132 +#define Html_TD 131 +#define Html_TABLE 129 +#define Html_TypeCount 151 +HtmlStyle HtmlPopStyleStack(HtmlWidget *htmlPtr,int tag); +#define HtmlAlloc(A) ((void*)Tcl_Alloc(A)) +typedef struct HtmlStyleStack HtmlStyleStack; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +#define ALIGN_Left 1 +#define COLOR_Background 4 /* Default background color */ +#define COLOR_Normal 0 /* Index for normal color (black) */ +#define NormalFont(X) (X) +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +typedef struct HtmlLayoutContext HtmlLayoutContext; +typedef struct HtmlMargin HtmlMargin; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +#define N_FONT_FAMILY 8 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/htmltable.c b/tkhtml1/src/htmltable.c new file mode 100644 index 0000000..98bbb48 --- /dev/null +++ b/tkhtml1/src/htmltable.c @@ -0,0 +1,1175 @@ +/* +** Routines for doing layout of HTML tables +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <tk.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <math.h> +#include "htmltable.h" + +/* +** Default values for various table style parameters +*/ +#define DFLT_BORDER 0 +#define DFLT_CELLSPACING_3D 5 +#define DFLT_CELLSPACING_FLAT 0 +#define DFLT_CELLPADDING 2 +#define DFLT_HSPACE 0 +#define DFLT_VSPACE 0 + +#if INTERFACE +/* +** Set parameter A to the maximum of A and B. +*/ +#define SETMAX(A,B) if( (A)<(B) ){ (A) = (B); } +#define MAX(A,B) ((A)<(B)?(B):(A)) +#endif + +/* +** Return the appropriate cell spacing for the given table. +*/ +static int CellSpacing(HtmlWidget *htmlPtr, HtmlElement *pTable){ + char *z; + int relief; + int cellSpacing; + + z = HtmlMarkupArg(pTable, "cellspacing", 0); + if( z==0 ){ + relief = htmlPtr->tableRelief; + if( relief==TK_RELIEF_RAISED || relief==TK_RELIEF_SUNKEN ){ + cellSpacing = DFLT_CELLSPACING_3D; + }else{ + cellSpacing = DFLT_CELLSPACING_FLAT; + } + }else{ + cellSpacing = atoi(z); + } + return cellSpacing; +} + +/* Forward declaration */ +static HtmlElement *MinMax(HtmlWidget*, HtmlElement *, int *, int *, int); + +/* pStart points to a <table>. Compute the number of columns, the +** minimum and maximum size for each column and the overall minimum +** and maximum size for this table and store these value in the +** pStart structure. Return a pointer to the </table> element, +** or to NULL if there is no </table>. +** +** The min and max size for column N (where the leftmost column has +** N==1) is pStart->minW[1] and pStart->maxW[1]. The pStart->minW[0] +** and pStart->maxW[0] entries contain the minimum and maximum widths +** of the whole table, including any cell padding, cell spacing, +** border width and "hspace". The values of pStart->minW[I] for I>=1 +** do not contain any cell padding, cell spacing or border width. +** Only pStart->minW[0] contains these extra spaces. +** +** The back references from </table>, </tr>, </td> and </th> back to +** the <table> markup are also filled in. And for each <td> and <th> +** markup, the pTable and pEnd fields are set to their proper values. +*/ +static HtmlElement *TableDimensions( + HtmlWidget *htmlPtr, /* The HTML widget */ + HtmlElement *pStart, /* The <table> markup */ + int lineWidth /* Total widget available to the table */ +){ + HtmlElement *p; /* Element being processed */ + HtmlElement *pNext; /* Next element to process */ + int iCol = 0; /* Current column number. 1..N */ + int iRow = 0; /* Current row number */ + int inRow = 0; /* True if in between <TR> and </TR> */ + int i, j; /* Loop counters */ + int n; /* Number of columns */ + int minW, maxW, requestedW; /* min, max, requested width for a cell */ + int noWrap; /* true for NOWRAP cells */ + int colspan; /* Column span for the current cell */ + int rowspan; /* Row span for the current cell */ + char *z; /* Value of a <table> parameter */ + int cellSpacing; /* Value of CELLSPACING parameter */ + int cellPadding; /* Value of CELLPADDING parameter */ + int tbw; /* Width of border around whole table */ + int cbw; /* Width of border around one cell */ + int hspace; /* Value of HSPACE parameter */ + int separation; /* Space between columns */ + int margin; /* Space between left margin and 1st col */ + int availWidth; /* Part of lineWidth still available */ + int maxTableWidth; /* Amount of lineWidth available to table*/ + int fromAbove[HTML_MAX_COLUMNS+1]; /* Cell above extends thru this row */ + int min0span[HTML_MAX_COLUMNS+1]; /* Min for colspan=0 cells */ + int max0span[HTML_MAX_COLUMNS+1]; /* Max for colspan=0 cells */ + int reqW[HTML_MAX_COLUMNS+1]; /* Requested width for each column */ + + /* colMin[A][B] is the absolute minimum width of all columns between + ** A+1 and B+1. colMin[B][A] is the requested width of columns between + ** A+1 and B+1. This information is used to add in the constraints imposed + ** by <TD COLSPAN=N> markup where N>=2. + */ + int colMin[HTML_MAX_COLUMNS+1][HTML_MAX_COLUMNS+1]; +# define ColMin(A,B) colMin[(A)-1][(B)-1] +# define ColReq(A,B) colMin[(B)-1][(A)-1] + + if( pStart==0 || pStart->base.type!=Html_TABLE ){ + TestPoint(0); + return pStart; + } + TRACE_PUSH(HtmlTrace_Table1); + TRACE(HtmlTrace_Table1, ("Starting TableDimensions..\n")); + pStart->table.nCol = 0; + pStart->table.nRow = 0; + z = HtmlMarkupArg(pStart, "border", 0); + if( z && *z==0 ) z = "2"; + tbw = pStart->table.borderWidth = z ? atoi(z) : DFLT_BORDER; + cbw = tbw>0; + z = HtmlMarkupArg(pStart, "cellpadding", 0); + cellPadding = z ? atoi(z) : DFLT_CELLPADDING; + cellSpacing = CellSpacing(htmlPtr, pStart); +#ifdef DEBUG + /* The HtmlTrace_Table4 flag causes tables to be draw with borders + ** of 2, cellPadding of 5 and cell spacing of 2. This makes the + ** table clearly visible. Useful for debugging. */ + if( HtmlTraceMask & HtmlTrace_Table4 ){ + tbw = pStart->table.borderWidth = 2; + cbw = 1; + cellPadding = 5; + cellSpacing = 2; + pStart->base.style.bgcolor = COLOR_Background; + } +#endif + separation = cellSpacing + 2*(cellPadding + cbw); + margin = tbw + cellSpacing + cbw + cellPadding; + z = HtmlMarkupArg(pStart, "hspace", 0); + hspace = z ? atoi(z) : DFLT_HSPACE; + + for(p=pStart->pNext; p && p->base.type!=Html_EndTABLE; p=pNext){ + pNext = p->pNext; + switch( p->base.type ){ + case Html_EndTD: + case Html_EndTH: + case Html_EndTABLE: + p->ref.pOther = pStart; + TestPoint(0); + break; + case Html_EndTR: + p->ref.pOther = pStart; + inRow = 0; + TestPoint(0); + break; + case Html_TR: + p->ref.pOther = pStart; + iRow++; + pStart->table.nRow++; + iCol = 0; + inRow = 1; + maxTableWidth = availWidth = lineWidth - 2*margin; + TestPoint(0); + break; + case Html_CAPTION: + while( p && p->base.type!=Html_EndTABLE + && p->base.type!=Html_EndCAPTION ){ + p = p->pNext; + TestPoint(0); + } + break; + case Html_TD: + case Html_TH: + if( !inRow ){ + /* If the <TR> markup is omitted, insert it. */ + HtmlElement *pNew = HtmlAlloc( sizeof(HtmlRef) ); + if( pNew==0 ) break; + memset(pNew, 0, sizeof(HtmlRef)); + pNew->base = p->base; + pNew->base.pNext = p; + pNew->base.type = Html_TR; + pNew->base.count = 0; + p->base.pPrev->base.pNext = pNew; + p->base.pPrev = pNew; + pNext = pNew; + break; + } + do{ + iCol++; + }while( iCol <= pStart->table.nCol && fromAbove[iCol] > iRow ); + p->cell.pTable = pStart; + colspan = p->cell.colspan; + if( colspan==0 ){ + colspan = 1; + } + if( iCol + colspan - 1 > pStart->table.nCol ){ + int nCol = iCol + colspan - 1; + if( nCol > HTML_MAX_COLUMNS ){ + nCol = HTML_MAX_COLUMNS; + } + for(i=pStart->table.nCol+1; i<=nCol; i++){ + fromAbove[i] = 0; + pStart->table.minW[i] = 0; + pStart->table.maxW[i] = 0; + min0span[i] = 0; + max0span[i] = 0; + reqW[i] = 0; + for(j=1; j<i; j++){ + ColMin(j,i) = 0; + ColReq(j,i) = 0; + } + } + pStart->table.nCol = nCol; + } + noWrap = HtmlMarkupArg(p, "nowrap", 0)!=0; + pNext = MinMax(htmlPtr, p, &minW, &maxW, availWidth); + p->cell.pEnd = pNext; + if( (z = HtmlMarkupArg(p, "width", 0))!=0 ){ + for(i=0; isdigit(z[i]); i++){} + if( strcmp(z,"*")==0 ){ + requestedW = availWidth; + }else if( z[i]==0 ){ + requestedW = atoi(z); + }else if( z[i]=='%' ){ + /* requestedW = (atoi(z)*availWidth + 99)/100; */ + requestedW = (atoi(z)*maxTableWidth + 99)/100; + } + }else{ + requestedW = 0; + } + TRACE(HtmlTrace_Table1, + ("Row %d Column %d: min=%d max=%d req=%d stop at %s\n", + iRow,iCol,minW,maxW,requestedW, HtmlTokenName(p->cell.pEnd))); + if( noWrap ){ + minW = maxW; + } + if( iCol + p->cell.colspan <= HTML_MAX_COLUMNS ){ + int min = 0; + if( p->cell.colspan==0 ){ + SETMAX( min0span[iCol], minW ); + SETMAX( max0span[iCol], maxW ); + min = min0span[iCol] + separation; + }else if( colspan==1 ){ + SETMAX( pStart->table.minW[iCol], minW ); + SETMAX( pStart->table.maxW[iCol], maxW ); + SETMAX( reqW[iCol], requestedW ); + min = pStart->table.minW[iCol] + separation; + }else{ + int n = p->cell.colspan; + SETMAX( ColMin(iCol,iCol+n-1), minW); + SETMAX( ColReq(iCol,iCol+n-1), requestedW); + min = minW + separation; +#if 0 + maxW = (maxW + (n - 1)*(1-separation))/n; + for(i=iCol; i<iCol + n && i<HTML_MAX_COLUMNS; i++){ + SETMAX( pStart->table.maxW[i], maxW ); + } +#endif + } + availWidth -= min; + } + rowspan = p->cell.rowspan; + if( rowspan==0 ){ + rowspan = LARGE_NUMBER; + } + if( rowspan>1 ){ + for(i=iCol; i<iCol + p->cell.colspan && i<HTML_MAX_COLUMNS; i++){ + fromAbove[i] = iRow + rowspan; + } + } + if( p->cell.colspan > 1 ){ + iCol += p->cell.colspan - 1; + }else if( p->cell.colspan==0 ){ + iCol = HTML_MAX_COLUMNS + 1; + } + break; + } + } + +#ifdef DEBUG + if( HtmlTraceMask & HtmlTrace_Table6 ){ + char *zSpace = ""; + TRACE_INDENT; + for(i=1; i<=pStart->table.nCol; i++){ + printf("%s%d:%d..%d",zSpace,i, + pStart->table.minW[i],pStart->table.maxW[i]); + if( reqW[i]>0 ){ + printf("(w=%d)",reqW[i]); + } + zSpace = " "; + } + printf("\n"); + for(i=1; i<pStart->table.nCol; i++){ + for(j=i+1; j<=pStart->table.nCol; j++){ + if( ColMin(i,j)>0 ){ + TRACE_INDENT; + printf("ColMin(%d,%d) = %d\n", i, j, ColMin(i,j)); + } + if( ColReq(i,j)>0 ){ + TRACE_INDENT; + printf("ColReq(%d,%d) = %d\n", i, j, ColReq(i,j)); + } + } + } + } +#endif + + /* Compute the min and max width of each column + */ + for(i=1; i<=pStart->table.nCol; i++){ + int sumMin, sumReq, sumMax; + + /* Reduce the max[] field to N for columns that have "width=N" */ + if( reqW[i]>0 ){ + pStart->table.maxW[i] = MAX(pStart->table.minW[i],reqW[i]); + } + + /* Expand the width of columns marked with "colspan=0". + */ + if( min0span[i]>0 || max0span[i]>0 ){ + int n = pStart->table.nCol - i + 1; + minW = (min0span[i] + (n - 1)*(1-separation))/n; + maxW = (max0span[i] + (n - 1)*(1-separation))/n; + for(j=i; j<=pStart->table.nCol; j++){ + SETMAX( pStart->table.minW[j], minW ); + SETMAX( pStart->table.maxW[j], maxW ); + } + } + + /* Expand the minW[] of columns to accomodate "colspan=N" constraints. + ** The minW[] is expanded up to the maxW[] first. Then all the maxW[]s + ** are expanded in proportion to their sizes. The same thing occurs + ** for reqW[]s. + */ + sumReq = reqW[i]; + sumMin = pStart->table.minW[i]; + sumMax = pStart->table.maxW[i]; + for(j=i-1; j>=1; j--){ + int cmin, creq; + sumMin += pStart->table.minW[j]; + sumMax += pStart->table.maxW[j]; + sumReq += reqW[i]; + cmin = ColMin(j,i); + if( cmin>sumMin ){ + int k; + double scale; + int *tminW = pStart->table.minW; + int *tmaxW = pStart->table.maxW; + if( sumMin<sumMax ){ + scale = (double)(cmin - sumMin)/(double)(sumMax - sumMin); + for(k=j; k<=i; k++){ + sumMin -= tminW[k]; + tminW[k] = (tmaxW[k] - tminW[k])*scale + tminW[k]; + sumMin += tminW[k]; + } + }else if( sumMin>0 ){ + scale = (double)cmin/(double)sumMin; + for(k=j; k<=i; k++){ + sumMin -= tminW[k]; + tminW[k] = tmaxW[k] = tminW[k]*scale; + sumMin += tminW[k]; + } + }else{ + int unit = cmin/(i-j+1); + for(k=j; k<=i; k++){ + tminW[k] = tmaxW[k] = unit; + sumMin += tminW[k]; + } + } + } + creq = ColReq(j,i); + if( creq>sumReq ){ + int k; + double scale; + int *tmaxW = pStart->table.maxW; + if( sumReq<sumMax ){ + scale = (double)(creq - sumReq)/(double)(sumMax - sumReq); + for(k=j; k<=i; k++){ + sumReq -= reqW[k]; + reqW[k] = (tmaxW[k] - reqW[k])*scale + reqW[k]; + sumReq += reqW[k]; + } + }else if( sumReq>0 ){ + scale = (double)creq/(double)sumReq; + for(k=j; k<=i; k++){ + sumReq -= reqW[k]; + reqW[k] = reqW[k]*scale; + sumReq += reqW[k]; + } + }else{ + int unit = creq/(i-j+1); + for(k=j; k<=i; k++){ + reqW[k] = unit; + sumReq += reqW[k]; + } + } + } + } + } + +#ifdef DEBUG + if( HtmlTraceMask & HtmlTrace_Table6 ){ + char *zSpace = ""; + TRACE_INDENT; + for(i=1; i<=pStart->table.nCol; i++){ + printf("%s%d:%d..%d",zSpace,i, + pStart->table.minW[i],pStart->table.maxW[i]); + if( reqW[i]>0 ){ + printf("(w=%d)",reqW[i]); + } + zSpace = " "; + } + printf("\n"); + } +#endif + + /* Compute the min and max width of the whole table + */ + n = pStart->table.nCol; + requestedW = tbw*2 + (n+1)*cellSpacing + n*2*(cellPadding + cbw); + pStart->table.minW[0] = requestedW; + pStart->table.maxW[0] = requestedW; + for(i=1; i<=pStart->table.nCol; i++){ + pStart->table.minW[0] += pStart->table.minW[i]; + pStart->table.maxW[0] += pStart->table.maxW[i]; + requestedW += MAX(reqW[i], pStart->table.minW[i]); + } + + /* Figure out how wide to draw the table */ + z = HtmlMarkupArg(pStart, "width", 0); + if( z ){ + int len = strlen(z); + int totalWidth; + if( len>0 && z[len-1]=='%' ){ + totalWidth = (atoi(z) * lineWidth)/100; + }else{ + totalWidth = atoi(z); + } + SETMAX( requestedW, totalWidth ); + } + if( lineWidth && (requestedW > lineWidth) ){ + TRACE(HtmlTrace_Table5,("RequestedW reduced to lineWidth: %d -> %d\n", + requestedW, lineWidth)); + requestedW = lineWidth; + } + if( requestedW > pStart->table.minW[0] ){ + float scale; + int *tminW = pStart->table.minW; + int *tmaxW = pStart->table.maxW; + TRACE(HtmlTrace_Table5, + ("Expanding table minW from %d to %d. (reqW=%d width=%s)\n", + tminW[0], requestedW, requestedW, z)); + if( tmaxW[0] > tminW[0] ){ + scale = (double)(requestedW - tminW[0]) / (double)(tmaxW[0] - tminW[0]); + for(i=1; i<=pStart->table.nCol; i++){ + tminW[i] += (tmaxW[i] - tminW[i]) * scale; + SETMAX(tmaxW[i], tminW[i]); + } + }else if( tminW[0]>0 ){ + scale = requestedW/(double)tminW[0]; + for(i=1; i<=pStart->table.nCol; i++){ + tminW[i] *= scale; + tmaxW[i] *= scale; + } + }else if( pStart->table.nCol>0 ){ + int unit = (requestedW - margin)/pStart->table.nCol - separation; + if( unit<0 ) unit = 0; + for(i=1; i<=pStart->table.nCol; i++){ + tminW[i] = tmaxW[i] = unit; + } + }else{ + tminW[0] = tmaxW[0] = requestedW; + } + pStart->table.minW[0] = requestedW; + SETMAX( pStart->table.maxW[0], requestedW ); + } + +#ifdef DEBUG + if( HtmlTraceMask & HtmlTrace_Table5 ){ + TRACE_INDENT; + printf("Start with %s and ", HtmlTokenName(pStart)); + printf("end with %s\n", HtmlTokenName(p)); + TRACE_INDENT; + printf("nCol=%d minWidth=%d maxWidth=%d\n", + pStart->table.nCol, pStart->table.minW[0], pStart->table.maxW[0]); + for(i=1; i<=pStart->table.nCol; i++){ + TRACE_INDENT; + printf("Column %d minWidth=%d maxWidth=%d\n", + i, pStart->table.minW[i], pStart->table.maxW[i]); + } + } +#endif + + TRACE(HtmlTrace_Table1, + ("Result of TableDimensions: min=%d max=%d nCol=%d\n", + pStart->table.minW[0], pStart->table.maxW[0], pStart->table.nCol)); + TRACE_POP(HtmlTrace_Table1); + return p; +} + +/* +** Given a list of elements, compute the minimum and maximum width needed +** to render the list. Stop the search at the first element seen that is +** in the following set: +** +** <tr> <td> <th> </tr> </td> </th> </table> +** +** Return a pointer to the element that stopped the search, or to NULL +** if we ran out of data. +** +** Sometimes the value returned for both min and max will be larger than +** the true minimum and maximum. This is rare, and only occurs if the +** element string contains figures with flow-around text. +*/ +static HtmlElement *MinMax( + HtmlWidget *htmlPtr, /* The Html widget */ + HtmlElement *p, /* Start the search here */ + int *pMin, /* Return the minimum width here */ + int *pMax, /* Return the maximum width here */ + int lineWidth /* Total width available */ +){ + int min = 0; /* Minimum width so far */ + int max = 0; /* Maximum width so far */ + int indent = 0; /* Amount of indentation (minimum) */ + int obstacle = 0; /* Possible obstacles in the margin */ + int x1 = 0; /* Length of current line assuming maximum length */ + int x2 = 0; /* Length of current line assuming minimum length */ + int go = 1; /* Change to 0 to stop the loop */ + HtmlElement *pNext; /* Next element in the list */ + + for(p=p->pNext; go && p; p = pNext){ + pNext = p->pNext; + switch( p->base.type ){ + case Html_Text: + x1 += p->text.w; + x2 += p->text.w; + if( p->base.style.flags & STY_Preformatted ){ + SETMAX( min, x1 ); + SETMAX( max, x1 ); + }else{ + SETMAX( min, x2 ); + SETMAX( max, x1 ); + } + break; + case Html_Space: + if( p->base.style.flags & STY_Preformatted ){ + if( p->base.flags & HTML_NewLine ){ + x1 = x2 = indent; + }else{ + x1 += p->space.w * p->base.count; + x2 += p->space.w * p->base.count; + } + }else if( p->base.style.flags & STY_NoBreak ){ + if( x1>indent ){ x1 += p->space.w; TestPoint(0);} + if( x2>indent ){ x2 += p->space.w; TestPoint(0);} + }else{ + if( x1>indent ){ x1 += p->space.w; TestPoint(0);} + x2 = indent; + } + break; + case Html_IMG: + switch( p->image.align ){ + case IMAGE_ALIGN_Left: + case IMAGE_ALIGN_Right: + obstacle += p->image.w; + x1 = obstacle + indent; + x2 = indent; + SETMAX( min, x2 ); + SETMAX( min, p->image.w ); + SETMAX( max, x1 ); + break; + default: + x1 += p->image.w; + x2 += p->image.w; + if( p->base.style.flags & STY_Preformatted ){ + SETMAX( min, x1 ); + SETMAX( max, x1 ); + }else{ + SETMAX( min, x2 ); + SETMAX( max, x1 ); + } + break; + } + break; + case Html_TABLE: + /* pNext = TableDimensions(htmlPtr, p, lineWidth-indent); */ + pNext = TableDimensions(htmlPtr, p, 0); + x1 = p->table.maxW[0] + indent + obstacle; + x2 = p->table.minW[0] + indent; + SETMAX( max, x1 ); + SETMAX( min, x2 ); + x1 = indent + obstacle; + x2 = indent; + if( pNext && pNext->base.type==Html_EndTABLE ){ + pNext = pNext->pNext; + } + break; + case Html_UL: + case Html_OL: + indent += HTML_INDENT; + x1 = indent + obstacle; + x2 = indent; + break; + case Html_EndUL: + case Html_EndOL: + indent -= HTML_INDENT; + if( indent < 0 ){ indent = 0; } + x1 = indent + obstacle; + x2 = indent; + break; + case Html_BLOCKQUOTE: + indent += 2*HTML_INDENT; + x1 = indent + obstacle; + x2 = indent; + break; + case Html_EndBLOCKQUOTE: + indent -= 2*HTML_INDENT; + if( indent < 0 ){ indent = 0; } + x1 = indent + obstacle; + x2 = indent; + break; + case Html_APPLET: + case Html_INPUT: + case Html_SELECT: + case Html_EMBED: + case Html_TEXTAREA: + x1 += p->input.w + p->input.padLeft; + if( p->base.style.flags & STY_Preformatted ){ + SETMAX( min, x1 ); + SETMAX( max, x1 ); + x2 += p->input.w + p->input.padLeft; + }else{ + SETMAX( min, indent + p->input.w ); + SETMAX( max, x1 ); + x2 = indent; + } + break; + case Html_BR: + case Html_P: + case Html_EndP: + case Html_DIV: + case Html_EndDIV: + case Html_H1: + case Html_EndH1: + case Html_H2: + case Html_EndH2: + case Html_H3: + case Html_EndH3: + case Html_H4: + case Html_EndH4: + case Html_H5: + case Html_H6: + x1 = indent + obstacle; + x2 = indent; + break; + case Html_EndTD: + case Html_EndTH: + case Html_CAPTION: + case Html_EndTABLE: + case Html_TD: + case Html_TR: + case Html_TH: + case Html_EndTR: + go = 0; + break; + default: + break; + } + if( !go ){ break; } + } + *pMin = min; + *pMax = max; + return p; +} + +/* Vertical alignments: +*/ +#define VAlign_Unknown 0 +#define VAlign_Top 1 +#define VAlign_Bottom 2 +#define VAlign_Center 3 +#define VAlign_Baseline 4 + +/* +** Return the vertical alignment specified by the given element. +*/ +static int GetVerticalAlignment(HtmlElement *p, int dflt){ + char *z; + int rc; + if( p==0 ) return dflt; + z = HtmlMarkupArg(p, "valign", 0); + if( z==0 ){ + rc = dflt; + TestPoint(0); + }else if( stricmp(z,"top")==0 ){ + rc = VAlign_Top; + TestPoint(0); + }else if( stricmp(z,"bottom")==0 ){ + rc = VAlign_Bottom; + TestPoint(0); + }else if( stricmp(z,"center")==0 ){ + rc = VAlign_Center; + TestPoint(0); + }else if( stricmp(z,"baseline")==0 ){ + rc = VAlign_Baseline; + TestPoint(0); + }else{ + rc = dflt; + TestPoint(0); + } + return rc; +} + +/* Do all layout for a single table. Return the </table> element or +** NULL if the table is unterminated. +*/ +HtmlElement *HtmlTableLayout( + HtmlLayoutContext *pLC, /* The layout context */ + HtmlElement *pTable /* The <table> element */ +){ + HtmlElement *pEnd; /* The </table> element */ + HtmlElement *p; /* For looping thru elements of the table */ + HtmlElement *pNext; /* Next element in the loop */ + HtmlElement *pCaption; /* Start of the caption text. The <caption> */ + HtmlElement *pEndCaption; /* End of the caption. The </caption> */ + int width; /* Width of the table as drawn */ + int cellSpacing; /* Value of cellspacing= parameter to <table> */ + int cellPadding; /* Value of cellpadding= parameter to <table> */ + int tbw; /* Width of the 3D border around the whole table */ + int cbw; /* Width of the 3D border around a cell */ + int pad; /* cellPadding + borderwidth */ + char *z; /* A string */ + int leftMargin; /* The left edge of space available for drawing */ + int lineWidth; /* Total horizontal space available for drawing */ + int separation; /* Distance between content of columns (or rows) */ + int i; /* Loop counter */ + int n; /* Number of columns */ + int btm; /* Bottom edge of previous row */ + int iRow; /* Current row number */ + int iCol; /* Current column number */ + int colspan; /* Number of columns spanned by current cell */ + int vspace; /* Value of the vspace= parameter to <table> */ + int hspace; /* Value of the hspace= parameter to <table> */ + int rowBottom; /* Bottom edge of content in the current row */ + int defaultVAlign; /* Default vertical alignment for the current row */ + char *zAlign; /* Value of the ALIGN= attribute of the <TABLE> */ +#define N HTML_MAX_COLUMNS+1 + int y[N]; /* Top edge of each cell's content */ + int x[N]; /* Left edge of each cell's content */ + int w[N]; /* Width of each cell's content */ + int ymax[N]; /* Bottom edge of cell's content if valign=top */ + HtmlElement *apElem[N]; /* The <td> or <th> for each cell in a row */ + int firstRow[N]; /* First row on which a cell appears */ + int lastRow[N]; /* Row to which each cell span's */ + int valign[N]; /* Vertical alignment for each cell */ + HtmlLayoutContext savedContext; /* Saved copy of the original pLC */ + HtmlLayoutContext cellContext; /* Used to render a single cell */ +#ifdef TABLE_TRIM_BLANK + extern int HtmlLineWasBlank; +#endif /* TABLE_TRIM_BLANK */ + + if( pTable==0 || pTable->base.type!=Html_TABLE ){ + TestPoint(0); + return pTable; + } + TRACE_PUSH(HtmlTrace_Table2); + TRACE(HtmlTrace_Table2, ("Starting TableLayout() at %s\n", + HtmlTokenName(pTable))); + + /* Figure how much horizontal space is available for rendering + ** this table. Store the answer in lineWidth. leftMargin is + ** the left-most X coordinate of the table. btm stores the top-most + ** Y coordinate. + */ + HtmlComputeMargins(pLC, &leftMargin, &btm, &lineWidth); + TRACE(HtmlTrace_Table2, ("...btm=%d left=%d width=%d\n", + btm, leftMargin, lineWidth)); + + /* figure out how much space the table wants for each column, + ** and in total.. */ + pEnd = TableDimensions(pLC->htmlPtr, pTable, lineWidth); + + /* If we don't have enough horizontal space to accomodate the minimum table + ** width, then try to move down past some obstruction (such as an + ** <IMG ALIGN=LEFT>) to give us more room. + */ + if( lineWidth < pTable->table.minW[0] ){ + HtmlWidenLine(pLC, pTable->table.minW[0], &leftMargin, &btm, &lineWidth); + TRACE(HtmlTrace_Table2, ("Widen to btm=%d left=%d width=%d\n", + btm, leftMargin, lineWidth)); + } + savedContext = *pLC; + + /* Figure out how wide to draw the table + */ + if( lineWidth < pTable->table.minW[0] ){ + width = pTable->table.minW[0]; + }else if( lineWidth <= pTable->table.maxW[0] ){ + width = lineWidth; + }else{ + width = pTable->table.maxW[0]; + } + + + /* Compute the width and left edge position of every column in + ** the table */ + z = HtmlMarkupArg(pTable, "cellpadding", 0); + cellPadding = z ? atoi(z) : DFLT_CELLPADDING; + cellSpacing = CellSpacing(pLC->htmlPtr, pTable); + z = HtmlMarkupArg(pTable, "vspace", 0); + vspace = z ? atoi(z) : DFLT_VSPACE; + z = HtmlMarkupArg(pTable, "hspace", 0); + hspace = z ? atoi(z) : DFLT_HSPACE; +#ifdef DEBUG + if( HtmlTraceMask & HtmlTrace_Table4 ){ + cellPadding = 5; + cellSpacing = 2; + if( vspace<2 ) vspace = 2; + if( hspace<2 ) hspace = 2; + } +#endif + tbw = pTable->table.borderWidth; + cbw = (tbw>0); + pad = cellPadding + cbw; + separation = cellSpacing + 2*pad; + x[1] = leftMargin + tbw + cellSpacing + pad; + n = pTable->table.nCol; + if( n<=0 || pTable->table.maxW[0]<=0 ){ + /* Abort if the table has no columns at all or if the total width + ** of the table is zero or less. */ + return pEnd; + } + zAlign = HtmlMarkupArg(pTable, "align", ""); + if( width < lineWidth ){ + int align = pTable->base.style.align; + if( align==ALIGN_Right || stricmp(zAlign,"right")==0 ){ + x[1] += lineWidth - width; + }else if( align==ALIGN_Center && stricmp(zAlign,"left")!=0 ){ + x[1] += (lineWidth - width)/2; + } + } + if( width==pTable->table.maxW[0] ){ + w[1] = pTable->table.maxW[1]; + for(i=2; i<=n; i++){ + w[i] = pTable->table.maxW[i]; + x[i] = x[i-1] + w[i-1] + separation; + TestPoint(0); + } + }else if( width > pTable->table.maxW[0] ){ + int *tmaxW = pTable->table.maxW; + double scale = ((double)width)/ (double)tmaxW[0]; + w[1] = tmaxW[1] * scale; + for(i=2; i<=n; i++){ + w[i] = tmaxW[i] * scale; + x[i] = x[i-1] + w[i-1] + separation; + TestPoint(0); + } + }else if( width > pTable->table.minW[0] ){ + float scale; + int *tminW = pTable->table.minW; + int *tmaxW = pTable->table.maxW; + scale = (double)(width - tminW[0]) / (double)(tmaxW[0] - tminW[0]); + w[1] = tminW[1] + (tmaxW[1] - tminW[1]) * scale; + for(i=2; i<=n; i++){ + w[i] = tminW[i] + (tmaxW[i] - tminW[i]) * scale; + x[i] = x[i-1] + w[i-1] + separation; + TestPoint(0); + } + }else{ + w[1] = pTable->table.minW[1]; + for(i=2; i<=n; i++){ + w[i] = pTable->table.minW[i]; + x[i] = x[i-1] + w[i-1] + separation; + TestPoint(0); + } + } + w[n] = width - ((x[n] - x[1]) + 2*(tbw + pad + cellSpacing)); + + /* Add notation to the pTable structure so that we will know where + ** to draw the outer box around the outside of the table. + */ + btm += vspace; + pTable->table.y = btm; + pTable->table.x = x[1] - (tbw + cellSpacing + pad); + pTable->table.w = width; + SETMAX(pLC->maxX, pTable->table.x + pTable->table.w); + btm += tbw + cellSpacing; + + /* Begin rendering rows of the table */ + for(i=1; i<=n; i++){ + firstRow[i] = 0; + lastRow[i] = 0; + apElem[i] = 0; + } + p = pTable->pNext; + rowBottom = btm; + for(iRow=1; iRow<=pTable->table.nRow; iRow++){ + TRACE(HtmlTrace_Table2, ("Row %d: btm=%d\n",iRow,btm)); + /* Find the start of the next row. Keep an eye out for the caption + ** while we search */ + while( p && p->base.type!=Html_TR ){ + if( p->base.type==Html_CAPTION ){ + pCaption = p; + while( p && p!=pEnd && p->base.type!=Html_EndCAPTION ){ + p = p->pNext; + } + pEndCaption = p; + } + TRACE(HtmlTrace_Table3, ("Skipping token %s\n", HtmlTokenName(p))); + p = p->pNext; + } + if( p==0 ){ TestPoint(0); break; } + + /* Record default vertical alignment flag for this row */ + defaultVAlign = GetVerticalAlignment(p, VAlign_Center); + + /* Find every new cell on this row */ + for(iCol=1; iCol<=pTable->table.nCol && iCol<HTML_MAX_COLUMNS; iCol++){ + if( lastRow[iCol]<iRow ) ymax[iCol] = 0; + } + iCol = 0; + for(p=p->pNext; p && p->base.type!=Html_TR && p!=pEnd; p=pNext){ + pNext = p->pNext; + TRACE(HtmlTrace_Table3, ("Processing token %s\n", HtmlTokenName(p))); + switch( p->base.type ){ + case Html_TD: + case Html_TH: + /* Find the column number for this cell. Be careful to skip + ** columns which extend down to this row from prior rows */ + do{ + iCol++; + }while( iCol <= HTML_MAX_COLUMNS && lastRow[iCol] >= iRow ); + TRACE(HtmlTrace_Table2, + ("Column %d: x=%d w=%d\n",iCol,x[iCol],w[iCol])); + /* Process the new cell. (Cells beyond the maximum number of + ** cells are simply ignored.) */ + if( iCol <= HTML_MAX_COLUMNS ){ + apElem[iCol] = p; + pNext = p->cell.pEnd; + if( p->cell.rowspan==0 ){ + lastRow[iCol] = pTable->table.nRow; + }else{ + lastRow[iCol] = iRow + p->cell.rowspan - 1; + } + firstRow[iCol] = iRow; + + /* Set vertical alignment flag for this cell */ + valign[iCol] = GetVerticalAlignment(p, defaultVAlign); + + /* Render cell contents and record the height */ + y[iCol] = btm + pad; + cellContext.htmlPtr = pLC->htmlPtr; + cellContext.pStart = p->pNext; + cellContext.pEnd = pNext; + cellContext.headRoom = 0; + cellContext.top = y[iCol]; + cellContext.bottom = y[iCol]; + cellContext.left = x[iCol]; + cellContext.right = 0; + cellContext.pageWidth = x[iCol]+w[iCol]; + colspan = p->cell.colspan; + if( colspan==0 ){ + for(i=iCol+1; i<=pTable->table.nCol; i++){ + cellContext.pageWidth += w[i] + separation; + lastRow[i] = lastRow[iCol]; + } + }else if( colspan>1 ){ + for(i=iCol+1; i<iCol+colspan; i++){ + cellContext.pageWidth += w[i] + separation; + lastRow[i] = lastRow[iCol]; + } + } + cellContext.maxX = 0; + cellContext.maxY = 0; + cellContext.leftMargin = 0; + cellContext.rightMargin = 0; + HtmlLock(cellContext.htmlPtr); + HtmlLayoutBlock(&cellContext); + if( HtmlUnlock(cellContext.htmlPtr) ) return 0; +#ifdef TABLE_TRIM_BLANK + /* + * Cancel any trailing vertical whitespace caused + * by break markup + */ + if (HtmlLineWasBlank) + cellContext.maxY -= cellContext.headRoom; +#endif /* TABLE_TRIM_BLANK */ + ymax[iCol] = cellContext.maxY; + SETMAX(ymax[iCol], y[iCol]); + HtmlClearMarginStack(&cellContext.leftMargin); + HtmlClearMarginStack(&cellContext.rightMargin); + + /* Set coordinates of the cell border */ + p->cell.x = x[iCol] - pad; + p->cell.y = btm; + p->cell.w = cellContext.pageWidth + 2*pad - x[iCol]; + TRACE(HtmlTrace_Table2, + ("Column %d top=%d bottom=%d h=%d left=%d w=%d\n", + iCol, y[iCol], ymax[iCol], ymax[iCol]-y[iCol], + p->cell.x, p->cell.w)); + + /* Advance the column counter for cells spaning multiple columns */ + if( colspan > 1 ){ + iCol += colspan - 1; + }else if( colspan==0 ){ + iCol = HTML_MAX_COLUMNS + 1; + } + } + break; + + case Html_CAPTION: + /* Gotta remember where the caption is so we can render it + ** at the end */ + pCaption = p; + while( pNext && pNext!=pEnd && pNext->base.type!=Html_EndCAPTION ){ + pNext = pNext->pNext; + } + pEndCaption = pNext; + break; + } + } + + /* Figure out how high to make this row. */ + for(iCol=1; iCol<=pTable->table.nCol; iCol++){ + if( lastRow[iCol] == iRow || iRow==pTable->table.nRow ){ + SETMAX( rowBottom, ymax[iCol] ); + } + } + TRACE(HtmlTrace_Table2, ("Total row height: %d..%d -> %d\n", + btm,rowBottom,rowBottom-btm)); + + /* Position every cell whose bottom edge ends on this row */ + for(iCol=1; iCol<=pTable->table.nCol; iCol++){ + int dy; /* Extra space at top of cell used for vertical alignment */ + + /* Skip any unused cells or cells that extend down thru + ** subsequent rows */ + if( apElem[iCol]==0 + || (iRow!=pTable->table.nRow && lastRow[iCol]>iRow) ){ continue; } + + /* Align the contents of the cell vertically. */ + switch( valign[iCol] ){ + case VAlign_Unknown: + case VAlign_Center: + dy = (rowBottom - ymax[iCol])/2; + break; + case VAlign_Top: + case VAlign_Baseline: + dy = 0; + break; + case VAlign_Bottom: + dy = rowBottom - ymax[iCol]; + break; + } + if( dy ){ + HtmlElement *pLast = apElem[iCol]->cell.pEnd; + TRACE(HtmlTrace_Table3, ("Delta column %d by %d\n",iCol,dy)); + HtmlMoveVertically(apElem[iCol]->pNext, pLast, dy); + } + + /* Record the height of the cell so that the border can be drawn */ + apElem[iCol]->cell.h = rowBottom + pad - apElem[iCol]->cell.y; + apElem[iCol] = 0; + } + + /* Update btm to the height of the row we just finished setting */ + btm = rowBottom + pad + cellSpacing; + } + + btm += tbw; + pTable->table.h = btm - pTable->table.y; + SETMAX( pLC->maxY, btm ); + pLC->bottom = btm + vspace; + + /* Render the caption, if there is one */ + if( pCaption ){ + } + + /* Whenever we do any table layout, we need to recompute all the + ** HtmlBlocks. The following statement forces this. */ + pLC->htmlPtr->firstBlock = pLC->htmlPtr->lastBlock = 0; + + /* Adjust the context for text that wraps around the table, if + ** requested by an ALIGN=RIGHT or ALIGN=LEFT attribute. + */ + if( stricmp(zAlign,"left")==0 ){ + savedContext.maxX = pLC->maxX; + savedContext.maxY = pLC->maxY; + *pLC = savedContext; + HtmlPushMargin(&pLC->leftMargin, pTable->table.w + 2, + pTable->table.y + pTable->table.h + 2, 0); + }else if( stricmp(zAlign,"right")==0 ){ + savedContext.maxX = pLC->maxX; + savedContext.maxY = pLC->maxY; + *pLC = savedContext; + HtmlPushMargin(&pLC->rightMargin, pTable->table.w + 2, + pTable->table.y + pTable->table.h + 2, 0); + } + + /* All done */ + TRACE(HtmlTrace_Table2, ( + "Done with TableLayout(). x=%d y=%d w=%d h=%d Return %s\n", + pTable->table.x, pTable->table.y, pTable->table.w, pTable->table.h, + HtmlTokenName(pEnd))); + TRACE_POP(HtmlTrace_Table2); + return pEnd; +} + + +/* +** Move all elements in the given list vertically by the amount dy +*/ +void HtmlMoveVertically( + HtmlElement *p, /* First element to move */ + HtmlElement *pLast, /* Last element. Do move this one */ + int dy /* Amount by which to move */ +){ + if( dy==0 ){ TestPoint(0); return; } + while( p && p!=pLast ){ + switch( p->base.type ){ + case Html_A: + p->anchor.y += dy; + break; + case Html_Text: + p->text.y += dy; + break; + case Html_LI: + p->li.y += dy; + break; + case Html_TD: + case Html_TH: + p->cell.y += dy; + break; + case Html_TABLE: + p->table.y += dy; + break; + case Html_IMG: + p->image.y += dy; + break; + case Html_INPUT: + case Html_SELECT: + case Html_APPLET: + case Html_EMBED: + case Html_TEXTAREA: + p->input.y += dy; + break; + default: + break; + } + p = p->pNext; + } +} diff --git a/tkhtml1/src/htmltable.h b/tkhtml1/src/htmltable.h new file mode 100644 index 0000000..b3f7975 --- /dev/null +++ b/tkhtml1/src/htmltable.h @@ -0,0 +1,542 @@ +/* This file was automatically generated. Do not edit! */ +#define Html_LI 81 +#define Html_A 5 +typedef struct HtmlMargin HtmlMargin; +void HtmlPushMargin(HtmlMargin **ppMargin,int indent,int bottom,int tag); +typedef union HtmlElement HtmlElement; +void HtmlMoveVertically(HtmlElement *p,HtmlElement *pLast,int dy); +void HtmlClearMarginStack(HtmlMargin **ppMargin); +typedef struct HtmlWidget HtmlWidget; +int HtmlUnlock(HtmlWidget *htmlPtr); +typedef struct HtmlLayoutContext HtmlLayoutContext; +void HtmlLayoutBlock(HtmlLayoutContext *pLC); +void HtmlLock(HtmlWidget *htmlPtr); +#define HtmlTrace_Table3 0x00000004 +#define ALIGN_Center 3 +#define ALIGN_Right 2 +void HtmlWidenLine(HtmlLayoutContext *pLC,int reqWidth,int *pX,int *pY,int *pW); +void HtmlComputeMargins(HtmlLayoutContext *pLC,int *pX,int *pY,int *pW); +#define HtmlTrace_Table2 0x00000002 +#if defined(TABLE_TRIM_BLANK) +extern int HtmlLineWasBlank; +#endif +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +HtmlElement *HtmlTableLayout(HtmlLayoutContext *pLC,HtmlElement *pTable); +#if !defined(HAVE_STRICMP) +# define stricmp strcasecmp +#endif +#define Html_H6 68 +#define Html_H5 66 +#define Html_EndH4 65 +#define Html_H4 64 +#define Html_EndH3 63 +#define Html_H3 62 +#define Html_EndH2 61 +#define Html_H2 60 +#define Html_EndH1 59 +#define Html_H1 58 +#define Html_EndDIV 42 +#define Html_DIV 41 +#define Html_EndP 105 +#define Html_P 104 +#define Html_BR 24 +#define Html_TEXTAREA 133 +#define Html_EMBED 49 +#define Html_SELECT 116 +#define Html_INPUT 77 +#define Html_APPLET 9 +#define Html_EndBLOCKQUOTE 21 +#define Html_BLOCKQUOTE 20 +#define Html_EndOL 101 +#define Html_EndUL 146 +#define HTML_INDENT 36 +#define Html_OL 100 +#define Html_UL 145 +#define IMAGE_ALIGN_Right 7 +#define IMAGE_ALIGN_Left 6 +#define Html_IMG 76 +#define STY_NoBreak 0x008 +#define HTML_NewLine 0x02 /* type==Html_Space and ends with newline */ +#define Html_Space 2 +#define STY_Preformatted 0x001 +#define Html_Text 1 +extern int HtmlTraceMask; +#define DEBUG 1 +#if defined(DEBUG) +extern int HtmlDepth; +# define TRACE_POP(Flag) if( (Flag)&HtmlTraceMask ){ HtmlDepth-=3; } +#endif +#if !(defined(DEBUG)) +# define TRACE_POP(Flag) +#endif +#define HtmlTrace_Table5 0x00000010 +#if defined(DEBUG) +# define TRACE_INDENT printf("%*s",HtmlDepth-3,"") +#endif +#if !(defined(DEBUG)) +# define TRACE_INDENT +#endif +#define HtmlTrace_Table6 0x00000020 +#define LARGE_NUMBER 100000000 +char *HtmlTokenName(HtmlElement *p); +typedef struct HtmlRef HtmlRef; +typedef struct HtmlMarkupElement HtmlMarkupElement; +typedef struct HtmlBaseElement HtmlBaseElement; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +typedef unsigned char Html_u8; +typedef short Html_16; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +#define HtmlAlloc(A) ((void*)Tcl_Alloc(A)) +#define Html_TH 135 +#define Html_TD 131 +#define Html_EndCAPTION 26 +#define Html_CAPTION 25 +#define Html_TR 139 +#define Html_EndTR 140 +#define Html_EndTH 136 +#define Html_EndTD 132 +#define Html_EndTABLE 130 +#define COLOR_Background 4 /* Default background color */ +#define HtmlTrace_Table4 0x00000008 +#if defined(DEBUG) +# define TRACE(Flag, Args) \ + if( (Flag)&HtmlTraceMask ){ \ + TRACE_INDENT; printf Args; fflush(stdout); \ + } +#endif +#if !(defined(DEBUG)) +# define TRACE(Flag, Args) +#endif +#define HtmlTrace_Table1 0x00000001 +#if defined(DEBUG) +# define TRACE_PUSH(Flag) if( (Flag)&HtmlTraceMask ){ HtmlDepth+=3; } +#endif +#if !(defined(DEBUG)) +# define TRACE_PUSH(Flag) +#endif +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +#define Html_TABLE 129 +#define HTML_MAX_COLUMNS 40 +char *HtmlMarkupArg(HtmlElement *p,const char *tag,char *zDefault); +typedef struct HtmlTextElement HtmlTextElement; +typedef int Html_32; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +typedef unsigned short Html_u16; +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +typedef struct HtmlImage HtmlImage; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +typedef struct HtmlScript HtmlScript; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +typedef struct HtmlBlock HtmlBlock; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +#define Html_TypeCount 151 +typedef struct HtmlStyleStack HtmlStyleStack; +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +#define MAX(A,B) ((A)<(B)?(B):(A)) +#define SETMAX(A,B) if( (A)<(B) ){ (A) = (B); } +#define INTERFACE 0 +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/htmltest.c b/tkhtml1/src/htmltest.c new file mode 100644 index 0000000..c57d98b --- /dev/null +++ b/tkhtml1/src/htmltest.c @@ -0,0 +1,122 @@ +/* +** This file contains the TestPoint routines used for profiling +** and coverage analysis of the code. +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +/* +** A macro named "TestPoint" is defined which increments a counter +** whenever it is encountered. This is very efficient, and should +** not impact performance of the system. For delivery, the macro +** can be nulled out by recompiling without the COVERAGE_TEST macro +** defined. +** +** See also the "renumber.c" program which can be used +** to assign unique numbers to all of the TestPoint(0) macros. +*/ +#include "tcl.h" +#include "htmltest.h" + +#if INTERFACE + +#if defined(COVERAGE_TEST) +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +# define UNTESTED HtmlTPUntested(__FILE__,__LINE__) +# define CANT_HAPPEN HtmlTPCantHappen(__FILE__,__LINE__) +# define HtmlVerifyLock(H) if((H)->locked==0)HtmlTPCantHappen(__FILE__,__LINE__) +#else +# define TestPoint(X) +# define UNTESTED +# define CANT_HAPPEN +# define HtmlVerifyLock(H) +#endif + +#endif /* INTERFACE */ + +/* +** The following global array keeps track of the number of visits to +** each testpoint. The size of the array must be set manually to the +** be at least one greater than the largest TestPoint number. +*/ +#if defined(COVERAGE_TEST) +int HtmlTPArray[2000]; +#endif + +/* Needed by the EslTestPointDump routine +*/ +#include <stdio.h> + +/* +** Recursion depth +*/ +#if defined(DEBUG) +int HtmlDepth = 0; +#endif +#if INTERFACE +#if defined(DEBUG) +#define HtmlPush HtmlDepth+=2 +#define HtmlPop HtmlDepth-=2 +#else +#define HtmlPush +#define HtmlPop +#endif +#endif + +/* This function is called to print the values of all elements of the +** TP_Array to the given file. Values are printed in decimal, one per line. +*/ +void HtmlTestPointDump(const char *filename){ +#if defined(COVERAGE_TEST) + FILE *fp; + + fp = fopen(filename,"a"); + if( fp ){ + int i; + for(i=0; i<sizeof(HtmlTPArray)/sizeof(HtmlTPArray[0]); i++){ + if( HtmlTPArray[i]>0 ){ + fprintf(fp,"%d %d\n",i,HtmlTPArray[i]); + } + } + } + fclose(fp); +#endif +} + +/* This function reports an error to stderr when code that is marked +** UNTESTED gets executed. +*/ +void HtmlTPUntested(const char *zFile, int line){ +#ifndef USE_TCL_STUBS + fprintf(stderr,"Untested HTML Widget code executed in file %s line %d\n", + zFile,line); +#endif +} + +/* This function reports an error to stderr when safety code that should +** never execute is called. +*/ +void HtmlTPCantHappen(const char *zFile, int line){ +#ifndef USE_TCL_STUBS + fprintf(stderr,"Unplanned behavior in the HTML Widget in file %s line %d\n", + zFile,line); +#endif +} diff --git a/tkhtml1/src/htmltest.h b/tkhtml1/src/htmltest.h new file mode 100644 index 0000000..060508f --- /dev/null +++ b/tkhtml1/src/htmltest.h @@ -0,0 +1,44 @@ +/* This file was automatically generated. Do not edit! */ +void HtmlTestPointDump(const char *filename); +#define DEBUG 1 +#if defined(DEBUG) +extern int HtmlDepth; +#define HtmlPop HtmlDepth-=2 +#endif +#if !(defined(DEBUG)) +#define HtmlPop +#endif +#if defined(DEBUG) +#define HtmlPush HtmlDepth+=2 +#endif +#if !(defined(DEBUG)) +#define HtmlPush +#endif +void HtmlTPCantHappen(const char *zFile,int line); +#if defined(COVERAGE_TEST) +# define HtmlVerifyLock(H) if((H)->locked==0)HtmlTPCantHappen(__FILE__,__LINE__) +#endif +#if !(defined(COVERAGE_TEST)) +# define HtmlVerifyLock(H) +#endif +#if defined(COVERAGE_TEST) +# define CANT_HAPPEN HtmlTPCantHappen(__FILE__,__LINE__) +#endif +#if !(defined(COVERAGE_TEST)) +# define CANT_HAPPEN +#endif +void HtmlTPUntested(const char *zFile,int line); +#if defined(COVERAGE_TEST) +# define UNTESTED HtmlTPUntested(__FILE__,__LINE__) +#endif +#if !(defined(COVERAGE_TEST)) +# define UNTESTED +#endif +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +#define INTERFACE 0 diff --git a/tkhtml1/src/htmltokens.c b/tkhtml1/src/htmltokens.c new file mode 100644 index 0000000..d8a3c99 --- /dev/null +++ b/tkhtml1/src/htmltokens.c @@ -0,0 +1,318 @@ +/* DO NOT EDIT +** The code in this file was automatically generated. +*/ +#include <tk.h> +#include "htmltokens.h" +#if INTERFACE +struct HtmlTokenMap { + char *zName; /* Name of a markup */ + Html_16 type; /* Markup type code */ + Html_16 extra; /* Extra space needed above HtmlBaseElement */ + HtmlTokenMap *pCollide; /* Hash table collision chain */ +}; +#define Html_Text 1 +#define Html_Space 2 +#define Html_Unknown 3 +#define Html_Block 4 +#define HtmlIsMarkup(X) ((X)->base.type>Html_Block) + +#define Html_A 5 +#define Html_EndA 6 +#define Html_ADDRESS 7 +#define Html_EndADDRESS 8 +#define Html_APPLET 9 +#define Html_EndAPPLET 10 +#define Html_AREA 11 +#define Html_B 12 +#define Html_EndB 13 +#define Html_BASE 14 +#define Html_BASEFONT 15 +#define Html_EndBASEFONT 16 +#define Html_BGSOUND 17 +#define Html_BIG 18 +#define Html_EndBIG 19 +#define Html_BLOCKQUOTE 20 +#define Html_EndBLOCKQUOTE 21 +#define Html_BODY 22 +#define Html_EndBODY 23 +#define Html_BR 24 +#define Html_CAPTION 25 +#define Html_EndCAPTION 26 +#define Html_CENTER 27 +#define Html_EndCENTER 28 +#define Html_CITE 29 +#define Html_EndCITE 30 +#define Html_CODE 31 +#define Html_EndCODE 32 +#define Html_COMMENT 33 +#define Html_EndCOMMENT 34 +#define Html_DD 35 +#define Html_EndDD 36 +#define Html_DFN 37 +#define Html_EndDFN 38 +#define Html_DIR 39 +#define Html_EndDIR 40 +#define Html_DIV 41 +#define Html_EndDIV 42 +#define Html_DL 43 +#define Html_EndDL 44 +#define Html_DT 45 +#define Html_EndDT 46 +#define Html_EM 47 +#define Html_EndEM 48 +#define Html_EMBED 49 +#define Html_FONT 50 +#define Html_EndFONT 51 +#define Html_FORM 52 +#define Html_EndFORM 53 +#define Html_FRAME 54 +#define Html_EndFRAME 55 +#define Html_FRAMESET 56 +#define Html_EndFRAMESET 57 +#define Html_H1 58 +#define Html_EndH1 59 +#define Html_H2 60 +#define Html_EndH2 61 +#define Html_H3 62 +#define Html_EndH3 63 +#define Html_H4 64 +#define Html_EndH4 65 +#define Html_H5 66 +#define Html_EndH5 67 +#define Html_H6 68 +#define Html_EndH6 69 +#define Html_HR 70 +#define Html_HTML 71 +#define Html_EndHTML 72 +#define Html_I 73 +#define Html_EndI 74 +#define Html_IFRAME 75 +#define Html_IMG 76 +#define Html_INPUT 77 +#define Html_ISINDEX 78 +#define Html_KBD 79 +#define Html_EndKBD 80 +#define Html_LI 81 +#define Html_EndLI 82 +#define Html_LINK 83 +#define Html_LISTING 84 +#define Html_EndLISTING 85 +#define Html_MAP 86 +#define Html_EndMAP 87 +#define Html_MARQUEE 88 +#define Html_EndMARQUEE 89 +#define Html_MENU 90 +#define Html_EndMENU 91 +#define Html_META 92 +#define Html_NEXTID 93 +#define Html_NOBR 94 +#define Html_EndNOBR 95 +#define Html_NOFRAME 96 +#define Html_EndNOFRAME 97 +#define Html_NOSCRIPT 98 +#define Html_EndNOSCRIPT 99 +#define Html_OL 100 +#define Html_EndOL 101 +#define Html_OPTION 102 +#define Html_EndOPTION 103 +#define Html_P 104 +#define Html_EndP 105 +#define Html_PARAM 106 +#define Html_EndPARAM 107 +#define Html_PLAINTEXT 108 +#define Html_PRE 109 +#define Html_EndPRE 110 +#define Html_S 111 +#define Html_EndS 112 +#define Html_SAMP 113 +#define Html_EndSAMP 114 +#define Html_SCRIPT 115 +#define Html_SELECT 116 +#define Html_EndSELECT 117 +#define Html_SMALL 118 +#define Html_EndSMALL 119 +#define Html_STRIKE 120 +#define Html_EndSTRIKE 121 +#define Html_STRONG 122 +#define Html_EndSTRONG 123 +#define Html_STYLE 124 +#define Html_SUB 125 +#define Html_EndSUB 126 +#define Html_SUP 127 +#define Html_EndSUP 128 +#define Html_TABLE 129 +#define Html_EndTABLE 130 +#define Html_TD 131 +#define Html_EndTD 132 +#define Html_TEXTAREA 133 +#define Html_EndTEXTAREA 134 +#define Html_TH 135 +#define Html_EndTH 136 +#define Html_TITLE 137 +#define Html_EndTITLE 138 +#define Html_TR 139 +#define Html_EndTR 140 +#define Html_TT 141 +#define Html_EndTT 142 +#define Html_U 143 +#define Html_EndU 144 +#define Html_UL 145 +#define Html_EndUL 146 +#define Html_VAR 147 +#define Html_EndVAR 148 +#define Html_WBR 149 +#define Html_XMP 150 +#define Html_EndXMP 151 +#define Html_TypeCount 151 +#define HTML_MARKUP_HASH_SIZE 163 +#define HTML_MARKUP_COUNT 147 +#endif /* INTERFACE */ +HtmlTokenMap HtmlMarkupMap[] = { + { "a", Html_A, sizeof(HtmlAnchor), }, + { "/a", Html_EndA, sizeof(HtmlRef), }, + { "address", Html_ADDRESS, 0, }, + { "/address", Html_EndADDRESS, 0, }, + { "applet", Html_APPLET, sizeof(HtmlInput), }, + { "/applet", Html_EndAPPLET, 0, }, + { "area", Html_AREA, 0, }, + { "b", Html_B, 0, }, + { "/b", Html_EndB, 0, }, + { "base", Html_BASE, 0, }, + { "basefont", Html_BASEFONT, 0, }, + { "/basefont", Html_EndBASEFONT, 0, }, + { "bgsound", Html_BGSOUND, 0, }, + { "big", Html_BIG, 0, }, + { "/big", Html_EndBIG, 0, }, + { "blockquote", Html_BLOCKQUOTE, 0, }, + { "/blockquote", Html_EndBLOCKQUOTE, 0, }, + { "body", Html_BODY, 0, }, + { "/body", Html_EndBODY, 0, }, + { "br", Html_BR, 0, }, + { "caption", Html_CAPTION, 0, }, + { "/caption", Html_EndCAPTION, 0, }, + { "center", Html_CENTER, 0, }, + { "/center", Html_EndCENTER, 0, }, + { "cite", Html_CITE, 0, }, + { "/cite", Html_EndCITE, 0, }, + { "code", Html_CODE, 0, }, + { "/code", Html_EndCODE, 0, }, + { "comment", Html_COMMENT, 0, }, + { "/comment", Html_EndCOMMENT, 0, }, + { "dd", Html_DD, sizeof(HtmlRef), }, + { "/dd", Html_EndDD, 0, }, + { "dfn", Html_DFN, 0, }, + { "/dfn", Html_EndDFN, 0, }, + { "dir", Html_DIR, sizeof(HtmlListStart), }, + { "/dir", Html_EndDIR, sizeof(HtmlRef), }, + { "div", Html_DIV, 0, }, + { "/div", Html_EndDIV, 0, }, + { "dl", Html_DL, sizeof(HtmlListStart), }, + { "/dl", Html_EndDL, sizeof(HtmlRef), }, + { "dt", Html_DT, sizeof(HtmlRef), }, + { "/dt", Html_EndDT, 0, }, + { "em", Html_EM, 0, }, + { "/em", Html_EndEM, 0, }, + { "embed", Html_EMBED, sizeof(HtmlInput), }, + { "font", Html_FONT, 0, }, + { "/font", Html_EndFONT, 0, }, + { "form", Html_FORM, sizeof(HtmlForm), }, + { "/form", Html_EndFORM, sizeof(HtmlRef), }, + { "frame", Html_FRAME, 0, }, + { "/frame", Html_EndFRAME, 0, }, + { "frameset", Html_FRAMESET, 0, }, + { "/frameset", Html_EndFRAMESET, 0, }, + { "h1", Html_H1, 0, }, + { "/h1", Html_EndH1, 0, }, + { "h2", Html_H2, 0, }, + { "/h2", Html_EndH2, 0, }, + { "h3", Html_H3, 0, }, + { "/h3", Html_EndH3, 0, }, + { "h4", Html_H4, 0, }, + { "/h4", Html_EndH4, 0, }, + { "h5", Html_H5, 0, }, + { "/h5", Html_EndH5, 0, }, + { "h6", Html_H6, 0, }, + { "/h6", Html_EndH6, 0, }, + { "hr", Html_HR, sizeof(HtmlHr), }, + { "html", Html_HTML, 0, }, + { "/html", Html_EndHTML, 0, }, + { "i", Html_I, 0, }, + { "/i", Html_EndI, 0, }, + { "iframe", Html_IFRAME, 0, }, + { "img", Html_IMG, sizeof(HtmlImageMarkup), }, + { "input", Html_INPUT, sizeof(HtmlInput), }, + { "isindex", Html_ISINDEX, 0, }, + { "kbd", Html_KBD, 0, }, + { "/kbd", Html_EndKBD, 0, }, + { "li", Html_LI, sizeof(HtmlLi), }, + { "/li", Html_EndLI, 0, }, + { "link", Html_LINK, 0, }, + { "listing", Html_LISTING, 0, }, + { "/listing", Html_EndLISTING, 0, }, + { "map", Html_MAP, 0, }, + { "/map", Html_EndMAP, 0, }, + { "marquee", Html_MARQUEE, 0, }, + { "/marquee", Html_EndMARQUEE, 0, }, + { "menu", Html_MENU, sizeof(HtmlListStart), }, + { "/menu", Html_EndMENU, sizeof(HtmlRef), }, + { "meta", Html_META, 0, }, + { "nextid", Html_NEXTID, 0, }, + { "nobr", Html_NOBR, 0, }, + { "/nobr", Html_EndNOBR, 0, }, + { "noframe", Html_NOFRAME, 0, }, + { "/noframe", Html_EndNOFRAME, 0, }, + { "noscript", Html_NOSCRIPT, 0, }, + { "/noscript", Html_EndNOSCRIPT, 0, }, + { "ol", Html_OL, sizeof(HtmlListStart), }, + { "/ol", Html_EndOL, sizeof(HtmlRef), }, + { "option", Html_OPTION, 0, }, + { "/option", Html_EndOPTION, 0, }, + { "p", Html_P, 0, }, + { "/p", Html_EndP, 0, }, + { "param", Html_PARAM, 0, }, + { "/param", Html_EndPARAM, 0, }, + { "plaintext", Html_PLAINTEXT, 0, }, + { "pre", Html_PRE, 0, }, + { "/pre", Html_EndPRE, 0, }, + { "s", Html_S, 0, }, + { "/s", Html_EndS, 0, }, + { "samp", Html_SAMP, 0, }, + { "/samp", Html_EndSAMP, 0, }, + { "script", Html_SCRIPT, sizeof(HtmlScript), }, + { "select", Html_SELECT, sizeof(HtmlInput), }, + { "/select", Html_EndSELECT, sizeof(HtmlRef), }, + { "small", Html_SMALL, 0, }, + { "/small", Html_EndSMALL, 0, }, + { "strike", Html_STRIKE, 0, }, + { "/strike", Html_EndSTRIKE, 0, }, + { "strong", Html_STRONG, 0, }, + { "/strong", Html_EndSTRONG, 0, }, + { "style", Html_STYLE, sizeof(HtmlScript), }, + { "sub", Html_SUB, 0, }, + { "/sub", Html_EndSUB, 0, }, + { "sup", Html_SUP, 0, }, + { "/sup", Html_EndSUP, 0, }, + { "table", Html_TABLE, sizeof(HtmlTable), }, + { "/table", Html_EndTABLE, sizeof(HtmlRef), }, + { "td", Html_TD, sizeof(HtmlCell), }, + { "/td", Html_EndTD, sizeof(HtmlRef), }, + { "textarea", Html_TEXTAREA, sizeof(HtmlInput), }, + { "/textarea", Html_EndTEXTAREA, sizeof(HtmlRef), }, + { "th", Html_TH, sizeof(HtmlCell), }, + { "/th", Html_EndTH, sizeof(HtmlRef), }, + { "title", Html_TITLE, 0, }, + { "/title", Html_EndTITLE, 0, }, + { "tr", Html_TR, sizeof(HtmlRef), }, + { "/tr", Html_EndTR, sizeof(HtmlRef), }, + { "tt", Html_TT, 0, }, + { "/tt", Html_EndTT, 0, }, + { "u", Html_U, 0, }, + { "/u", Html_EndU, 0, }, + { "ul", Html_UL, sizeof(HtmlListStart), }, + { "/ul", Html_EndUL, sizeof(HtmlRef), }, + { "var", Html_VAR, 0, }, + { "/var", Html_EndVAR, 0, }, + { "wbr", Html_WBR, 0, }, + { "xmp", Html_XMP, 0, }, + { "/xmp", Html_EndXMP, 0, }, +}; diff --git a/tkhtml1/src/htmltokens.h b/tkhtml1/src/htmltokens.h new file mode 100644 index 0000000..0736806 --- /dev/null +++ b/tkhtml1/src/htmltokens.h @@ -0,0 +1,590 @@ +/* This file was automatically generated. Do not edit! */ +typedef struct HtmlCell HtmlCell; +typedef struct HtmlMarkupElement HtmlMarkupElement; +typedef struct HtmlBaseElement HtmlBaseElement; +typedef union HtmlElement HtmlElement; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +typedef unsigned char Html_u8; +typedef short Html_16; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +typedef int Html_32; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +typedef unsigned short Html_u16; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlScript HtmlScript; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +typedef struct HtmlImage HtmlImage; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlInput HtmlInput; +typedef struct HtmlWidget HtmlWidget; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +typedef struct HtmlTokenMap HtmlTokenMap; +struct HtmlTokenMap { + char *zName; /* Name of a markup */ + Html_16 type; /* Markup type code */ + Html_16 extra; /* Extra space needed above HtmlBaseElement */ + HtmlTokenMap *pCollide; /* Hash table collision chain */ +}; +extern HtmlTokenMap HtmlMarkupMap[]; +#define HTML_MARKUP_COUNT 147 +#define HTML_MARKUP_HASH_SIZE 163 +#define Html_TypeCount 151 +#define Html_EndXMP 151 +#define Html_XMP 150 +#define Html_WBR 149 +#define Html_EndVAR 148 +#define Html_VAR 147 +#define Html_EndUL 146 +#define Html_UL 145 +#define Html_EndU 144 +#define Html_U 143 +#define Html_EndTT 142 +#define Html_TT 141 +#define Html_EndTR 140 +#define Html_TR 139 +#define Html_EndTITLE 138 +#define Html_TITLE 137 +#define Html_EndTH 136 +#define Html_TH 135 +#define Html_EndTEXTAREA 134 +#define Html_TEXTAREA 133 +#define Html_EndTD 132 +#define Html_TD 131 +#define Html_EndTABLE 130 +#define Html_TABLE 129 +#define Html_EndSUP 128 +#define Html_SUP 127 +#define Html_EndSUB 126 +#define Html_SUB 125 +#define Html_STYLE 124 +#define Html_EndSTRONG 123 +#define Html_STRONG 122 +#define Html_EndSTRIKE 121 +#define Html_STRIKE 120 +#define Html_EndSMALL 119 +#define Html_SMALL 118 +#define Html_EndSELECT 117 +#define Html_SELECT 116 +#define Html_SCRIPT 115 +#define Html_EndSAMP 114 +#define Html_SAMP 113 +#define Html_EndS 112 +#define Html_S 111 +#define Html_EndPRE 110 +#define Html_PRE 109 +#define Html_PLAINTEXT 108 +#define Html_EndPARAM 107 +#define Html_PARAM 106 +#define Html_EndP 105 +#define Html_P 104 +#define Html_EndOPTION 103 +#define Html_OPTION 102 +#define Html_EndOL 101 +#define Html_OL 100 +#define Html_EndNOSCRIPT 99 +#define Html_NOSCRIPT 98 +#define Html_EndNOFRAME 97 +#define Html_NOFRAME 96 +#define Html_EndNOBR 95 +#define Html_NOBR 94 +#define Html_NEXTID 93 +#define Html_META 92 +#define Html_EndMENU 91 +#define Html_MENU 90 +#define Html_EndMARQUEE 89 +#define Html_MARQUEE 88 +#define Html_EndMAP 87 +#define Html_MAP 86 +#define Html_EndLISTING 85 +#define Html_LISTING 84 +#define Html_LINK 83 +#define Html_EndLI 82 +#define Html_LI 81 +#define Html_EndKBD 80 +#define Html_KBD 79 +#define Html_ISINDEX 78 +#define Html_INPUT 77 +#define Html_IMG 76 +#define Html_IFRAME 75 +#define Html_EndI 74 +#define Html_I 73 +#define Html_EndHTML 72 +#define Html_HTML 71 +#define Html_HR 70 +#define Html_EndH6 69 +#define Html_H6 68 +#define Html_EndH5 67 +#define Html_H5 66 +#define Html_EndH4 65 +#define Html_H4 64 +#define Html_EndH3 63 +#define Html_H3 62 +#define Html_EndH2 61 +#define Html_H2 60 +#define Html_EndH1 59 +#define Html_H1 58 +#define Html_EndFRAMESET 57 +#define Html_FRAMESET 56 +#define Html_EndFRAME 55 +#define Html_FRAME 54 +#define Html_EndFORM 53 +#define Html_FORM 52 +#define Html_EndFONT 51 +#define Html_FONT 50 +#define Html_EMBED 49 +#define Html_EndEM 48 +#define Html_EM 47 +#define Html_EndDT 46 +#define Html_DT 45 +#define Html_EndDL 44 +#define Html_DL 43 +#define Html_EndDIV 42 +#define Html_DIV 41 +#define Html_EndDIR 40 +#define Html_DIR 39 +#define Html_EndDFN 38 +#define Html_DFN 37 +#define Html_EndDD 36 +#define Html_DD 35 +#define Html_EndCOMMENT 34 +#define Html_COMMENT 33 +#define Html_EndCODE 32 +#define Html_CODE 31 +#define Html_EndCITE 30 +#define Html_CITE 29 +#define Html_EndCENTER 28 +#define Html_CENTER 27 +#define Html_EndCAPTION 26 +#define Html_CAPTION 25 +#define Html_BR 24 +#define Html_EndBODY 23 +#define Html_BODY 22 +#define Html_EndBLOCKQUOTE 21 +#define Html_BLOCKQUOTE 20 +#define Html_EndBIG 19 +#define Html_BIG 18 +#define Html_BGSOUND 17 +#define Html_EndBASEFONT 16 +#define Html_BASEFONT 15 +#define Html_BASE 14 +#define Html_EndB 13 +#define Html_B 12 +#define Html_AREA 11 +#define Html_EndAPPLET 10 +#define Html_APPLET 9 +#define Html_EndADDRESS 8 +#define Html_ADDRESS 7 +#define Html_EndA 6 +#define Html_A 5 +#define Html_Block 4 +#define HtmlIsMarkup(X) ((X)->base.type>Html_Block) +#define Html_Unknown 3 +#define Html_Space 2 +#define Html_Text 1 +#define INTERFACE 0 +typedef struct HtmlTextElement HtmlTextElement; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlBlock HtmlBlock; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +typedef struct HtmlStyleStack HtmlStyleStack; +typedef struct HtmlLayoutContext HtmlLayoutContext; +typedef struct HtmlMargin HtmlMargin; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/htmlurl.c b/tkhtml1/src/htmlurl.c new file mode 100644 index 0000000..bf8808f --- /dev/null +++ b/tkhtml1/src/htmlurl.c @@ -0,0 +1,402 @@ +/* +** Routines for processing URLs. +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <tk.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> +#include "htmlurl.h" + +#if LOCAL_INTERFACE +/* +** A parsed URI is held in an instance of the following structure. +** Each component is recorded in memory obtained from HtmlAlloc(). +** +** The examples are from the URI +** +** http://192.168.1.1:8080/cgi-bin/printenv?name=xyzzy&addr=none#frag +*/ +struct HtmlUri { + char *zScheme; /* Ex: "http" */ + char *zAuthority; /* Ex: "192.168.1.1:8080" */ + char *zPath; /* Ex: "cgi-bin/printenv" */ + char *zQuery; /* Ex: "name=xyzzy&addr=none" */ + char *zFragment; /* Ex: "frag" */ +}; +#endif + +/* +** Return the length of the next component of the URL in z[] given +** that the component starts at z[0]. The initial sequence of the +** component must be zInit[]. The component is terminated by any +** character in zTerm[]. The length returned is 0 if the component +** doesn't exist. The length includes the zInit[] string, but not +** the termination character. +** +** Component zInit zTerm +** ---------- ------- ------- +** scheme "" ":/?#" +** authority "//" "/?#" +** path "/" "?#" +** query "?" "#" +** fragment "#" "" +*/ +static int ComponentLength(const char *z, const char *zInit, const char *zTerm){ + int i, n; + for(n=0; zInit[n]; n++){ + if( zInit[n]!=z[n] ) return 0; + } + while( z[n] ){ + for(i=0; zTerm[i]; i++){ + if( z[n]==zTerm[i] ) return n; + } + n++; + } + return n; +} + +/* +** Duplicate a string of length n. +*/ +static char *StrNDup(const char *z, int n){ + char *zResult; + if(!n) + return NULL; + if( n<=0 ){ + n = strlen(z); + } + zResult = HtmlAlloc( n + 1 ); + if( zResult ){ + memcpy(zResult, z, n); + zResult[n] = 0; + TestPoint(0); + } + return zResult; +} + +/* +** Parse a text URI into an HtmlUri structure. +*/ +static HtmlUri *ParseUri(const char *zUri){ + HtmlUri *p; + int n; + + p = HtmlAlloc( sizeof(*p) ); + if( p==0 ) return 0; + memset(p, 0, sizeof(*p)); + if( zUri==0 || zUri[0]==0 ) return p; + while( isspace(zUri[0]) ){ zUri++; } + n = ComponentLength(zUri, "", ":/?# "); + if( n>0 && zUri[n]==':' ){ + p->zScheme = StrNDup(zUri, n); + zUri += n+1; + } + n = ComponentLength(zUri, "//", "/?# "); + if( n>0 ){ + p->zAuthority = StrNDup(&zUri[2], n-2); + zUri += n; + } + /* allow spaces in path */ + /* n = ComponentLength(zUri, "", "?# ");*/ + n = ComponentLength(zUri, "", "?#"); + if( n>0 ){ + p->zPath = StrNDup(zUri, n); + zUri += n; + } + n = ComponentLength(zUri, "?", "# "); + if( n>0 ){ + p->zQuery = StrNDup(&zUri[1], n-1); + zUri += n; + } + n = ComponentLength(zUri, "#", " "); + if( n>0 ){ + p->zFragment = StrNDup(&zUri[1], n-1); + } + return p; +} + +/* +** Delete an HtmlUri structure. +*/ +static void FreeUri(HtmlUri *p){ + if( p==0 ) return; + if( p->zScheme ) HtmlFree(p->zScheme); + if( p->zAuthority ) HtmlFree(p->zAuthority); + if( p->zPath ) HtmlFree(p->zPath); + if( p->zQuery ) HtmlFree(p->zQuery); + if( p->zFragment ) HtmlFree(p->zFragment); + HtmlFree(p); +} + +/* +** Create a string to hold the given URI. Memory to hold the string +** is obtained from HtmlAlloc() and must be freed by the calling +** function. +*/ +static char *BuildUri(HtmlUri *p){ + int n = 1; + char *z; + if( p->zScheme ) n += strlen(p->zScheme)+1; + if( p->zAuthority ) n += strlen(p->zAuthority)+2; + if( p->zPath ) n += strlen(p->zPath)+1; + if( p->zQuery ) n += strlen(p->zQuery)+1; + if( p->zFragment ) n += strlen(p->zFragment)+1; + z = HtmlAlloc( n ); + if( z==0 ) return 0; + n = 0; + if( p->zScheme ){ + sprintf(z, "%s:", p->zScheme); + n = strlen(z); + } + if( p->zAuthority ){ + sprintf(&z[n], "//%s", p->zAuthority); + n += strlen(&z[n]); + } + if( p->zPath ){ + sprintf(&z[n], "%s", p->zPath); + n += strlen(&z[n]); + } + if( p->zQuery ){ + sprintf(&z[n], "?%s", p->zQuery); + n += strlen(&z[n]); + } + if( p->zFragment ){ + sprintf(&z[n], "#%s", p->zFragment); + }else{ + z[n] = 0; + } + return z; +} + +/* +** Replace the string in *pzDest with the string in zSrc +*/ +static void ReplaceStr(char **pzDest, const char *zSrc){ + if( *pzDest!=0 ) HtmlFree(*pzDest); + if( zSrc==0 ){ + *pzDest = 0; + }else{ + *pzDest = StrNDup(zSrc, -1); + } +} + +/* +** Remove leading and trailing spaces from the given string. Return +** a new string obtained from HtmlAlloc(). +*/ +static char *Trim(char *z){ + int i; + char *zNew; + while( isspace(*z) ) z++; + i = strlen(z); + zNew = HtmlAlloc( i+1 ); + if( zNew==0 ) return 0; + strcpy(zNew, z); + if( i>0 && isspace(zNew[i-1]) ){ + i--; + zNew[i] = 0; + } + return zNew; +} + +/* +** The input azSeries[] is a sequence of URIs. This command must +** resolve them all and put the result in the interp->result field +** of the interpreter associated with the HTML widget. Return +** TCL_OK on success and TCL_ERROR if there is a failure. +** +** This function can cause the HTML widget to be deleted or changed +** arbitrarily. +*/ +int HtmlCallResolver( + HtmlWidget *htmlPtr, /* The widget that is doing the resolving. */ + char **azSeries /* A list of URIs. NULL terminated */ +){ + int rc = TCL_OK; /* Return value of this function. */ + char *z; + + HtmlVerifyLock(htmlPtr); + if( htmlPtr->zResolverCommand && htmlPtr->zResolverCommand[0] ){ + /* + ** Append the current base URI then the azSeries arguments to the + ** TCL command specified by the -resolvercommand optoin, then execute + ** the result. + ** + ** The -resolvercommand could do nasty things, such as delete + ** the HTML widget out from under us. Be prepared for the worst. + */ + Tcl_DString cmd; + Tcl_DStringInit(&cmd); + Tcl_DStringAppend(&cmd, htmlPtr->zResolverCommand, -1); + if( htmlPtr->zBaseHref && htmlPtr->zBaseHref[0] ){ + z = Trim(htmlPtr->zBaseHref); + }else if( htmlPtr->zBase && htmlPtr->zBase[0] ){ + z = Trim(htmlPtr->zBase); + } + else + z=0; + + if( z ){ + Tcl_DStringAppendElement(&cmd, z); + HtmlFree(z); + } + while( azSeries[0] ){ + z = Trim(azSeries[0]); + if( z ){ + Tcl_DStringAppendElement(&cmd, z); + HtmlFree(z); + } + azSeries++; + } + HtmlLock(htmlPtr); + rc = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&cmd)); + Tcl_DStringFree(&cmd); + if( HtmlUnlock(htmlPtr) ) return TCL_ERROR; + if( rc!=TCL_OK ){ + Tcl_AddErrorInfo(htmlPtr->interp, + "\n (-resolvercommand executed by HTML widget)"); + } + }else{ + /* + ** No -resolvercommand has been specified. Do the default + ** resolver algorithm specified in section 5.2 of RFC 2396. + */ + HtmlUri *base, *term; + if( htmlPtr->zBaseHref && htmlPtr->zBaseHref[0] ){ + base = ParseUri(htmlPtr->zBaseHref); + }else{ + base = ParseUri(htmlPtr->zBase); + } + while( azSeries[0] ){ + term = ParseUri(azSeries[0]); + azSeries++; + if( term->zScheme==0 && term->zAuthority==0 && term->zPath==0 + && term->zQuery==0 && term->zFragment ){ + ReplaceStr(&base->zFragment, term->zFragment); + }else if( term->zScheme ){ + HtmlUri temp; + temp = *term; + *term = *base; + *base = temp; + }else if( term->zAuthority ){ + ReplaceStr(&base->zAuthority, term->zAuthority); + ReplaceStr(&base->zPath, term->zPath); + ReplaceStr(&base->zQuery, term->zQuery); + ReplaceStr(&base->zFragment, term->zFragment); + }else if( term->zPath && (term->zPath[0]=='/' || base->zPath==0) ){ + ReplaceStr(&base->zPath, term->zPath); + ReplaceStr(&base->zQuery, term->zQuery); + ReplaceStr(&base->zFragment, term->zFragment); + }else if( term->zPath && base->zPath ){ + char *zBuf; + int i, j; + zBuf = HtmlAlloc( strlen(base->zPath) + strlen(term->zPath) + 2 ); + if( zBuf ){ + sprintf(zBuf,"%s", base->zPath); + for(i=strlen(zBuf)-1; i>=0 && zBuf[i]!='/'; i--){ zBuf[i] = 0; } + strcat(zBuf, term->zPath); + for(i=0; zBuf[i]; i++){ + if( zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]=='/' ){ + // strcpy into same buf is undefined + // strcpy(&zBuf[i+1], &zBuf[i+3]); + int ll = strlen(zBuf+i+3)+1; + char* tmp = malloc(ll); + strncpy(tmp,zBuf+i+3,ll); + strcpy(zBuf+i+1, tmp); + free(tmp); + i--; + continue; + } + if( zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]==0 ){ + zBuf[i+1] = 0; + continue; + } + if( i>0 && zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]=='.' + && (zBuf[i+3]=='/' || zBuf[i+3]==0) ){ + for(j=i-1; j>=0 && zBuf[j]!='/'; j--){} + if( zBuf[i+3] ){ + // strcpy into same buf is undefined + // strcpy(&zBuf[j+1], &zBuf[i+4]); + int ll = strlen(zBuf+i+4)+1; + char* tmp = malloc(ll); + strncpy(tmp,zBuf+i+4,ll); + strcpy(zBuf+j+1, tmp); + free(tmp); + }else{ + zBuf[j+1] = 0; + } + i = j-1; + if( i<-1 ) i = -1; + continue; + } + } + /* look for /../ at begining */ + if (!strncmp(zBuf,"/../",4)) { + // strcpy into same buf is undefined + // strcpy(zBuf,zBuf+3); + int ll = strlen(zBuf+3)+1; + char* tmp = malloc(ll); + strncpy(tmp,zBuf+3,ll); + strcpy(zBuf, tmp); + free(tmp); + } + HtmlFree(base->zPath); + base->zPath = zBuf; + } + ReplaceStr(&base->zQuery, term->zQuery); + ReplaceStr(&base->zFragment, term->zFragment); + } + FreeUri(term); + } + Tcl_SetResult(htmlPtr->interp, BuildUri(base), TCL_DYNAMIC); + FreeUri(base); + } + return rc; +} + +/* +** This is a convenient wrapper routine for HtmlCallResolver. +** It makes a copy of the result into memory obtained from HtmlAlloc() +** and invokes Tcl_ResetResult(). +*/ +char *HtmlResolveUri(HtmlWidget *htmlPtr, char *zUri){ + char *azSeq[2]; + char *zSrc; + int result; + + if( zUri==0 || *zUri==0 ) return 0; + azSeq[0] = zUri; + azSeq[1] = 0; + HtmlLock(htmlPtr); + result = HtmlCallResolver(htmlPtr, azSeq); + if( HtmlUnlock(htmlPtr) ) return 0; + if( result==TCL_OK ){ + zSrc = HtmlAlloc( strlen(Tcl_GetStringResult(htmlPtr->interp)) + 1 ); + if( zSrc ) strcpy(zSrc, Tcl_GetStringResult(htmlPtr->interp)); + }else{ + zSrc = 0; + } + Tcl_ResetResult(htmlPtr->interp); + return zSrc; +} diff --git a/tkhtml1/src/htmlurl.h b/tkhtml1/src/htmlurl.h new file mode 100644 index 0000000..dba8115 --- /dev/null +++ b/tkhtml1/src/htmlurl.h @@ -0,0 +1,456 @@ +/* This file was automatically generated. Do not edit! */ +typedef struct HtmlWidget HtmlWidget; +char *HtmlResolveUri(HtmlWidget *htmlPtr,char *zUri); +int HtmlUnlock(HtmlWidget *htmlPtr); +void HtmlLock(HtmlWidget *htmlPtr); +void HtmlTPCantHappen(const char *zFile,int line); +#if defined(COVERAGE_TEST) +# define HtmlVerifyLock(H) if((H)->locked==0)HtmlTPCantHappen(__FILE__,__LINE__) +#endif +#if !(defined(COVERAGE_TEST)) +# define HtmlVerifyLock(H) +#endif +typedef union HtmlElement HtmlElement; +typedef struct HtmlBlock HtmlBlock; +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +typedef short Html_16; +typedef struct HtmlScript HtmlScript; +#define Html_TypeCount 151 +typedef struct HtmlStyleStack HtmlStyleStack; +typedef struct HtmlLayoutContext HtmlLayoutContext; +typedef struct HtmlMargin HtmlMargin; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +#define N_FONT_FAMILY 8 +#define N_FONT_SIZE 7 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define N_COLOR 16 /* Total number of colors */ +typedef struct GcCache GcCache; +typedef unsigned char Html_u8; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +#define N_CACHE_GC 16 +typedef struct HtmlImage HtmlImage; +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +int HtmlCallResolver(HtmlWidget *htmlPtr,char **azSeries); +#define HtmlFree(A) Tcl_Free((char*)(A)) +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +#define HtmlAlloc(A) ((void*)Tcl_Alloc(A)) +typedef struct HtmlUri HtmlUri; +struct HtmlUri { + char *zScheme; /* Ex: "http" */ + char *zAuthority; /* Ex: "192.168.1.1:8080" */ + char *zPath; /* Ex: "cgi-bin/printenv" */ + char *zQuery; /* Ex: "name=xyzzy&addr=none" */ + char *zFragment; /* Ex: "frag" */ +}; +#define LOCAL_INTERFACE 0 +typedef struct HtmlBaseElement HtmlBaseElement; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +typedef struct HtmlTextElement HtmlTextElement; +typedef int Html_32; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlMarkupElement HtmlMarkupElement; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +typedef unsigned short Html_u16; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/htmlwidget.c b/tkhtml1/src/htmlwidget.c new file mode 100644 index 0000000..712ca3c --- /dev/null +++ b/tkhtml1/src/htmlwidget.c @@ -0,0 +1,2043 @@ +/* +** The main routine for the HTML widget for Tcl/Tk +** +** Copyright (C) 1997-2000 D. Richard Hipp +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public +** License as published by the Free Software Foundation; either +** version 2 of the License, or (at your option) any later version. +** +** This library is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. +** +** You should have received a copy of the GNU Library General Public +** License along with this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@acm.org +** http://www.hwaci.com/drh/ +*/ +#include <tk.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include "htmlwidget.h" +/* +#ifdef USE_TK_STUBS +# include <tkIntXlibDecls.h> +#endif +*/ +/* +** This global variable is used for tracing the operation of +** the Html formatter. +*/ +int HtmlTraceMask = 0; + +#ifdef __WIN32__ +# define DEF_FRAME_BG_COLOR "SystemButtonFace" +# define DEF_FRAME_BG_MONO "White" +# define DEF_FRAME_CURSOR "" +# define DEF_BUTTON_FG "SystemButtonText" +# define DEF_BUTTON_HIGHLIGHT_BG "SystemButtonFace" +# define DEF_BUTTON_HIGHLIGHT "SystemWindowFrame" +#else +# define DEF_FRAME_BG_COLOR "#d9d9d9" +# define DEF_FRAME_BG_MONO "White" +# define DEF_FRAME_CURSOR "" +# define DEF_BUTTON_FG "Black" +# define DEF_BUTTON_HIGHLIGHT_BG "#d9d9d9" +# define DEF_BUTTON_HIGHLIGHT "Black" +#endif + +/* +** Information used for argv parsing. +*/ +static Tk_ConfigSpec configSpecs[] = { + {TK_CONFIG_STRING, "-appletcommand", "appletCommand", "HtmlCallback", + DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zAppletCommand), 0}, + {TK_CONFIG_BORDER, "-background", "background", "Background", + DEF_HTML_BG_COLOR, Tk_Offset(HtmlWidget, border), + TK_CONFIG_COLOR_ONLY}, + {TK_CONFIG_BORDER, "-background", "background", "Background", + DEF_HTML_BG_MONO, Tk_Offset(HtmlWidget, border), + TK_CONFIG_MONO_ONLY}, + {TK_CONFIG_STRING, "-base", "base", "Base", + "", Tk_Offset(HtmlWidget, zBase), 0}, + {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL, + (char *) NULL, 0, 0}, + {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL, + (char *) NULL, 0, 0}, + {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", + DEF_HTML_BORDER_WIDTH, Tk_Offset(HtmlWidget, borderWidth), 0}, + {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor", + DEF_HTML_CURSOR, Tk_Offset(HtmlWidget, cursor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BOOLEAN, "-exportselection", "exportSelection","ExportSelection", + DEF_HTML_EXPORT_SEL, Tk_Offset(HtmlWidget, exportSelection), 0}, + {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL, + (char *) NULL, 0, 0}, + {TK_CONFIG_STRING, "-fontcommand", "fontCommand", "FontCommand", + DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zFontCommand), 0}, + {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground", + DEF_HTML_FG, Tk_Offset(HtmlWidget, fgColor), 0}, + {TK_CONFIG_STRING, "-formcommand", "formlCommand", "HtmlCallback", + DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zFormCommand), 0}, + {TK_CONFIG_STRING, "-framecommand", "frameCommand", "HtmlCallback", + DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zFrameCommand), 0}, + {TK_CONFIG_PIXELS, "-height", "height", "Height", + DEF_HTML_HEIGHT, Tk_Offset(HtmlWidget, height), 0}, + {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground", + "HighlightBackground", DEF_HTML_HIGHLIGHT_BG, + Tk_Offset(HtmlWidget, highlightBgColorPtr), 0}, + {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", + DEF_HTML_HIGHLIGHT, Tk_Offset(HtmlWidget, highlightColorPtr), 0}, + {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", + "HighlightThickness", + DEF_HTML_HIGHLIGHT_WIDTH, Tk_Offset(HtmlWidget, highlightWidth), 0}, + {TK_CONFIG_STRING, "-hyperlinkcommand", "hyperlinkCommand", "HtmlCallback", + DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zHyperlinkCommand), 0}, + {TK_CONFIG_STRING, "-imagecommand", "imageCommand", "HtmlCallback", + DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zGetImage), 0}, + {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime", + DEF_HTML_INSERT_OFF_TIME, Tk_Offset(HtmlWidget, insOffTime), 0}, + {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime", + DEF_HTML_INSERT_ON_TIME, Tk_Offset(HtmlWidget, insOnTime), 0}, + {TK_CONFIG_STRING, "-isvisitedcommand", "isVisitedCommand", "HtmlCallback", + DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zIsVisited), 0}, + {TK_CONFIG_PIXELS, "-padx", "padX", "Pad", + DEF_HTML_PADX, Tk_Offset(HtmlWidget, padx), 0}, + {TK_CONFIG_PIXELS, "-pady", "padY", "Pad", + DEF_HTML_PADY, Tk_Offset(HtmlWidget, pady), 0}, + {TK_CONFIG_RELIEF, "-relief", "relief", "Relief", + DEF_HTML_RELIEF, Tk_Offset(HtmlWidget, relief), 0}, + {TK_CONFIG_STRING, "-resolvercommand", "resolverCommand", "HtmlCallback", + DEF_HTML_CALLBACK, Tk_Offset(HtmlWidget, zResolverCommand), 0}, + {TK_CONFIG_RELIEF, "-rulerelief", "ruleRelief","RuleRelief", + "sunken", Tk_Offset(HtmlWidget, ruleRelief), 0}, + {TK_CONFIG_STRING, "-scriptcommand", "scriptCommand", "HtmlCallback", + "", Tk_Offset(HtmlWidget, zScriptCommand), 0}, + {TK_CONFIG_COLOR, "-selectioncolor", "background", "Background", + DEF_HTML_SELECTION_COLOR, Tk_Offset(HtmlWidget, selectionColor), 0}, + {TK_CONFIG_RELIEF, "-tablerelief", "tableRelief","TableRelief", + "raised", Tk_Offset(HtmlWidget, tableRelief), 0}, + {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus", + DEF_HTML_TAKE_FOCUS, Tk_Offset(HtmlWidget, takeFocus), + TK_CONFIG_NULL_OK}, + {TK_CONFIG_COLOR, "-unvisitedcolor", "foreground", "Foreground", + DEF_HTML_UNVISITED, Tk_Offset(HtmlWidget, newLinkColor), 0}, + {TK_CONFIG_BOOLEAN, "-underlinehyperlinks", "underlineHyperlinks", + "UnderlineHyperlinks", "1", Tk_Offset(HtmlWidget, underlineLinks), 0}, + {TK_CONFIG_COLOR, "-visitedcolor", "foreground", "Foreground", + DEF_HTML_VISITED, Tk_Offset(HtmlWidget, oldLinkColor), 0}, + {TK_CONFIG_PIXELS, "-width", "width", "Width", + DEF_HTML_WIDTH, Tk_Offset(HtmlWidget, width), 0}, + {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", + DEF_HTML_SCROLL_COMMAND, Tk_Offset(HtmlWidget, xScrollCmd), + TK_CONFIG_NULL_OK}, + {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", + DEF_HTML_SCROLL_COMMAND, Tk_Offset(HtmlWidget, yScrollCmd), + TK_CONFIG_NULL_OK}, + {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, + (char *) NULL, 0, 0} +}; + +/* +** Get a copy of the config specs. +*/ +Tk_ConfigSpec *HtmlConfigSpec(void){ + return configSpecs; +} + +/* +** Find the width of the usable drawing area in pixels. If the window isn't +** mapped, use the size requested by the user. +** +** The usable drawing area is the area available for displaying rendered +** HTML. The usable drawing area does not include the 3D border or the +** padx and pady boundry within the 3D border. The usable drawing area +** is the size of the clipping window. +*/ +int HtmlUsableWidth(HtmlWidget *htmlPtr){ + int w; + Tk_Window tkwin = htmlPtr->tkwin; + if( tkwin && Tk_IsMapped(tkwin) ){ + w = Tk_Width(tkwin) - 2*(htmlPtr->padx + htmlPtr->inset); + TestPoint(0); + }else{ + w = htmlPtr->width; + TestPoint(0); + } + return w; +} + +/* +** Find the height of the usable drawing area in pixels. If the window isn't +** mapped, use the size requested by the user. +** +** The usable drawing area is the area available for displaying rendered +** HTML. The usable drawing area does not include the 3D border or the +** padx and pady boundry within the 3D border. The usable drawing area +** is the size of the clipping window. +*/ +int HtmlUsableHeight(HtmlWidget *htmlPtr){ + int h; + Tk_Window tkwin = htmlPtr->tkwin; + if( tkwin && Tk_IsMapped(tkwin) ){ + h = Tk_Height(tkwin) - 2*(htmlPtr->pady + htmlPtr->inset); + TestPoint(0); + }else{ + h = htmlPtr->height; + TestPoint(0); + } + return h; +} + +/* +** Compute a pair of floating point numbers that describe the current +** vertical scroll position. The first number is the fraction of +** the document that is off the top of the visible region and the second +** number is the fraction that is beyond the end of the visible region. +*/ +void HtmlComputeVerticalPosition( + HtmlWidget *htmlPtr, + char *buf /* Write the two floating point values here */ +){ + int actual; /* Size of the viewing area */ + double frac1, frac2; + + actual = HtmlUsableHeight(htmlPtr); + if( htmlPtr->maxY <= 0 ){ + frac1 = 0.0; + frac2 = 1.0; + TestPoint(0); + }else{ + frac1 = (double)htmlPtr->yOffset/(double)htmlPtr->maxY; + if( frac1 > 1.0 ){ + frac1 = 1.0; + TestPoint(0); + }else if( frac1 < 0.0 ){ + frac1 = 0.0; + TestPoint(0); + } + frac2 = (double)(htmlPtr->yOffset+actual)/(double)htmlPtr->maxY; + if( frac2 > 1.0 ){ + frac2 = 1.0; + TestPoint(0); + }else if( frac2 < 0.0 ){ + frac2 = 0.0; + TestPoint(0); + } + } + sprintf(buf,"%g %g",frac1, frac2); +} + +/* +** Do the same thing for the horizontal direction +*/ +void HtmlComputeHorizontalPosition( + HtmlWidget *htmlPtr, + char *buf /* Write the two floating point values here */ +){ + int actual; /* Size of the viewing area */ + double frac1, frac2; + + actual = HtmlUsableWidth(htmlPtr); + if( htmlPtr->maxX <= 0 ){ + frac1 = 0.0; + frac2 = 1.0; + TestPoint(0); + }else{ + frac1 = (double)htmlPtr->xOffset/(double)htmlPtr->maxX; + if( frac1 > 1.0 ){ + frac1 = 1.0; + TestPoint(0); + }else if( frac1 < 0.0 ){ + frac1 = 0.0; + TestPoint(0); + } + frac2 = (double)(htmlPtr->xOffset+actual)/(double)htmlPtr->maxX; + if( frac2 > 1.0 ){ + frac2 = 1.0; + TestPoint(0); + }else if( frac2 < 0.0 ){ + frac2 = 0.0; + TestPoint(0); + } + } + sprintf(buf,"%g %g",frac1, frac2); +} + +/* +** Clear the cache of GCs +*/ +static void ClearGcCache(HtmlWidget *htmlPtr){ + int i; + for(i=0; i<N_CACHE_GC; i++){ + if( htmlPtr->aGcCache[i].index ){ + Tk_FreeGC(htmlPtr->display, htmlPtr->aGcCache[i].gc); + htmlPtr->aGcCache[i].index = 0; + TestPoint(0); + }else{ + TestPoint(0); + } + } +} + + +/* +** This routine is called when the widget command is deleted. If the +** widget isn't already in the process of being destroyed, this command +** starts that process rolling. +** +** This routine can be called in two ways. +** +** (1) The window is destroyed, which causes the command to be deleted. +** In this case, we don't have to do anything. +** +** (2) The command only is deleted (ex: "rename .html {}"). In that +** case we need to destroy the window. +*/ +static void HtmlCmdDeletedProc(ClientData clientData){ + HtmlWidget *htmlPtr = (HtmlWidget*) clientData; + if (htmlPtr != NULL && htmlPtr->tkwin!=NULL ) { + Tk_Window tkwin = htmlPtr->tkwin; + htmlPtr->tkwin = NULL; + Tk_DestroyWindow(tkwin); + } +} + +/* +** Reset the main layout context in the main widget. This happens +** before we redo the layout, or just before deleting the widget. +*/ +static void ResetLayoutContext(HtmlWidget *htmlPtr){ + htmlPtr->layoutContext.headRoom = 0; + htmlPtr->layoutContext.top = 0; + htmlPtr->layoutContext.bottom = 0; + HtmlClearMarginStack(&htmlPtr->layoutContext.leftMargin); + HtmlClearMarginStack(&htmlPtr->layoutContext.rightMargin); +} + +/* +** This routine is invoked in order to redraw all or part of the HTML +** widget. This might happen because the display has changed, or in +** response to an expose event. In all cases, though, this routine +** is called by an idle callback. +*/ +static void HtmlRedrawCallback(ClientData clientData){ + HtmlWidget *htmlPtr = (HtmlWidget*)clientData; + Tk_Window tkwin = htmlPtr->tkwin; + Tk_Window clipwin = htmlPtr->clipwin; + Pixmap pixmap; /* The buffer on which to render HTML */ + int x, y, w, h; /* Virtual canvas coordinates of area to draw */ + int hw; /* highlight thickness */ + int insetX, insetY; /* Total highlight thickness, border width and + ** padx/y */ + int clipwinH, clipwinW; /* Width and height of the clipping window */ + HtmlBlock *pBlock; /* For looping over blocks to be drawn */ + int redoSelection = 0; /* True to recompute the selection */ + + /* + ** Don't bother doing anything if the widget is in the process of + ** being destroyed. + */ + if( tkwin==0 ){ + goto redrawExit; + } + + /* + ** Recompute the layout, if necessary or requested. + ** + ** Calling HtmlLayout() is tricky because HtmlLayout() may invoke one + ** or more callbacks (thru the "-imagecommand" callback, for instance) + ** and these callbacks could, in theory, do nasty things like delete + ** or unmap this widget. So we have to take precautions: + ** + ** * Don't remove the REDRAW_PENDING flag until after HtmlLayout() + ** has been called, to prevent a recursive call to HtmlRedrawCallback(). + ** + ** * Call HtmlLock() on the htmlPtr structure to prevent it from + ** being deleted out from under us. + ** + */ + if( (htmlPtr->flags & RESIZE_ELEMENTS)!=0 + && (htmlPtr->flags & STYLER_RUNNING)==0 ){ + HtmlImage *pImage; + for(pImage=htmlPtr->imageList; pImage; pImage=pImage->pNext){ + pImage->pList = 0; + } + htmlPtr->lastSized = 0; + htmlPtr->flags &= ~RESIZE_ELEMENTS; + htmlPtr->flags |= RELAYOUT; + } + + /* We used to make a distinction between RELAYOUT and EXTEND_LAYOUT. + ** RELAYOUT would be used when the widget was resized, but the + ** less compute-intensive EXTEND_LAYOUT would be used when new + ** text was appended. + ** + ** Unfortunately, EXTEND_LAYOUT has some problem that arise when + ** tables are used. The quick fix is to make an EXTEND_LAYOUT do + ** a complete RELAYOUT. Someday, we need to fix EXTEND_LAYOUT so + ** that it works right... + */ + if( (htmlPtr->flags & (RELAYOUT|EXTEND_LAYOUT))!=0 + && (htmlPtr->flags & STYLER_RUNNING)==0 ){ + htmlPtr->nextPlaced = 0; + htmlPtr->nInput = 0; + htmlPtr->varId = 0; + htmlPtr->maxX = 0; + htmlPtr->maxY = 0; + ResetLayoutContext(htmlPtr); + htmlPtr->firstBlock = 0; + htmlPtr->lastBlock = 0; + redoSelection = 1; + htmlPtr->flags &= ~RELAYOUT; + htmlPtr->flags |= HSCROLL | VSCROLL | REDRAW_TEXT | EXTEND_LAYOUT; + } + if( (htmlPtr->flags & EXTEND_LAYOUT) && htmlPtr->pFirst!=0 ){ + HtmlLock(htmlPtr); + HtmlLayout(htmlPtr); + if( HtmlUnlock(htmlPtr) ) goto redrawExit; + tkwin = htmlPtr->tkwin; + htmlPtr->flags &= ~EXTEND_LAYOUT; + HtmlFormBlocks(htmlPtr); + HtmlMapControls(htmlPtr); + if( redoSelection && htmlPtr->selBegin.p && htmlPtr->selEnd.p ){ + HtmlUpdateSelection(htmlPtr,1); + HtmlUpdateInsert(htmlPtr); + } + } + htmlPtr->flags &= ~REDRAW_PENDING; + + /* No need to do any actual drawing if we aren't mapped + */ + if( !Tk_IsMapped(tkwin) ){ + goto redrawExit; + } + + /* Redraw the scrollbars. Take care here, since the scrollbar + ** update command could (in theory) delete the html widget, or + ** even the whole interpreter. Preserve critical data structures, + ** and check to see if we are still alive before continuing. + */ + if( (htmlPtr->flags & (HSCROLL|VSCROLL)) != 0 ){ + Tcl_Interp *interp = htmlPtr->interp; + int result; + char buf[200]; + + if( (htmlPtr->flags & HSCROLL)!=0 ){ + if( htmlPtr->xScrollCmd && htmlPtr->xScrollCmd[0] ){ + HtmlComputeHorizontalPosition(htmlPtr,buf); + HtmlLock(htmlPtr); + result = Tcl_VarEval(interp, htmlPtr->xScrollCmd, " ", buf, 0); + if( HtmlUnlock(htmlPtr) ) goto redrawExit; + if (result != TCL_OK) { + Tcl_AddErrorInfo(interp, + "\n (horizontal scrolling command executed by html widget)"); + Tcl_BackgroundError(interp); + TestPoint(0); + } + } + htmlPtr->flags &= ~HSCROLL; + } + if( (htmlPtr->flags & VSCROLL)!=0 && tkwin && Tk_IsMapped(tkwin) ){ + if( htmlPtr->yScrollCmd && htmlPtr->yScrollCmd[0] ){ + Tcl_Interp *interp = htmlPtr->interp; + int result; + char buf[200]; + HtmlComputeVerticalPosition(htmlPtr,buf); + HtmlLock(htmlPtr); + result = Tcl_VarEval(interp, htmlPtr->yScrollCmd, " ", buf, 0); + if( HtmlUnlock(htmlPtr) ) goto redrawExit; + if (result != TCL_OK) { + Tcl_AddErrorInfo(interp, + "\n (horizontal scrolling command executed by html widget)"); + Tcl_BackgroundError(interp); + TestPoint(0); + } + } + htmlPtr->flags &= ~VSCROLL; + } + tkwin = htmlPtr->tkwin; + if( tkwin==0 || !Tk_IsMapped(tkwin) ){ goto redrawExit; } + if( htmlPtr->flags & REDRAW_PENDING ){ return; } + clipwin = htmlPtr->clipwin; + if( clipwin==0 ){ TestPoint(0); goto redrawExit; } + } + + /* Redraw the focus highlight, if requested */ + hw = htmlPtr->highlightWidth; + if( htmlPtr->flags & REDRAW_FOCUS ){ + if( hw>0 ){ + GC gc; + Tk_Window tkwin = htmlPtr->tkwin; + + if( htmlPtr->flags & GOT_FOCUS ){ + gc = Tk_GCForColor(htmlPtr->highlightColorPtr, Tk_WindowId(tkwin)); + TestPoint(0); + }else{ + gc = Tk_GCForColor(htmlPtr->highlightBgColorPtr, Tk_WindowId(tkwin)); + TestPoint(0); + } + Tk_DrawFocusHighlight(tkwin, gc, hw, Tk_WindowId(tkwin)); + } + htmlPtr->flags &= ~REDRAW_FOCUS; + } + + /* Draw the borders around the parameter of the window. This is + ** drawn directly -- it is not double buffered. + */ + if( htmlPtr->flags & REDRAW_BORDER ){ + htmlPtr->flags &= ~REDRAW_BORDER; + Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), htmlPtr->border, + hw, /* x */ + hw, /* y */ + Tk_Width(tkwin) - 2*hw, /* width */ + Tk_Height(tkwin) - 2*hw, /* height */ + htmlPtr->borderWidth, htmlPtr->relief); + } + + /* + ** If the styler is in a callback, unmap the clipping window and + ** abort further processing. + */ + if( htmlPtr->flags & STYLER_RUNNING ){ + if( Tk_IsMapped(clipwin) ){ + Tk_UnmapWindow(clipwin); + } + goto earlyOut; + } + + /* + ** If we don't have a clipping window, then something is seriously + ** wrong. We might as well give up. + */ + if( clipwin==NULL ){ TestPoint(0); goto earlyOut; } + + /* Resize, reposition and map the clipping window, if necessary */ + insetX = htmlPtr->padx + htmlPtr->inset; + insetY = htmlPtr->pady + htmlPtr->inset; + if( htmlPtr->flags & RESIZE_CLIPWIN ){ + int h, w; + Tk_MoveResizeWindow(clipwin, insetX, insetY, + htmlPtr->realWidth - 2*insetX, + htmlPtr->realHeight - 2*insetY); + if( !Tk_IsMapped(clipwin) ){ + Tk_MapWindow(clipwin); + } + h = htmlPtr->realHeight - 2*insetY; + if( htmlPtr->yOffset + h > htmlPtr->maxY ){ + htmlPtr->yOffset = htmlPtr->maxY - h; + } + if( htmlPtr->yOffset < 0 ){ + htmlPtr->yOffset = 0; + } + w = htmlPtr->realWidth - 2*insetX; + if( htmlPtr->xOffset + h > htmlPtr->maxX ){ + htmlPtr->xOffset = htmlPtr->maxX - w; + } + if( htmlPtr->xOffset < 0 ){ + htmlPtr->xOffset = 0; + } + htmlPtr->flags &= ~RESIZE_CLIPWIN; + } + HtmlMapControls(htmlPtr); + + /* + ** Compute the virtual canvas coordinates corresponding to the + ** dirty region of the clipping window. + */ + clipwinW = Tk_Width(clipwin); + clipwinH = Tk_Height(clipwin); + if( htmlPtr->flags & REDRAW_TEXT ){ + w = clipwinW; + h = clipwinH; + x = htmlPtr->xOffset; + y = htmlPtr->yOffset; + htmlPtr->dirtyLeft = 0; + htmlPtr->dirtyTop = 0; + htmlPtr->flags &= ~REDRAW_TEXT; + }else{ + if( htmlPtr->dirtyLeft < 0 ){ + htmlPtr->dirtyLeft = 0; + TestPoint(0); + } + if( htmlPtr->dirtyRight > clipwinW ){ + htmlPtr->dirtyRight = clipwinW; + TestPoint(0); + } + if( htmlPtr->dirtyTop < 0 ){ + htmlPtr->dirtyTop = 0; + TestPoint(0); + } + if( htmlPtr->dirtyBottom > clipwinH ){ + htmlPtr->dirtyBottom = clipwinH; + TestPoint(0); + } + w = htmlPtr->dirtyRight - htmlPtr->dirtyLeft; + h = htmlPtr->dirtyBottom - htmlPtr->dirtyTop; + x = htmlPtr->xOffset + htmlPtr->dirtyLeft; + y = htmlPtr->yOffset + htmlPtr->dirtyTop; + } + + /* Skip the rest of the drawing process if the area to be refreshed is + ** less than zero */ + if( w>0 && h>0 ){ + Display *display = htmlPtr->display; + int dead; + GC gcBg; + XRectangle xrec; + /* printf("Redraw %dx%d at %d,%d\n", w, h, x, y); */ + + /* Allocate and clear a pixmap upon which to draw */ + gcBg = HtmlGetGC(htmlPtr, COLOR_Background, FONT_Any); + pixmap = Tk_GetPixmap(display, Tk_WindowId(clipwin),w,h,Tk_Depth(clipwin)); + xrec.x = 0; + xrec.y = 0; + xrec.width = w; + xrec.height = h; + XFillRectangles(display, pixmap, gcBg, &xrec, 1); + + /* Render all visible HTML onto the pixmap */ + HtmlLock(htmlPtr); + for(pBlock=htmlPtr->firstBlock; pBlock; pBlock=pBlock->pNext){ + if( pBlock->top <= y+h && pBlock->bottom >= y + && pBlock->left <= x+w && pBlock->right >= x ){ + HtmlBlockDraw(htmlPtr,pBlock,pixmap,x,y,w,h); + if( htmlPtr->tkwin==0 ) break; + } + } + dead = HtmlUnlock(htmlPtr); + + /* Finally, copy the pixmap onto the window and delete the pixmap */ + if( !dead ){ + XCopyArea(display, pixmap, Tk_WindowId(clipwin), + gcBg, 0, 0, w, h, htmlPtr->dirtyLeft, htmlPtr->dirtyTop); + } + Tk_FreePixmap(display, pixmap); + if( dead ) goto redrawExit; + /* XFlush(display); */ + } + + /* Redraw images, if requested */ + if( htmlPtr->flags & REDRAW_IMAGES ){ + HtmlImage *pImage; + HtmlElement *pElem; + int top, bottom, left, right; /* Coordinates of the clipping window */ + int imageTop; /* Top edge of image */ + + top = htmlPtr->yOffset; + bottom = top + HtmlUsableHeight(htmlPtr); + left = htmlPtr->xOffset; + right = left + HtmlUsableWidth(htmlPtr); + for(pImage = htmlPtr->imageList; pImage; pImage=pImage->pNext){ + for(pElem = pImage->pList; pElem; pElem=pElem->image.pNext){ + if( pElem->image.redrawNeeded==0 ) continue; + imageTop = pElem->image.y - pElem->image.ascent; + if( imageTop > bottom + || imageTop + pElem->image.h < top + || pElem->image.x > right + || pElem->image.x + pElem->image.w < left ){ + TestPoint(0); + continue; + } + HtmlDrawImage(pElem, Tk_WindowId(htmlPtr->clipwin), + left, top, right, bottom); + } + } + htmlPtr->flags &= ~REDRAW_IMAGES; + } + + /* Set the dirty region to the empty set. */ + earlyOut: + htmlPtr->dirtyTop = LARGE_NUMBER; + htmlPtr->dirtyLeft = LARGE_NUMBER; + htmlPtr->dirtyBottom = 0; + htmlPtr->dirtyRight = 0; + redrawExit: + return; +} + +/* +** Make sure that a call to the HtmlRedrawCallback() routine has been +** queued. +*/ +void HtmlScheduleRedraw(HtmlWidget *htmlPtr){ + if( (htmlPtr->flags & REDRAW_PENDING)==0 + && htmlPtr->tkwin!=0 + && Tk_IsMapped(htmlPtr->tkwin) + ){ + Tcl_DoWhenIdle(HtmlRedrawCallback, (ClientData)htmlPtr); + htmlPtr->flags |= REDRAW_PENDING; + } +} + +/* +** If any part of the screen needs to be redrawn, Then call this routine +** with the values of a box (in window coordinates) that needs to be +** redrawn. This routine will make sure an idle callback is scheduled +** to do the redraw. +** +** The box coordinates are relative to the clipping window (clipwin), +** not the main window (tkwin). +*/ +void HtmlRedrawArea( + HtmlWidget *htmlPtr, /* The widget to be redrawn */ + int left, int top, /* Top left corner of area to redraw */ + int right, int bottom /* bottom right corner of area to redraw */ +){ + if( bottom < 0 ){ TestPoint(0); return; } + if( top > htmlPtr->realHeight ){ TestPoint(0); return; } + if( right < 0 ){ TestPoint(0); return; } + if( left > htmlPtr->realWidth ){ TestPoint(0); return; } + if( htmlPtr->dirtyTop > top ){ htmlPtr->dirtyTop = top; TestPoint(0);} + if( htmlPtr->dirtyLeft > left ){ htmlPtr->dirtyLeft = left; TestPoint(0);} + if( htmlPtr->dirtyBottom < bottom ){ + htmlPtr->dirtyBottom = bottom; + TestPoint(0); + } + if( htmlPtr->dirtyRight < right ){ htmlPtr->dirtyRight = right; TestPoint(0);} + HtmlScheduleRedraw(htmlPtr); + TestPoint(0); +} + +/* Redraw the HtmlBlock given. +*/ +void HtmlRedrawBlock(HtmlWidget *htmlPtr, HtmlBlock *p){ + if( p ){ + HtmlRedrawArea(htmlPtr, + p->left - htmlPtr->xOffset, + p->top - htmlPtr->yOffset, + p->right - htmlPtr->xOffset + 1, + p->bottom - htmlPtr->yOffset + ); + TestPoint(0); + }else{ + TestPoint(0); + } +} + +/* +** Call this routine to force the entire widget to be redrawn. +*/ +void HtmlRedrawEverything(HtmlWidget *htmlPtr){ + htmlPtr->flags |= REDRAW_FOCUS | REDRAW_TEXT | REDRAW_BORDER; + HtmlScheduleRedraw(htmlPtr); + TestPoint(0); +} + +/* +** Do the redrawing right now. Don't wait. +*/ +#if 0 /* NOT_USED */ +static void HtmlRedrawPush(HtmlWidget *htmlPtr){ + if( htmlPtr->flags & REDRAW_PENDING ){ + Tcl_CancelIdleCall(HtmlRedrawCallback, (ClientData)htmlPtr); + TestPoint(0); + }else{ + TestPoint(0); + } + HtmlRedrawCallback( (ClientData)htmlPtr ); +} +#endif + +/* +** Call this routine to cause all of the rendered HTML at the +** virtual canvas coordinate of Y and beyond to be redrawn. +*/ +void HtmlRedrawText(HtmlWidget *htmlPtr, int y){ + int yOffset; /* Top-most visible canvas coordinate */ + int clipHeight; /* Height of the clipping window */ + + yOffset = htmlPtr->yOffset; + clipHeight = HtmlUsableHeight(htmlPtr); + y -= yOffset; + if( y < clipHeight ){ + HtmlRedrawArea(htmlPtr, 0, y, LARGE_NUMBER, clipHeight); + TestPoint(0); + }else{ + TestPoint(0); + } +} + +/* +** Recalculate the preferred size of the html widget and pass this +** along to the geometry manager. +*/ +static void HtmlRecomputeGeometry(HtmlWidget *htmlPtr){ + int w, h; /* Total width and height of the widget */ + + htmlPtr->inset = htmlPtr->highlightWidth + htmlPtr->borderWidth; + w = htmlPtr->width + 2*(htmlPtr->padx + htmlPtr->inset); + h = htmlPtr->height + 2*(htmlPtr->pady + htmlPtr->inset); + Tk_GeometryRequest(htmlPtr->tkwin, w, h); + Tk_SetInternalBorder(htmlPtr->tkwin, htmlPtr->inset); + TestPoint(0); +} + +/* +** This routine is called in order to process a "configure" subcommand +** on the given html widget. +*/ +int ConfigureHtmlWidget( + Tcl_Interp *interp, /* Write error message to this interpreter */ + HtmlWidget *htmlPtr, /* The Html widget to be configured */ + int argc, /* Number of configuration arguments */ + const char **argv, /* Text of configuration arguments */ + int flags, /* Configuration flags */ + int realign /* Always do a redraw if set */ +){ + int rc; + int i; + int redraw = realign; /* True if a redraw is required. */ + + /* Scan thru the configuration options to see if we need to redraw + ** the widget. + */ + for(i=0; redraw==0 && i<argc; i+=2){ + int c; + int n; + if( argv[i][0]!='-' ){ + redraw = 1; + break; + } + c = argv[i][1]; + n = strlen(argv[i]); + if( c=='c' && n>4 && strncmp(argv[i],"-cursor",n)==0 ){ + /* do nothing */ + }else + /* The default case */ + { + redraw = 1; + } + } + rc = Tk_ConfigureWidget(interp, htmlPtr->tkwin, configSpecs, argc, (const char**)argv, + (char *) htmlPtr, flags); + if( rc!=TCL_OK || redraw==0 ){ TestPoint(0); return rc; } + memset(htmlPtr->fontValid, 0, sizeof(htmlPtr->fontValid)); + htmlPtr->apColor[COLOR_Normal] = htmlPtr->fgColor; + htmlPtr->apColor[COLOR_Visited] = htmlPtr->oldLinkColor; + htmlPtr->apColor[COLOR_Unvisited] = htmlPtr->newLinkColor; + htmlPtr->apColor[COLOR_Selection] = htmlPtr->selectionColor; + htmlPtr->apColor[COLOR_Background] = Tk_3DBorderColor(htmlPtr->border); + Tk_SetBackgroundFromBorder(htmlPtr->tkwin, htmlPtr->border); + if( htmlPtr->highlightWidth < 0 ){ htmlPtr->highlightWidth = 0; TestPoint(0);} + if (htmlPtr->padx < 0) { htmlPtr->padx = 0; TestPoint(0);} + if (htmlPtr->pady < 0) { htmlPtr->pady = 0; TestPoint(0);} + if (htmlPtr->width < 100) { htmlPtr->width = 100; TestPoint(0);} + if (htmlPtr->height < 100) { htmlPtr->height = 100; TestPoint(0);} + if (htmlPtr->borderWidth < 0) {htmlPtr->borderWidth = 0; TestPoint(0);} + htmlPtr->flags |= RESIZE_ELEMENTS | RELAYOUT | REDRAW_BORDER | RESIZE_CLIPWIN; + HtmlRecomputeGeometry(htmlPtr); + HtmlRedrawEverything(htmlPtr); + ClearGcCache(htmlPtr); + return rc; +} + +/* +** Delete a single HtmlElement +*/ +void HtmlDeleteElement(HtmlElement *p){ + switch( p->base.type ){ + case Html_Block: + if( p->block.z ){ + HtmlFree(p->block.z); + } + break; + default: + break; + } + HtmlFree(p); +} + +/* +** Erase all data from the HTML widget. Bring it back to an +** empty screen. +** +** This happens (for example) when the "clear" method is invoked +** on the widget, or just before the widget is deleted. +*/ +void HtmlClear(HtmlWidget *htmlPtr){ + int i; + HtmlElement *p, *pNext; + + HtmlDeleteControls(htmlPtr); + for(p=htmlPtr->pFirst; p; p=pNext){ + pNext = p->pNext; + HtmlDeleteElement(p); + } + htmlPtr->pFirst = 0; + htmlPtr->pLast = 0; + htmlPtr->nToken = 0; + if( htmlPtr->zText ){ + HtmlFree(htmlPtr->zText); + } + htmlPtr->zText = 0; + htmlPtr->nText = 0; + htmlPtr->nAlloc = 0; + htmlPtr->nComplete = 0; + htmlPtr->iPlaintext = 0; + for(i=N_PREDEFINED_COLOR; i<N_COLOR; i++){ + if( htmlPtr->apColor[i] != 0 ){ + Tk_FreeColor(htmlPtr->apColor[i]); + htmlPtr->apColor[i] = 0; + } + } + for(i=0; i<N_COLOR; i++){ + htmlPtr->iDark[i] = 0; + htmlPtr->iLight[i] = 0; + } + htmlPtr->colorUsed = 0; + while( htmlPtr->imageList ){ + HtmlImage *p = htmlPtr->imageList; + htmlPtr->imageList = p->pNext; + Tk_FreeImage(p->image); + HtmlFree(p); + TestPoint(0); + } + while( htmlPtr->styleStack ){ + HtmlStyleStack *p = htmlPtr->styleStack; + htmlPtr->styleStack = p->pNext; + HtmlFree(p); + } + ClearGcCache(htmlPtr); + ResetLayoutContext(htmlPtr); + if( htmlPtr->zBaseHref ){ + HtmlFree(htmlPtr->zBaseHref); + htmlPtr->zBaseHref = 0; + } + htmlPtr->lastSized = 0; + htmlPtr->nextPlaced = 0; + htmlPtr->firstBlock = 0; + htmlPtr->lastBlock = 0; + htmlPtr->nInput = 0; + htmlPtr->nForm = 0; + htmlPtr->varId = 0; + htmlPtr->paraAlignment = ALIGN_None; + htmlPtr->rowAlignment = ALIGN_None; + htmlPtr->anchorFlags = 0; + htmlPtr->inDt = 0; + htmlPtr->anchorStart = 0; + htmlPtr->formStart = 0; + htmlPtr->innerList = 0; + htmlPtr->maxX = 0; + htmlPtr->maxY = 0; + htmlPtr->xOffset = 0; + htmlPtr->yOffset = 0; + htmlPtr->pInsBlock = 0; + htmlPtr->ins.p = 0; + htmlPtr->selBegin.p = 0; + htmlPtr->selEnd.p = 0; + htmlPtr->pSelStartBlock = 0; + htmlPtr->pSelEndBlock = 0; +} + +/* +** This routine attempts to delete the widget structure. But it won't +** do it if the widget structure is locked. If the widget structure is +** locked, then when HtmlUnlock() is called and the lock count reaches +** zero, this routine will be called to finish the job. +*/ +static void DestroyHtmlWidget(HtmlWidget *htmlPtr){ + int i; + + if( htmlPtr->locked>0 ) return; + Tcl_DeleteCommand(htmlPtr->interp, htmlPtr->zCmdName); + Tcl_DeleteCommand(htmlPtr->interp, htmlPtr->zClipwin); + HtmlClear(htmlPtr); + Tk_FreeOptions(configSpecs, (char*) htmlPtr, htmlPtr->display, 0); + for(i=0; i<N_FONT; i++){ + if( htmlPtr->aFont[i] != 0 ){ + Tk_FreeFont(htmlPtr->aFont[i]); + htmlPtr->aFont[i] = 0; + } + } + for(i=0; i<Html_TypeCount; i++){ + if( htmlPtr->zHandler[i] ){ + HtmlFree(htmlPtr->zHandler[i]); + htmlPtr->zHandler[i] = 0; + } + } + if( htmlPtr->insTimer ){ + Tcl_DeleteTimerHandler(htmlPtr->insTimer); + htmlPtr->insTimer = 0; + } + HtmlFree(htmlPtr->zClipwin); + HtmlFree(htmlPtr); +} + +/* +** Remove a lock from the HTML widget. If the widget has been +** deleted, then delete the widget structure. Return 1 if the +** widget has been deleted. Return 0 if it still exists. +** +** Normal Tk code (that is to say, code in the Tk core) uses +** Tcl_Preserve() and Tcl_Release() to accomplish what this +** function does. But preserving and releasing are much more +** common in this code than in regular widgets, so this routine +** was invented to do the same thing easier and faster. +*/ +int HtmlUnlock(HtmlWidget *htmlPtr){ + htmlPtr->locked--; + if( htmlPtr->tkwin==0 && htmlPtr->locked<=0 ){ + Tcl_Interp *interp = htmlPtr->interp; + Tcl_Preserve(interp); + DestroyHtmlWidget(htmlPtr); + Tcl_Release(interp); + return 1; + } + return htmlPtr->tkwin==0; +} + +/* +** Lock the HTML widget. This prevents the widget structure from +** being deleted even if the widget itself is destroyed. There must +** be a call to HtmlUnlock() to release the structure. +*/ +void HtmlLock(HtmlWidget *htmlPtr){ + htmlPtr->locked++; +} + +/* +** This routine checks to see if an HTML widget has been +** destroyed. It is always called after calling HtmlLock(). +** +** If the widget has been destroyed, then the structure +** is unlocked and the function returns 1. If the widget +** has not been destroyed, then the structure is not unlocked +** and the routine returns 0. +** +** This routine is intended for use in code like the following: +** +** HtmlLock(htmlPtr); +** // Do something that might destroy the widget +** if( HtmlIsDead(htmlPtr) ) return; +** // Do something that might destroy the widget +** if( HtmlIsDead(htmlPtr) ) return; +** // Do something that might destroy the widget +** if( HtmlUnlock(htmlPtr) ) return; +*/ +int HtmlIsDead(HtmlWidget *htmlPtr){ + if( htmlPtr->tkwin==0 ){ + HtmlUnlock(htmlPtr); + return 1; + } + return 0; +} + +/* +** Flash the insertion cursor. +*/ +void HtmlFlashCursor(ClientData clientData){ + HtmlWidget *htmlPtr = (HtmlWidget*)clientData; + if( htmlPtr->pInsBlock==0 || htmlPtr->insOnTime<=0 + || htmlPtr->insOffTime<=0 ){ + htmlPtr->insTimer = 0; + TestPoint(0); + return; + } + HtmlRedrawBlock(htmlPtr, htmlPtr->pInsBlock); + if( (htmlPtr->flags & GOT_FOCUS)==0 ){ + htmlPtr->insStatus = 0; + htmlPtr->insTimer = 0; + TestPoint(0); + }else if( htmlPtr->insStatus ){ + htmlPtr->insTimer = Tcl_CreateTimerHandler(htmlPtr->insOffTime, + HtmlFlashCursor, clientData); + htmlPtr->insStatus = 0; + TestPoint(0); + }else{ + htmlPtr->insTimer = Tcl_CreateTimerHandler(htmlPtr->insOnTime, + HtmlFlashCursor, clientData); + htmlPtr->insStatus = 1; + TestPoint(0); + } +} + +/* +** Return a GC from the cache. As many as N_CACHE_GCs are kept valid +** at any one time. They are replaced using an LRU algorithm. +** +** A value of FONT_Any (-1) for the font means "don't care". +*/ +GC HtmlGetGC(HtmlWidget *htmlPtr, int color, int font){ + int i, j; + GcCache *p = htmlPtr->aGcCache; + XGCValues gcValues; + int mask; + Tk_Font tkfont; + + /* + ** Check for an existing GC. + */ + if( color < 0 || color >= N_COLOR ){ color = 0; TestPoint(0); } + if( font < FONT_Any || font >= N_FONT ){ font = FONT_Default; TestPoint(0); } + for(i=0; i<N_CACHE_GC; i++, p++){ + if( p->index==0 ){ TestPoint(0); continue; } + if( (font<0 || p->font==font) && p->color==color ){ + if( p->index>1 ){ + for(j=0; j<N_CACHE_GC; j++){ + if( htmlPtr->aGcCache[j].index + && htmlPtr->aGcCache[j].index < p->index ){ + htmlPtr->aGcCache[j].index++; + } + } + p->index = 1; + } + return htmlPtr->aGcCache[i].gc; + } + } + + /* + ** No GC matches. Find a place to allocate a new GC. + */ + p = htmlPtr->aGcCache; + for(i=0; i<N_CACHE_GC; i++, p++){ + if( p->index==0 || p->index==N_CACHE_GC ){ TestPoint(0); break; } + } + if( p->index ){ + Tk_FreeGC(htmlPtr->display, p->gc); + } + gcValues.foreground = htmlPtr->apColor[color]->pixel; + gcValues.graphics_exposures = True; + mask = GCForeground | GCGraphicsExposures; + if( font<0 ){ font = FONT_Default; TestPoint(0); } + tkfont = HtmlGetFont(htmlPtr, font); + if( tkfont ){ + gcValues.font = Tk_FontId(tkfont); + mask |= GCFont; + } + p->gc = Tk_GetGC(htmlPtr->tkwin, mask, &gcValues); + if( p->index==0 ){ p->index = N_CACHE_GC + 1; TestPoint(0); } + for(j=0; j<N_CACHE_GC; j++){ + if( htmlPtr->aGcCache[j].index && htmlPtr->aGcCache[j].index < p->index ){ + htmlPtr->aGcCache[j].index++; + } + } + p->index = 1; + p->font = font; + p->color = color; + return p->gc; +} + +/* +** Retrieve any valid GC. The font and color don't matter since the +** GC will only be used for copying. +*/ +GC HtmlGetAnyGC(HtmlWidget *htmlPtr){ + int i; + GcCache *p = htmlPtr->aGcCache; + + for(i=0; i<N_CACHE_GC; i++, p++){ + if( p->index ){ TestPoint(0); return p->gc; } + } + TestPoint(0); + return HtmlGetGC(htmlPtr, COLOR_Normal, FONT_Default); +} + +/* +** All window events (for both tkwin and clipwin) are +** sent to this routine. +*/ +static void HtmlEventProc(ClientData clientData, XEvent *eventPtr){ + HtmlWidget *htmlPtr = (HtmlWidget*) clientData; + int redraw_needed = 0; + XConfigureRequestEvent *p; + + switch( eventPtr->type ){ + case GraphicsExpose: + case Expose: + if( htmlPtr->tkwin==0 ){ + /* The widget is being deleted. Do nothing */ + TestPoint(0); + }else if( eventPtr->xexpose.window!=Tk_WindowId(htmlPtr->tkwin) ){ + /* Exposure in the clipping window */ + HtmlRedrawArea(htmlPtr, eventPtr->xexpose.x - 1, + eventPtr->xexpose.y - 1, + eventPtr->xexpose.x + eventPtr->xexpose.width + 1, + eventPtr->xexpose.y + eventPtr->xexpose.height + 1); + TestPoint(0); + }else{ + /* Exposure in the main window */ + htmlPtr->flags |= REDRAW_BORDER; + HtmlScheduleRedraw(htmlPtr); + TestPoint(0); + } + break; + case DestroyNotify: + if( (htmlPtr->flags & REDRAW_PENDING) ){ + Tcl_CancelIdleCall(HtmlRedrawCallback, (ClientData)htmlPtr); + htmlPtr->flags &= ~REDRAW_PENDING; + } + if( htmlPtr->tkwin != 0 ){ + if( eventPtr->xany.window!=Tk_WindowId(htmlPtr->tkwin) ){ + Tk_DestroyWindow(htmlPtr->tkwin); + htmlPtr->clipwin = 0; + break; + } + htmlPtr->tkwin = 0; + Tcl_DeleteCommand(htmlPtr->interp, htmlPtr->zCmdName); + Tcl_DeleteCommand(htmlPtr->interp, htmlPtr->zClipwin); + } + HtmlUnlock(htmlPtr); + break; + case ConfigureNotify: + if( htmlPtr->tkwin!=0 + && eventPtr->xconfigure.window==Tk_WindowId(htmlPtr->tkwin) + ){ + p = (XConfigureRequestEvent*)eventPtr; + if( p->width != htmlPtr->realWidth ){ + redraw_needed = 1; + htmlPtr->realWidth = p->width; + TestPoint(0); + }else{ + TestPoint(0); + } + if( p->height != htmlPtr->realHeight ){ + redraw_needed = 1; + htmlPtr->realHeight = p->height; + TestPoint(0); + }else{ + TestPoint(0); + } + if( redraw_needed ){ + htmlPtr->flags |= RELAYOUT | VSCROLL | HSCROLL | RESIZE_CLIPWIN; + HtmlRedrawEverything(htmlPtr); + TestPoint(0); + }else{ + TestPoint(0); + } + } + break; + case FocusIn: + if( htmlPtr->tkwin!=0 + && eventPtr->xfocus.window==Tk_WindowId(htmlPtr->tkwin) + && eventPtr->xfocus.detail != NotifyInferior + ){ + htmlPtr->flags |= GOT_FOCUS | REDRAW_FOCUS; + HtmlScheduleRedraw(htmlPtr); + HtmlUpdateInsert(htmlPtr); + TestPoint(0); + }else{ + TestPoint(0); + } + break; + case FocusOut: + if( htmlPtr->tkwin!=0 + && eventPtr->xfocus.window==Tk_WindowId(htmlPtr->tkwin) + && eventPtr->xfocus.detail != NotifyInferior + ){ + htmlPtr->flags &= ~GOT_FOCUS; + htmlPtr->flags |= REDRAW_FOCUS; + HtmlScheduleRedraw(htmlPtr); + TestPoint(0); + }else{ + TestPoint(0); + } + break; + } +} + + +/* +** The rendering and layout routines should call this routine in order to get +** a font structure. The iFont parameter specifies which of the N_FONT +** fonts should be obtained. The font is allocated if necessary. +** +** Because the -fontcommand callback can be invoked, this function can +** (in theory) cause the HTML widget to be changed arbitrarily or even +** deleted. Callers of this function much be prepared to be called +** recursively and/or to have the HTML widget deleted out from under +** them. This routine will return NULL if the HTML widget is deleted. +*/ +Tk_Font HtmlGetFont( + HtmlWidget *htmlPtr, /* The HTML widget to which the font applies */ + int iFont /* Which font to obtain */ +){ + Tk_Font toFree = 0; + + if( iFont<0 ){ iFont = 0; TestPoint(0); } + if( iFont>=N_FONT ){ iFont = N_FONT - 1; CANT_HAPPEN; } + + /* + ** If the font has previously been allocated, but the "fontValid" bitmap + ** shows it is no longer valid, then mark it for freeing later. We use + ** a policy of allocate-before-free because Tk's font cache operates + ** much more efficiently that way. + */ + if( !FontIsValid(htmlPtr, iFont) && htmlPtr->aFont[iFont]!=0 ){ + toFree = htmlPtr->aFont[iFont]; + htmlPtr->aFont[iFont] = 0; + TestPoint(0); + } + + /* + ** If we need to allocate a font, first construct the font name then + ** allocate it. + */ + if( htmlPtr->aFont[iFont]==0 ){ + char name[200]; /* Name of the font */ + + name[0] = 0; + + /* Run the -fontcommand if it is specified + */ + if( htmlPtr->zFontCommand && htmlPtr->zFontCommand[0] ){ + int iFam; /* The font family index. Value between 0 and 7 */ + Tcl_DString str; /* The command we'll execute to get the font name */ + char *zSep = ""; /* Separator between font attributes */ + int rc; /* Return code from the font command */ + char zBuf[100]; /* Temporary buffer */ + + Tcl_DStringInit(&str); + Tcl_DStringAppend(&str, htmlPtr->zFontCommand, -1); + sprintf(zBuf, " %d {", FontSize(iFont)+1); + Tcl_DStringAppend(&str,zBuf, -1); + iFam = iFont / N_FONT_SIZE ; + if( iFam & 1 ){ + Tcl_DStringAppend(&str,"bold",-1); + zSep = " "; + } + if( iFam & 2 ){ + Tcl_DStringAppend(&str,zSep,-1); + Tcl_DStringAppend(&str,"italic",-1); + zSep = " "; + } + if( iFam & 4 ){ + Tcl_DStringAppend(&str,zSep,-1); + Tcl_DStringAppend(&str,"fixed",-1); + } + Tcl_DStringAppend(&str,"}",-1); + HtmlLock(htmlPtr); + rc = Tcl_GlobalEval(htmlPtr->interp, Tcl_DStringValue(&str)); + Tcl_DStringFree(&str); + if( HtmlUnlock(htmlPtr) ){ + return NULL; + } + if( rc!=TCL_OK ){ + Tcl_AddErrorInfo(htmlPtr->interp, + "\n (-fontcommand callback of HTML widget)"); + Tcl_BackgroundError(htmlPtr->interp); + }else{ + sprintf(name,"%.100s", Tcl_GetStringResult(htmlPtr->interp)); + } + Tcl_ResetResult(htmlPtr->interp); + } + + /* + ** If the -fontcommand failed or returned an empty string, or if + ** there is no -fontcommand, then get the default font name. + */ + if( name[0]==0 ){ + char *familyStr = ""; + int iFamily; + int iSize; + int size; + + iFamily = iFont / N_FONT_SIZE; + iSize = iFont % N_FONT_SIZE + 1; + switch( iFamily ){ + case 0: familyStr = "helvetica -%d"; break; + case 1: familyStr = "helvetica -%d bold"; break; + case 2: familyStr = "helvetica -%d italic"; break; + case 3: familyStr = "helvetica -%d bold italic"; break; + case 4: familyStr = "courier -%d"; break; + case 5: familyStr = "courier -%d bold"; break; + case 6: familyStr = "courier -%d italic"; break; + case 7: familyStr = "courier -%d bold italic"; break; + default: familyStr = "helvetica -14"; CANT_HAPPEN; + } + switch( iSize ){ + case 1: size = 8; break; + case 2: size = 10; break; + case 3: size = 12; break; + case 4: size = 14; break; + case 5: size = 16; break; + case 6: size = 18; break; + case 7: size = 24; break; + default: size = 14; CANT_HAPPEN; + } + sprintf(name, familyStr, size); + } + + /* Get the named font + */ + htmlPtr->aFont[iFont] = Tk_GetFont(htmlPtr->interp, htmlPtr->tkwin, name); + if( htmlPtr->aFont[iFont]==0 ){ + Tcl_AddErrorInfo(htmlPtr->interp, + "\n (trying to create a font named \""); + Tcl_AddErrorInfo(htmlPtr->interp, name); + Tcl_AddErrorInfo(htmlPtr->interp, "\" in the HTML widget)"); + Tcl_BackgroundError(htmlPtr->interp); + htmlPtr->aFont[iFont] = + Tk_GetFont(htmlPtr->interp, htmlPtr->tkwin, "fixed"); + } + if( htmlPtr->aFont[iFont]==0 ){ + Tcl_AddErrorInfo(htmlPtr->interp, + "\n (trying to create font \"fixed\" in the HTML widget)"); + Tcl_BackgroundError(htmlPtr->interp); + htmlPtr->aFont[iFont] = + Tk_GetFont(htmlPtr->interp, htmlPtr->tkwin, "helvetica -12"); + } + FontSetValid(htmlPtr, iFont); + TestPoint(0); + } + + /* + ** Free the expired font, if any. + */ + if( toFree!=0 ){ + Tk_FreeFont(toFree); + } + return htmlPtr->aFont[iFont]; +} + +/* +** Compute the squared distance between two colors +*/ +static float colorDistance(XColor *pA, XColor *pB){ + float x, y, z; + + x = 0.30 * (pA->red - pB->red); + y = 0.61 * (pA->green - pB->green); + z = 0.11 * (pA->blue - pB->blue); + TestPoint(0); + return x*x + y*y + z*z; +} + +/* +** This routine returns an index between 0 and N_COLOR-1 which indicates +** which XColor structure in the apColor[] array of htmlPtr should be +** used to describe the color specified by the given name. +*/ +int HtmlGetColorByName(HtmlWidget *htmlPtr, char *zColor){ + XColor *pNew; + int iColor; + Tk_Uid name; + int i, n; + char zAltColor[16]; + + /* Netscape accepts color names that are just HEX values, without + ** the # up front. This isn't valid HTML, but we support it for + ** compatibility. + */ + n = strlen(zColor); + + /* trucate any spaces on the end */ + while (n>0 && zColor[n-1]==' ') { + zColor[n-1] = '\0'; + n--; + } + + if( n==6 || n==3 || n==9 || n==12 ){ + for(i=0; i<n; i++){ + if( !isxdigit(zColor[i]) ) break; + } + if( i==n ){ + sprintf(zAltColor,"#%s",zColor); + }else{ + strcpy(zAltColor, zColor); + } + name = Tk_GetUid(zAltColor); + }else{ + name = Tk_GetUid(zColor); + } + pNew = Tk_GetColor(htmlPtr->interp, htmlPtr->clipwin, name); + if( pNew==0 ){ + return 0; /* Color 0 is always the default */ + } + + iColor = GetColorByValue(htmlPtr, pNew); + Tk_FreeColor(pNew); + return iColor; +} + +/* +** Macros used in the computation of appropriate shadow colors. +*/ +#define MAX_COLOR 65535 +#define MAX(A,B) ((A)<(B)?(B):(A)) +#define MIN(A,B) ((A)<(B)?(A):(B)) + +/* +** Check to see if the given color is too dark to be easily distinguished +** from black. +*/ +static int isDarkColor(XColor *p){ + float x, y, z; + + x = 0.50 * p->red; + y = 1.00 * p->green; + z = 0.28 * p->blue; + return (x*x + y*y + z*z)<0.05*MAX_COLOR*MAX_COLOR; +} + +/* +** Given that the background color is iBgColor, figure out an +** appropriate color for the dark part of a 3D shadow. +*/ +int HtmlGetDarkShadowColor(HtmlWidget *htmlPtr, int iBgColor){ + if( htmlPtr->iDark[iBgColor]==0 ){ + XColor *pRef, val; + pRef = htmlPtr->apColor[iBgColor]; + if( isDarkColor(pRef) ){ + int t1, t2; + t1 = MIN(MAX_COLOR,pRef->red*1.2); + t2 = (pRef->red*3 + MAX_COLOR)/4; + val.red = MAX(t1,t2); + t1 = MIN(MAX_COLOR,pRef->green*1.2); + t2 = (pRef->green*3 + MAX_COLOR)/4; + val.green = MAX(t1,t2); + t1 = MIN(MAX_COLOR,pRef->blue*1.2); + t2 = (pRef->blue*3 + MAX_COLOR)/4; + val.blue = MAX(t1,t2); + }else{ + val.red = pRef->red*0.6; + val.green = pRef->green*0.6; + val.blue = pRef->blue*0.6; + } + htmlPtr->iDark[iBgColor] = GetColorByValue(htmlPtr, &val) + 1; + } + return htmlPtr->iDark[iBgColor] - 1; +} + +/* +** Check to see if the given color is too light to be easily distinguished +** from white. +*/ +static int isLightColor(XColor *p){ + return p->green>=0.85*MAX_COLOR; +} + +/* +** Given that the background color is iBgColor, figure out an +** appropriate color for the bright part of the 3D shadow. +*/ +int HtmlGetLightShadowColor(HtmlWidget *htmlPtr, int iBgColor){ + if( htmlPtr->iLight[iBgColor]==0 ){ + XColor *pRef, val; + pRef = htmlPtr->apColor[iBgColor]; + if( isLightColor(pRef) ){ + val.red = pRef->red*0.9; + val.green = pRef->green*0.9; + val.blue = pRef->blue*0.9; + }else{ + int t1, t2; + t1 = MIN(MAX_COLOR,pRef->green*1.4); + t2 = (pRef->green + MAX_COLOR)/2; + val.green = MAX(t1,t2); + t1 = MIN(MAX_COLOR,pRef->red*1.4); + t2 = (pRef->red + MAX_COLOR)/2; + val.red = MAX(t1,t2); + t1 = MIN(MAX_COLOR,pRef->blue*1.4); + t2 = (pRef->blue + MAX_COLOR)/2; + val.blue = MAX(t1,t2); + } + htmlPtr->iLight[iBgColor] = GetColorByValue(htmlPtr, &val) + 1; + } + return htmlPtr->iLight[iBgColor] - 1; +} + +/* +** Find a color integer for the color whose color components +** are given by pRef. +*/ +LOCAL int GetColorByValue(HtmlWidget *htmlPtr, XColor *pRef){ + int i; + float dist; + float closestDist; + int closest; + /* + int r, g, b; +# define COLOR_MASK 0xf800 + */ + + XColor* q; + q = Tk_GetColorByValue(htmlPtr->clipwin, pRef); + + /* Search for an exact match */ + /* + r = pRef->red &= COLOR_MASK; + g = pRef->green &= COLOR_MASK; + b = pRef->blue &= COLOR_MASK; + */ + for(i=0; i<N_COLOR; i++){ + XColor *p = htmlPtr->apColor[i]; + /* + if( p && (p->red & COLOR_MASK)==r && (p->green & COLOR_MASK)==g + && (p->blue & COLOR_MASK)==b ){ + */ + if (p && (q->red == p->red) + && (q->green == p->green) + && (q->blue == p->blue)) { + htmlPtr->colorUsed |= (1<<i); + Tk_FreeColor(q); + return i; + } + } + Tk_FreeColor(q); + + /* No exact matches. Look for a completely unused slot */ + for(i=N_PREDEFINED_COLOR; i<N_COLOR; i++){ + if( htmlPtr->apColor[i]==0 ){ + htmlPtr->apColor[i] = Tk_GetColorByValue(htmlPtr->clipwin, pRef); + htmlPtr->colorUsed |= (1<<i); + return i; + } + } + + /* No empty slots. Look for a slot that contains a color that + ** isn't currently in use. */ + for(i=N_PREDEFINED_COLOR; i<N_COLOR; i++){ + if( ((htmlPtr->colorUsed >> i) & 1) == 0 ){ + Tk_FreeColor(htmlPtr->apColor[i]); + htmlPtr->apColor[i] = Tk_GetColorByValue(htmlPtr->clipwin, pRef); + htmlPtr->colorUsed |= (1<<i); + return i; + } + } + + /* Ok, find the existing color that is closest to the color requested + ** and use it. */ + closest = 0; + closestDist = colorDistance(pRef, htmlPtr->apColor[0]); + for(i=1; i<N_COLOR; i++){ + dist = colorDistance(pRef, htmlPtr->apColor[i]); + if( dist < closestDist ){ + closestDist = dist; + closest = i; + } + } + return i; +} + +/* +** This routine searchs for a hyperlink beneath the coordinates x,y +** and returns a pointer to the HREF for that hyperlink. The text +** is held one of the markup.argv[] fields of the <a> markup. +*/ +char *HtmlGetHref(HtmlWidget *htmlPtr, int x, int y){ + HtmlBlock *pBlock; + HtmlElement *pElem; + + for(pBlock=htmlPtr->firstBlock; pBlock; pBlock=pBlock->pNext){ + if( pBlock->top > y || pBlock->bottom < y + || pBlock->left > x || pBlock->right < x + ){ + TestPoint(0); + continue; + } + pElem = pBlock->base.pNext; + if( (pElem->base.style.flags & STY_Anchor)==0 ){ TestPoint(0); continue; } + switch( pElem->base.type ){ + case Html_Text: + case Html_Space: + case Html_IMG: + while( pElem && pElem->base.type!=Html_A ){ + pElem = pElem->base.pPrev; + } + if( pElem==0 || pElem->base.type!=Html_A ){ break; } + return HtmlMarkupArg(pElem,"href", 0); + default: + break; + } + } + TestPoint(0); + return 0; +} + +/* +** Change the "yOffset" field from its current value to the value given. +** This has the effect of scrolling the widget vertically. +*/ +void HtmlVerticalScroll(HtmlWidget *htmlPtr, int yOffset){ + int inset; /* The 3D border plus the pady */ + int h; /* Height of the clipping window */ + int diff; /* Difference between old and new offset */ + GC gc; /* Graphics context used for copying */ + int w; /* Width of text area */ + + if( yOffset==htmlPtr->yOffset ){ TestPoint(0); return; } + inset = htmlPtr->pady + htmlPtr->inset; + h = htmlPtr->realHeight - 2*inset; + if( (htmlPtr->flags & REDRAW_TEXT)!=0 + || (htmlPtr->dirtyTop < h && htmlPtr->dirtyBottom > 0) + || htmlPtr->yOffset > yOffset + (h - 30) + || htmlPtr->yOffset < yOffset - (h - 30) + ){ + htmlPtr->yOffset = yOffset; + htmlPtr->flags |= VSCROLL | REDRAW_TEXT; + HtmlScheduleRedraw(htmlPtr); + TestPoint(0); + return; + } + diff = htmlPtr->yOffset - yOffset; + gc = HtmlGetAnyGC(htmlPtr); + w = htmlPtr->realWidth - 2*(htmlPtr->inset + htmlPtr->padx); + htmlPtr->flags |= VSCROLL; + htmlPtr->yOffset = yOffset; +#ifndef MAC_OSX_TK + if( diff < 0 ){ + XCopyArea(htmlPtr->display, + Tk_WindowId(htmlPtr->clipwin), /* source */ + Tk_WindowId(htmlPtr->clipwin), /* destination */ + gc, + 0, -diff, /* source X, Y */ + w, h + diff, /* Width and height */ + 0, 0); /* Destination X, Y */ + HtmlRedrawArea(htmlPtr, 0, h + diff, w, h); + TestPoint(0); + }else{ + XCopyArea(htmlPtr->display, + Tk_WindowId(htmlPtr->clipwin), /* source */ + Tk_WindowId(htmlPtr->clipwin), /* destination */ + gc, + 0, 0, /* source X, Y */ + w, h - diff, /* Width and height */ + 0, diff); /* Destination X, Y */ + HtmlRedrawArea(htmlPtr, 0, 0, w, diff); + TestPoint(0); + } +#else + HtmlRedrawArea(htmlPtr, 0, 0, w, h); +#endif + /* HtmlMapControls(htmlPtr);*/ +} + +/* +** Change the "xOffset" field from its current value to the value given. +** This has the effect of scrolling the widget horizontally. +*/ +void HtmlHorizontalScroll(HtmlWidget *htmlPtr, int xOffset){ + if( xOffset==htmlPtr->xOffset ){ TestPoint(0); return; } + htmlPtr->xOffset = xOffset; + HtmlMapControls(htmlPtr); + htmlPtr->flags |= HSCROLL | REDRAW_TEXT; + HtmlScheduleRedraw(htmlPtr); + TestPoint(0); +} + +/* +** The following array defines all possible widget command. The main +** widget command function just parses up the command line, then vectors +** control to one of the command service routines defined in the +** following array: +*/ +static struct HtmlSubcommand { + char *zCmd1; /* First-level subcommand. Required */ + char *zCmd2; /* Second-level subcommand. May be NULL */ + int minArgc; /* Minimum number of arguments */ + int maxArgc; /* Maximum number of arguments */ + char *zHelp; /* Help string if wrong number of arguments */ + int (*xFunc)(HtmlWidget*,Tcl_Interp*,int,const char**); /* Cmd service routine */ +} aSubcommand[] = { + { "cget", 0, 3, 3, "CONFIG-OPTION", HtmlCgetCmd }, + { "clear", 0, 2, 2, 0, HtmlClearCmd }, + { "configure", 0, 2, 0, "?ARGS...?", HtmlConfigCmd }, + { "href", 0, 4, 4, "X Y", HtmlHrefCmd }, + { "index", 0, 3, 3, "INDEX", HtmlIndexCmd }, + { "insert", 0, 3, 3, "INDEX", HtmlInsertCmd }, + { "names", 0, 2, 2, 0, HtmlNamesCmd }, + { "parse", 0, 3, 3, "HTML-TEXT", HtmlParseCmd }, + { "resolve", 0, 2, 0, "?URI ...?", HtmlResolveCmd }, + { "selection", "clear", 3, 3, 0, HtmlSelectionClearCmd}, + { 0, "set", 5, 5, "START END", HtmlSelectionSetCmd }, + { "text", "ascii", 5, 5, "START END", HtmlTextAsciiCmd}, + { 0, "delete", 5, 5, "START END", 0 }, + { 0, "html", 5, 5, "START END", 0 }, + { 0, "insert", 5, 5, "INDEX TEXT", 0 }, + { "token", "append", 5, 5, "TAG ARGUMENTS", 0 }, + { 0, "delete", 4, 5, "INDEX ?INDEX?", 0 }, + { 0, "find", 4, 6, "TAG ?before|after INDEX?", 0 }, + { 0, "get", 4, 5, "INDEX ?INDEX?", 0 }, + { 0, "handler", 4, 5, "TAG ?SCRIPT?", HtmlTokenHandlerCmd }, + { 0, "insert", 6, 6, "INDEX TAG ARGUMENTS", 0 }, + { 0, "list", 5, 5, "START END", HtmlTokenListCmd }, + { "xview", 0, 2, 5, "OPTIONS...", HtmlXviewCmd }, + { "yview", 0, 2, 5, "OPTIONS...", HtmlYviewCmd }, +#ifdef DEBUG + { "debug", "dump", 5, 5, "START END", HtmlDebugDumpCmd }, + { 0, "testpt", 4, 4, "FILENAME", HtmlDebugTestPtCmd }, +#endif +}; +#define nSubcommand (sizeof(aSubcommand)/sizeof(aSubcommand[0])) + +/* +** This routine implements the command used by individual HTML widgets. +*/ +static int HtmlWidgetCommand( + ClientData clientData, /* The HTML widget data structure */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + const char **argv /* Argument strings. */ +){ + HtmlWidget *htmlPtr = (HtmlWidget*) clientData; + size_t length; + int c; + int i; + struct HtmlSubcommand *pCmd; + + if (argc < 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " option ?arg arg ...?\"", 0); + TestPoint(0); + return TCL_ERROR; + } + c = argv[1][0]; + length = strlen(argv[1]); + for(i=0, pCmd=aSubcommand; i<nSubcommand; i++, pCmd++){ + if( pCmd->zCmd1==0 || c!=pCmd->zCmd1[0] + || strncmp(pCmd->zCmd1,argv[1],length)!=0 ){ + TestPoint(0); + continue; + } + if( pCmd->zCmd2 ){ + int length2; + int j; + if( argc<3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], " ", pCmd->zCmd1, " SUBCOMMAND ?OPTIONS...?", 0); + TestPoint(0); + return TCL_ERROR; + } + length2 = strlen(argv[2]); + for(j=i; j<nSubcommand && (j==i || pCmd->zCmd1==0); j++, pCmd++){ + if( strncmp(pCmd->zCmd2,argv[2],length2)==0 ){ + TestPoint(0); + break; + } + } + if( j>=nSubcommand || (j!=i && aSubcommand[j].zCmd1!=0) ){ + Tcl_AppendResult(interp,"unknown subcommand \"", argv[2], + "\" -- should be one of:", 0); + for(j=i; j<nSubcommand && (j==i || aSubcommand[j].zCmd1==0); j++){ + Tcl_AppendResult(interp, " ", aSubcommand[j].zCmd2, 0); + TestPoint(0); + } + return TCL_ERROR; + } + } + if( argc<pCmd->minArgc || (argc>pCmd->maxArgc && pCmd->maxArgc>0) ){ + Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], + " ", pCmd->zCmd1, 0); + if( pCmd->zCmd2 ){ + Tcl_AppendResult(interp, " ", pCmd->zCmd2, 0); + TestPoint(0); + } + if( pCmd->zHelp ){ + Tcl_AppendResult(interp, " ", pCmd->zHelp, 0); + TestPoint(0); + } + Tcl_AppendResult(interp, "\"", 0); + TestPoint(0); + return TCL_ERROR; + } + if( pCmd->xFunc==0 ){ + Tcl_AppendResult(interp,"command not yet implemented", 0); + TestPoint(0); + return TCL_ERROR; + } + TestPoint(0); + return (*pCmd->xFunc)(htmlPtr, interp, argc, argv); + } + Tcl_AppendResult(interp,"unknown command \"", argv[1], "\" -- should be " + "one of:", 0); + for(i=0; i<nSubcommand; i++){ + if( aSubcommand[i].zCmd1==0 || aSubcommand[i].zCmd1[0]=='_' ){ + TestPoint(0); + continue; + } + Tcl_AppendResult(interp, " ", aSubcommand[i].zCmd1, 0); + TestPoint(0); + } + TestPoint(0); + return TCL_ERROR; +} + +/* +** The following routine implements the Tcl "html" command. This command +** is used to create new HTML widgets only. After the widget has been +** created, it is manipulated using the widget command defined above. +*/ +static int HtmlCommand( + ClientData clientData, /* Main window */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + const char **argv /* Argument strings. */ +){ + int n, c; + char *z; + + if (argc < 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], " pathName ?options?\"", (char *) NULL); + return TCL_ERROR; + } + z = (char*)argv[1]; + n = strlen(z); + c = z[0]; + + /* If the first argument begins with ".", then it must be the + ** name of a new window the user wants to create. + */ + if( argv[1][0]=='.' ){ + HtmlWidget *htmlPtr; + Tk_Window new; + Tk_Window clipwin; + char *zClipwin; + Tk_Window tkwin = (Tk_Window)clientData; + static int varId = 1; /* Used to construct unique names */ + + new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL); + if (new == NULL) { + return TCL_ERROR; + } + zClipwin = HtmlAlloc( strlen(argv[1]) + 3 ); + if( zClipwin==0 ){ + Tk_DestroyWindow(new); + return TCL_ERROR; + } + sprintf(zClipwin,"%s.x",argv[1]); + clipwin = Tk_CreateWindowFromPath(interp, new, zClipwin, 0); + if( clipwin==0 ){ + Tk_DestroyWindow(new); + HtmlFree(zClipwin); + return TCL_ERROR; + } + + htmlPtr = HtmlAlloc(sizeof(HtmlWidget) + strlen(argv[1]) + 1); + memset(htmlPtr, 0, sizeof(HtmlWidget)); + htmlPtr->tkwin = new; + htmlPtr->clipwin = clipwin; + htmlPtr->zClipwin = zClipwin; + htmlPtr->display = Tk_Display(new); + htmlPtr->interp = interp; + htmlPtr->zCmdName = (char*)&htmlPtr[1]; + strcpy(htmlPtr->zCmdName, argv[1]); + htmlPtr->relief = TK_RELIEF_FLAT; + htmlPtr->dirtyLeft = LARGE_NUMBER; + htmlPtr->dirtyTop = LARGE_NUMBER; + htmlPtr->flags = RESIZE_CLIPWIN; + htmlPtr->varId = varId++; + Tcl_CreateCommand(interp, htmlPtr->zCmdName, + HtmlWidgetCommand, (ClientData)htmlPtr, HtmlCmdDeletedProc); + Tcl_CreateCommand(interp, htmlPtr->zClipwin, + HtmlWidgetCommand, (ClientData)htmlPtr, HtmlCmdDeletedProc); + + Tk_SetClass(new,"Html"); + Tk_SetClass(clipwin,"HtmlClip"); + Tk_CreateEventHandler(htmlPtr->tkwin, + ExposureMask|StructureNotifyMask|FocusChangeMask, + HtmlEventProc, (ClientData) htmlPtr); + Tk_CreateEventHandler(htmlPtr->clipwin, + ExposureMask|StructureNotifyMask, + HtmlEventProc, (ClientData) htmlPtr); + if (ConfigureHtmlWidget(interp, htmlPtr, argc-2, argv+2, 0, 1) != TCL_OK) { + goto error; + } + Tcl_SetResult(interp,Tk_PathName(htmlPtr->tkwin),NULL); + return TCL_OK; + + error: + Tk_DestroyWindow(htmlPtr->tkwin); + return TCL_ERROR; + } + + /* html reformat $from $to $text + ** + ** Convert the format of text. + */ + if( c=='r' && strncmp(z,"reformat",n)==0 ){ + if( argc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], " reformat FROM TO TEXT", (char *) NULL); + return TCL_ERROR; + } + Tcl_AppendResult(interp, "not yet implemented", 0); + return TCL_ERROR; + }else + + + /* html urljoin $scheme $authority $path $query $fragment + ** + ** Merge together the parts of a URL into a single value URL. + */ + if( c=='u' && strncmp(z,"urljoin",n)==0 ){ + if( argc!=7 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], " url join SCHEME AUTHORITY PATH QUERY FRAGMENT\"", 0); + return TCL_ERROR; + } + Tcl_AppendResult(interp, "not yet implemented", 0); + return TCL_ERROR; + }else + + + /* html urlsplit $url + ** + ** Split a URL into a list of its parts. + */ + if( c=='u' && strncmp(z,"urlsplit",n)==0 ){ + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], " url split URL\"", 0); + return TCL_ERROR; + } + Tcl_AppendResult(interp, "not yet implemented", 0); + return TCL_ERROR; + }else + + /* No match. Report an error. + */ + { + Tcl_AppendResult(interp, "unknown command \"", z, "\": should be " + "a window name or one of: " + "reformat urljoin urlsplit", 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** The following mess is used to define DLL_EXPORT. DLL_EXPORT is +** blank except when we are building a Windows95/NT DLL from this +** library. Some special trickery is necessary to make this wall +** work together with makeheaders. +*/ +#if INTERFACE +#define DLL_EXPORT +#endif +#if defined(USE_TCL_STUBS) && defined(__WIN32__) +# undef DLL_EXPORT +# define DLL_EXPORT __declspec(dllexport) +#endif + +/* +** This routine is used to register the "html" command with the +** Tcl interpreter. This is the only routine in this file with +** external linkage. +*/ +DLL_EXPORT int Tkhtml1_Init(Tcl_Interp *interp) { + + if (Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0) == NULL) + return TCL_ERROR; + + if (Tk_InitStubs(interp, TK_PATCH_LEVEL, 0) == NULL) + return TCL_ERROR; + + Tcl_CreateCommand(interp,"html", HtmlCommand, Tk_MainWindow(interp), 0); + +#ifdef DEBUG + Tcl_LinkVar(interp, "HtmlTraceMask", (char*)&HtmlTraceMask, TCL_LINK_INT); +#endif + + if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION) != TCL_OK) + return TCL_ERROR; + + return TCL_OK; +} diff --git a/tkhtml1/src/htmlwidget.h b/tkhtml1/src/htmlwidget.h new file mode 100644 index 0000000..86e9da1 --- /dev/null +++ b/tkhtml1/src/htmlwidget.h @@ -0,0 +1,561 @@ +/* This file was automatically generated. Do not edit! */ +#define DLL_EXPORT +DLL_EXPORT int Tkhtml1_Init(Tcl_Interp *interp); +#define INTERFACE 0 +#define HtmlAlloc(A) ((void*)Tcl_Alloc(A)) +typedef struct HtmlWidget HtmlWidget; +#define DEBUG 1 +#if defined(DEBUG) +int HtmlDebugTestPtCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlDebugDumpCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +#endif +int HtmlYviewCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlXviewCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlTokenListCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlTokenHandlerCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlTextAsciiCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlSelectionSetCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlSelectionClearCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlResolveCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlParseCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlNamesCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlInsertCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlIndexCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlHrefCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlConfigCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlClearCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +int HtmlCgetCmd(HtmlWidget *htmlPtr,Tcl_Interp *interp,int argc,const char **argv); +void HtmlHorizontalScroll(HtmlWidget *htmlPtr,int xOffset); +void HtmlVerticalScroll(HtmlWidget *htmlPtr,int yOffset); +typedef union HtmlElement HtmlElement; +char *HtmlMarkupArg(HtmlElement *p,const char *tag,char *zDefault); +#define Html_A 5 +#define Html_IMG 76 +#define Html_Space 2 +#define Html_Text 1 +#define STY_Anchor 0x010 +char *HtmlGetHref(HtmlWidget *htmlPtr,int x,int y); +#define LOCAL static +int HtmlGetLightShadowColor(HtmlWidget *htmlPtr,int iBgColor); +int HtmlGetDarkShadowColor(HtmlWidget *htmlPtr,int iBgColor); +#define MAX(A,B) ((A)<(B)?(B):(A)) +LOCAL int GetColorByValue(HtmlWidget *htmlPtr,XColor *pRef); +int HtmlGetColorByName(HtmlWidget *htmlPtr,char *zColor); +#define FontSetValid(H,I) ((H)->fontValid[(I)>>3] |= (1<<((I)&3))) +#define N_FONT_SIZE 7 +#define FontSize(X) ((X)%N_FONT_SIZE) +#define FontIsValid(H,I) (((H)->fontValid[(I)>>3] & (1<<((I)&3)))!=0) +void HtmlTPCantHappen(const char *zFile,int line); +#if defined(COVERAGE_TEST) +# define CANT_HAPPEN HtmlTPCantHappen(__FILE__,__LINE__) +#endif +#if !(defined(COVERAGE_TEST)) +# define CANT_HAPPEN +#endif +GC HtmlGetAnyGC(HtmlWidget *htmlPtr); +Tk_Font HtmlGetFont(HtmlWidget *htmlPtr,int iFont); +#define FONT_Default 3 +typedef struct GcCache GcCache; +typedef unsigned char Html_u8; +struct GcCache { + GC gc; /* The graphics context */ + Html_u8 font; /* Font used for this context */ + Html_u8 color; /* Color used for this context */ + Html_u8 index; /* Index used for LRU replacement */ +}; +void HtmlFlashCursor(ClientData clientData); +int HtmlIsDead(HtmlWidget *htmlPtr); +#define Html_TypeCount 151 +#define N_FONT_FAMILY 8 +#define N_FONT (N_FONT_FAMILY*N_FONT_SIZE) +#define ALIGN_None 0 +typedef struct HtmlStyleStack HtmlStyleStack; +typedef struct HtmlStyle HtmlStyle; +struct HtmlStyle { + unsigned int font : 6; /* Font to use for display */ + unsigned int color : 4; /* Foreground color */ + signed int subscript : 4; /* Positive for <sup>, negative for <sub> */ + unsigned int align : 2; /* Horizontal alignment */ + unsigned int bgcolor : 4; /* Background color */ + unsigned int flags : 12; /* the STY_ flags below */ +}; +struct HtmlStyleStack { + HtmlStyleStack *pNext; /* Next style on the stack */ + int type; /* A markup that ends this style. Ex: Html_EndEM */ + HtmlStyle style; /* The currently active style. */ +}; +#define N_COLOR 16 /* Total number of colors */ +#define N_PREDEFINED_COLOR 5 /* Number of predefined colors */ +void HtmlDeleteControls(HtmlWidget *htmlPtr); +void HtmlClear(HtmlWidget *htmlPtr); +#define HtmlFree(A) Tcl_Free((char*)(A)) +#define Html_Block 4 +void HtmlDeleteElement(HtmlElement *p); +#define COLOR_Selection 3 /* Background color for the selection */ +#define COLOR_Unvisited 1 /* Index for unvisited hyperlinks */ +#define COLOR_Visited 2 /* Color for visited hyperlinks */ +#define COLOR_Normal 0 /* Index for normal color (black) */ +int ConfigureHtmlWidget(Tcl_Interp *interp,HtmlWidget *htmlPtr,int argc,const char **argv,int flags,int realign); +void HtmlRedrawText(HtmlWidget *htmlPtr,int y); +void HtmlRedrawEverything(HtmlWidget *htmlPtr); +typedef struct HtmlBlock HtmlBlock; +void HtmlRedrawBlock(HtmlWidget *htmlPtr,HtmlBlock *p); +void HtmlRedrawArea(HtmlWidget *htmlPtr,int left,int top,int right,int bottom); +void HtmlScheduleRedraw(HtmlWidget *htmlPtr); +#define LARGE_NUMBER 100000000 +void HtmlDrawImage(HtmlElement *pElem,Drawable drawable,int drawableLeft,int drawableTop,int drawableRight,int drawableBottom); +typedef struct HtmlBaseElement HtmlBaseElement; +typedef short Html_16; +struct HtmlBaseElement { + HtmlElement *pNext; /* Next input token in a list of them all */ + HtmlElement *pPrev; /* Previous token in a list of them all */ + HtmlStyle style; /* The rendering style for this token */ + Html_u8 type; /* The token type. */ + Html_u8 flags; /* The HTML_ flags below */ + Html_16 count; /* Various uses, depending on "type" */ +}; +typedef struct HtmlTextElement HtmlTextElement; +typedef int Html_32; +struct HtmlTextElement { + HtmlBaseElement base; /* All the base information */ + Html_32 y; /* y coordinate where text should be rendered */ + Html_16 x; /* x coordinate where text should be rendered */ + Html_16 w; /* width of this token in pixels */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_u8 spaceWidth; /* Width of one space in the current font */ + char zText[1]; /* Text for this element. Null terminated */ +}; +typedef struct HtmlSpaceElement HtmlSpaceElement; +struct HtmlSpaceElement { + HtmlBaseElement base; /* All the base information */ + Html_16 w; /* Width of a single space in current font */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ +}; +typedef struct HtmlMarkupElement HtmlMarkupElement; +struct HtmlMarkupElement { + HtmlBaseElement base; + char **argv; +}; +typedef struct HtmlCell HtmlCell; +struct HtmlCell { + HtmlMarkupElement markup; + Html_16 rowspan; /* Number of rows spanned by this cell */ + Html_16 colspan; /* Number of columns spanned by this cell */ + Html_16 x; /* X coordinate of left edge of border */ + Html_16 w; /* Width of the border */ + Html_32 y; /* Y coordinate of top of border indentation */ + Html_32 h; /* Height of the border */ + HtmlElement *pTable; /* Pointer back to the <table> */ + HtmlElement *pEnd; /* Element that ends this cell */ +}; +typedef struct HtmlTable HtmlTable; +typedef unsigned short Html_u16; +#define HTML_MAX_COLUMNS 40 +struct HtmlTable { + HtmlMarkupElement markup; + Html_u8 borderWidth; /* Width of the border */ + Html_u8 nCol; /* Number of columns */ + Html_u16 nRow; /* Number of rows */ + Html_32 y; /* top edge of table border */ + Html_32 h; /* height of the table border */ + Html_16 x; /* left edge of table border */ + Html_16 w; /* width of the table border */ + int minW[HTML_MAX_COLUMNS+1]; /* minimum width of each column */ + int maxW[HTML_MAX_COLUMNS+1]; /* maximum width of each column */ +}; +typedef struct HtmlRef HtmlRef; +struct HtmlRef { + HtmlMarkupElement markup; + HtmlElement *pOther; /* Pointer to some other Html element */ +}; +typedef struct HtmlLi HtmlLi; +struct HtmlLi { + HtmlMarkupElement markup; + Html_u8 type; /* What type of list is this? */ + Html_u8 ascent; /* height above the baseline */ + Html_u8 descent; /* depth below the baseline */ + Html_16 cnt; /* Value for this element (if inside <OL>) */ + Html_16 x; /* X coordinate of the bullet */ + Html_32 y; /* Y coordinate of the bullet */ +}; +typedef struct HtmlListStart HtmlListStart; +struct HtmlListStart { + HtmlMarkupElement markup; + Html_u8 type; /* One of the LI_TYPE_ defines above */ + Html_u8 compact; /* True if the COMPACT flag is present */ + Html_u16 cnt; /* Next value for <OL> */ + Html_u16 width; /* How much space to allow for indentation */ + HtmlElement *pPrev; /* Next higher level list, or NULL */ +}; +typedef struct HtmlImageMarkup HtmlImageMarkup; +typedef struct HtmlImage HtmlImage; +struct HtmlImageMarkup { + HtmlMarkupElement markup; + Html_u8 align; /* Alignment. See IMAGE_ALIGN_ defines below */ + Html_u8 textAscent; /* Ascent of text font in force at the <IMG> */ + Html_u8 textDescent; /* Descent of text font in force at the <IMG> */ + Html_u8 redrawNeeded; /* Need to redraw this image because the image + ** content changed. */ + Html_16 h; /* Actual height of the image */ + Html_16 w; /* Actual width of the image */ + Html_16 ascent; /* How far image extends above "y" */ + Html_16 descent; /* How far image extends below "y" */ + Html_16 x; /* X coordinate of left edge of the image */ + Html_32 y; /* Y coordinate of image baseline */ + char *zAlt; /* Alternative text */ + HtmlImage *pImage; /* Corresponding HtmlImage structure */ + HtmlElement *pNext; /* Next markup using the same HtmlImage structure */ +}; +typedef struct HtmlInput HtmlInput; +struct HtmlInput { + HtmlMarkupElement markup; + HtmlElement *pForm; /* The <FORM> to which this belongs */ + HtmlElement *pNext; /* Next element in a list of all input elements */ + Tk_Window tkwin; /* The window that implements this control */ + HtmlWidget *htmlPtr; /* The whole widget. Needed by geometry callbacks */ + HtmlElement *pEnd; /* End tag for <TEXTAREA>, etc. */ + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 padLeft; /* Extra padding on left side of the control */ + Html_u8 align; /* One of the IMAGE_ALIGN_xxx types */ + Html_u8 textAscent; /* Ascent for the current font */ + Html_u8 textDescent; /* descent for the current font */ + Html_u8 type; /* What type of input is this? */ + Html_u8 sized; /* True if this input has been sized already */ + Html_u16 cnt; /* Used to derive widget name. 0 if no widget */ +}; +typedef struct HtmlForm HtmlForm; +struct HtmlForm { + HtmlMarkupElement markup; + Html_u16 id; /* Unique number assigned to this form */ +}; +typedef struct HtmlHr HtmlHr; +struct HtmlHr { + HtmlMarkupElement markup; + Html_32 y; /* Baseline for this input element */ + Html_u16 x; /* Left edge */ + Html_u16 w, h; /* Width and height of this control */ + Html_u8 is3D; /* Is it drawn 3D? */ +}; +typedef struct HtmlAnchor HtmlAnchor; +struct HtmlAnchor { + HtmlMarkupElement markup; + Html_32 y; /* Top edge for this element */ +}; +typedef struct HtmlScript HtmlScript; +struct HtmlScript { + HtmlMarkupElement markup; + char *zScript; /* Complete text of this script */ + int nScript; /* Number of characters of text */ +}; +struct HtmlBlock { + HtmlBaseElement base; /* Superclass. Must be first */ + char *z; /* Space to hold text when n>0 */ + int top, bottom; /* Extremes of y coordinates */ + Html_u16 left, right; /* Left and right boundry of this object */ + Html_u16 n; /* Number of characters in z[] */ + HtmlBlock *pPrev, *pNext; /* Linked list of all Blocks */ +}; +union HtmlElement { + HtmlElement *pNext; + HtmlBaseElement base; + HtmlTextElement text; + HtmlSpaceElement space; + HtmlMarkupElement markup; + HtmlCell cell; + HtmlTable table; + HtmlRef ref; + HtmlLi li; + HtmlListStart list; + HtmlImageMarkup image; + HtmlInput input; + HtmlForm form; + HtmlHr hr; + HtmlAnchor anchor; + HtmlScript script; + HtmlBlock block; +}; +#define REDRAW_IMAGES 0x002000 +void HtmlBlockDraw(HtmlWidget *htmlPtr,HtmlBlock *pBlock,Drawable drawable,int drawableLeft,int drawableTop,int drawableWidth,int drawableHeight); +#define FONT_Any -1 +#define COLOR_Background 4 /* Default background color */ +GC HtmlGetGC(HtmlWidget *htmlPtr,int color,int font); +#define RESIZE_CLIPWIN 0x000400 +#define REDRAW_BORDER 0x000100 +#define GOT_FOCUS 0x000002 +#define REDRAW_FOCUS 0x000040 +#define REDRAW_PENDING 0x000001 +void HtmlUpdateInsert(HtmlWidget *htmlPtr); +void HtmlUpdateSelection(HtmlWidget *htmlPtr,int forceUpdate); +int HtmlMapControls(HtmlWidget *htmlPtr); +void HtmlFormBlocks(HtmlWidget *htmlPtr); +int HtmlUnlock(HtmlWidget *htmlPtr); +void HtmlLayout(HtmlWidget *htmlPtr); +void HtmlLock(HtmlWidget *htmlPtr); +#define REDRAW_TEXT 0x000080 +#define VSCROLL 0x000008 +#define HSCROLL 0x000004 +#define EXTEND_LAYOUT 0x000200 +#define RELAYOUT 0x000010 +struct HtmlImage { + HtmlWidget *htmlPtr; /* The owner of this image */ + Tk_Image image; /* The Tk image token */ + Html_32 w; /* Requested width of this image (0 if none) */ + Html_32 h; /* Requested height of this image (0 if none) */ + char *zUrl; /* The URL for this image. */ + char *zWidth, *zHeight; /* Width and height in the <img> markup. */ + HtmlImage *pNext; /* Next image on the list */ + HtmlElement *pList; /* List of all <IMG> markups that use this + ** same image */ +}; +#define STYLER_RUNNING 0x000800 +#define RESIZE_ELEMENTS 0x000020 +typedef struct HtmlMargin HtmlMargin; +void HtmlClearMarginStack(HtmlMargin **ppMargin); +#define N_CACHE_GC 16 +void HtmlComputeHorizontalPosition(HtmlWidget *htmlPtr,char *buf); +void HtmlComputeVerticalPosition(HtmlWidget *htmlPtr,char *buf); +int HtmlUsableHeight(HtmlWidget *htmlPtr); +#if defined(COVERAGE_TEST) +extern int HtmlTPArray[2000]; +# define TestPoint(X) {extern int HtmlTPArray[]; HtmlTPArray[X]++;} +#endif +#if !(defined(COVERAGE_TEST)) +# define TestPoint(X) +#endif +int HtmlUsableWidth(HtmlWidget *htmlPtr); +Tk_ConfigSpec *HtmlConfigSpec(void); +#define DEF_HTML_SCROLL_COMMAND "" +#define DEF_HTML_WIDTH "600" +#define DEF_HTML_VISITED "blue3" +#define DEF_HTML_UNVISITED "blue1" +#define DEF_HTML_TAKE_FOCUS "0" +#define DEF_HTML_SELECTION_COLOR "skyblue" +#define DEF_HTML_RELIEF "raised" +#define DEF_HTML_PADY "5" +#define DEF_HTML_PADX "5" +#define DEF_HTML_INSERT_ON_TIME "600" +#define DEF_HTML_INSERT_OFF_TIME "300" +#define DEF_HTML_HIGHLIGHT_WIDTH "0" +#define DEF_HTML_HIGHLIGHT DEF_BUTTON_HIGHLIGHT +#define DEF_HTML_HIGHLIGHT_BG DEF_BUTTON_HIGHLIGHT_BG +#define DEF_HTML_HEIGHT "400" +#define DEF_HTML_FG DEF_BUTTON_FG +#define DEF_HTML_EXPORT_SEL "yes" +#define DEF_HTML_CURSOR DEF_FRAME_CURSOR +#define DEF_HTML_BORDER_WIDTH "2" +#define DEF_HTML_BG_MONO DEF_FRAME_BG_MONO +#define DEF_HTML_BG_COLOR DEF_FRAME_BG_COLOR +typedef struct HtmlIndex HtmlIndex; +struct HtmlIndex { + HtmlElement *p; /* The token containing the character */ + int i; /* Index of the character */ +}; +typedef struct HtmlLayoutContext HtmlLayoutContext; +struct HtmlLayoutContext { + HtmlWidget *htmlPtr; /* The html widget undergoing layout */ + HtmlElement *pStart; /* Start of elements to layout */ + HtmlElement *pEnd; /* Stop when reaching this element */ + int headRoom; /* Extra space wanted above this line */ + int top; /* Absolute top of drawing area */ + int bottom; /* Bottom of previous line */ + int left, right; /* Left and right extremes of drawing area */ + int pageWidth; /* Width of the layout field, including + ** the margins */ + int maxX, maxY; /* Maximum X and Y values of paint */ + HtmlMargin *leftMargin; /* Stack of left margins */ + HtmlMargin *rightMargin; /* Stack of right margins */ +}; +struct HtmlWidget { + Tk_Window tkwin; /* The main window for this widget */ + Tk_Window clipwin; /* The clipping window in which all text is + ** rendered. */ + char *zClipwin; /* Name of the clipping window. */ + Display *display; /* The X11 Server that contains tkwin */ + Tcl_Interp *interp; /* The interpreter in which the widget lives */ + char *zCmdName; /* Name of the command */ + HtmlElement *pFirst; /* First HTML token on a list of them all */ + HtmlElement *pLast; /* Last HTML token on the list */ + int nToken; /* Number of HTML tokens on the list. + * Html_Block tokens don't count. */ + HtmlElement *lastSized; /* Last HTML element that has been sized */ + HtmlElement *nextPlaced; /* Next HTML element that needs to be + * positioned on canvas. */ + HtmlBlock *firstBlock; /* List of all HtmlBlock tokens */ + HtmlBlock *lastBlock; /* Last HtmlBlock in the list */ + HtmlElement *firstInput; /* First <INPUT> element */ + HtmlElement *lastInput; /* Last <INPUT> element */ + int nInput; /* The number of <INPUT> elements */ + int nForm; /* The number of <FORM> elements */ + int varId; /* Used to construct a unique name for a + ** global array used by <INPUT> elements */ + + /* + * Information about the selected region of text + */ + HtmlIndex selBegin; /* Start of the selection */ + HtmlIndex selEnd; /* End of the selection */ + HtmlBlock *pSelStartBlock; /* Block in which selection starts */ + Html_16 selStartIndex; /* Index in pSelStartBlock of first selected + * character */ + Html_16 selEndIndex; /* Index of last selecte char in pSelEndBlock */ + HtmlBlock *pSelEndBlock; /* Block in which selection ends */ + + /* + * Information about the insertion cursor + */ + int insOnTime; /* How long the cursor states one (millisec) */ + int insOffTime; /* How long it is off (milliseconds) */ + int insStatus; /* Is it visible? */ + Tcl_TimerToken insTimer; /* Timer used to flash the insertion cursor */ + HtmlIndex ins; /* The insertion cursor position */ + HtmlBlock *pInsBlock; /* The HtmlBlock containing the cursor */ + int insIndex; /* Index in pInsBlock of the cursor */ + + /* + * The following fields hold state information used by + * the tokenizer. + */ + char *zText; /* Complete text of the unparsed HTML */ + int nText; /* Number of characters in zText */ + int nAlloc; /* Space allocated for zText */ + int nComplete; /* How much of zText has actually been + * converted into tokens */ + int iCol; /* The column in which zText[nComplete] + * occurs. Used to resolve tabs in input */ + int iPlaintext; /* If not zero, this is the token type that + * caused us to go into plaintext mode. One + * of Html_PLAINTEXT, Html_LISTING or + * Html_XMP */ + HtmlScript *pScript; /* <SCRIPT> currently being parsed */ + char *zHandler[Html_TypeCount]; /* If not NULL, this is a TCL routine that + * is used to process tokens of the given + * type */ + /* + * These fields hold state information used by the HtmlAddStyle routine. + * We have to store this state information here since HtmlAddStyle + * operates incrementally. This information must be carried from + * one incremental execution to the next. + */ + HtmlStyleStack *styleStack; /* The style stack */ + int paraAlignment; /* Justification associated with <p> */ + int rowAlignment; /* Justification associated with <tr> */ + int anchorFlags; /* Style flags associated with <A>...</A> */ + int inDt; /* Style flags associated with <DT>...</DT> */ + int inTr; /* True if within <tr>..</tr> */ + int inTd; /* True if within <td>..</td> or <th>..</th> */ + HtmlElement *anchorStart; /* Most recent <a href=...> */ + HtmlElement *formStart; /* Most recent <form> */ + HtmlElement *formElemStart; /* Most recent <textarea> or <select> */ + HtmlElement *innerList; /* The inner most <OL> or <UL> */ + + /* + * These fields are used to hold the state of the layout engine. + * Because the layout is incremental, this state must be held for + * the life of the widget. + */ + HtmlLayoutContext layoutContext; + + /* + * Information used when displaying the widget: + */ + Tk_3DBorder border; /* Background color */ + int borderWidth; /* Width of the border. */ + int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ + int highlightWidth; /* Width in pixels of highlight to draw + * around widget when it has the focus. + * <= 0 means don't draw a highlight. */ + XColor *highlightBgColorPtr; /* Color for drawing traversal highlight + * area when highlight is off. */ + XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ + int inset; /* Total width of highlight and 3-D border */ + Tk_Font aFont[N_FONT]; /* Information about all screen fonts */ + char fontValid[(N_FONT+7)/8]; /* If bit N%8 of work N/8 of this field is 0 + * if aFont[N] needs to be reallocated before + * being used. */ + XColor *apColor[N_COLOR]; /* Information about all colors */ + int colorUsed; /* bit N is 1 if color N is in use. Only + ** applies to colors that aren't predefined */ + int iDark[N_COLOR]; /* Dark 3D shadow of color K is iDark[K] */ + int iLight[N_COLOR]; /* Light 3D shadow of color K is iLight[K] */ + XColor *fgColor; /* Color of normal text. apColor[0] */ + XColor *newLinkColor; /* Color of unvisitied links. apColor[1] */ + XColor *oldLinkColor; /* Color of visitied links. apColor[2] */ + XColor *selectionColor; /* Background color for selections */ + GcCache aGcCache[N_CACHE_GC]; /* A cache of GCs for general use */ + int lastGC; /* Index of recently used GC */ + HtmlImage *imageList; /* A list of all images */ + int width, height; /* User-requested size of the usable drawing + * area, in pixels. Borders and padding + * make the actual window a little larger */ + int realWidth, realHeight; /* The actual physical size of tkwin as + * reported in the most recent ConfigureNotify + * event. */ + int padx, pady; /* Separation between the edge of the window + * and rendered HTML. */ + int underlineLinks; /* TRUE if we should underline hyperlinks */ + + /* Information about the selection + */ + int exportSelection; /* True if the selection is automatically + * exported to the clipboard */ + + /* Callback commands. The HTML parser will invoke callbacks from time + ** to time to find out information it needs to complete formatting of + ** the document. The following fields define the callback commands. + */ + char *zIsVisited; /* Command to tell if a hyperlink has already + ** been visited */ + char *zGetImage; /* Command to get an image from a URL */ + char *zFrameCommand; /* Command for handling <frameset> markup */ + char *zAppletCommand; /* Command to process applets */ + char *zResolverCommand; /* Command to resolve URIs */ + char *zFormCommand; /* When user presses Submit */ + char *zHyperlinkCommand; /* Invoked when a hyperlink is clicked */ + char *zFontCommand; /* Invoked to find font names */ + char *zScriptCommand; /* Invoked for each <SCRIPT> markup */ + + /* + * Miscellaneous information: + */ + int tableRelief; /* 3d effects on <TABLE> */ + int ruleRelief; /* 3d effects on <HR> */ + char *zBase; /* The base URI */ + char *zBaseHref; /* zBase as modified by <BASE HREF=..> markup */ + Tk_Cursor cursor; /* Current cursor for window, or None. */ + char *takeFocus; /* Value of -takefocus option; not used in + * the C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + char *yScrollCmd; /* Command prefix for communicating with + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ + char *xScrollCmd; /* Command prefix for communicating with + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ + int xOffset, yOffset; /* Current scroll position. These form the + * coordinate in the virtual canvas that + * corresponds to (0,0) on the physical screen + * in window tkwin */ + int maxX, maxY; /* Maximum extent of any "paint" that appears + * on the virtual canvas. Used to compute + * scrollbar positions. */ + int dirtyLeft, dirtyTop; /* Top left corner of region to redraw. These + * are physical screen coordinates relative to + * clipwin, not tkwin. */ + int dirtyRight, dirtyBottom; /* Bottom right corner of region to redraw */ + int locked; /* Number of locks on this structure. Don't + ** delete until it reaches zero. */ + int flags; /* Various flags; see below for + * definitions. */ +}; +#define DEF_HTML_CALLBACK "" +extern int HtmlTraceMask; +struct HtmlMargin { + int indent; /* Size of the current margin */ + int bottom; /* Y value at which this margin expires */ + int tag; /* Markup that will cancel this margin */ + HtmlMargin *pNext; /* Previous margin */ +}; diff --git a/tkhtml1/src/tokenlist.txt b/tkhtml1/src/tokenlist.txt new file mode 100644 index 0000000..6b0b638 --- /dev/null +++ b/tkhtml1/src/tokenlist.txt @@ -0,0 +1,116 @@ +# +# This file contains raw data used to build the "htmltokens.c" file. +# Each line contains 2 or 3 elements. The first word on each line is +# the name of some HTML markup. The second word is the amount of +# space to allocate for the corresponding element. "0" appears if +# no extra space (beyond HtmlMarkup) is required. If there is a +# corresponding end-tag, then the third column specifies the size of +# the end markup. +# $Revision$ +# +# Copyright (C) 1997-2000 D. Richard Hipp +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# +# Author contact information: +# drh@acm.org +# http://www.hwaci.com/drh/ + + +# Order is not important. Comments begin with #. Spacing is ignored. + +a HtmlAnchor HtmlRef +address 0 0 +applet HtmlInput 0 +area 0 +b 0 0 +base 0 +basefont 0 0 +bgsound 0 +big 0 0 +blockquote 0 0 +body 0 0 +br 0 +caption 0 0 +center 0 0 +cite 0 0 +code 0 0 +comment 0 0 +dd HtmlRef 0 +dfn 0 0 +dir HtmlListStart HtmlRef +div 0 0 +dl HtmlListStart HtmlRef +dt HtmlRef 0 +em 0 0 +embed HtmlInput +font 0 0 +form HtmlForm HtmlRef +frame 0 0 +frameset 0 0 +h1 0 0 +h2 0 0 +h3 0 0 +h4 0 0 +h5 0 0 +h6 0 0 +hr HtmlHr +html 0 0 +i 0 0 +iframe 0 +img HtmlImageMarkup +input HtmlInput +isindex 0 +kbd 0 0 +li HtmlLi 0 +link 0 +listing 0 0 +map 0 0 +marquee 0 0 +menu HtmlListStart HtmlRef +meta 0 +nextid 0 +nobr 0 0 +noframe 0 0 +noscript 0 0 +ol HtmlListStart HtmlRef +option 0 0 +p 0 0 +param 0 0 +plaintext 0 +pre 0 0 +s 0 0 +samp 0 0 +script HtmlScript +select HtmlInput HtmlRef +small 0 0 +strike 0 0 +strong 0 0 +style HtmlScript +sub 0 0 +sup 0 0 +table HtmlTable HtmlRef +td HtmlCell HtmlRef +textarea HtmlInput HtmlRef +th HtmlCell HtmlRef +title 0 0 +tr HtmlRef HtmlRef +tt 0 0 +u 0 0 +ul HtmlListStart HtmlRef +var 0 0 +wbr 0 +xmp 0 0 diff --git a/tkhtml1/tclconfig/ChangeLog b/tkhtml1/tclconfig/ChangeLog new file mode 100644 index 0000000..ffda2bb --- /dev/null +++ b/tkhtml1/tclconfig/ChangeLog @@ -0,0 +1,980 @@ +2013-07-04 Jan Nijtmans <nijtmans@users.sf.net> + + * unix/tcl.m4: Bug [3324676]: AC_PROG_INSTALL incompat, + Bug [3606445]: Unneeded -DHAVE_NO_SEH=1 when not building on Windows + +2013-07-02 Jan Nijtmans <nijtmans@users.sf.net> + + * unix/tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4 + (thanks to Brian Griffin) + +2013-06-20 Jan Nijtmans <nijtmans@users.sf.net> + + * unix/tcl.m4: Use X11/Xlib.h for checking where X11 can be found + in stead of X11/XIntrinsic.h. Suggested by Pietro Cerutti. + +2013-06-04 Jan Nijtmans <nijtmans@users.sf.net> + + * unix/tcl.m4: Eliminate NO_VIZ macro as current + zlib uses HAVE_HIDDEN in stead. One more last-moment + fix for FreeBSD by Pietro Cerutti + +2013-05-19 Jan Nijtmans <nijtmans@users.sf.net> + + * unix/tcl.m4: Fix for FreeBSD, and remove support for old + FreeBSD versions. Patch by Pietro Cerutti + +2013-03-12 Jan Nijtmans <nijtmans@users.sf.net> + + * unix/tcl.m4: Patch by Andrew Shadura, providing better support for + * three architectures they have in Debian. + +2012-08-07 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: Added "-DNDEBUG" to CFLAGS_DEFAULT + when building with --disable-symbols. + +2012-08-07 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: [Bug 3555058]: Checkin [30736d63f0] broke + CFLAGS_DEFAULT, LDFLAGS_DEFAULT + +2012-08-07 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: [Bug 3511806]: Checkin [30736d63f0] broke CFLAGS + +2012-08-07 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [Bug 3511806]: Checkin [30736d63f0] broke CFLAGS + +2012-07-25 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: My previous commit (2012-04-03) broke the ActiveTcl + build for AMD64, because of the quotes in "C:/<path>/AMD64/cl.exe". + It turns out that the AC_TRY_COMPILE macro cannot handle that. + +2012-07-22 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: Tidy: consistency, spelling, phrasing, whitespace. + No functional change. + +2012-04-03 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [Bug 3511806] Compiler checks too early + This change allows to build the cygwin and mingw32 ports of + Tcl/Tk extensions to build out-of-the-box using a native or + cross-compiler, e.g. on Cygwin, Linux or Darwin. + +2011-04-02 Jan Nijtmans <nijtmans@users.sf.net> + + * install-sh: Fix issue with library stripping in install-sh + (backported from kevin_walzer's patch from Tcl 8.6 trunk) + +2011-04-05 Andreas Kupries <andreask@activestate.com> + + * tcl.m4: Applied patch by Jeff Lawson. Nicer error message when + tclConfig.sh was not found. + +2010-12-15 Stuart Cassoff <stwo@users.sourceforge.net> + + * install-sh: Upgrade to newer install-sh and use it. + * tcl.m4: + +2010-12-14 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: Better building on OpenBSD. + +2010-12-14 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: when using gcc, don't try to determine Win64 SDK + +2010-12-12 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Determine correctly a cross-compiler-windres + +2010-11-23 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: add some cross-compile support, borrowed from Tcl 8.6 + +2010-09-16 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct HP-UX LDFLAGS (only used when building big shell) + +2010-09-14 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: add extra if check for .manifest file generation + Add notice about package name and version being built. + +2010-09-09 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [FREQ #3058486] TEA_LOAD_CONFIG doesn't set all BUILD_ vars + Slightly related: defining BUILD_$1 on all platforms - not only win - + allows the -fvisibility feature to be used in extensions as well, at + least if you compile against tcl >= 8.5. + +2010-08-26 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: ensure safe quoting for autoheader usage + +2010-08-19 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: add TEA_ADD_CLEANFILES macro to make adding cleanfiles + easier, and add *.exp to CLEANFILES Windows default. + (TEA_MAKE_LIB): Enhanced to check for MSVC that requires manifests + and auto-embed it into proj DLL via MAKE_SHARED_LIB. Also define + VC_MANIFEST_EMBED_DLL and VC_MANIFEST_EMBED_EXE that do the same + magic in case it is needed for extended TEA projects. + +2010-08-16 Jeff Hobbs <jeffh@ActiveState.com> + + *** Bump to TEA_VERSION 3.9 *** + If upgrading from TEA_VERSION 3.8, copy over tcl.m4, change + TEA_INIT to use 3.9 and reconfigure (ac-2.59+). + BUILD_${PACKAGE_NAME} will be auto-defined on Windows for + correct setting of TCL_STORAGE_CLASS. + TEA_LOAD_CONFIG users should remove the SHLIB_LD_LIBS setting done + in configure.in (LIBS will be automagically populated by + TEA_LOAD_CONFIG). + TEA_EXPORT_CONFIG has been added for ${pkg}Config.sh creators + SHLIB_LD_FLAGS was deprecated a while ago, remove it if it is + still in your Makefile.in. + + * tcl.m4: add /usr/lib64 to set of auto-search dirs. [Bug 1230554] + Auto-define BUILD_$PACKAGE_NAME so users don't need to. This + needs to correspond with $pkg.h define magic for TCL_STORAGE_CLASS. + Auto-define CLEANFILES. Users can expand it. + (SHLIB_LD_LIBS): define to '${LIBS}' default and change it only if + necessary. Platforms not using this may simply not work or have + very funky linkers. + (TEA_LOAD_CONFIG): When loading config for another extension, + auto-add stub libraries found with TEA_ADD_LIBS. Eases + configure.in for modules like itk and img::*. + (TEA_EXPORT_CONFIG): Add standardized function for exporting a + ${pkg}Config.sh. See use by img::* and itcl. + +2010-08-12 Jeff Hobbs <jeffh@ActiveState.com> + + *** Bump to TEA_VERSION 3.8 *** + If upgrading from TEA_VERSION 3.7, copy over tcl.m4, change + TEA_INIT to use 3.8 and reconfigure (ac-2.59+). + No other changes should be necessary. + + * tcl.m4: remove more vestigial bits from removed platforms. + Add back SCO_SV-3.2*. + Remove use of DL_LIBS and DL_OBJS and related baggage - these are + only needed by the core to support 'load'. + Allow for macosx in TEA_ADD_SOURCES. + Correct check for found_xincludes=no in TEA_PATH_UNIX_X. + +2010-08-11 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: remove the following old platform configurations: + UNIX_SV*|UnixWare-5*, SunOS-4.*, SINIX*5.4*, SCO_SV-3.2*<readded>, + OSF1-1.*, NEXTSTEP-*, NetBSD-1.*|FreeBSD-[[1-2]].*, MP-RAS-*, + IRIX-5.*, HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*, dgux*, + BSD/OS-2.1*|BSD/OS-3* + (AIX): drop AIX-pre4 support and use of ldAix, use -bexpall/-brtl + +2010-07-05 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [Patch #1055668] removal of exported internals from + tclInt.h (EXTERN macro) + +2010-04-14 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4 - Backport a lot of quoting fixes from tcl8.6/unix/tcl.m4 + - Fix determination of CYGPATH for CYGWIN + With those fixes, itcl and tdbc compile fine with CYGWIN + +2010-04-06 Jan Nijtmans <nijtmans@users.sf.net> + + * install-sh [Bug 2982540] configure and install* script files + should always have LF + +2010-02-19 Stuart Cassoff <stwo@users.sourceforge.net> + + * tcl.m4: Correct compiler/linker flags for threaded builds on + OpenBSD. + +2010-01-19 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: Detect CYGWIN variant: win32 or unix + +2010-01-03 Donal K. Fellows <dkf@users.sf.net> + + * unix/tcl.m4 (TEA_CONFIG_CFLAGS): [Tcl Bug 1636685]: Use the + configuration for modern FreeBSD suggested by the FreeBSD porter. + +2009-10-22 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [Tcl Patch #2883533] tcl.m4 support for Haiku OS + +2009-04-27 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_CONFIG_CFLAGS): harden the check to add _r to CC on + AIX with threads. + +2009-04-10 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): check for 64-bit TkAqua. + +2009-03-26 Jan Nijtmans <nijtmans@users.sf.net> + + * tclconfig/tcl.m4: Adapt LDFLAGS and LD_SEARCH_FLAGS + together with SHLIB_LD definition to unbreak building on HPUX. + +2009-03-20 Andreas Kupries <andreask@activestate.com> + + * tclconfig/tcl.m4: Changed SHLIB_LD definition to unbreak + building on HPUX. + +2009-03-16 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4(TEA_PUBLIC_TK_HEADERS): Look at ${TK_INCLUDE_SPEC} + (found in tkConfig.sh) when trying to guess where tk.h might be + [Patch 1960628]. + +2009-03-11 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4: Allow ${SHLIB_SUFFIX} to be overridden at + configure-time [Patch 1960628]. Also fix some comment typos, + and an uninitialized variable bug-waiting-to-happen. + +2008-12-21 Jan Nijtmans <nijtmans@users.sf.net> + + * tcl.m4: [Bug 2073255] Tcl_GetString(NULL) doesn't crash on HP-UX + (this bug report was for Tcl, but holds for TEA as well.) + +2008-12-20 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: sync with tdbc tcl.m4 changes + (SunOS-5.11): Sun cc SHLIB_LD: use LDFLAGS_DEFAULT instead of LDFLAGS + +2008-12-02 Jeff Hobbs <jeffh@ActiveState.com> + + *** Bump to TEA_VERSION 3.7 *** + + * tcl.m4: in private header check, check for <plat>Port.h instead + of Int.h to ensure all private headers are available. + +2008-11-04 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): sync TEA_PRIVATE_TK_HEADERS handling of + Tk.framework PrivateHeaders with TEA_PRIVATE_TCL_HEADERS. + +2008-11-04 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_PATH_TCLCONFIG, TEA_PATH_TKCONFIG): exit with error + when tclConfig.sh cannot be found. [Bug #1997760] + (TEA_PRIVATE_TCL_HEADERS, TEA_PRIVATE_TK_HEADERS): allow for + finding the headers installed in the public areas, e.g. a result of + make install-private-headers. [Bug #1631922] + +2008-08-12 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): link shlib with current and compatiblity version + flags; look for libX11.dylib when searching for X11 libraries. + +2008-06-12 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (SunOS-5.11): fix 64bit amd64 support with gcc & Sun cc. + +2008-03-27 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (SunOS-5.1x): fix 64bit support for Sun cc. [Bug 1921166] + +2008-02-01 Donal K. Fellows <donal.k.fellows@man.ac.uk> + + * tcl.m4 (TEA_CONFIG_CFLAGS): Updated to work at least in part with + more modern VC versions. Currently just made the linker flags more + flexible; more work may be needed. + +2007-10-26 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): add support for 64-bit X11. + +2007-10-23 Jeff Hobbs <jeffh@ActiveState.com> + + *** Tagged tea-3-branch to start TEA 4 development on HEAD *** + +2007-09-17 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4: use '${CC} -shared' instead of 'ld -Bshareable' + to build shared libraries on current NetBSDs [Bug 1749251]. + +2007-09-15 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: replace all direct references to compiler by ${CC} to + enable CC overriding at configure & make time. + (SunOS-5.1x): replace direct use of '/usr/ccs/bin/ld' in SHLIB_LD by + 'cc' compiler driver. + +2007-08-08 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: check Ttk dir for Tk private headers (8.5). + Add some comments to other bits. + +2007-06-25 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_PROG_TCLSH, TEA_PROG_WISH): move where / is added. + +2007-06-13 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: fix --with-tkinclude alignment. [Bug 1506111] + +2007-06-06 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): fix 64bit arch removal in fat 32&64bit builds. + +2007-05-18 Donal K. Fellows <donal.k.fellows@man.ac.uk> + + * tcl.m4: Added quoting so that paths with spaces cause fewer + problems. + +2007-03-07 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in -mmacosx-version-min check. + +2007-02-15 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct private header check to search in generic subdir + +2007-02-09 Jeff Hobbs <jeffh@ActiveState.com> + + *** Bump to TEA_VERSION 3.6 *** + + * tcl.m4: correct -d to -f + (TEA_CONFIG_CFLAGS): SHLIB_SUFFIX is .so on HP ia64 [Bug 1615058] + +2007-02-08 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_PRIVATE_TCL_HEADERS, TEA_PRIVATE_TK_HEADERS): check + that the dirs actually have private headers. [Bug 1631922] + +2007-02-04 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: add caching to -pipe check. + +2007-01-25 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: integrate CPPFLAGS into CFLAGS as late as possible and + move (rather than duplicate) -isysroot flags from CFLAGS to CPPFLAGS to + avoid errors about multiple -isysroot flags from some older gcc builds. + +2006-01-19 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: ensure CPPFLAGS env var is used when set. [Bug 1586861] + (Darwin): add -isysroot and -mmacosx-version-min flags to CPPFLAGS when + present in CFLAGS to avoid discrepancies between what headers configure + sees during preprocessing tests and compiling tests. + +2006-12-19 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): --enable-64bit: verify linking with 64bit -arch flag + succeeds before enabling 64bit build. + +2006-12-16 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Linux): fix previous change to use makefile variable + LDFLAGS_DEFAULT instead of LDFLAGS in SHLIB_LD, to ensure linker + flags in sampleextension Makefile are picked up. + +2006-11-26 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Linux): --enable-64bit support. [Patch 1597389], [Bug 1230558] + +2006-08-18 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): add support for --enable-64bit on x86_64, for + universal builds including x86_64 and for use of -mmacosx-version-min + instead of MACOSX_DEPLOYMENT_TARGET. For Tk extensions, remove 64-bit + arch flags from CFLAGS like in the Tk configure, as neither TkAqua nor + TkX11 can be built for 64-bit at present. + +2006-03-28 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: []-quote AC_DEFUN functions. + (TEA_PATH_TKCONFIG): Fixed Windows-specific check for tkConfig.sh. + (TEA_MAKE_LIB): Prepend 'lib' for Windows-gcc configs. + +2006-03-07 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4: Set SHLIB_LD_FLAGS='${LIBS}' on NetBSD, + as per the other *BSD variants [Bug 1334613]. + +2006-01-25 Jeff Hobbs <jeffh@ActiveState.com> + + *** Bump to TEA version 3.5 *** + + * tcl.m4: keep LD_SEARCH_FLAGS and CC_SEARCH_FLAGS synchronous + with core tcl.m4 meaning. + +2006-01-24 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): use makefile variable LDFLAGS_DEFAULT instead of + LDFLAGS in SHLIB_LD, to ensure linker flags in sampleextension Makefile + are picked up. [Bug 1403343] + +2006-01-23 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: add C:/Tcl/lib and C:/Progra~1/Tcl/lib dirs to check for + *Config.sh on Windows. [Bug 1407544] + +2006-01-23 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): for Tk extensions, remove -arch ppc64 from CFLAGS + like in the Tk configure, as neither TkAqua nor TkX11 can be built for + 64bit at present (no 64bit GUI libraries). + +2006-01-22 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: restore system=windows on Windows. + Remove error if 'ar' isn't found (it may not be on Windows). + Do not add -lxnet or define _XOPEN_SOURCE on HP-UX by default. + Ensure the C|LDFLAGS_DEFAULT gets the fully sub'd value at + configure time. + +2006-01-10 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: add caching, use AC_CACHE_CHECK instead of AC_CACHE_VAL + where possible, consistent message quoting, sync relevant + tcl/unix/tcl.m4 HEAD changes and gratuitous formatting differences + (notably sunc removal of support for for ancient BSD's, IRIX 4, + RISCos and Ultrix by kennykb), Darwin improvements to + TEA_LOAD_*CONFIG to make linking work against Tcl/Tk frameworks + installed in arbitrary location, change TEA_PROG_* search order + (look in *_BIN_DIR parents before *_PREFIX). + +2006-01-05 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: add dkf's system config refactor + +2006-01-04 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: remove extraneous ' that causes bash 3.1 to choke + +2005-12-19 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4 (TEA_PATH_TCLCONFIG &c): Look for tclConfig.sh &c + in ${libdir}, where they are installed by default [Patch #1377407]. + +2005-12-05 Don Porter <dgp@users.sf.net> + + * tcl.m4 (TEA_PUBLIC_*_HEADERS): Better support for finding + header files for uninstalled Tcl and Tk. + +2005-12-02 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correctly bump TEA_VERSION var to 3.4 + +2005-12-01 Daniel Steffen <das@users.sourceforge.net> + + * unix/tcl.m4 (Darwin): fixed error when MACOSX_DEPLOYMENT_TARGET unset + +2005-11-29 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: *** Bump to TEA version 3.4 *** + Add Windows x64 build support. + Remove TEA_PATH_NOSPACE and handle the problem with ""s where + necessary - the macro relied on TCLSH_PROG which didn't work for + cross-compiles. + +2005-11-27 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): add 64bit support, add CFLAGS to SHLIB_LD to + support passing -isysroot in env(CFLAGS) to configure (flag can't + be present twice, so can't be in both CFLAGS and LDFLAGS during + configure), don't use -prebind when deploying on 10.4. + (TEA_ENABLE_LANGINFO, TEA_TIME_HANDLER): add/fix caching. + +2005-10-30 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: fixed two tests for TEA_WINDOWINGSYSTEM = "aqua" that + should have been for `uname -s` = "Darwin" instead; added some + missing quoting. + (TEA_PROG_TCLSH, TEA_PROG_WISH): fix incorrect assumption that + install location of tclConfig.sh/tkConfig.sh allows to determine + the tclsh/wish install dir via ../bin. Indeed tcl/tk can be + configured with arbitrary --libdir and --bindir (independent of + prefix) and such a configuration is in fact standard with Darwin + framework builds. At least now also check ${TCL_PREFIX}/bin + resp. ${TK_PREFIX}/bin for presence of tclsh resp. wish (if tcl/tk + have been configured with arbitrary --bindir, this will still not + find them, for a general solution *Config.sh would need to contain + the values of bindir/libdir/includedir passed to configure). + +2005-10-07 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: Fix Solaris 5.10 check and Solaris AMD64 64-bit builds. + +2005-10-04 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_PRIVATE_TCL_HEADERS): add / to finish sed macro + (TEA_ENABLE_THREADS): don't check for pthread_attr_setstacksize func + +2005-09-13 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: *** Update to TEA version 3.3 *** + define TEA_WINDOWINGSYSTEM in TEA_LOAD_TKCONFIG. + Make --enable-threads the default (users can --disable-threads). + Improve AIX ${CC}_r fix to better check existing ${CC} value. + Do the appropriate evals to not require the *TOP_DIR_NATIVE vars + be set for extensions that use private headers. + Make aqua check for Xlib compat headers the same as win32. + +2005-07-26 Mo DeJong <mdejong@users.sourceforge.net> + + * tcl.m4 (TEA_PROG_TCLSH, TEA_BUILD_TCLSH, + TEA_PROG_WISH, TEA_BUILD_WISH): Remove + TEA_BUILD_TCLSH and TEA_BUILD_WISH because + of complaints that it broke the build when + only an installed version of Tcl was available + at extension build time. The TEA_PROG_TCLSH and + TEA_PROG_WISH macros will no longer search the + path at all. The build tclsh or installed + tclsh shell will now be found by TEA_PROG_TCLSH. + +2005-07-24 Mo DeJong <mdejong@users.sourceforge.net> + + * tcl.m4 (TEA_PROG_TCLSH, TEA_BUILD_TCLSH, + TEA_PROG_WISH, TEA_BUILD_WISH): + Split confused search for tclsh on PATH and + build and install locations into two macros. + TEA_PROG_TCLSH and TEA_PROG_WISH search the + system PATH for an installed tclsh or wish. + The TEA_BUILD_TCLSH and TEA_BUILD_WISH + macros determine the name of tclsh or + wish in the Tcl or Tk build directory even + if tclsh or wish has not yet been built. + [Tcl bug 1160114] + [Tcl patch 1244153] + +2005-06-23 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (TEA_PRIVATE_TK_HEADERS): add ${TK_SRC_DIR}/macosx to + TK_INCLUDES when building against TkAqua. + + * tcl.m4 (TEA_PATH_X): fixed missing comma in AC_DEFINE + + * tcl.m4: changes to better support framework builds of Tcl and Tk out + of the box: search framework install locations for *Config.sh, and if in + presence of a framework build, use the framework's Headers and + PrivateHeaders directories for public and private includes. [FR 947735] + +2005-06-18 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): add -headerpad_max_install_names to LDFLAGS to + ensure we can always relocate binaries with install_name_tool. + +2005-06-04 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (TEA_PATH_X): for TEA_WINDOWINGSYSTEM == aqua, check if xlib + compat headers are available in tkheaders location, otherwise add xlib + sourcedir to TK_XINCLUDES. + +2005-04-25 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4: added AC_DEFINE* descriptions (from core tcl.m4) to allow + use with autoheader. + (Darwin): added configure checks for recently added linker flags + -single_module and -search_paths_first to allow building with older + tools (and on Mac OS X 10.1), use -single_module in SHLIB_LD. + (TEA_MISSING_POSIX_HEADERS): added caching of dirent.h check. + (TEA_BUGGY_STRTOD): added caching (sync with core tcl.m4). + +2005-03-24 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_TCL_64BIT_FLAGS): use Tcl header defaults for wide + int type only on Windows when __int64 is detected as valid. + +2005-03-24 Don Porter <dgp@users.sf.net> + + * README.txt: Update reference to "SC_* macros" to "TEA_* macros". + * tcl.m4: Incorporated recent improvements in SC_PATH_TCLCONFIG + and SC_PATH_TKCONFIG into TEA_PATH_TCLCONFIG and TEA_PATH_TKCONFIG. + Corrected search path in TEA_PATH_CONFIG and added + AC_SUBST($1_BIN_DIR) to TEA_LOAD_CONFIG so that packages that load + the configuration of another package can know where they loaded + it from. + +2005-03-18 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_CONFIG_CFLAGS): correct 2005-03-17 change to have + variant LD_SEARCH_FLAGS for gcc and cc builds. + + * tcl.m4 (TEA_PROG_TCLSH, TEA_PROG_WISH): correct x-compile check. + +2005-03-17 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: Correct gcc build and HP-UX-11. + +2005-02-08 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_ADD_LIBS): don't touch lib args starting with -. + (TEA_CONFIG_CFLAGS): only define _DLL for CE in shared build. + (TEA_MAKE_LIB): set RANLIB* to : on Windows (it's not needed). + +2005-02-01 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: redo of 2005-01-27 changes to correctly handle paths + with spaces. Win/CE and Win/64 builds now require a prebuilt + tclsh to handle conversion to short pathnames. This is done in + the new TEA_PATH_NOSPACE macro. For Win/CE|64, make CC just the + compiler and move the necessary includes to CFLAGS. + (TEA_CONFIG_CFLAGS): Add Solaris 64-bit gcc build support. + (TEA_PROG_TCLSH, TEA_PROG_WISH): Allow TCLSH_PROG and WISH_PROG to + be set in the env and prevent resetting. + (TEA_ADD_LIBS): On Windows using GCC (mingw), convert foo.lib + args to -lfoo, for use with mingw. + *** POTENTIAL INCOMPATABILITY *** + (TEA_CONFIG_CFLAGS): Fix AIX gcc builds to work out-of-box. + Bumped TEA to 3.2. + +2005-01-27 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: remove cygpath calls to support msys. + Update base CE build assumption to "420,ARMV4,ARM,Pocket PC 2003". + Make STLIB_LD use $LINKBIN -lib. + +2005-01-25 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (Darwin): fixed bug with static build linking to dynamic + library in /usr/lib etc instead of linking to static library earlier + in search path. [Tcl Bug 956908] + Removed obsolete references to Rhapsody. + +2004-12-29 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: Updates for VC7 compatibility, fixing CFLAGS and LDFLAGS + options, using better default -O levels. [Bug 1092952, 1091967] + +2004-12-29 Joe English <jenglish@users.sourceforge.net> + + * tcl.m4: Do not use ${DBGX} suffix when building + shared libraries [patch #1081595, TIP #34] + +2004-09-07 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_CONFIG_CFLAGS): support eVC4 Win/CE builds + +2004-08-10 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_INIT, TEA_PREFIX): update handling of exec_prefix to + work around subdir configures since autoconf only propagates the + prefix (not exec_prefix). + +2004-07-23 Daniel Steffen <das@users.sourceforge.net> + + * tcl.m4 (TEA_CONFIG_CFLAGS): Darwin section: brought inline with + Tcl 8.5 HEAD config, removed core specific & obsolete settings. + +2004-07-22 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_PATH_X): check in TK_DEFS for MAC_OSX_TK to see if + we are compiling on Aqua. Add TEA_WINDOWINGSYSTEM var that + reflects 'tk windowingsystem' value. + +2004-07-16 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_ENABLE_THREADS): force a threaded build when + building against a threaded core. + (CFLAGS_WARNING): Remove -Wconversion for gcc builds + (TEA_CONFIG_CFLAGS): Reorder configure.in for better 64-bit build + configuration, replacing EXTRA_CFLAGS with CFLAGS. [Bug #874058] + Update to latest Tcl 8.5 head config settings. + Call this TEA version 3.1. + +2004-04-29 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_TCL_64BIT_FLAGS): replace AC_TRY_RUN test with + AC_TRY_COMPILE for the long vs. long long check. (kenny) + +2004-04-26 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_TCL_64BIT_FLAGS): update against core tcl.m4 to + define TCL_WIDE_INT_IS_LONG if 'using long'. + +2004-03-19 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct Windows builds getting LDFLAGS info in MAKE_LIB + +2004-02-11 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct TCL_INCLUDES for private headers on Windows - it + doesn't need the eval. + +2004-02-10 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: don't require TK_INCLUDES and TCL_INCLUDES to have the + DIR_NATIVE vars defined when using private headers on unix. + Allow $... to TEA_ADD_SOURCES for constructs like + TEA_ADD_SOURCES([\$(WIN_OBJECTS)]), that allow the developer to + place more in the Makefile.in. + tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and + CHECK on limits.h + +2003-12-10 Jeff Hobbs <jeffh@ActiveState.com> + + * Makefile.in: added TEA_ADD_LIBS, TEA_ADD_INCLUDES and + * configure: TEA_ADD_CFLAGS to configurable parameters with + * configure.in: PKG_* equivs in the Makefile. This allows the + * tclconfig/tcl.m4: user to worry less about actual magic VAR names. + Corrected Makefile.in to note that TEA_ADD_TCL_SOURCES requires + exact file names. + +2003-12-09 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: updated OpenBSD support based on [Patch #775246] (cassoff) + +2003-12-05 Jeff Hobbs <jeffh@ActiveState.com> + + * configure: + * configure.in: + * Makefile.in (VPATH): readd $(srcdir) to front of VPATH as the + first part of VPATH can get chopped off. + Change .c.$(OBJEXT) rule to .c.@OBJEXT@ to support more makes. + * tclconfig/tcl.m4: add TEA_ADD_STUB_SOURCES to support libstub + generation and TEA_ADD_TCL_SOURCES to replace RUNTIME_SOURCES as + the way the user specifies library files. + +2003-12-03 Jeff Hobbs <jeffh@ActiveState.com> + + * configure: Update of TEA spec to (hopefully) simplify + * configure.in: some aspects of TEA by making use of more + * Makefile.in: AC 2.5x features. Use PACKAGE_NAME (instead + * generic/tclsample.c: of PACKAGE) and PACKAGE_VERSION (instead of + * tclconfig/tcl.m4: VERSION) arguments to AC_INIT as the TEA + package name and version. + Provide a version argument to TEA_INIT - starting with 3.0. + Drop all use of interior shell substs that older makefiles didn't + like. Use PKG_* naming convention instead. + Move specification of source files and public headers into + configure.in with TEA_ADD_SOURCES and TEA_ADD_HEADERS. These will + be munged during ./configure into the right obj file names (no + $(SOURCES:.c=.obj) needed). + There is almost nothing that should be touched in Makefile.in now + for the developer. May want to add a TEA_ADD_TCL_SOURCES for the + RUNTIME_SOURCES that remains. + Use SHLID_LD_FLAGS (instead of SHLID_LDFLAGS) as Tcl does. + Only specify the user requested LDFLAGS/CFLAGS in the Makefile, + don't mention the _OPTIMIZE/_DEBUG variants. + +2003-10-15 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: create a TEA_SETUP_COMPILER_CC the precedes the + TEA_SETUP_COMPILER macro. They are split so the check for CC + occurs before any use of CC. Also add AC_PROG_CPP to the compiler + checks. + +2003-10-06 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: Updated for autoconf 2.5x prereq. + Where TCL_WIDE_INT_TYPE would be __int64, defer to the code checks + in tcl.h, which also handles TCL_LL_MODIFIER* properly. + +2003-04-22 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct default setting of ARCH for WinCE builds. + Correct \ escaping for CE sed macros. + +2003-04-10 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: replace $(syscal) construct with older `syscall` for + systems where sh != bash. + +2003-04-09 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_WITH_CELIB): add --enable-wince and --with-celib + options for Windows/CE compilation support. Requires the + Microsoft eMbedded SDK and Keuchel's celib emulation layer. + +2003-02-18 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_ENABLE_THREADS): Make sure -lpthread gets passed on + the link line when checking for the pthread_attr_setstacksize + symbol. (dejong) + + * tcl.m4 (TEA_SETUP_COMPILER): added default calls to + TEA_TCL_EARLY_FLAGS, TEA_TCL_64BIT_FLAGS, + TEA_MISSING_POSIX_HEADERS and TEA_BUGGY_STRTOD. + +2003-02-14 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: correct HP-UX ia64 --enable-64bit build flags + +2003-01-29 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: check $prefix/lib as well as $exec_prefix/lib when + looking for tcl|tkConfig.sh, as this check is done before we would + set exec_prefix when the user does not define it. + +2003-01-21 Mo DeJong <mdejong@users.sourceforge.net> + + * tcl.m4 (TEA_CONFIG_CFLAGS): Fix build support + for mingw, the previous implementation would + use VC++ when compiling with mingw gcc. Don't + pass -fPIC since gcc always compiles pic code + under win32. Change some hard coded cases + of gcc to ${CC}. + +2002-10-15 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: move the CFLAGS definition from TEA_ENABLE_SHARED to + TEA_MAKE_LIB because setting too early confuses other AC_* macros. + Correct the HP-11 SHLIB_LD_LIBS setting. + + * tcl.m4: add the CFLAGS definition into TEA_ENABLE_SHARED and + make it pick up the env CFLAGS at configure time. + +2002-10-09 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: add --enable-symbols=mem option to enable TCL_MEM_DEBUG. + Improved AIX 64-bit build support, allow it on AIX-4 as well. + Enable 64-bit HP-11 compilation with gcc. + Enable 64-bit IRIX64-6 cc build support. + Correct FreeBSD thread library linkage. + Add OSF1 static build support. + Improve SunOS-5 shared build SHLIB_LD macro. + +2002-07-20 Zoran Vasiljevic <zoran@archiware.com> + + * tcl.m4: Added MINGW32 to list of systems checked for Windows build. + Also, fixes some indentation issues with "--with-XXX" options. + +2002-04-23 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_ENABLE_THREADS): added USE_THREAD_ALLOC define to + use new threaded allocatory by default on Unix for Tcl 8.4. + (TEA_CONFIG_CFLAGS): corrected LD_SEARCH_FLAGS for FreeBSD-3+. + +2002-04-22 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4 (TEA_SETUP_COMPILER): removed call to AC_CYGWIN so that + we can use autoconf 2.5x as well as 2.13. This prevents us from + being able to warn against the use of cygwin gcc at configure + time, but allows autoconf 2.5x, which is what is shipped with most + newer systems. + +2002-04-11 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: Enabled COFF as well as CV style debug info with + --enable-symbols to allow Dr. Watson users to see function info. + More info on debugging levels can be obtained at: + http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp + +2002-04-03 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: change all SC_* macros to TEA_*. The SC_ was for + Scriptics, which is no more. TEA represents a better, independent + prefix that won't need changing. + Added preliminary mingw gcc support. [Patch #538772] + Added TEA_PREFIX macro that handles defaulting the prefix and + exec_prefix vars to those used by Tcl if none were specified. + Added TEA_SETUP_COMPILER macro that encompasses the AC_PROG_CC + check and several other basic AC_PROG checks needed for making + executables. This greatly simplifies user's configure.in files. + Collapsed AIX-5 defines into AIX-* with extra checks for doing the + ELF stuff on AIX-5-ia64. + Updated TEA_ENABLE_THREADS to take an optional arg to allow + switching it on by default (for Thread) and add sanity checking to + warn the user if configuring threads incompatibly. + +2002-03-29 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: made sure that SHLIB_LDFLAGS was set to LDFLAGS_DEFAULT. + Removed --enable-64bit support for AIX-4 because it wasn't correct. + Added -MT or -MD Windows linker switches to properly support + symbols-enabled builds. + +2002-03-28 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: called AC_MSG_ERROR when SC_TEA_INIT wasn't called first + instead of calling it as that inlines it each time in shell code. + Changed Windows CFLAGS_OPTIMIZE to use -O2 instead of -Oti. + Noted TCL_LIB_VERSIONS_OK=nodots for Windows builds. + A few changes to support itcl (and perhaps others): + Added support for making your own stub libraries to SC_MAKE_LIB. + New SC_PATH_CONFIG and SC_LOAD_CONFIG that take a package name arg + and find that ${pkg}Config.sh file. itk uses this for itcl. + +2002-03-27 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: made SC_LOAD_TKCONFIG recognize when working with a Tk + build dir setup. + Added EXTRA_CFLAGS and SHLIB_LD_LIBS substs to SC_CONFIG_CFLAGS. + Added XLIBSW onto LIBS when it is defined. + Remove TCL_LIBS from MAKE_LIB and correctly use SHLIB_LD_LIBS + instead to not rely as much on tclConfig.sh cached info. + Add TK_BIN_DIR to paths to find wish in SC_PROG_WISH. + These move towards making TEA much more independent of *Config.sh. + +2002-03-19 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: corrected forgotten (UN)SHARED_LIB_SUFFIX and + SHLIB_SUFFIX defines for Win. + (SC_PATH_X): made this only do the check on unix platforms. + +2002-03-12 Jeff Hobbs <jeffh@ActiveState.com> + + * README.txt: updated to reflect fewer files + +2002-03-06 Jeff Hobbs <jeffh@ActiveState.com> + + * config.guess (removed): + * config.sub (removed): removed unnecessary files + + * installFile.tcl (removed): + * mkinstalldirs (removed): these aren't really necessary for + making TEA work + + * tcl.m4 (SC_PUBLIC_TCL_HEADERS, SC_PUBLIC_TK_HEADERS): don't + check /usr(/local)/include for includes on Windows when not using + gcc + +2002-03-05 Jeff Hobbs <jeffh@ActiveState.com> + + * tcl.m4: added warnings on Windows, removed RELPATH define and + added TCL_LIBS to MAKE_LIB macro. + + This import represents 2.0.0, or a new start at attempting to + make TEA much easier for C extension developers. + + **** moved from tclpro project to core tcl project, **** + **** renamed to 'tclconfig' **** + +2001-03-15 Karl Lehenbauer <karl@procplace.com> + + * installFile.tcl: Added updating of the modification time of + the target file whether we overwrote it or decided that it + hadn't changed. This was necessary for us to be able to + determine whether or not a module install touched the file. + +2001-03-08 Karl Lehenbauer <karl@procplace.com> + + * installFile.tcl: Added support for converting new-style (1.1+) + Cygnus drive paths to Tcl-style. + +2001-01-15 <brent.welch@interwoven.com> + + * tcl.m4: Added FreeBSD clause. + +2001-01-03 <brent.welch@interwoven.com> + + * tcl.m4: Fixed typo in SC_LIB_SPEC where it is checking + for exec-prefix. + +2000-12-01 <brent.welch@interwoven.com> + + * tcl.m4: Concatenated most of the Ajuba acsite.m4 file + so we don't need to modify the autoconf installation. + * config.guess: + * config.sub: + * installFile.tcl: + Added files from the itcl config subdirectory, + which should go away. + +2000-7-29 <welch@ajubasolutions.com> + + * Fixed the use of TCL_SRC_DIR and TK_SRC_DIR within + TCL_PRIVATE_INCLUDES and TK_PRIVATE_INCLUDES to match their recent + change from $(srcdir) to $(srcdir)/.. diff --git a/tkhtml1/tclconfig/README.txt b/tkhtml1/tclconfig/README.txt new file mode 100644 index 0000000..59b5a3e --- /dev/null +++ b/tkhtml1/tclconfig/README.txt @@ -0,0 +1,26 @@ +These files comprise the basic building blocks for a Tcl Extension +Architecture (TEA) extension. For more information on TEA see: + + http://www.tcl.tk/doc/tea/ + +This package is part of the Tcl project at SourceForge, and latest +sources should be available there: + + http://tcl.sourceforge.net/ + +This package is a freely available open source package. You can do +virtually anything you like with it, such as modifying it, redistributing +it, and selling it either in whole or in part. + +CONTENTS +======== +The following is a short description of the files you will find in +the sample extension. + +README.txt This file + +install-sh Program used for copying binaries and script files + to their install locations. + +tcl.m4 Collection of Tcl autoconf macros. Included by a package's + aclocal.m4 to define TEA_* macros. diff --git a/tkhtml1/tclconfig/install-sh b/tkhtml1/tclconfig/install-sh new file mode 100755 index 0000000..7c34c3f --- /dev/null +++ b/tkhtml1/tclconfig/install-sh @@ -0,0 +1,528 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-04-20.01; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -S $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -S) stripcmd="$stripprog $2" + shift;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/tkhtml1/tclconfig/tcl.m4 b/tkhtml1/tclconfig/tcl.m4 new file mode 100644 index 0000000..c641fe0 --- /dev/null +++ b/tkhtml1/tclconfig/tcl.m4 @@ -0,0 +1,4150 @@ +# tcl.m4 -- +# +# This file provides a set of autoconf macros to help TEA-enable +# a Tcl extension. +# +# Copyright (c) 1999-2000 Ajuba Solutions. +# Copyright (c) 2002-2005 ActiveState Corporation. +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. + +AC_PREREQ(2.57) + +dnl TEA extensions pass us the version of TEA they think they +dnl are compatible with (must be set in TEA_INIT below) +dnl TEA_VERSION="3.9" + +# Possible values for key variables defined: +# +# TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem') +# TEA_PLATFORM - windows unix +# + +#------------------------------------------------------------------------ +# TEA_PATH_TCLCONFIG -- +# +# Locate the tclConfig.sh file and perform a sanity check on +# the Tcl compile flags +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-tcl=... +# +# Defines the following vars: +# TCL_BIN_DIR Full path to the directory containing +# the tclConfig.sh file +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_TCLCONFIG], [ + dnl TEA specific: Make sure we are initialized + AC_REQUIRE([TEA_INIT]) + # + # Ok, lets find the tcl configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tcl + # + + if test x"${no_tcl}" = x ; then + # we reset no_tcl in case something fails here + no_tcl=true + AC_ARG_WITH(tcl, + AC_HELP_STRING([--with-tcl], + [directory containing tcl configuration (tclConfig.sh)]), + with_tclconfig="${withval}") + AC_MSG_CHECKING([for Tcl configuration]) + AC_CACHE_VAL(ac_cv_c_tclconfig,[ + + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + case "${with_tclconfig}" in + */tclConfig.sh ) + if test -f "${with_tclconfig}"; then + AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself]) + with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" + else + AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) + fi + fi + + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + ; do + if test -f "$i/Tcl.framework/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) + else + no_tcl= + TCL_BIN_DIR="${ac_cv_c_tclconfig}" + AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_PATH_TKCONFIG -- +# +# Locate the tkConfig.sh file +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-tk=... +# +# Defines the following vars: +# TK_BIN_DIR Full path to the directory containing +# the tkConfig.sh file +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_TKCONFIG], [ + # + # Ok, lets find the tk configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tk + # + + if test x"${no_tk}" = x ; then + # we reset no_tk in case something fails here + no_tk=true + AC_ARG_WITH(tk, + AC_HELP_STRING([--with-tk], + [directory containing tk configuration (tkConfig.sh)]), + with_tkconfig="${withval}") + AC_MSG_CHECKING([for Tk configuration]) + AC_CACHE_VAL(ac_cv_c_tkconfig,[ + + # First check to see if --with-tkconfig was specified. + if test x"${with_tkconfig}" != x ; then + case "${with_tkconfig}" in + */tkConfig.sh ) + if test -f "${with_tkconfig}"; then + AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself]) + with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" + fi ;; + esac + if test -f "${with_tkconfig}/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" + else + AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) + fi + fi + + # then check for a private Tk library + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ../tk \ + `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../tk \ + `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../../tk \ + `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + + # on Darwin, check in Framework installation locations + if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ + `ls -d /Library/Frameworks 2>/dev/null` \ + `ls -d /Network/Library/Frameworks 2>/dev/null` \ + `ls -d /System/Library/Frameworks 2>/dev/null` \ + ; do + if test -f "$i/Tk.framework/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`" + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # TEA specific: on Windows, check in common installation locations + if test "${TEA_PLATFORM}" = "windows" \ + -a x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d C:/Tcl/lib 2>/dev/null` \ + `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ + ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i; pwd)`" + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ${srcdir}/../tk \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test "${TEA_PLATFORM}" = "windows" \ + -a -f "$i/win/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/win; pwd)`" + break + fi + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tkconfig}" = x ; then + TK_BIN_DIR="# no Tk configs found" + AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) + else + no_tk= + TK_BIN_DIR="${ac_cv_c_tkconfig}" + AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_TCLCONFIG -- +# +# Load the tclConfig.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# TCL_BIN_DIR +# +# Results: +# +# Substitutes the following vars: +# TCL_BIN_DIR +# TCL_SRC_DIR +# TCL_LIB_FILE +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LOAD_TCLCONFIG], [ + AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh]) + + if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then + AC_MSG_RESULT([loading]) + . "${TCL_BIN_DIR}/tclConfig.sh" + else + AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh]) + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" + + # If the TCL_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TCL_LIB_SPEC will be set to the value + # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC + # instead of TCL_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" + TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" + TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tcl.framework installed in an arbitrary location. + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then + for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ + "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then + TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" + break + fi + done + fi + if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then + TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" + TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TCL_DBGX substitution + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" + eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" + + AC_SUBST(TCL_VERSION) + AC_SUBST(TCL_PATCH_LEVEL) + AC_SUBST(TCL_BIN_DIR) + AC_SUBST(TCL_SRC_DIR) + + AC_SUBST(TCL_LIB_FILE) + AC_SUBST(TCL_LIB_FLAG) + AC_SUBST(TCL_LIB_SPEC) + + AC_SUBST(TCL_STUB_LIB_FILE) + AC_SUBST(TCL_STUB_LIB_FLAG) + AC_SUBST(TCL_STUB_LIB_SPEC) + + AC_MSG_CHECKING([platform]) + hold_cc=$CC; CC="$TCL_CC" + AC_TRY_COMPILE(,[ + #ifdef _WIN32 + #error win32 + #endif + ], TEA_PLATFORM="unix", + TEA_PLATFORM="windows" + ) + CC=$hold_cc + AC_MSG_RESULT($TEA_PLATFORM) + + # The BUILD_$pkg is to define the correct extern storage class + # handling when making this package + AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}, [], + [Building extension source?]) + # Do this here as we have fully defined TEA_PLATFORM now + if test "${TEA_PLATFORM}" = "windows" ; then + EXEEXT=".exe" + CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" + fi + + # TEA specific: + AC_SUBST(CLEANFILES) + AC_SUBST(TCL_LIBS) + AC_SUBST(TCL_DEFS) + AC_SUBST(TCL_EXTRA_CFLAGS) + AC_SUBST(TCL_LD_FLAGS) + AC_SUBST(TCL_SHLIB_LD_LIBS) +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_TKCONFIG -- +# +# Load the tkConfig.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# TK_BIN_DIR +# +# Results: +# +# Sets the following vars that should be in tkConfig.sh: +# TK_BIN_DIR +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LOAD_TKCONFIG], [ + AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh]) + + if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then + AC_MSG_RESULT([loading]) + . "${TK_BIN_DIR}/tkConfig.sh" + else + AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh]) + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FILE=\"${TK_LIB_FILE}\"" + eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\"" + + # If the TK_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TK_LIB_SPEC will be set to the value + # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC + # instead of TK_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + if test -f "${TK_BIN_DIR}/Makefile" ; then + TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}" + TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}" + TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}" + elif test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use the libraries + # from the framework at the given location so that linking works + # against Tk.framework installed in an arbitrary location. + case ${TK_DEFS} in + *TK_FRAMEWORK*) + if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then + for i in "`cd "${TK_BIN_DIR}"; pwd`" \ + "`cd "${TK_BIN_DIR}"/../..; pwd`"; do + if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then + TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}" + break + fi + done + fi + if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then + TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" + TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}" + fi + ;; + esac + fi + + # eval is required to do the TK_DBGX substitution + eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\"" + eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\"" + eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\"" + eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\"" + + # TEA specific: Ensure windowingsystem is defined + if test "${TEA_PLATFORM}" = "unix" ; then + case ${TK_DEFS} in + *MAC_OSX_TK*) + AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?]) + TEA_WINDOWINGSYSTEM="aqua" + ;; + *) + TEA_WINDOWINGSYSTEM="x11" + ;; + esac + elif test "${TEA_PLATFORM}" = "windows" ; then + TEA_WINDOWINGSYSTEM="win32" + fi + + AC_SUBST(TK_VERSION) + AC_SUBST(TK_BIN_DIR) + AC_SUBST(TK_SRC_DIR) + + AC_SUBST(TK_LIB_FILE) + AC_SUBST(TK_LIB_FLAG) + AC_SUBST(TK_LIB_SPEC) + + AC_SUBST(TK_STUB_LIB_FILE) + AC_SUBST(TK_STUB_LIB_FLAG) + AC_SUBST(TK_STUB_LIB_SPEC) + + # TEA specific: + AC_SUBST(TK_LIBS) + AC_SUBST(TK_XINCLUDES) +]) + +#------------------------------------------------------------------------ +# TEA_PROG_TCLSH +# Determine the fully qualified path name of the tclsh executable +# in the Tcl build directory or the tclsh installed in a bin +# directory. This macro will correctly determine the name +# of the tclsh executable even if tclsh has not yet been +# built in the build directory. The tclsh found is always +# associated with a tclConfig.sh file. This tclsh should be used +# only for running extension test cases. It should never be +# or generation of files (like pkgIndex.tcl) at build time. +# +# Arguments: +# none +# +# Results: +# Substitutes the following vars: +# TCLSH_PROG +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PROG_TCLSH], [ + AC_MSG_CHECKING([for tclsh]) + if test -f "${TCL_BIN_DIR}/Makefile" ; then + # tclConfig.sh is in Tcl build directory + if test "${TEA_PLATFORM}" = "windows"; then + TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + else + TCLSH_PROG="${TCL_BIN_DIR}/tclsh" + fi + else + # tclConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" + else + TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}" + fi + list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${TCLSH_PROG}" ; then + REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" + fi + AC_MSG_RESULT([${TCLSH_PROG}]) + AC_SUBST(TCLSH_PROG) +]) + +#------------------------------------------------------------------------ +# TEA_PROG_WISH +# Determine the fully qualified path name of the wish executable +# in the Tk build directory or the wish installed in a bin +# directory. This macro will correctly determine the name +# of the wish executable even if wish has not yet been +# built in the build directory. The wish found is always +# associated with a tkConfig.sh file. This wish should be used +# only for running extension test cases. It should never be +# or generation of files (like pkgIndex.tcl) at build time. +# +# Arguments: +# none +# +# Results: +# Substitutes the following vars: +# WISH_PROG +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PROG_WISH], [ + AC_MSG_CHECKING([for wish]) + if test -f "${TK_BIN_DIR}/Makefile" ; then + # tkConfig.sh is in Tk build directory + if test "${TEA_PLATFORM}" = "windows"; then + WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" + else + WISH_PROG="${TK_BIN_DIR}/wish" + fi + else + # tkConfig.sh is in install location + if test "${TEA_PLATFORM}" = "windows"; then + WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" + else + WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}" + fi + list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \ + `ls -d ${TK_BIN_DIR}/.. 2>/dev/null` \ + `ls -d ${TK_PREFIX}/bin 2>/dev/null`" + for i in $list ; do + if test -f "$i/${WISH_PROG}" ; then + REAL_TK_BIN_DIR="`cd "$i"; pwd`/" + break + fi + done + WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}" + fi + AC_MSG_RESULT([${WISH_PROG}]) + AC_SUBST(WISH_PROG) +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_SHARED -- +# +# Allows the building of shared libraries +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-shared=yes|no +# +# Defines the following vars: +# STATIC_BUILD Used for building import/export libraries +# on Windows. +# +# Sets the following vars: +# SHARED_BUILD Value of 1 or 0 +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_ENABLE_SHARED], [ + AC_MSG_CHECKING([how to build libraries]) + AC_ARG_ENABLE(shared, + AC_HELP_STRING([--enable-shared], + [build and link with shared libraries (default: on)]), + [tcl_ok=$enableval], [tcl_ok=yes]) + + if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" ; then + AC_MSG_RESULT([shared]) + SHARED_BUILD=1 + else + AC_MSG_RESULT([static]) + SHARED_BUILD=0 + AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?]) + fi + AC_SUBST(SHARED_BUILD) +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_THREADS -- +# +# Specify if thread support should be enabled. If "yes" is specified +# as an arg (optional), threads are enabled by default, "no" means +# threads are disabled. "yes" is the default. +# +# TCL_THREADS is checked so that if you are compiling an extension +# against a threaded core, your extension must be compiled threaded +# as well. +# +# Note that it is legal to have a thread enabled extension run in a +# threaded or non-threaded Tcl core, but a non-threaded extension may +# only run in a non-threaded Tcl core. +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-threads +# +# Sets the following vars: +# THREADS_LIBS Thread library(s) +# +# Defines the following vars: +# TCL_THREADS +# _REENTRANT +# _THREAD_SAFE +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_ENABLE_THREADS], [ + AC_ARG_ENABLE(threads, + AC_HELP_STRING([--enable-threads], + [build with threads]), + [tcl_ok=$enableval], [tcl_ok=yes]) + + if test "${enable_threads+set}" = set; then + enableval="$enable_threads" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then + TCL_THREADS=1 + + if test "${TEA_PLATFORM}" != "windows" ; then + # We are always OK on Windows, so check what this platform wants: + + # USE_THREAD_ALLOC tells us to try the special thread-based + # allocator that significantly reduces lock contention + AC_DEFINE(USE_THREAD_ALLOC, 1, + [Do we want to use the threaded memory allocator?]) + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + if test "`uname -s`" = "SunOS" ; then + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + fi + AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?]) + AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no) + if test "$tcl_ok" = "no"; then + # Check a little harder for __pthread_mutex_init in the same + # library, as some systems hide it there until pthread.h is + # defined. We could alternatively do an AC_TRY_COMPILE with + # pthread.h, but that will work with libpthread really doesn't + # exist, like AIX 4.2. [Bug: 4359] + AC_CHECK_LIB(pthread, __pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + fi + + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthread" + else + AC_CHECK_LIB(pthreads, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthreads" + else + AC_CHECK_LIB(c, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "no"; then + AC_CHECK_LIB(c_r, pthread_mutex_init, + tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -pthread" + else + TCL_THREADS=0 + AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled]) + fi + fi + fi + fi + fi + else + TCL_THREADS=0 + fi + # Do checking message here to not mess up interleaved configure output + AC_MSG_CHECKING([for building with threads]) + if test "${TCL_THREADS}" = 1; then + AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?]) + AC_MSG_RESULT([yes (default)]) + else + AC_MSG_RESULT([no]) + fi + # TCL_THREADS sanity checking. See if our request for building with + # threads is the same as the way Tcl was built. If not, warn the user. + case ${TCL_DEFS} in + *THREADS=1*) + if test "${TCL_THREADS}" = "0"; then + AC_MSG_WARN([ + Building ${PACKAGE_NAME} without threads enabled, but building against Tcl + that IS thread-enabled. It is recommended to use --enable-threads.]) + fi + ;; + *) + if test "${TCL_THREADS}" = "1"; then + AC_MSG_WARN([ + --enable-threads requested, but building against a Tcl that is NOT + thread-enabled. This is an OK configuration that will also run in + a thread-enabled core.]) + fi + ;; + esac + AC_SUBST(TCL_THREADS) +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_SYMBOLS -- +# +# Specify if debugging symbols should be used. +# Memory (TCL_MEM_DEBUG) debugging can also be enabled. +# +# Arguments: +# none +# +# TEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives +# the value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted. +# Requires the following vars to be set in the Makefile: +# CFLAGS_DEFAULT +# LDFLAGS_DEFAULT +# +# Results: +# +# Adds the following arguments to configure: +# --enable-symbols +# +# Defines the following vars: +# CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true +# Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false +# LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true +# Sets to $(LDFLAGS_OPTIMIZE) if false +# DBGX Formerly used as debug library extension; +# always blank now. +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_ENABLE_SYMBOLS], [ + dnl TEA specific: Make sure we are initialized + AC_REQUIRE([TEA_CONFIG_CFLAGS]) + AC_MSG_CHECKING([for build with symbols]) + AC_ARG_ENABLE(symbols, + AC_HELP_STRING([--enable-symbols], + [build with debugging symbols (default: off)]), + [tcl_ok=$enableval], [tcl_ok=no]) + DBGX="" + if test "$tcl_ok" = "no"; then + CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" + LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" + AC_MSG_RESULT([no]) + else + CFLAGS_DEFAULT="${CFLAGS_DEBUG}" + LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" + if test "$tcl_ok" = "yes"; then + AC_MSG_RESULT([yes (standard debugging)]) + fi + fi + # TEA specific: + if test "${TEA_PLATFORM}" != "windows" ; then + LDFLAGS_DEFAULT="${LDFLAGS}" + fi + AC_SUBST(CFLAGS_DEFAULT) + AC_SUBST(LDFLAGS_DEFAULT) + AC_SUBST(TCL_DBGX) + + if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then + AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?]) + fi + + if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then + if test "$tcl_ok" = "all"; then + AC_MSG_RESULT([enabled symbols mem debugging]) + else + AC_MSG_RESULT([enabled $tcl_ok debugging]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_ENABLE_LANGINFO -- +# +# Allows use of modern nl_langinfo check for better l10n. +# This is only relevant for Unix. +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-langinfo=yes|no (default is yes) +# +# Defines the following vars: +# HAVE_LANGINFO Triggers use of nl_langinfo if defined. +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_ENABLE_LANGINFO], [ + AC_ARG_ENABLE(langinfo, + AC_HELP_STRING([--enable-langinfo], + [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]), + [langinfo_ok=$enableval], [langinfo_ok=yes]) + + HAVE_LANGINFO=0 + if test "$langinfo_ok" = "yes"; then + AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no]) + fi + AC_MSG_CHECKING([whether to use nl_langinfo]) + if test "$langinfo_ok" = "yes"; then + AC_CACHE_VAL(tcl_cv_langinfo_h, [ + AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);], + [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])]) + AC_MSG_RESULT([$tcl_cv_langinfo_h]) + if test $tcl_cv_langinfo_h = yes; then + AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?]) + fi + else + AC_MSG_RESULT([$langinfo_ok]) + fi +]) + +#-------------------------------------------------------------------- +# TEA_CONFIG_SYSTEM +# +# Determine what the system is (some things cannot be easily checked +# on a feature-driven basis, alas). This can usually be done via the +# "uname" command. +# +# Arguments: +# none +# +# Results: +# Defines the following var: +# +# system - System/platform/version identification code. +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_CONFIG_SYSTEM], [ + AC_CACHE_CHECK([system version], tcl_cv_sys_version, [ + # TEA specific: + if test "${TEA_PLATFORM}" = "windows" ; then + tcl_cv_sys_version=windows + else + tcl_cv_sys_version=`uname -s`-`uname -r` + if test "$?" -ne 0 ; then + AC_MSG_WARN([can't find uname command]) + tcl_cv_sys_version=unknown + else + if test "`uname -s`" = "AIX" ; then + tcl_cv_sys_version=AIX-`uname -v`.`uname -r` + fi + fi + fi + ]) + system=$tcl_cv_sys_version +]) + +#-------------------------------------------------------------------- +# TEA_CONFIG_CFLAGS +# +# Try to determine the proper flags to pass to the compiler +# for building shared libraries and other such nonsense. +# +# Arguments: +# none +# +# Results: +# +# Defines and substitutes the following vars: +# +# DL_OBJS, DL_LIBS - removed for TEA, only needed by core. +# LDFLAGS - Flags to pass to the compiler when linking object +# files into an executable application binary such +# as tclsh. +# LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib", +# that tell the run-time dynamic linker where to look +# for shared libraries such as libtcl.so. Depends on +# the variable LIB_RUNTIME_DIR in the Makefile. Could +# be the same as CC_SEARCH_FLAGS if ${CC} is used to link. +# CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib", +# that tell the run-time dynamic linker where to look +# for shared libraries such as libtcl.so. Depends on +# the variable LIB_RUNTIME_DIR in the Makefile. +# SHLIB_CFLAGS - Flags to pass to cc when compiling the components +# of a shared library (may request position-independent +# code, among other things). +# SHLIB_LD - Base command to use for combining object files +# into a shared library. +# SHLIB_LD_LIBS - Dependent libraries for the linker to scan when +# creating shared libraries. This symbol typically +# goes at the end of the "ld" commands that build +# shared libraries. The value of the symbol defaults to +# "${LIBS}" if all of the dependent libraries should +# be specified when creating a shared library. If +# dependent libraries should not be specified (as on +# SunOS 4.x, where they cause the link to fail, or in +# general if Tcl and Tk aren't themselves shared +# libraries), then this symbol has an empty string +# as its value. +# SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable +# extensions. An empty string means we don't know how +# to use shared libraries on this platform. +# LIB_SUFFIX - Specifies everything that comes after the "libfoo" +# in a static or shared library name, using the $PACKAGE_VERSION variable +# to put the version in the right place. This is used +# by platforms that need non-standard library names. +# Examples: ${PACKAGE_VERSION}.so.1.1 on NetBSD, since it needs +# to have a version after the .so, and ${PACKAGE_VERSION}.a +# on AIX, since a shared library needs to have +# a .a extension whereas shared objects for loadable +# extensions have a .so extension. Defaults to +# ${PACKAGE_VERSION}${SHLIB_SUFFIX}. +# CFLAGS_DEBUG - +# Flags used when running the compiler in debug mode +# CFLAGS_OPTIMIZE - +# Flags used when running the compiler in optimize mode +# CFLAGS - Additional CFLAGS added as necessary (usually 64-bit) +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_CONFIG_CFLAGS], [ + dnl TEA specific: Make sure we are initialized + AC_REQUIRE([TEA_INIT]) + + # Step 0.a: Enable 64 bit support? + + AC_MSG_CHECKING([if 64bit support is requested]) + AC_ARG_ENABLE(64bit, + AC_HELP_STRING([--enable-64bit], + [enable 64bit support (default: off)]), + [do64bit=$enableval], [do64bit=no]) + AC_MSG_RESULT([$do64bit]) + + # Step 0.b: Enable Solaris 64 bit VIS support? + + AC_MSG_CHECKING([if 64bit Sparc VIS support is requested]) + AC_ARG_ENABLE(64bit-vis, + AC_HELP_STRING([--enable-64bit-vis], + [enable 64bit Sparc VIS support (default: off)]), + [do64bitVIS=$enableval], [do64bitVIS=no]) + AC_MSG_RESULT([$do64bitVIS]) + # Force 64bit on with VIS + AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes]) + + # Step 0.c: Check if visibility support is available. Do this here so + # that platform specific alternatives can be used below if this fails. + + AC_CACHE_CHECK([if compiler supports visibility "hidden"], + tcl_cv_cc_visibility_hidden, [ + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" + AC_TRY_LINK([ + extern __attribute__((__visibility__("hidden"))) void f(void); + void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes, + tcl_cv_cc_visibility_hidden=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [ + AC_DEFINE(MODULE_SCOPE, + [extern __attribute__((__visibility__("hidden")))], + [Compiler support for module scope symbols]) + AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols]) + ]) + + # Step 0.d: Disable -rpath support? + + AC_MSG_CHECKING([if rpath support is requested]) + AC_ARG_ENABLE(rpath, + AC_HELP_STRING([--disable-rpath], + [disable rpath support (default: on)]), + [doRpath=$enableval], [doRpath=yes]) + AC_MSG_RESULT([$doRpath]) + + # TEA specific: Cross-compiling options for Windows/CE builds? + + AS_IF([test "${TEA_PLATFORM}" = windows], [ + AC_MSG_CHECKING([if Windows/CE build is requested]) + AC_ARG_ENABLE(wince, + AC_HELP_STRING([--enable-wince], + [enable Win/CE support (where applicable)]), + [doWince=$enableval], [doWince=no]) + AC_MSG_RESULT([$doWince]) + ]) + + # Set the variable "system" to hold the name and version number + # for the system. + + TEA_CONFIG_SYSTEM + + # Require ranlib early so we can override it in special cases below. + + AC_REQUIRE([AC_PROG_RANLIB]) + + # Set configuration options based on system name and version. + # This is similar to Tcl's unix/tcl.m4 except that we've added a + # "windows" case and removed some core-only vars. + + do64bit_ok=no + # default to '{$LIBS}' and set to "" on per-platform necessary basis + SHLIB_LD_LIBS='${LIBS}' + # When ld needs options to work in 64-bit mode, put them in + # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] + # is disabled by the user. [Bug 1016796] + LDFLAGS_ARCH="" + UNSHARED_LIB_SUFFIX="" + # TEA specific: use PACKAGE_VERSION instead of VERSION + TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' + ECHO_VERSION='`echo ${PACKAGE_VERSION}`' + TCL_LIB_VERSIONS_OK=ok + CFLAGS_DEBUG=-g + AS_IF([test "$GCC" = yes], [ + CFLAGS_OPTIMIZE=-O2 + CFLAGS_WARNING="-Wall" + ], [ + CFLAGS_OPTIMIZE=-O + CFLAGS_WARNING="" + ]) + AC_CHECK_TOOL(AR, ar) + STLIB_LD='${AR} cr' + LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" + AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION="1.0"]) + case $system in + # TEA specific: + windows) + # This is a 2-stage check to make sure we have the 64-bit SDK + # We have to know where the SDK is installed. + # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs + # MACHINE is IX86 for LINK, but this is used by the manifest, + # which requires x86|amd64|ia64. + MACHINE="X86" + if test "$do64bit" != "no" ; then + if test "x${MSSDK}x" = "xx" ; then + MSSDK="C:/Progra~1/Microsoft Platform SDK" + fi + MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'` + PATH64="" + case "$do64bit" in + amd64|x64|yes) + MACHINE="AMD64" ; # default to AMD64 64-bit build + PATH64="${MSSDK}/Bin/Win64/x86/AMD64" + ;; + ia64) + MACHINE="IA64" + PATH64="${MSSDK}/Bin/Win64" + ;; + esac + if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then + AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode]) + AC_MSG_WARN([Ensure latest Platform SDK is installed]) + do64bit="no" + else + AC_MSG_RESULT([ Using 64-bit $MACHINE mode]) + do64bit_ok="yes" + fi + fi + + if test "$doWince" != "no" ; then + if test "$do64bit" != "no" ; then + AC_MSG_ERROR([Windows/CE and 64-bit builds incompatible]) + fi + if test "$GCC" = "yes" ; then + AC_MSG_ERROR([Windows/CE and GCC builds incompatible]) + fi + TEA_PATH_CELIB + # Set defaults for common evc4/PPC2003 setup + # Currently Tcl requires 300+, possibly 420+ for sockets + CEVERSION=420; # could be 211 300 301 400 420 ... + TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ... + ARCH=ARM; # could be ARM MIPS X86EM ... + PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002" + if test "$doWince" != "yes"; then + # If !yes then the user specified something + # Reset ARCH to allow user to skip specifying it + ARCH= + eval `echo $doWince | awk -F, '{ \ + if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \ + if ([$]1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \ + if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \ + if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \ + if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \ + }'` + if test "x${ARCH}" = "x" ; then + ARCH=$TARGETCPU; + fi + fi + OSVERSION=WCE$CEVERSION; + if test "x${WCEROOT}" = "x" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0" + if test ! -d "${WCEROOT}" ; then + WCEROOT="C:/Program Files/Microsoft eMbedded Tools" + fi + fi + if test "x${SDKROOT}" = "x" ; then + SDKROOT="C:/Program Files/Windows CE Tools" + if test ! -d "${SDKROOT}" ; then + SDKROOT="C:/Windows CE Tools" + fi + fi + WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'` + SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'` + if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \ + -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then + AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]]) + doWince="no" + else + # We could PATH_NOSPACE these, but that's not important, + # as long as we quote them when used. + CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include" + if test -d "${CEINCLUDE}/${TARGETCPU}" ; then + CEINCLUDE="${CEINCLUDE}/${TARGETCPU}" + fi + CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" + fi + fi + + if test "$GCC" != "yes" ; then + if test "${SHARED_BUILD}" = "0" ; then + runtime=-MT + else + runtime=-MD + fi + + if test "$do64bit" != "no" ; then + # All this magic is necessary for the Win64 SDK RC1 - hobbs + CC="\"${PATH64}/cl.exe\"" + CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\"" + RC="\"${MSSDK}/bin/rc.exe\"" + lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\"" + LINKBIN="\"${PATH64}/link.exe\"" + CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + # Avoid 'unresolved external symbol __security_cookie' + # errors, c.f. http://support.microsoft.com/?id=894573 + TEA_ADD_LIBS([bufferoverflowU.lib]) + elif test "$doWince" != "no" ; then + CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin" + if test "${TARGETCPU}" = "X86"; then + CC="\"${CEBINROOT}/cl.exe\"" + else + CC="\"${CEBINROOT}/cl${ARCH}.exe\"" + fi + CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\"" + RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" + arch=`echo ${ARCH} | awk '{print tolower([$]0)}'` + defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS" + if test "${SHARED_BUILD}" = "1" ; then + # Static CE builds require static celib as well + defs="${defs} _DLL" + fi + for i in $defs ; do + AC_DEFINE_UNQUOTED($i, 1, [WinCE def ]$i) + done + AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION, [_WIN32_WCE version]) + AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION, [UNDER_CE version]) + CFLAGS_DEBUG="-nologo -Zi -Od" + CFLAGS_OPTIMIZE="-nologo -Ox" + lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'` + lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" + LINKBIN="\"${CEBINROOT}/link.exe\"" + AC_SUBST(CELIB_DIR) + else + RC="rc" + lflags="-nologo" + LINKBIN="link" + CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" + fi + fi + + if test "$GCC" = "yes"; then + # mingw gcc mode + AC_CHECK_TOOL(RC, windres) + CFLAGS_DEBUG="-g" + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + SHLIB_LD='${CC} -shared' + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" + LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" + + AC_CACHE_CHECK(for cross-compile version of gcc, + ac_cv_cross, + AC_TRY_COMPILE([ + #ifdef __WIN32__ + #error cross-compiler + #endif + ], [], + ac_cv_cross=yes, + ac_cv_cross=no) + ) + if test "$ac_cv_cross" = "yes"; then + case "$do64bit" in + amd64|x64|yes) + CC="x86_64-w64-mingw32-gcc" + LD="x86_64-w64-mingw32-ld" + AR="x86_64-w64-mingw32-ar" + RANLIB="x86_64-w64-mingw32-ranlib" + RC="x86_64-w64-mingw32-windres" + ;; + *) + CC="i686-w64-mingw32-gcc" + LD="i686-w64-mingw32-ld" + AR="i686-w64-mingw32-ar" + RANLIB="i686-w64-mingw32-ranlib" + RC="i686-w64-mingw32-windres" + ;; + esac + fi + + else + SHLIB_LD="${LINKBIN} -dll ${lflags}" + # link -lib only works when -lib is the first arg + STLIB_LD="${LINKBIN} -lib ${lflags}" + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' + PATHTYPE=-w + # For information on what debugtype is most useful, see: + # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp + # and also + # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx + # This essentially turns it all on. + LDFLAGS_DEBUG="-debug -debugtype:cv" + LDFLAGS_OPTIMIZE="-release" + if test "$doWince" != "no" ; then + LDFLAGS_CONSOLE="-link ${lflags}" + LDFLAGS_WINDOW=${LDFLAGS_CONSOLE} + else + LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" + LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" + fi + fi + + SHLIB_SUFFIX=".dll" + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' + + TCL_LIB_VERSIONS_OK=nodots + ;; + AIX-*) + AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [ + # AIX requires the _r compiler when gcc isn't being used + case "${CC}" in + *_r|*_r\ *) + # ok ... + ;; + *) + # Make sure only first arg gets _r + CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'` + ;; + esac + AC_MSG_RESULT([Using $CC for compiling with threads]) + ]) + LIBS="$LIBS -lc" + SHLIB_CFLAGS="" + SHLIB_SUFFIX=".so" + + LD_LIBRARY_PATH_VAR="LIBPATH" + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = yes], [ + AS_IF([test "$GCC" = yes], [ + AC_MSG_WARN([64bit mode not supported with GCC on $system]) + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS -q64" + LDFLAGS_ARCH="-q64" + RANLIB="${RANLIB} -X64" + AR="${AR} -X64" + SHLIB_LD_FLAGS="-b64" + ]) + ]) + + AS_IF([test "`uname -m`" = ia64], [ + # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + AS_IF([test "$GCC" = yes], [ + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + ], [ + CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' + ]) + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + ], [ + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared -Wl,-bexpall' + ], [ + SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" + LDFLAGS="$LDFLAGS -brtl" + ]) + SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" + CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ]) + ;; + BeOS*) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -nostart' + SHLIB_SUFFIX=".so" + + #----------------------------------------------------------- + # Check for inet_ntoa in -lbind, for BeOS (which also needs + # -lsocket, even if the network functions are in -lnet which + # is always linked to, for compatibility. + #----------------------------------------------------------- + AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"]) + ;; + BSD/OS-4.*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + CYGWIN_*) + SHLIB_CFLAGS="" + SHLIB_LD='${CC} -shared' + SHLIB_SUFFIX=".dll" + EXEEXT=".exe" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + Haiku*) + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}' + AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"]) + ;; + HP-UX-*.11.*) + # Use updated header definitions where possible + AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?]) + # TEA specific: Needed by Tcl, but not most extensions + #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) + #LIBS="$LIBS -lxnet" # Use the XOPEN network library + + AS_IF([test "`uname -m`" = ia64], [ + SHLIB_SUFFIX=".so" + # Use newer C++ library for C++ extensions + #if test "$GCC" != "yes" ; then + # CPPFLAGS="-AA" + #fi + ], [ + SHLIB_SUFFIX=".sl" + ]) + AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) + AS_IF([test "$tcl_ok" = yes], [ + LDFLAGS="$LDFLAGS -Wl,-E" + CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' + LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' + LD_LIBRARY_PATH_VAR="SHLIB_PATH" + ]) + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ], [ + CFLAGS="$CFLAGS -z" + # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc + #CFLAGS="$CFLAGS +DAportable" + SHLIB_CFLAGS="+z" + SHLIB_LD="ld -b" + ]) + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = "yes"], [ + AS_IF([test "$GCC" = yes], [ + case `${CC} -dumpmachine` in + hppa64*) + # 64-bit gcc in use. Fix flags for GNU ld. + do64bit_ok=yes + SHLIB_LD='${CC} -shared' + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ;; + *) + AC_MSG_WARN([64bit mode not supported with GCC on $system]) + ;; + esac + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS +DD64" + LDFLAGS_ARCH="+DD64" + ]) + ]) ;; + IRIX-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + AS_IF([test "$GCC" = yes], [ + CFLAGS="$CFLAGS -mabi=n32" + LDFLAGS="$LDFLAGS -mabi=n32" + ], [ + case $system in + IRIX-6.3) + # Use to build 6.2 compatible binaries on 6.3. + CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" + ;; + *) + CFLAGS="$CFLAGS -n32" + ;; + esac + LDFLAGS="$LDFLAGS -n32" + ]) + ;; + IRIX64-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + + # Check to enable 64-bit flags for compiler/linker + + AS_IF([test "$do64bit" = yes], [ + AS_IF([test "$GCC" = yes], [ + AC_MSG_WARN([64bit mode not supported by gcc]) + ], [ + do64bit_ok=yes + SHLIB_LD="ld -64 -shared -rdata_shared" + CFLAGS="$CFLAGS -64" + LDFLAGS_ARCH="-64" + ]) + ]) + ;; + Linux*|GNU*|NetBSD-Debian) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + + # TEA specific: + CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" + + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}' + LDFLAGS="$LDFLAGS -Wl,--export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"]) + AS_IF([test $do64bit = yes], [ + AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -m64" + AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_m64 = yes], [ + CFLAGS="$CFLAGS -m64" + do64bit_ok=yes + ]) + ]) + + # The combo of gcc + glibc has a bug related to inlining of + # functions like strtod(). The -fno-builtin flag should address + # this problem but it does not work. The -fno-inline flag is kind + # of overkill but it works. Disable inlining only when one of the + # files in compat/*.c is being linked in. + + AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"]) + ;; + Lynx*) + SHLIB_CFLAGS="-fPIC" + SHLIB_SUFFIX=".so" + CFLAGS_OPTIMIZE=-02 + SHLIB_LD='${CC} -shared' + LD_FLAGS="-Wl,--export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + ;; + OpenBSD-*) + arch=`arch -s` + case "$arch" in + vax) + SHLIB_SUFFIX="" + SHARED_LIB_SUFFIX="" + LDFLAGS="" + ;; + *) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' + LDFLAGS="-Wl,-export-dynamic" + ;; + esac + case "$arch" in + vax) + CFLAGS_OPTIMIZE="-O1" + ;; + *) + CFLAGS_OPTIMIZE="-O2" + ;; + esac + AS_IF([test "${TCL_THREADS}" = "1"], [ + # On OpenBSD: Compile with -pthread + # Don't link with -lpthread + LIBS=`echo $LIBS | sed s/-lpthread//` + CFLAGS="$CFLAGS -pthread" + ]) + # OpenBSD doesn't do version numbers with dots. + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + NetBSD-*) + # NetBSD has ELF and can use 'cc -shared' to build shared libs + SHLIB_CFLAGS="-fPIC" + SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' + SHLIB_SUFFIX=".so" + LDFLAGS="$LDFLAGS -export-dynamic" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "${TCL_THREADS}" = "1"], [ + # The -pthread needs to go in the CFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + ]) + ;; + FreeBSD-*) + # This configuration from FreeBSD Ports. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="${CC} -shared" + TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$[@]" + SHLIB_SUFFIX=".so" + LDFLAGS="" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) + AS_IF([test "${TCL_THREADS}" = "1"], [ + # The -pthread needs to go in the LDFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) + # Version numbers are dot-stripped by system policy. + TCL_TRIM_DOTS=`echo ${PACKAGE_VERSION} | tr -d .` + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1' + TCL_LIB_VERSIONS_OK=nodots + ;; + Darwin-*) + CFLAGS_OPTIMIZE="-Os" + SHLIB_CFLAGS="-fno-common" + # To avoid discrepancies between what headers configure sees during + # preprocessing tests and compiling tests, move any -isysroot and + # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: + CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`" + CFLAGS="`echo " ${CFLAGS}" | \ + awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ + if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`" + AS_IF([test $do64bit = yes], [ + case `arch` in + ppc) + AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag], + tcl_cv_cc_arch_ppc64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes, + tcl_cv_cc_arch_ppc64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [ + CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" + do64bit_ok=yes + ]);; + i386) + AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag], + tcl_cv_cc_arch_x86_64, [ + hold_cflags=$CFLAGS + CFLAGS="$CFLAGS -arch x86_64" + AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes, + tcl_cv_cc_arch_x86_64=no) + CFLAGS=$hold_cflags]) + AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [ + CFLAGS="$CFLAGS -arch x86_64" + do64bit_ok=yes + ]);; + *) + AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);; + esac + ], [ + # Check for combined 32-bit and 64-bit fat build + AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ + && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [ + fat_32_64=yes]) + ]) + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' + AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" + AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_single_module = yes], [ + SHLIB_LD="${SHLIB_LD} -Wl,-single_module" + ]) + # TEA specific: link shlib with current and compatibility version flags + vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` + SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" + SHLIB_SUFFIX=".dylib" + # Don't use -prebind when building for Mac OS X 10.4 or later only: + AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \ + "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [ + LDFLAGS="$LDFLAGS -prebind"]) + LDFLAGS="$LDFLAGS -headerpad_max_install_names" + AC_CACHE_CHECK([if ld accepts -search_paths_first flag], + tcl_cv_ld_search_paths_first, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes, + tcl_cv_ld_search_paths_first=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_search_paths_first = yes], [ + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + ]) + AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ + AC_DEFINE(MODULE_SCOPE, [__private_extern__], + [Compiler support for module scope symbols]) + tcl_cv_cc_visibility_hidden=yes + ]) + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" + # TEA specific: for combined 32 & 64 bit fat builds of Tk + # extensions, verify that 64-bit build is possible. + AS_IF([test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"], [ + AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [ + AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [ + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" + LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" + AC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();], + tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done]) + ]) + AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [ + AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [ + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' + done + CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" + LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" + AC_TRY_LINK([#include <tk.h>], [Tk_InitStubs(NULL, "", 0);], + tcl_cv_lib_tk_64=yes, tcl_cv_lib_tk_64=no) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="$hold_'$v'"' + done]) + ]) + # remove 64-bit arch flags from CFLAGS et al. if configuration + # does not support 64-bit. + AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [ + AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags]) + for v in CFLAGS CPPFLAGS LDFLAGS; do + eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' + done]) + ]) + ;; + OS/390-*) + CFLAGS_OPTIMIZE="" # Optimizer is buggy + AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h + [Should OS/390 do the right thing with sockets?]) + ;; + OSF1-V*) + # Digital OSF/1 + SHLIB_CFLAGS="" + AS_IF([test "$SHARED_BUILD" = 1], [ + SHLIB_LD='ld -shared -expect_unresolved "*"' + ], [ + SHLIB_LD='ld -non_shared -expect_unresolved "*"' + ]) + SHLIB_SUFFIX=".so" + AS_IF([test $doRpath = yes], [ + CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) + AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [ + CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"]) + # see pthread_intro(3) for pthread support on osf1, k.furukawa + AS_IF([test "${TCL_THREADS}" = 1], [ + CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" + CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" + LIBS=`echo $LIBS | sed s/-lpthreads//` + AS_IF([test "$GCC" = yes], [ + LIBS="$LIBS -lpthread -lmach -lexc" + ], [ + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + ]) + ]) + ;; + QNX-6*) + # QNX RTP + # This may work for all QNX, but it was only reported for v6. + SHLIB_CFLAGS="-fPIC" + SHLIB_LD="ld -Bshareable -x" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SCO_SV-3.2*) + AS_IF([test "$GCC" = yes], [ + SHLIB_CFLAGS="-fPIC -melf" + LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" + ], [ + SHLIB_CFLAGS="-Kpic -belf" + LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" + ]) + SHLIB_LD="ld -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + SunOS-5.[[0-6]]) + # Careful to not let 5.10+ fall into this case + + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + + SHLIB_CFLAGS="-KPIC" + SHLIB_SUFFIX=".so" + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ], [ + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + ]) + ;; + SunOS-5*) + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + + AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) + AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, + [Do we really want to follow the standard? Yes we do!]) + + SHLIB_CFLAGS="-KPIC" + + # Check to enable 64-bit flags for compiler/linker + AS_IF([test "$do64bit" = yes], [ + arch=`isainfo` + AS_IF([test "$arch" = "sparcv9 sparc"], [ + AS_IF([test "$GCC" = yes], [ + AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [ + AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system]) + ], [ + do64bit_ok=yes + CFLAGS="$CFLAGS -m64 -mcpu=v9" + LDFLAGS="$LDFLAGS -m64 -mcpu=v9" + SHLIB_CFLAGS="-fPIC" + ]) + ], [ + do64bit_ok=yes + AS_IF([test "$do64bitVIS" = yes], [ + CFLAGS="$CFLAGS -xarch=v9a" + LDFLAGS_ARCH="-xarch=v9a" + ], [ + CFLAGS="$CFLAGS -xarch=v9" + LDFLAGS_ARCH="-xarch=v9" + ]) + # Solaris 64 uses this as well + #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" + ]) + ], [AS_IF([test "$arch" = "amd64 i386"], [ + AS_IF([test "$GCC" = yes], [ + case $system in + SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) + do64bit_ok=yes + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + AC_MSG_WARN([64bit mode not supported with GCC on $system]);; + esac + ], [ + do64bit_ok=yes + case $system in + SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) + CFLAGS="$CFLAGS -m64" + LDFLAGS="$LDFLAGS -m64";; + *) + CFLAGS="$CFLAGS -xarch=amd64" + LDFLAGS="$LDFLAGS -xarch=amd64";; + esac + ]) + ], [AC_MSG_WARN([64bit mode not supported for $arch])])]) + ]) + + SHLIB_SUFFIX=".so" + AS_IF([test "$GCC" = yes], [ + SHLIB_LD='${CC} -shared' + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} + AS_IF([test "$do64bit_ok" = yes], [ + AS_IF([test "$arch" = "sparcv9 sparc"], [ + # We need to specify -static-libgcc or we need to + # add the path to the sparv9 libgcc. + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" + # for finding sparcv9 libgcc, get the regular libgcc + # path, remove so name and append 'sparcv9' + #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." + #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" + ], [AS_IF([test "$arch" = "amd64 i386"], [ + # JH: static-libgcc is necessary for core Tcl, but may + # not be necessary for extensions. + SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" + ])]) + ]) + ], [ + case $system in + SunOS-5.[[1-9]][[0-9]]*) + # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS + SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; + *) + SHLIB_LD='/usr/ccs/bin/ld -G -z text';; + esac + CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + ]) + ;; + UNIX_SV* | UnixWare-5*) + SHLIB_CFLAGS="-KPIC" + SHLIB_LD='${CC} -G' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers + # that don't grok the -Bexport option. Test that it does. + AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [ + hold_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-Bexport" + AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no) + LDFLAGS=$hold_ldflags]) + AS_IF([test $tcl_cv_ld_Bexport = yes], [ + LDFLAGS="$LDFLAGS -Wl,-Bexport" + ]) + CC_SEARCH_FLAGS="" + LD_SEARCH_FLAGS="" + ;; + esac + + AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [ + AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform]) + ]) + +dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so +dnl # until the end of configure, as configure's compile and link tests use +dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's +dnl # preprocessing tests use only CPPFLAGS. + AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""]) + + # Add in the arch flags late to ensure it wasn't removed. + # Not necessary in TEA, but this is aligned with core + LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" + + # If we're running gcc, then change the C flags for compiling shared + # libraries to the right flags for gcc, instead of those for the + # standard manufacturer compiler. + + AS_IF([test "$GCC" = yes], [ + case $system in + AIX-*) ;; + BSD/OS*) ;; + CYGWIN_*|MINGW32_*) ;; + IRIX*) ;; + NetBSD-*|FreeBSD-*|OpenBSD-*) ;; + Darwin-*) ;; + SCO_SV-3.2*) ;; + windows) ;; + *) SHLIB_CFLAGS="-fPIC" ;; + esac]) + + AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ + AC_DEFINE(MODULE_SCOPE, [extern], + [No Compiler support for module scope symbols]) + ]) + + AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [ + # TEA specific: use PACKAGE_VERSION instead of VERSION + SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}']) + AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [ + # TEA specific: use PACKAGE_VERSION instead of VERSION + UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a']) + + if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then + AC_CACHE_CHECK(for SEH support in compiler, + tcl_cv_seh, + AC_TRY_RUN([ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef WIN32_LEAN_AND_MEAN + + int main(int argc, char** argv) { + int a, b = 0; + __try { + a = 666 / b; + } + __except (EXCEPTION_EXECUTE_HANDLER) { + return 0; + } + return 1; + } + ], + tcl_cv_seh=yes, + tcl_cv_seh=no, + tcl_cv_seh=no) + ) + if test "$tcl_cv_seh" = "no" ; then + AC_DEFINE(HAVE_NO_SEH, 1, + [Defined when mingw does not support SEH]) + fi + + # + # Check to see if the excpt.h include file provided contains the + # definition for EXCEPTION_DISPOSITION; if not, which is the case + # with Cygwin's version as of 2002-04-10, define it to be int, + # sufficient for getting the current code to work. + # + AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files, + tcl_cv_eh_disposition, + AC_TRY_COMPILE([ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# undef WIN32_LEAN_AND_MEAN + ],[ + EXCEPTION_DISPOSITION x; + ], + tcl_cv_eh_disposition=yes, + tcl_cv_eh_disposition=no) + ) + if test "$tcl_cv_eh_disposition" = "no" ; then + AC_DEFINE(EXCEPTION_DISPOSITION, int, + [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION]) + fi + + # Check to see if winnt.h defines CHAR, SHORT, and LONG + # even if VOID has already been #defined. The win32api + # used by mingw and cygwin is known to do this. + + AC_CACHE_CHECK(for winnt.h that ignores VOID define, + tcl_cv_winnt_ignore_void, + AC_TRY_COMPILE([ +#define VOID void +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef WIN32_LEAN_AND_MEAN + ], [ + CHAR c; + SHORT s; + LONG l; + ], + tcl_cv_winnt_ignore_void=yes, + tcl_cv_winnt_ignore_void=no) + ) + if test "$tcl_cv_winnt_ignore_void" = "yes" ; then + AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1, + [Defined when cygwin/mingw ignores VOID define in winnt.h]) + fi + fi + + # See if the compiler supports casting to a union type. + # This is used to stop gcc from printing a compiler + # warning when initializing a union member. + + AC_CACHE_CHECK(for cast to union support, + tcl_cv_cast_to_union, + AC_TRY_COMPILE([], + [ + union foo { int i; double d; }; + union foo f = (union foo) (int) 0; + ], + tcl_cv_cast_to_union=yes, + tcl_cv_cast_to_union=no) + ) + if test "$tcl_cv_cast_to_union" = "yes"; then + AC_DEFINE(HAVE_CAST_TO_UNION, 1, + [Defined when compiler supports casting to union type.]) + fi + + AC_SUBST(CFLAGS_DEBUG) + AC_SUBST(CFLAGS_OPTIMIZE) + AC_SUBST(CFLAGS_WARNING) + + AC_SUBST(STLIB_LD) + AC_SUBST(SHLIB_LD) + + AC_SUBST(SHLIB_LD_LIBS) + AC_SUBST(SHLIB_CFLAGS) + + AC_SUBST(LD_LIBRARY_PATH_VAR) + + # These must be called after we do the basic CFLAGS checks and + # verify any possible 64-bit or similar switches are necessary + TEA_TCL_EARLY_FLAGS + TEA_TCL_64BIT_FLAGS +]) + +#-------------------------------------------------------------------- +# TEA_SERIAL_PORT +# +# Determine which interface to use to talk to the serial port. +# Note that #include lines must begin in leftmost column for +# some compilers to recognize them as preprocessor directives, +# and some build environments have stdin not pointing at a +# pseudo-terminal (usually /dev/null instead.) +# +# Arguments: +# none +# +# Results: +# +# Defines only one of the following vars: +# HAVE_SYS_MODEM_H +# USE_TERMIOS +# USE_TERMIO +# USE_SGTTY +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_SERIAL_PORT], [ + AC_CHECK_HEADERS(sys/modem.h) + AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [ + AC_TRY_RUN([ +#include <termios.h> + +int main() { + struct termios t; + if (tcgetattr(0, &t) == 0) { + cfsetospeed(&t, 0); + t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; +}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + if test $tcl_cv_api_serial = no ; then + AC_TRY_RUN([ +#include <termio.h> + +int main() { + struct termio t; + if (ioctl(0, TCGETA, &t) == 0) { + t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; +}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no ; then + AC_TRY_RUN([ +#include <sgtty.h> + +int main() { + struct sgttyb t; + if (ioctl(0, TIOCGETP, &t) == 0) { + t.sg_ospeed = 0; + t.sg_flags |= ODDP | EVENP | RAW; + return 0; + } + return 1; +}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no ; then + AC_TRY_RUN([ +#include <termios.h> +#include <errno.h> + +int main() { + struct termios t; + if (tcgetattr(0, &t) == 0 + || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { + cfsetospeed(&t, 0); + t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; +}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no; then + AC_TRY_RUN([ +#include <termio.h> +#include <errno.h> + +int main() { + struct termio t; + if (ioctl(0, TCGETA, &t) == 0 + || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { + t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; + }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no) + fi + if test $tcl_cv_api_serial = no; then + AC_TRY_RUN([ +#include <sgtty.h> +#include <errno.h> + +int main() { + struct sgttyb t; + if (ioctl(0, TIOCGETP, &t) == 0 + || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { + t.sg_ospeed = 0; + t.sg_flags |= ODDP | EVENP | RAW; + return 0; + } + return 1; +}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none) + fi]) + case $tcl_cv_api_serial in + termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);; + termio) AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);; + sgtty) AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);; + esac +]) + +#-------------------------------------------------------------------- +# TEA_MISSING_POSIX_HEADERS +# +# Supply substitutes for missing POSIX header files. Special +# notes: +# - stdlib.h doesn't define strtol, strtoul, or +# strtod in some versions of SunOS +# - some versions of string.h don't declare procedures such +# as strstr +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# NO_DIRENT_H +# NO_ERRNO_H +# NO_VALUES_H +# HAVE_LIMITS_H or NO_LIMITS_H +# NO_STDLIB_H +# NO_STRING_H +# NO_SYS_WAIT_H +# NO_DLFCN_H +# HAVE_SYS_PARAM_H +# +# HAVE_STRING_H ? +# +# tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and +# CHECK on limits.h +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_MISSING_POSIX_HEADERS], [ + AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [ + AC_TRY_LINK([#include <sys/types.h> +#include <dirent.h>], [ +#ifndef _POSIX_SOURCE +# ifdef __Lynx__ + /* + * Generate compilation error to make the test fail: Lynx headers + * are only valid if really in the POSIX environment. + */ + + missing_procedure(); +# endif +#endif +DIR *d; +struct dirent *entryPtr; +char *p; +d = opendir("foobar"); +entryPtr = readdir(d); +p = entryPtr->d_name; +closedir(d); +], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)]) + + if test $tcl_cv_dirent_h = no; then + AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?]) + fi + + # TEA specific: + AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])]) + AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])]) + AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])]) + AC_CHECK_HEADER(limits.h, + [AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have <limits.h>?])], + [AC_DEFINE(NO_LIMITS_H, 1, [Do we have <limits.h>?])]) + AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0) + AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0) + AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0) + AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0) + if test $tcl_ok = 0; then + AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?]) + fi + AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0) + AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0) + AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0) + + # See also memmove check below for a place where NO_STRING_H can be + # set and why. + + if test $tcl_ok = 0; then + AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?]) + fi + + AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])]) + AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])]) + + # OS/390 lacks sys/param.h (and doesn't need it, by chance). + AC_HAVE_HEADERS(sys/param.h) +]) + +#-------------------------------------------------------------------- +# TEA_PATH_X +# +# Locate the X11 header files and the X11 library archive. Try +# the ac_path_x macro first, but if it doesn't find the X stuff +# (e.g. because there's no xmkmf program) then check through +# a list of possible directories. Under some conditions the +# autoconf macro will return an include directory that contains +# no include files, so double-check its result just to be safe. +# +# This should be called after TEA_CONFIG_CFLAGS as setting the +# LIBS line can confuse some configure macro magic. +# +# Arguments: +# none +# +# Results: +# +# Sets the following vars: +# XINCLUDES +# XLIBSW +# PKG_LIBS (appends to) +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_PATH_X], [ + if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then + TEA_PATH_UNIX_X + fi +]) + +AC_DEFUN([TEA_PATH_UNIX_X], [ + AC_PATH_X + not_really_there="" + if test "$no_x" = ""; then + if test "$x_includes" = ""; then + AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes") + else + if test ! -r $x_includes/X11/Xlib.h; then + not_really_there="yes" + fi + fi + fi + if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then + AC_MSG_CHECKING([for X11 header files]) + found_xincludes="no" + AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no") + if test "$found_xincludes" = "no"; then + dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" + for i in $dirs ; do + if test -r $i/X11/Xlib.h; then + AC_MSG_RESULT([$i]) + XINCLUDES=" -I$i" + found_xincludes="yes" + break + fi + done + fi + else + if test "$x_includes" != ""; then + XINCLUDES="-I$x_includes" + found_xincludes="yes" + fi + fi + if test "$found_xincludes" = "no"; then + AC_MSG_RESULT([couldn't find any!]) + fi + + if test "$no_x" = yes; then + AC_MSG_CHECKING([for X11 libraries]) + XLIBSW=nope + dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" + for i in $dirs ; do + if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then + AC_MSG_RESULT([$i]) + XLIBSW="-L$i -lX11" + x_libraries="$i" + break + fi + done + else + if test "$x_libraries" = ""; then + XLIBSW=-lX11 + else + XLIBSW="-L$x_libraries -lX11" + fi + fi + if test "$XLIBSW" = nope ; then + AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow) + fi + if test "$XLIBSW" = nope ; then + AC_MSG_RESULT([could not find any! Using -lX11.]) + XLIBSW=-lX11 + fi + # TEA specific: + if test x"${XLIBSW}" != x ; then + PKG_LIBS="${PKG_LIBS} ${XLIBSW}" + fi +]) + +#-------------------------------------------------------------------- +# TEA_BLOCKING_STYLE +# +# The statements below check for systems where POSIX-style +# non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. +# On these systems (mostly older ones), use the old BSD-style +# FIONBIO approach instead. +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# HAVE_SYS_IOCTL_H +# HAVE_SYS_FILIO_H +# USE_FIONBIO +# O_NONBLOCK +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_BLOCKING_STYLE], [ + AC_CHECK_HEADERS(sys/ioctl.h) + AC_CHECK_HEADERS(sys/filio.h) + TEA_CONFIG_SYSTEM + AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O]) + case $system in + OSF*) + AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) + AC_MSG_RESULT([FIONBIO]) + ;; + *) + AC_MSG_RESULT([O_NONBLOCK]) + ;; + esac +]) + +#-------------------------------------------------------------------- +# TEA_TIME_HANDLER +# +# Checks how the system deals with time.h, what time structures +# are used on the system, and what fields the structures have. +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# USE_DELTA_FOR_TZ +# HAVE_TM_GMTOFF +# HAVE_TM_TZADJ +# HAVE_TIMEZONE_VAR +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_TIME_HANDLER], [ + AC_CHECK_HEADERS(sys/time.h) + AC_HEADER_TIME + AC_STRUCT_TIMEZONE + + AC_CHECK_FUNCS(gmtime_r localtime_r) + + AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [ + AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;], + tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)]) + if test $tcl_cv_member_tm_tzadj = yes ; then + AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?]) + fi + + AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [ + AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;], + tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)]) + if test $tcl_cv_member_tm_gmtoff = yes ; then + AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?]) + fi + + # + # Its important to include time.h in this check, as some systems + # (like convex) have timezone functions, etc. + # + AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [ + AC_TRY_COMPILE([#include <time.h>], + [extern long timezone; + timezone += 1; + exit (0);], + tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)]) + if test $tcl_cv_timezone_long = yes ; then + AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) + else + # + # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. + # + AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [ + AC_TRY_COMPILE([#include <time.h>], + [extern time_t timezone; + timezone += 1; + exit (0);], + tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)]) + if test $tcl_cv_timezone_time = yes ; then + AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) + fi + fi +]) + +#-------------------------------------------------------------------- +# TEA_BUGGY_STRTOD +# +# Under Solaris 2.4, strtod returns the wrong value for the +# terminating character under some conditions. Check for this +# and if the problem exists use a substitute procedure +# "fixstrtod" (provided by Tcl) that corrects the error. +# Also, on Compaq's Tru64 Unix 5.0, +# strtod(" ") returns 0.0 instead of a failure to convert. +# +# Arguments: +# none +# +# Results: +# +# Might defines some of the following vars: +# strtod (=fixstrtod) +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_BUGGY_STRTOD], [ + AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0) + if test "$tcl_strtod" = 1; then + AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[ + AC_TRY_RUN([ + extern double strtod(); + int main() { + char *infString="Inf", *nanString="NaN", *spaceString=" "; + char *term; + double value; + value = strtod(infString, &term); + if ((term != infString) && (term[-1] == 0)) { + exit(1); + } + value = strtod(nanString, &term); + if ((term != nanString) && (term[-1] == 0)) { + exit(1); + } + value = strtod(spaceString, &term); + if (term == (spaceString+1)) { + exit(1); + } + exit(0); + }], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy, + tcl_cv_strtod_buggy=buggy)]) + if test "$tcl_cv_strtod_buggy" = buggy; then + AC_LIBOBJ([fixstrtod]) + USE_COMPAT=1 + AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?]) + fi + fi +]) + +#-------------------------------------------------------------------- +# TEA_TCL_LINK_LIBS +# +# Search for the libraries needed to link the Tcl shell. +# Things like the math library (-lm) and socket stuff (-lsocket vs. +# -lnsl) are dealt with here. +# +# Arguments: +# Requires the following vars to be set in the Makefile: +# DL_LIBS (not in TEA, only needed in core) +# LIBS +# MATH_LIBS +# +# Results: +# +# Substitutes the following vars: +# TCL_LIBS +# MATH_LIBS +# +# Might append to the following vars: +# LIBS +# +# Might define the following vars: +# HAVE_NET_ERRNO_H +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_TCL_LINK_LIBS], [ + #-------------------------------------------------------------------- + # On a few very rare systems, all of the libm.a stuff is + # already in libc.a. Set compiler flags accordingly. + # Also, Linux requires the "ieee" library for math to work + # right (and it must appear before "-lm"). + #-------------------------------------------------------------------- + + AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm") + AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"]) + + #-------------------------------------------------------------------- + # Interactive UNIX requires -linet instead of -lsocket, plus it + # needs net/errno.h to define the socket-related error codes. + #-------------------------------------------------------------------- + + AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"]) + AC_CHECK_HEADER(net/errno.h, [ + AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])]) + + #-------------------------------------------------------------------- + # Check for the existence of the -lsocket and -lnsl libraries. + # The order here is important, so that they end up in the right + # order in the command line generated by make. Here are some + # special considerations: + # 1. Use "connect" and "accept" to check for -lsocket, and + # "gethostbyname" to check for -lnsl. + # 2. Use each function name only once: can't redo a check because + # autoconf caches the results of the last check and won't redo it. + # 3. Use -lnsl and -lsocket only if they supply procedures that + # aren't already present in the normal libraries. This is because + # IRIX 5.2 has libraries, but they aren't needed and they're + # bogus: they goof up name resolution if used. + # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. + # To get around this problem, check for both libraries together + # if -lsocket doesn't work by itself. + #-------------------------------------------------------------------- + + tcl_checkBoth=0 + AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1) + if test "$tcl_checkSocket" = 1; then + AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt, + LIBS="$LIBS -lsocket", tcl_checkBoth=1)]) + fi + if test "$tcl_checkBoth" = 1; then + tk_oldLibs=$LIBS + LIBS="$LIBS -lsocket -lnsl" + AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs]) + fi + AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname, + [LIBS="$LIBS -lnsl"])]) + + # TEA specific: Don't perform the eval of the libraries here because + # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS + + TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' + AC_SUBST(TCL_LIBS) + AC_SUBST(MATH_LIBS) +]) + +#-------------------------------------------------------------------- +# TEA_TCL_EARLY_FLAGS +# +# Check for what flags are needed to be passed so the correct OS +# features are available. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# _ISOC99_SOURCE +# _LARGEFILE64_SOURCE +# _LARGEFILE_SOURCE64 +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_TCL_EARLY_FLAG],[ + AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]), + AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no, + AC_TRY_COMPILE([[#define ]$1[ 1 +]$2], $3, + [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes, + [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no))) + if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then + AC_DEFINE($1, 1, [Add the ]$1[ flag when building]) + tcl_flags="$tcl_flags $1" + fi +]) + +AC_DEFUN([TEA_TCL_EARLY_FLAGS],[ + AC_MSG_CHECKING([for required early compiler flags]) + tcl_flags="" + TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>], + [char *p = (char *)strtoll; char *q = (char *)strtoull;]) + TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>], + [struct stat64 buf; int i = stat64("/", &buf);]) + TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>], + [char *p = (char *)open64;]) + if test "x${tcl_flags}" = "x" ; then + AC_MSG_RESULT([none]) + else + AC_MSG_RESULT([${tcl_flags}]) + fi +]) + +#-------------------------------------------------------------------- +# TEA_TCL_64BIT_FLAGS +# +# Check for what is defined in the way of 64-bit features. +# +# Arguments: +# None +# +# Results: +# +# Might define the following vars: +# TCL_WIDE_INT_IS_LONG +# TCL_WIDE_INT_TYPE +# HAVE_STRUCT_DIRENT64 +# HAVE_STRUCT_STAT64 +# HAVE_TYPE_OFF64_T +#-------------------------------------------------------------------- + +AC_DEFUN([TEA_TCL_64BIT_FLAGS], [ + AC_MSG_CHECKING([for 64-bit integer type]) + AC_CACHE_VAL(tcl_cv_type_64bit,[ + tcl_cv_type_64bit=none + # See if the compiler knows natively about __int64 + AC_TRY_COMPILE(,[__int64 value = (__int64) 0;], + tcl_type_64bit=__int64, tcl_type_64bit="long long") + # See if we should use long anyway Note that we substitute in the + # type that is our current guess for a 64-bit type inside this check + # program, so it should be modified only carefully... + AC_TRY_COMPILE(,[switch (0) { + case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ; + }],tcl_cv_type_64bit=${tcl_type_64bit})]) + if test "${tcl_cv_type_64bit}" = none ; then + AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?]) + AC_MSG_RESULT([using long]) + elif test "${tcl_cv_type_64bit}" = "__int64" \ + -a "${TEA_PLATFORM}" = "windows" ; then + # TEA specific: We actually want to use the default tcl.h checks in + # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* + AC_MSG_RESULT([using Tcl header defaults]) + else + AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit}, + [What type should be used to define wide integers?]) + AC_MSG_RESULT([${tcl_cv_type_64bit}]) + + # Now check for auxiliary declarations + AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[ + AC_TRY_COMPILE([#include <sys/types.h> +#include <dirent.h>],[struct dirent64 p;], + tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)]) + if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?]) + fi + + AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ + AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p; +], + tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)]) + if test "x${tcl_cv_struct_stat64}" = "xyes" ; then + AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?]) + fi + + AC_CHECK_FUNCS(open64 lseek64) + AC_MSG_CHECKING([for off64_t]) + AC_CACHE_VAL(tcl_cv_type_off64_t,[ + AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset; +], + tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)]) + dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the + dnl functions lseek64 and open64 are defined. + if test "x${tcl_cv_type_off64_t}" = "xyes" && \ + test "x${ac_cv_func_lseek64}" = "xyes" && \ + test "x${ac_cv_func_open64}" = "xyes" ; then + AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?]) + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + fi +]) + +## +## Here ends the standard Tcl configuration bits and starts the +## TEA specific functions +## + +#------------------------------------------------------------------------ +# TEA_INIT -- +# +# Init various Tcl Extension Architecture (TEA) variables. +# This should be the first called TEA_* macro. +# +# Arguments: +# none +# +# Results: +# +# Defines and substs the following vars: +# CYGPATH +# EXEEXT +# Defines only: +# TEA_VERSION +# TEA_INITED +# TEA_PLATFORM (windows or unix) +# +# "cygpath" is used on windows to generate native path names for include +# files. These variables should only be used with the compiler and linker +# since they generate native path names. +# +# EXEEXT +# Select the executable extension based on the host type. This +# is a lightweight replacement for AC_EXEEXT that doesn't require +# a compiler. +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_INIT], [ + # TEA extensions pass this us the version of TEA they think they + # are compatible with. + TEA_VERSION="3.9" + + AC_MSG_CHECKING([for correct TEA configuration]) + if test x"${PACKAGE_NAME}" = x ; then + AC_MSG_ERROR([ +The PACKAGE_NAME variable must be defined by your TEA configure.in]) + fi + if test x"$1" = x ; then + AC_MSG_ERROR([ +TEA version not specified.]) + elif test "$1" != "${TEA_VERSION}" ; then + AC_MSG_RESULT([warning: requested TEA version "$1", have "${TEA_VERSION}"]) + else + AC_MSG_RESULT([ok (TEA ${TEA_VERSION})]) + fi + + # If the user did not set CFLAGS, set it now to keep macros + # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". + if test "${CFLAGS+set}" != "set" ; then + CFLAGS="" + fi + + case "`uname -s`" in + *win32*|*WIN32*|*MINGW32_*) + AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo) + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *CYGWIN_*) + CYGPATH=echo + EXEEXT=".exe" + # TEA_PLATFORM is determined later in LOAD_TCLCONFIG + ;; + *) + CYGPATH=echo + # Maybe we are cross-compiling.... + case ${host_alias} in + *mingw32*) + EXEEXT=".exe" + TEA_PLATFORM="windows" + ;; + *) + EXEEXT="" + TEA_PLATFORM="unix" + ;; + esac + ;; + esac + + # Check if exec_prefix is set. If not use fall back to prefix. + # Note when adjusted, so that TEA_PREFIX can correct for this. + # This is needed for recursive configures, since autoconf propagates + # $prefix, but not $exec_prefix (doh!). + if test x$exec_prefix = xNONE ; then + exec_prefix_default=yes + exec_prefix=$prefix + fi + + AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}]) + + AC_SUBST(EXEEXT) + AC_SUBST(CYGPATH) + + # This package name must be replaced statically for AC_SUBST to work + AC_SUBST(PKG_LIB_FILE) + # Substitute STUB_LIB_FILE in case package creates a stub library too. + AC_SUBST(PKG_STUB_LIB_FILE) + + # We AC_SUBST these here to ensure they are subst'ed, + # in case the user doesn't call TEA_ADD_... + AC_SUBST(PKG_STUB_SOURCES) + AC_SUBST(PKG_STUB_OBJECTS) + AC_SUBST(PKG_TCL_SOURCES) + AC_SUBST(PKG_HEADERS) + AC_SUBST(PKG_INCLUDES) + AC_SUBST(PKG_LIBS) + AC_SUBST(PKG_CFLAGS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_SOURCES -- +# +# Specify one or more source files. Users should check for +# the right platform before adding to their list. +# It is not important to specify the directory, as long as it is +# in the generic, win or unix subdirectory of $(srcdir). +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_SOURCES +# PKG_OBJECTS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_SOURCES], [ + vars="$@" + for i in $vars; do + case $i in + [\$]*) + # allow $-var names + PKG_SOURCES="$PKG_SOURCES $i" + PKG_OBJECTS="$PKG_OBJECTS $i" + ;; + *) + # check for existence - allows for generic/win/unix VPATH + # To add more dirs here (like 'src'), you have to update VPATH + # in Makefile.in as well + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + AC_MSG_ERROR([could not find source file '$i']) + fi + PKG_SOURCES="$PKG_SOURCES $i" + # this assumes it is in a VPATH dir +# i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" + fi + PKG_OBJECTS="$PKG_OBJECTS $j" + ;; + esac + done + AC_SUBST(PKG_SOURCES) + AC_SUBST(PKG_OBJECTS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_STUB_SOURCES -- +# +# Specify one or more source files. Users should check for +# the right platform before adding to their list. +# It is not important to specify the directory, as long as it is +# in the generic, win or unix subdirectory of $(srcdir). +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_STUB_SOURCES +# PKG_STUB_OBJECTS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_STUB_SOURCES], [ + vars="$@" + for i in $vars; do + # check for existence - allows for generic/win/unix VPATH + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + AC_MSG_ERROR([could not find stub source file '$i']) + fi + PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" + fi + PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" + done + AC_SUBST(PKG_STUB_SOURCES) + AC_SUBST(PKG_STUB_OBJECTS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_TCL_SOURCES -- +# +# Specify one or more Tcl source files. These should be platform +# independent runtime files. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_TCL_SOURCES +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_TCL_SOURCES], [ + vars="$@" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i']) + fi + PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" + done + AC_SUBST(PKG_TCL_SOURCES) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_HEADERS -- +# +# Specify one or more source headers. Users should check for +# the right platform before adding to their list. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_HEADERS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_HEADERS], [ + vars="$@" + for i in $vars; do + # check for existence, be strict because it is installed + if test ! -f "${srcdir}/$i" ; then + AC_MSG_ERROR([could not find header file '${srcdir}/$i']) + fi + PKG_HEADERS="$PKG_HEADERS $i" + done + AC_SUBST(PKG_HEADERS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_INCLUDES -- +# +# Specify one or more include dirs. Users should check for +# the right platform before adding to their list. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_INCLUDES +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_INCLUDES], [ + vars="$@" + for i in $vars; do + PKG_INCLUDES="$PKG_INCLUDES $i" + done + AC_SUBST(PKG_INCLUDES) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_LIBS -- +# +# Specify one or more libraries. Users should check for +# the right platform before adding to their list. For Windows, +# libraries provided in "foo.lib" format will be converted to +# "-lfoo" when using GCC (mingw). +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_LIBS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_LIBS], [ + vars="$@" + for i in $vars; do + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then + # Convert foo.lib to -lfoo for GCC. No-op if not *.lib + i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.lib[$]/-l\1/i'` + fi + PKG_LIBS="$PKG_LIBS $i" + done + AC_SUBST(PKG_LIBS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_CFLAGS -- +# +# Specify one or more CFLAGS. Users should check for +# the right platform before adding to their list. +# +# Arguments: +# one or more file names +# +# Results: +# +# Defines and substs the following vars: +# PKG_CFLAGS +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_CFLAGS], [ + PKG_CFLAGS="$PKG_CFLAGS $@" + AC_SUBST(PKG_CFLAGS) +]) + +#------------------------------------------------------------------------ +# TEA_ADD_CLEANFILES -- +# +# Specify one or more CLEANFILES. +# +# Arguments: +# one or more file names to clean target +# +# Results: +# +# Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG +#------------------------------------------------------------------------ +AC_DEFUN([TEA_ADD_CLEANFILES], [ + CLEANFILES="$CLEANFILES $@" +]) + +#------------------------------------------------------------------------ +# TEA_PREFIX -- +# +# Handle the --prefix=... option by defaulting to what Tcl gave +# +# Arguments: +# none +# +# Results: +# +# If --prefix or --exec-prefix was not specified, $prefix and +# $exec_prefix will be set to the values given to Tcl when it was +# configured. +#------------------------------------------------------------------------ +AC_DEFUN([TEA_PREFIX], [ + if test "${prefix}" = "NONE"; then + prefix_default=yes + if test x"${TCL_PREFIX}" != x; then + AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}]) + prefix=${TCL_PREFIX} + else + AC_MSG_NOTICE([--prefix defaulting to /usr/local]) + prefix=/usr/local + fi + fi + if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ + -o x"${exec_prefix_default}" = x"yes" ; then + if test x"${TCL_EXEC_PREFIX}" != x; then + AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}]) + exec_prefix=${TCL_EXEC_PREFIX} + else + AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}]) + exec_prefix=$prefix + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_SETUP_COMPILER_CC -- +# +# Do compiler checks the way we want. This is just a replacement +# for AC_PROG_CC in TEA configure.in files to make them cleaner. +# +# Arguments: +# none +# +# Results: +# +# Sets up CC var and other standard bits we need to make executables. +#------------------------------------------------------------------------ +AC_DEFUN([TEA_SETUP_COMPILER_CC], [ + # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) + # in this macro, they need to go into TEA_SETUP_COMPILER instead. + + AC_PROG_CC + AC_PROG_CPP + + INSTALL="\$(SHELL) \$(srcdir)/tclconfig/install-sh -c" + AC_SUBST(INSTALL) + + #-------------------------------------------------------------------- + # Checks to see if the make program sets the $MAKE variable. + #-------------------------------------------------------------------- + + AC_PROG_MAKE_SET + + #-------------------------------------------------------------------- + # Find ranlib + #-------------------------------------------------------------------- + + AC_CHECK_TOOL(RANLIB, ranlib) + + #-------------------------------------------------------------------- + # Determines the correct binary file extension (.o, .obj, .exe etc.) + #-------------------------------------------------------------------- + + AC_OBJEXT + AC_EXEEXT +]) + +#------------------------------------------------------------------------ +# TEA_SETUP_COMPILER -- +# +# Do compiler checks that use the compiler. This must go after +# TEA_SETUP_COMPILER_CC, which does the actual compiler check. +# +# Arguments: +# none +# +# Results: +# +# Sets up CC var and other standard bits we need to make executables. +#------------------------------------------------------------------------ +AC_DEFUN([TEA_SETUP_COMPILER], [ + # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. + AC_REQUIRE([TEA_SETUP_COMPILER_CC]) + + #------------------------------------------------------------------------ + # If we're using GCC, see if the compiler understands -pipe. If so, use it. + # It makes compiling go faster. (This is only a performance feature.) + #------------------------------------------------------------------------ + + if test -z "$no_pipe" -a -n "$GCC"; then + AC_CACHE_CHECK([if the compiler understands -pipe], + tcl_cv_cc_pipe, [ + hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" + AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no) + CFLAGS=$hold_cflags]) + if test $tcl_cv_cc_pipe = yes; then + CFLAGS="$CFLAGS -pipe" + fi + fi + + #-------------------------------------------------------------------- + # Common compiler flag setup + #-------------------------------------------------------------------- + + AC_C_BIGENDIAN + if test "${TEA_PLATFORM}" = "unix" ; then + TEA_TCL_LINK_LIBS + TEA_MISSING_POSIX_HEADERS + # Let the user call this, because if it triggers, they will + # need a compat/strtod.c that is correct. Users can also + # use Tcl_GetDouble(FromObj) instead. + #TEA_BUGGY_STRTOD + fi +]) + +#------------------------------------------------------------------------ +# TEA_MAKE_LIB -- +# +# Generate a line that can be used to build a shared/unshared library +# in a platform independent manner. +# +# Arguments: +# none +# +# Requires: +# +# Results: +# +# Defines the following vars: +# CFLAGS - Done late here to note disturb other AC macros +# MAKE_LIB - Command to execute to build the Tcl library; +# differs depending on whether or not Tcl is being +# compiled as a shared library. +# MAKE_SHARED_LIB Makefile rule for building a shared library +# MAKE_STATIC_LIB Makefile rule for building a static library +# MAKE_STUB_LIB Makefile rule for building a stub library +# VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL +# VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_MAKE_LIB], [ + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then + MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)" + AC_EGREP_CPP([manifest needed], [ +#if defined(_MSC_VER) && _MSC_VER >= 1400 +print("manifest needed") +#endif + ], [ + # Could do a CHECK_PROG for mt, but should always be with MSVC8+ + VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi" + VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi" + MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" + TEA_ADD_CLEANFILES([*.manifest]) + ]) + MAKE_STUB_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_STUB_OBJECTS)" + else + MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" + MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)" + fi + + if test "${SHARED_BUILD}" = "1" ; then + MAKE_LIB="${MAKE_SHARED_LIB} " + else + MAKE_LIB="${MAKE_STATIC_LIB} " + fi + + #-------------------------------------------------------------------- + # Shared libraries and static libraries have different names. + # Use the double eval to make sure any variables in the suffix is + # substituted. (@@@ Might not be necessary anymore) + #-------------------------------------------------------------------- + + if test "${TEA_PLATFORM}" = "windows" ; then + if test "${SHARED_BUILD}" = "1" ; then + # We force the unresolved linking of symbols that are really in + # the private libraries of Tcl and Tk. + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" + fi + eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + else + eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + if test "$GCC" = "yes"; then + PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} + fi + # These aren't needed on Windows (either MSVC or gcc) + RANLIB=: + RANLIB_STUB=: + else + RANLIB_STUB="${RANLIB}" + if test "${SHARED_BUILD}" = "1" ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" + if test x"${TK_BIN_DIR}" != x ; then + SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" + fi + eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" + RANLIB=: + else + eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" + fi + # Some packages build their own stubs libraries + eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" + fi + + # These are escaped so that only CFLAGS is picked up at configure time. + # The other values will be substituted at make time. + CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" + if test "${SHARED_BUILD}" = "1" ; then + CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" + fi + + AC_SUBST(MAKE_LIB) + AC_SUBST(MAKE_SHARED_LIB) + AC_SUBST(MAKE_STATIC_LIB) + AC_SUBST(MAKE_STUB_LIB) + AC_SUBST(RANLIB_STUB) + AC_SUBST(VC_MANIFEST_EMBED_DLL) + AC_SUBST(VC_MANIFEST_EMBED_EXE) +]) + +#------------------------------------------------------------------------ +# TEA_LIB_SPEC -- +# +# Compute the name of an existing object library located in libdir +# from the given base name and produce the appropriate linker flags. +# +# Arguments: +# basename The base name of the library without version +# numbers, extensions, or "lib" prefixes. +# extra_dir Extra directory in which to search for the +# library. This location is used first, then +# $prefix/$exec-prefix, then some defaults. +# +# Requires: +# TEA_INIT and TEA_PREFIX must be called first. +# +# Results: +# +# Defines the following vars: +# ${basename}_LIB_NAME The computed library name. +# ${basename}_LIB_SPEC The computed linker flags. +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LIB_SPEC], [ + AC_MSG_CHECKING([for $1 library]) + + # Look in exec-prefix for the library (defined by TEA_PREFIX). + + tea_lib_name_dir="${exec_prefix}/lib" + + # Or in a user-specified location. + + if test x"$2" != x ; then + tea_extra_lib_dir=$2 + else + tea_extra_lib_dir=NONE + fi + + for i in \ + `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr /usr/lib64/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr /usr/lib64/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do + if test -f "$i" ; then + tea_lib_name_dir=`dirname $i` + $1_LIB_NAME=`basename $i` + $1_LIB_PATH_NAME=$i + break + fi + done + + if test "${TEA_PLATFORM}" = "windows"; then + $1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\" + else + # Strip off the leading "lib" and trailing ".a" or ".so" + + tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'` + $1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}" + fi + + if test "x${$1_LIB_NAME}" = x ; then + AC_MSG_ERROR([not found]) + else + AC_MSG_RESULT([${$1_LIB_SPEC}]) + fi +]) + +#------------------------------------------------------------------------ +# TEA_PRIVATE_TCL_HEADERS -- +# +# Locate the private Tcl include files +# +# Arguments: +# +# Requires: +# TCL_SRC_DIR Assumes that TEA_LOAD_TCLCONFIG has +# already been called. +# +# Results: +# +# Substitutes the following vars: +# TCL_TOP_DIR_NATIVE +# TCL_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [ + # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh} + AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS]) + AC_MSG_CHECKING([for Tcl private include files]) + + TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}` + TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\" + + # Check to see if tcl<Plat>Port.h isn't already with the public headers + # Don't look for tclInt.h because that resides with tcl.h in the core + # sources, but the <plat>Port headers are in a different directory + if test "${TEA_PLATFORM}" = "windows" -a \ + -f "${ac_cv_c_tclh}/tclWinPort.h"; then + result="private headers found with public headers" + elif test "${TEA_PLATFORM}" = "unix" -a \ + -f "${ac_cv_c_tclh}/tclUnixPort.h"; then + result="private headers found with public headers" + else + TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" + if test "${TEA_PLATFORM}" = "windows"; then + TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" + else + TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" + fi + # Overwrite the previous TCL_INCLUDES as this should capture both + # public and private headers in the same set. + # We want to ensure these are substituted so as not to require + # any *_NATIVE vars be defined in the Makefile + TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}" + if test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use + # the framework's Headers and PrivateHeaders directories + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + if test -d "${TCL_BIN_DIR}/Headers" -a \ + -d "${TCL_BIN_DIR}/PrivateHeaders"; then + TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}" + else + TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" + fi + ;; + esac + result="Using ${TCL_INCLUDES}" + else + if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then + AC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}]) + fi + result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" + fi + fi + + AC_SUBST(TCL_TOP_DIR_NATIVE) + + AC_SUBST(TCL_INCLUDES) + AC_MSG_RESULT([${result}]) +]) + +#------------------------------------------------------------------------ +# TEA_PUBLIC_TCL_HEADERS -- +# +# Locate the installed public Tcl header files +# +# Arguments: +# None. +# +# Requires: +# CYGPATH must be set +# +# Results: +# +# Adds a --with-tclinclude switch to configure. +# Result is cached. +# +# Substitutes the following vars: +# TCL_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [ + AC_MSG_CHECKING([for Tcl public headers]) + + AC_ARG_WITH(tclinclude, [ --with-tclinclude directory containing the public Tcl header files], with_tclinclude=${withval}) + + AC_CACHE_VAL(ac_cv_c_tclh, [ + # Use the value from --with-tclinclude, if it was given + + if test x"${with_tclinclude}" != x ; then + if test -f "${with_tclinclude}/tcl.h" ; then + ac_cv_c_tclh=${with_tclinclude} + else + AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h]) + fi + else + list="" + if test "`uname -s`" = "Darwin"; then + # If Tcl was built as a framework, attempt to use + # the framework's Headers directory + case ${TCL_DEFS} in + *TCL_FRAMEWORK*) + list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" + ;; + esac + fi + + # Look in the source dir only if Tcl is not installed, + # and in that situation, look there before installed locations. + if test -f "${TCL_BIN_DIR}/Makefile" ; then + list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" + fi + + # Check order: pkg --prefix location, Tcl's --prefix location, + # relative to directory of tclConfig.sh. + + eval "temp_includedir=${includedir}" + list="$list \ + `ls -d ${temp_includedir} 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" + if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then + list="$list /usr/local/include /usr/include" + if test x"${TCL_INCLUDE_SPEC}" != x ; then + d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` + list="$list `ls -d ${d} 2>/dev/null`" + fi + fi + for i in $list ; do + if test -f "$i/tcl.h" ; then + ac_cv_c_tclh=$i + break + fi + done + fi + ]) + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tclh}" = x ; then + AC_MSG_ERROR([tcl.h not found. Please specify its location with --with-tclinclude]) + else + AC_MSG_RESULT([${ac_cv_c_tclh}]) + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` + + TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + AC_SUBST(TCL_INCLUDES) +]) + +#------------------------------------------------------------------------ +# TEA_PRIVATE_TK_HEADERS -- +# +# Locate the private Tk include files +# +# Arguments: +# +# Requires: +# TK_SRC_DIR Assumes that TEA_LOAD_TKCONFIG has +# already been called. +# +# Results: +# +# Substitutes the following vars: +# TK_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [ + # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh} + AC_REQUIRE([TEA_PUBLIC_TK_HEADERS]) + AC_MSG_CHECKING([for Tk private include files]) + + TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}` + TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\" + + # Check to see if tk<Plat>Port.h isn't already with the public headers + # Don't look for tkInt.h because that resides with tk.h in the core + # sources, but the <plat>Port headers are in a different directory + if test "${TEA_PLATFORM}" = "windows" -a \ + -f "${ac_cv_c_tkh}/tkWinPort.h"; then + result="private headers found with public headers" + elif test "${TEA_PLATFORM}" = "unix" -a \ + -f "${ac_cv_c_tkh}/tkUnixPort.h"; then + result="private headers found with public headers" + else + TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\" + TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\" + if test "${TEA_PLATFORM}" = "windows"; then + TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\" + else + TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\" + fi + # Overwrite the previous TK_INCLUDES as this should capture both + # public and private headers in the same set. + # We want to ensure these are substituted so as not to require + # any *_NATIVE vars be defined in the Makefile + TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}" + # Detect and add ttk subdir + if test -d "${TK_SRC_DIR}/generic/ttk"; then + TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\"" + fi + if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then + TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\"" + fi + if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then + TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\"" + fi + if test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use + # the framework's Headers and PrivateHeaders directories + case ${TK_DEFS} in + *TK_FRAMEWORK*) + if test -d "${TK_BIN_DIR}/Headers" -a \ + -d "${TK_BIN_DIR}/PrivateHeaders"; then + TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}" + else + TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" + fi + ;; + esac + result="Using ${TK_INCLUDES}" + else + if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then + AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}]) + fi + result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}" + fi + fi + + AC_SUBST(TK_TOP_DIR_NATIVE) + AC_SUBST(TK_XLIB_DIR_NATIVE) + + AC_SUBST(TK_INCLUDES) + AC_MSG_RESULT([${result}]) +]) + +#------------------------------------------------------------------------ +# TEA_PUBLIC_TK_HEADERS -- +# +# Locate the installed public Tk header files +# +# Arguments: +# None. +# +# Requires: +# CYGPATH must be set +# +# Results: +# +# Adds a --with-tkinclude switch to configure. +# Result is cached. +# +# Substitutes the following vars: +# TK_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [ + AC_MSG_CHECKING([for Tk public headers]) + + AC_ARG_WITH(tkinclude, [ --with-tkinclude directory containing the public Tk header files], with_tkinclude=${withval}) + + AC_CACHE_VAL(ac_cv_c_tkh, [ + # Use the value from --with-tkinclude, if it was given + + if test x"${with_tkinclude}" != x ; then + if test -f "${with_tkinclude}/tk.h" ; then + ac_cv_c_tkh=${with_tkinclude} + else + AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h]) + fi + else + list="" + if test "`uname -s`" = "Darwin"; then + # If Tk was built as a framework, attempt to use + # the framework's Headers directory. + case ${TK_DEFS} in + *TK_FRAMEWORK*) + list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`" + ;; + esac + fi + + # Look in the source dir only if Tk is not installed, + # and in that situation, look there before installed locations. + if test -f "${TK_BIN_DIR}/Makefile" ; then + list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`" + fi + + # Check order: pkg --prefix location, Tk's --prefix location, + # relative to directory of tkConfig.sh, Tcl's --prefix location, + # relative to directory of tclConfig.sh. + + eval "temp_includedir=${includedir}" + list="$list \ + `ls -d ${temp_includedir} 2>/dev/null` \ + `ls -d ${TK_PREFIX}/include 2>/dev/null` \ + `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \ + `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ + `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" + if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then + list="$list /usr/local/include /usr/include" + if test x"${TK_INCLUDE_SPEC}" != x ; then + d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'` + list="$list `ls -d ${d} 2>/dev/null`" + fi + fi + for i in $list ; do + if test -f "$i/tk.h" ; then + ac_cv_c_tkh=$i + break + fi + done + fi + ]) + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tkh}" = x ; then + AC_MSG_ERROR([tk.h not found. Please specify its location with --with-tkinclude]) + else + AC_MSG_RESULT([${ac_cv_c_tkh}]) + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}` + + TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + AC_SUBST(TK_INCLUDES) + + if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then + # On Windows and Aqua, we need the X compat headers + AC_MSG_CHECKING([for X11 header files]) + if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then + INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`" + TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + AC_SUBST(TK_XINCLUDES) + fi + AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}]) + fi +]) + +#------------------------------------------------------------------------ +# TEA_PATH_CONFIG -- +# +# Locate the ${1}Config.sh file and perform a sanity check on +# the ${1} compile flags. These are used by packages like +# [incr Tk] that load *Config.sh files from more than Tcl and Tk. +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-$1=... +# +# Defines the following vars: +# $1_BIN_DIR Full path to the directory containing +# the $1Config.sh file +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_CONFIG], [ + # + # Ok, lets find the $1 configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-$1 + # + + if test x"${no_$1}" = x ; then + # we reset no_$1 in case something fails here + no_$1=true + AC_ARG_WITH($1, [ --with-$1 directory containing $1 configuration ($1Config.sh)], with_$1config=${withval}) + AC_MSG_CHECKING([for $1 configuration]) + AC_CACHE_VAL(ac_cv_c_$1config,[ + + # First check to see if --with-$1 was specified. + if test x"${with_$1config}" != x ; then + case ${with_$1config} in + */$1Config.sh ) + if test -f ${with_$1config}; then + AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself]) + with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'` + fi;; + esac + if test -f "${with_$1config}/$1Config.sh" ; then + ac_cv_c_$1config=`(cd ${with_$1config}; pwd)` + else + AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh]) + fi + fi + + # then check for a private $1 installation + if test x"${ac_cv_c_$1config}" = x ; then + for i in \ + ../$1 \ + `ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ../../$1 \ + `ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ../../../$1 \ + `ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ${srcdir}/../$1 \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ + ; do + if test -f "$i/$1Config.sh" ; then + ac_cv_c_$1config=`(cd $i; pwd)` + break + fi + if test -f "$i/unix/$1Config.sh" ; then + ac_cv_c_$1config=`(cd $i/unix; pwd)` + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_$1config}" = x ; then + for i in `ls -d ${libdir} 2>/dev/null` \ + `ls -d ${exec_prefix}/lib 2>/dev/null` \ + `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` \ + `ls -d /usr/lib64 2>/dev/null` \ + ; do + if test -f "$i/$1Config.sh" ; then + ac_cv_c_$1config=`(cd $i; pwd)` + break + fi + done + fi + ]) + + if test x"${ac_cv_c_$1config}" = x ; then + $1_BIN_DIR="# no $1 configs found" + AC_MSG_WARN([Cannot find $1 configuration definitions]) + exit 0 + else + no_$1= + $1_BIN_DIR=${ac_cv_c_$1config} + AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh]) + fi + fi +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_CONFIG -- +# +# Load the $1Config.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# $1_BIN_DIR +# +# Results: +# +# Substitutes the following vars: +# $1_SRC_DIR +# $1_LIB_FILE +# $1_LIB_SPEC +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_LOAD_CONFIG], [ + AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh]) + + if test -f "${$1_BIN_DIR}/$1Config.sh" ; then + AC_MSG_RESULT([loading]) + . "${$1_BIN_DIR}/$1Config.sh" + else + AC_MSG_RESULT([file not found]) + fi + + # + # If the $1_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable $1_LIB_SPEC will be set to the value + # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC + # instead of $1_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + # + + if test -f "${$1_BIN_DIR}/Makefile" ; then + AC_MSG_WARN([Found Makefile - using build library specs for $1]) + $1_LIB_SPEC=${$1_BUILD_LIB_SPEC} + $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC} + $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH} + $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC} + $1_LIBRARY_PATH=${$1_LIBRARY_PATH} + fi + + AC_SUBST($1_VERSION) + AC_SUBST($1_BIN_DIR) + AC_SUBST($1_SRC_DIR) + + AC_SUBST($1_LIB_FILE) + AC_SUBST($1_LIB_SPEC) + + AC_SUBST($1_STUB_LIB_FILE) + AC_SUBST($1_STUB_LIB_SPEC) + AC_SUBST($1_STUB_LIB_PATH) + + # Allow the caller to prevent this auto-check by specifying any 2nd arg + AS_IF([test "x$2" = x], [ + # Check both upper and lower-case variants + # If a dev wanted non-stubs libs, this function could take an option + # to not use _STUB in the paths below + AS_IF([test "x${$1_STUB_LIB_SPEC}" = x], + [TEA_LOAD_CONFIG_LIB(translit($1,[a-z],[A-Z])_STUB)], + [TEA_LOAD_CONFIG_LIB($1_STUB)]) + ]) +]) + +#------------------------------------------------------------------------ +# TEA_LOAD_CONFIG_LIB -- +# +# Helper function to load correct library from another extension's +# ${PACKAGE}Config.sh. +# +# Results: +# Adds to LIBS the appropriate extension library +#------------------------------------------------------------------------ +AC_DEFUN([TEA_LOAD_CONFIG_LIB], [ + AC_MSG_CHECKING([For $1 library for LIBS]) + # This simplifies the use of stub libraries by automatically adding + # the stub lib to your path. Normally this would add to SHLIB_LD_LIBS, + # but this is called before CONFIG_CFLAGS. More importantly, this adds + # to PKG_LIBS, which becomes LIBS, and that is only used by SHLIB_LD. + if test "x${$1_LIB_SPEC}" != "x" ; then + if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes" ; then + TEA_ADD_LIBS([\"`${CYGPATH} ${$1_LIB_PATH}`\"]) + AC_MSG_RESULT([using $1_LIB_PATH ${$1_LIB_PATH}]) + else + TEA_ADD_LIBS([${$1_LIB_SPEC}]) + AC_MSG_RESULT([using $1_LIB_SPEC ${$1_LIB_SPEC}]) + fi + else + AC_MSG_RESULT([file not found]) + fi +]) + +#------------------------------------------------------------------------ +# TEA_EXPORT_CONFIG -- +# +# Define the data to insert into the ${PACKAGE}Config.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# $1 +# +# Results: +# Substitutes the following vars: +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_EXPORT_CONFIG], [ + #-------------------------------------------------------------------- + # These are for $1Config.sh + #-------------------------------------------------------------------- + + # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib) + eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}" + if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then + eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}${DBGX}" + eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}${DBGX}" + else + eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}" + eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}" + fi + $1_BUILD_LIB_SPEC="-L`pwd` ${$1_LIB_FLAG}" + $1_LIB_SPEC="-L${pkglibdir} ${$1_LIB_FLAG}" + $1_BUILD_STUB_LIB_SPEC="-L`pwd` [$]{$1_STUB_LIB_FLAG}" + $1_STUB_LIB_SPEC="-L${pkglibdir} [$]{$1_STUB_LIB_FLAG}" + $1_BUILD_STUB_LIB_PATH="`pwd`/[$]{PKG_STUB_LIB_FILE}" + $1_STUB_LIB_PATH="${pkglibdir}/[$]{PKG_STUB_LIB_FILE}" + + AC_SUBST($1_BUILD_LIB_SPEC) + AC_SUBST($1_LIB_SPEC) + AC_SUBST($1_BUILD_STUB_LIB_SPEC) + AC_SUBST($1_STUB_LIB_SPEC) + AC_SUBST($1_BUILD_STUB_LIB_PATH) + AC_SUBST($1_STUB_LIB_PATH) + + AC_SUBST(MAJOR_VERSION) + AC_SUBST(MINOR_VERSION) + AC_SUBST(PATCHLEVEL) +]) + + +#------------------------------------------------------------------------ +# TEA_PATH_CELIB -- +# +# Locate Keuchel's celib emulation layer for targeting Win/CE +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-celib=... +# +# Defines the following vars: +# CELIB_DIR Full path to the directory containing +# the include and platform lib files +#------------------------------------------------------------------------ + +AC_DEFUN([TEA_PATH_CELIB], [ + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-celib + + if test x"${no_celib}" = x ; then + # we reset no_celib in case something fails here + no_celib=true + AC_ARG_WITH(celib,[ --with-celib=DIR use Windows/CE support library from DIR], with_celibconfig=${withval}) + AC_MSG_CHECKING([for Windows/CE celib directory]) + AC_CACHE_VAL(ac_cv_c_celibconfig,[ + # First check to see if --with-celibconfig was specified. + if test x"${with_celibconfig}" != x ; then + if test -d "${with_celibconfig}/inc" ; then + ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)` + else + AC_MSG_ERROR([${with_celibconfig} directory doesn't contain inc directory]) + fi + fi + + # then check for a celib library + if test x"${ac_cv_c_celibconfig}" = x ; then + for i in \ + ../celib-palm-3.0 \ + ../celib \ + ../../celib-palm-3.0 \ + ../../celib \ + `ls -dr ../celib-*3.[[0-9]]* 2>/dev/null` \ + ${srcdir}/../celib-palm-3.0 \ + ${srcdir}/../celib \ + `ls -dr ${srcdir}/../celib-*3.[[0-9]]* 2>/dev/null` \ + ; do + if test -d "$i/inc" ; then + ac_cv_c_celibconfig=`(cd $i; pwd)` + break + fi + done + fi + ]) + if test x"${ac_cv_c_celibconfig}" = x ; then + AC_MSG_ERROR([Cannot find celib support library directory]) + else + no_celib= + CELIB_DIR=${ac_cv_c_celibconfig} + CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` + AC_MSG_RESULT([found $CELIB_DIR]) + fi + fi +]) + + +# Local Variables: +# mode: autoconf +# End: diff --git a/tkhtml1/tests/all.test b/tkhtml1/tests/all.test new file mode 100644 index 0000000..4a1d17d --- /dev/null +++ b/tkhtml1/tests/all.test @@ -0,0 +1,8 @@ +# Run all tests +# +cd [file dirname $argv0] +set me [file tail $argv0] +foreach file [lsort -dictionary [glob *.test]] { + if {$file==$me} continue + source $file +} diff --git a/tkhtml1/tests/engine.tcl b/tkhtml1/tests/engine.tcl new file mode 100644 index 0000000..2739b40 --- /dev/null +++ b/tkhtml1/tests/engine.tcl @@ -0,0 +1,144 @@ +# This file contains the test driver for the html widget. It defines +# a special version of the test procedure to use for testing the +# html widget. +# + +# Initialize variables +# +namespace eval tcltest { + set mode run + set current {} + set passed 0 + set failed 0 + set total 0 + set status {} +} + +# Arguments: +# +# tag A symbolic tag for this test. Ex: html-1.0 +# +# desc A human-readable description of what this test does. +# +# script Tcl code to implement the test +# +# result The expected result from this test. If the actual result +# is different the test fails. +# +proc ::tcltest::test {tag desc script result} { + ::tcltest::change-desc $tag $desc + if {[info exists ::tcltest::idle]} { + catch {after cancel $::tcltest::idle} + catch {unset ::tcltest::idle} + } + set rc [catch {uplevel #0 $script} msg] + set r [list $rc $msg] + if {$r==$result} { + incr ::tcltest::passed + puts "---- Test $tag passed" + } else { + incr ::tcltest::failed + puts "**** Test $tag failed" + puts "Expected: [list $result]" + puts "Got: [list $r]" + } + incr ::tcltest::total + ::tcltest::update-status + set ::tcltest::idle [after 100 ::tcltest::testing-complete] +} + +# Create the test control window +# +proc ::tcltest::mainwin {} { + set w .testinfo + toplevel $w + wm title $w {Html Widget Test Information} + wm iconname $w {Html-Test} + set f $w.f1 + frame $f + pack $f -side top -fill x + label $f.l -text {Status: } + label $f.v -textvariable ::tcltest::status + pack $f.l $f.v -side left + set f $w.f2 + frame $f + pack $f -side top -fill x + label $f.l -text {Current Test: } + label $f.v -textvariable ::tcltest::current + pack $f.l $f.v -side left + set f $w.b + frame $f + pack $f -side bottom -fill x + button $f.pause -text Pause -command ::tcltest::pause + button $f.pass -text {Pass} -command {::tcltest::set-result pass} + button $f.fail -text {Fail} -command {::tcltest::set-result fail} + button $f.exit -text Exit -command exit + pack $f.pause $f.pass $f.fail $f.exit -side right -pady 10 -expand 1 + scrollbar $w.sb -orient vertical -command "$w.t yview" + pack $w.sb -side right -fill y + html $w.t -yscrollcommand "$w.sb set" -width 400 -height 150 \ + -bd 2 -relief sunken -padx 5 -pady 5 + pack $w.t -side right -fill both -expand 1 + ::tcltest::update-status +} + +# Change the test description in the control window +# +proc ::tcltest::change-desc {tag desc} { + if {![winfo exists .testinfo]} ::tcltest::mainwin + .testinfo.t clear + .testinfo.t parse $desc\n + set ::tcltest::current $tag +} + +# Update the status line +# +proc ::tcltest::update-status {} { + set v "$::tcltest::passed passed $::tcltest::failed failed " + append v "$::tcltest::total total" + set ::tcltest::status $v +} + +# Wait for the user to press either the pass or failed buttons. +# +proc ::tcltest::user-result {} { + .testinfo.b.pass config -state normal + .testinfo.b.fail config -state normal + update + raise .testinfo + focus .testinfo.b.pass + set ::tcltest::result {} + vwait ::tcltest::result + .testinfo.b.pass config -state disabled + .testinfo.b.fail config -state disabled + return $::tcltest::result +} + +# Called when the user presses either the failed or passed buttons. +# +proc ::tcltest::set-result v { + set ::tcltest::result $v +} + +# Call this routine at the end of all tests +# +proc ::tcltest::testing-complete {} { + ::tcltest::change-desc {} {Testing is now complete} +} + +# Construct an HTML widget to use for testing. +# +proc tkhtml_test_widget {} { + set w .tkhtml_test + if {[winfo exists $w]} { + return $w.h + } + toplevel $w + wm title $w {TkHtml Test Widget} + wm iconname $w {TkHtml Test} + scrollbar $w.sb -orient vertical -command "$w.h yview" + pack $w.sb -side right -fill y + html $w.h -yscrollcommand "$w.sb set" + pack $w.h -side right -fill both -expand 1 + return $w.h +} diff --git a/tkhtml1/tests/html1.test b/tkhtml1/tests/html1.test new file mode 100644 index 0000000..043113a --- /dev/null +++ b/tkhtml1/tests/html1.test @@ -0,0 +1,181 @@ +# +# Test script for the Tk HTML widget +# +wm withdraw . +if {[lsearch [namespace children] ::tcltest] == -1} { + source [file dirname $argv0]/engine.tcl + namespace import ::tcltest::* +} + +::tcltest::test html-1.0 { + Verify that all of the entites are displayed correctly. +} { + set h [tkhtml_test_widget] + $h clear + $h parse { +<html> +<h1>Entity and special character test</h1> +<p>The following list shows each entity of HTML 3.2 in four +formats: (1) the name, (2) as &entity;, (3) as &#123;, and +(4) as a raw UTF-8 or Ascii character.</p> +<ul> +<li> quot " " " </li> +<li> amp & & & </li> +<li> lt < < < </li> +<li> gt > > > </li> +<li> nbsp   </li> +<li> iexcl ¡ ¡ ¡ </li> +<li> cent ¢ ¢ ¢ </li> +<li> pound £ £ £ </li> +<li> curren ¤ ¤ ¤ </li> +<li> yen ¥ ¥ ¥ </li> +<li> brvbar ¦ ¦ ¦ </li> +<li> sect § § § </li> +<li> uml ¨ ¨ ¨ </li> +<li> copy © © © </li> +<li> ordf ª ª ª </li> +<li> laquo « « « </li> +<li> not ¬ ¬ ¬ </li> +<li> shy ­ ­ </li> +<li> reg ® ® ® </li> +<li> macr ¯ ¯ ¯ </li> +<li> deg ° ° ° </li> +<li> plusmn ± ± ± </li> +<li> sup2 ² ² ² </li> +<li> sup3 ³ ³ ³ </li> +<li> acute ´ ´ ´ </li> +<li> micro µ µ µ </li> +<li> para ¶ ¶ ¶ </li> +<li> middot · · · </li> +<li> cedil ¸ ¸ ¸ </li> +<li> sup1 ¹ ¹ ¹ </li> +<li> ordm º º º </li> +<li> raquo » » » </li> +<li> frac14 ¼ ¼ ¼ </li> +<li> frac12 ½ ½ ½ </li> +<li> frac34 ¾ ¾ ¾ </li> +<li> iquest ¿ ¿ ¿ </li> +<li> Agrave À À À </li> +<li> Aacute Á Á Á </li> +<li> Acirc    </li> +<li> Atilde à à à </li> +<li> Auml Ä Ä Ä </li> +<li> Aring Å Å Å </li> +<li> AElig Æ Æ Æ </li> +<li> Ccedil Ç Ç Ç </li> +<li> Egrave È È È </li> +<li> Eacute É É É </li> +<li> Ecirc Ê Ê Ê </li> +<li> Euml Ë Ë Ë </li> +<li> Igrave Ì Ì Ì </li> +<li> Iacute Í Í Í </li> +<li> Icirc Î Î Î </li> +<li> Iuml Ï Ï Ï </li> +<li> ETH Ð Ð Ð </li> +<li> Ntilde Ñ Ñ Ñ </li> +<li> Ograve Ò Ò Ò </li> +<li> Oacute Ó Ó Ó </li> +<li> Ocirc Ô Ô Ô </li> +<li> Otilde Õ Õ Õ </li> +<li> Ouml Ö Ö Ö </li> +<li> times × × × </li> +<li> Oslash Ø Ø Ø </li> +<li> Ugrave Ù Ù Ù </li> +<li> Uacute Ú Ú Ú </li> +<li> Ucirc Û Û Û </li> +<li> Uuml Ü Ü Ü </li> +<li> Yacute Ý Ý Ý </li> +<li> THORN Þ Þ Þ </li> +<li> szlig ß ß ß </li> +<li> agrave à à à </li> +<li> aacute á á á </li> +<li> acirc â â â </li> +<li> atilde ã ã ã </li> +<li> auml ä ä ä </li> +<li> aring å å å </li> +<li> aelig æ æ æ </li> +<li> ccedil ç ç ç </li> +<li> egrave è è è </li> +<li> eacute é é é </li> +<li> ecirc ê ê ê </li> +<li> euml ë ë ë </li> +<li> igrave ì ì ì </li> +<li> iacute í í í </li> +<li> icirc î î î </li> +<li> iuml ï ï ï </li> +<li> eth ð ð ð </li> +<li> ntilde ñ ñ ñ </li> +<li> ograve ò ò ò </li> +<li> oacute ó ó ó </li> +<li> ocirc ô ô ô </li> +<li> otilde õ õ õ </li> +<li> ouml ö ö ö </li> +<li> divide ÷ ÷ ÷ </li> +<li> oslash ø ø ø </li> +<li> ugrave ù ù ù </li> +<li> uacute ú ú ú </li> +<li> ucirc û û û </li> +<li> uuml ü ü ü </li> +<li> yacute ý ý ý </li> +<li> thorn þ þ þ </li> +<li> yuml ÿ ÿ ÿ </li> +</ul> +</html> +} + ::tcltest::user-result +} {0 pass} + +::tcltest::test html-1.1 { + Verify that all subscripting and superscripting works. +} { + set h [tkhtml_test_widget] + $h clear + $h parse { +<html> +<body> +<h1>A test of subscripting and superscripting</h1> + +<p>Here is sub<sub>script</sub>. And now super<sup>script</sup>.</p> +<p>Here is sub<sub>sub<sub>script</sub></sub>. + And now super<sup>super<sup>script</sup></sup>.</p> + +<p>Here is sub<sub>super<sup>script</sup></sub></p> + +</body> +</html> +} + ::tcltest::user-result +} {0 pass} + +::tcltest::test html-1.2 { + Verify stylistic markup. +} { + set h [tkhtml_test_widget] + $h clear + $h parse { +<html> +<body> +<h1>A test of font changing markup</h1> + +<p>This is normal text</p> +<p><b>: <b>bold text</b></p> +<p><big>: <big>big text</big></p> +<p><cite>: <cite>cite text</cite></p> +<p><code>: <code>code text</code></p> +<p><em>: <em>emphasized text</em></p> +<p><i>: <i>italic text</i></p> +<p><kbd>: <kbd>keyboard text</kbd></p> +<p><s>: <s>strike-thru text</s></p> +<p><samp>: <samp>sample text</samp></p> +<p><small>: <small>small text</small></p> +<p><strike>: <strike>strike-thru text</strike></p> +<p><strong>: <strong>strong text</strong></p> +<p><tt>: <tt>teletype text</tt></p> +<p><u>: <u>underlined text</u></p> +<p><var>: <var>variable text</var></p> +<p>This is normal text</p> +</body> +</html> +} + ::tcltest::user-result +} {0 pass} diff --git a/tkhtml1/tests/html2.test b/tkhtml1/tests/html2.test new file mode 100644 index 0000000..79f42a9 --- /dev/null +++ b/tkhtml1/tests/html2.test @@ -0,0 +1,100 @@ +# +# Test script for the Tk HTML widget +# +wm withdraw . +if {[lsearch [namespace children] ::tcltest] == -1} { + source [file dirname $argv0]/engine.tcl + namespace import ::tcltest::* + cd [file dirname $argv0] +} + + +# in image to use for all GIFs. +# +image create photo nogifsm -data { + R0lGODdhEAAQAPEAAACQkADQ0PgAAAAAACwAAAAAEAAQAAACNISPacHtD4IQz80QJ60as25d + 3idKZdR0IIOm2ta0Lhw/Lz2S1JqvK8ozbTKlEIVYceWSjwIAO/// +} + +# A callback to handle image requests +# +proc ImageCmd {args} { + set fn [lindex $args 0] + if {[catch {image create photo -file $fn} img]} { + set img nogifsm + } + return $img +} + +# Free all images +# +proc FreeImages {} { + foreach img [image names] { + image delete $img + } +} + +# Create the HTML widget to use for all testing. +# +set h [tkhtml_test_widget] +$h config -imagecommand ImageCmd + +::tcltest::test html-2.1 { + A snapshot of Slashdot on Jan 29, 2000. +} { + set file page1/index.html + $h clear + set f [open $file r] + $h config -base $file + $h parse [read $f [file size $file]] + close $f + set r [::tcltest::user-result] + $h clear + FreeImages + return $r +} {2 pass} + +::tcltest::test html-2.2 { + A snapshot of a page from the Scriptics website on Jan 29, 2000. +} { + set file page2/index.html + $h clear + set f [open $file r] + $h config -base $file + $h parse [read $f [file size $file]] + close $f + set r [::tcltest::user-result] + $h clear + FreeImages + return $r +} {2 pass} + +::tcltest::test html-2.3 { + A snapshot of freshmeat on Jan 29, 2000 +} { + set file page4/index.html + $h clear + set f [open $file r] + $h config -base $file + $h parse [read $f [file size $file]] + close $f + set r [::tcltest::user-result] + $h clear + FreeImages + return $r +} {2 pass} + +::tcltest::test html-2.4 { + A slide show about mktclapp +} { + set file page3/index.html + $h clear + set f [open $file r] + $h config -base $file + $h parse [read $f [file size $file]] + close $f + set r [::tcltest::user-result] + $h clear + FreeImages + return $r +} {2 pass} diff --git a/tkhtml1/tests/html3.test b/tkhtml1/tests/html3.test new file mode 100644 index 0000000..f804f56 --- /dev/null +++ b/tkhtml1/tests/html3.test @@ -0,0 +1,243 @@ +# +# Test script for the Tk HTML widget +# +wm withdraw . +if {[lsearch [namespace children] ::tcltest] == -1} { + source [file dirname $argv0]/engine.tcl + namespace import ::tcltest::* +} + +::tcltest::test html-3.1 {Check the HTML parser for sanity} { + set h [tkhtml_test_widget] + $h clear + $h parse "<p align=center>Test1 \nEnd\n" + $h token list 1.0 end +} {0 {{Markup p align center} {Text Test1} {Space 1 1} {Text End} {Space 1 1}}} + +::tcltest::test html-3.2 {Check that markup arguments are parsed correctly} { + set h [tkhtml_test_widget] + $h clear + $h parse {<p align="center" id='"5"' id2 = "'4'">} + $h token list 1.0 end +} {0 {{Markup p align center id {"5"} id2 '4'}}} + +::tcltest::test html-3.3 {Check that comments are ignored} { + set h [tkhtml_test_widget] + $h clear + $h parse {<p><!-- This is comment --></p>} + $h token list 1.0 end +} {0 {{Markup p} {Markup /p}}} + +::tcltest::test html-3.4 {Check that entities are resolved} { + set h [tkhtml_test_widget] + $h clear + $h parse {& <>H<p>} + $h token list 1.0 end +} {0 {{Text {& <>H}} {Markup p}}} + +::tcltest::test html-3.5 {Check that spacing is recorded properly} { + set h [tkhtml_test_widget] + $h clear + $h parse "<pre>\n\tHi\tThere\n</pre>" + $h token list 1.0 end +} {0 {{Markup pre} {Space 1 1} {Space 8 0} {Text Hi} {Space 6 0} {Text There} {Space 1 1} {Markup /pre}}} + +::tcltest::test html-3.6 {Script markup should become a single token} { + set h [tkhtml_test_widget] + $h clear + $h parse "<script>Contents of script are not tokenized</script>\n" + $h token list 1.0 end +} {0 {{Markup script} {Space 1 1}}} + +::tcltest::test html-3.6b {Style markup should become a single token} { + set h [tkhtml_test_widget] + $h clear + $h parse "<style>Contents of style are not tokenized</style>\n" + $h token list 1.0 end +} {0 {{Markup style} {Space 1 1}}} + +::tcltest::test html-3.7 {All markup within listing is normal text} { + set h [tkhtml_test_widget] + $h clear + $h parse "<listing><p>Hello</p></listing>\n" + $h token list 1.0 end +} {0 {{Markup listing} {Text <p>Hello} {Text </p>} {Markup /listing} {Space 1 1}}} + +::tcltest::test html-3.8 {All markup within xmp is normal text} { + set h [tkhtml_test_widget] + $h clear + $h parse "<xmp><p>Hello</p></xmp>\n" + $h token list 1.0 end +} {0 {{Markup xmp} {Text <p>Hello} {Text </p>} {Markup /xmp} {Space 1 1}}} + +::tcltest::test html-3.9 {All markup within textarea is treated as normal +text. This is not valid HTML, but it is what Netscape does.} { + set h [tkhtml_test_widget] + $h clear + $h parse "<textarea><p>Hello</p></textarea>\n" + $h token list 1.0 end +} {0 {{Markup textarea} {Text <p>Hello} {Text </p>} {Markup /textarea} {Space 1 1}}} + +::tcltest::test html-3.10 {All markup after plaintext become normal text} { + set h [tkhtml_test_widget] + $h clear + $h parse "<plaintext><p>Hello</p></plaintext>\n" + $h token list 1.0 end +} {0 {{Markup plaintext} {Text <p>Hello} {Text </p>} {Text </plaintext>} {Space 1 1}}} + +::tcltest::test html-3.11 {Unrecognized markup is ignored} { + set h [tkhtml_test_widget] + $h clear + $h parse "<unknown>Text\n" + $h token list 1.0 end +} {0 {{Text Text} {Space 1 1}}} + +::tcltest::test html-3.12 {Entities are resolved within markup arguments} { + set h [tkhtml_test_widget] + $h clear + $h parse {<p id="<hi>">} + $h token list 1.0 end +} {0 {{Markup p id <hi>}}} + +::tcltest::test html-3.13 {Entites are resolved within markup arguments} { + set h [tkhtml_test_widget] + $h clear + $h parse {<p id=<hi>>} + $h token list 1.0 end +} {0 {{Markup p id <hi>}}} + +::tcltest::test html-3.14 {White space within markup is ignored} { + set h [tkhtml_test_widget] + $h clear + $h parse {<br >} + $h token list 1.0 end +} {0 {{Markup br}}} + +::tcltest::test html-3.15 {Whitespace within markup is ignored} { + set h [tkhtml_test_widget] + $h clear + $h parse {<br id = 5>} + $h token list 1.0 end +} {0 {{Markup br id 5}}} + +::tcltest::test html-3.16 {Whitespace in markup is ignored} { + set h [tkhtml_test_widget] + $h clear + $h parse {<br id = 5 >} + $h token list 1.0 end +} {0 {{Markup br id 5}}} + +::tcltest::test html-3.17 {Whitespace in markup is ignored} { + set h [tkhtml_test_widget] + $h clear + $h parse {<br id =5>} + $h token list 1.0 end +} {0 {{Markup br id 5}}} + +::tcltest::test html-3.18 {Whitespace in markup is ignored} { + set h [tkhtml_test_widget] + $h clear + $h parse {<br id= 5 >} + $h token list 1.0 end +} {0 {{Markup br id 5}}} + +::tcltest::test html-3.19 {Whitespace in markup is ignored, except when quoted} { + set h [tkhtml_test_widget] + $h clear + $h parse {<br id= " 5 " >} + $h token list 1.0 end +} {0 {{Markup br id { 5 }}}} + +::tcltest::test html-3.20 {Tabs in markup are treated like whitespace} { + set h [tkhtml_test_widget] + $h clear + $h parse "<br id\t=\t' 5 '\t>" + $h token list 1.0 end +} {0 {{Markup br id { 5 }}}} + +::tcltest::test html-3.21 {Newlines in markup are treated like whitespace} { + set h [tkhtml_test_widget] + $h clear + $h parse "<br id\n=\n\" 5 \"\n>" + $h token list 1.0 end +} {0 {{Markup br id { 5 }}}} + +::tcltest::test html-3.22 {Markup arguments without values} { + set h [tkhtml_test_widget] + $h clear + $h parse "<br clear >" + $h token list 1.0 end +} {0 {{Markup br clear {}}}} + +::tcltest::test html-3.23 {Markup arguments without values} { + set h [tkhtml_test_widget] + $h clear + $h parse "<br clear id=9>" + $h token list 1.0 end +} {0 {{Markup br clear {} id 9}}} + +::tcltest::test html-3.24 {XHTML style / at the end of markup} { + set h [tkhtml_test_widget] + $h clear + $h parse {<br clear="both"/>} + $h token list 1.0 end +} {0 {{Markup br clear both}}} + +::tcltest::test html-3.25 {XHTML style / at the end of markup} { + set h [tkhtml_test_widget] + $h clear + $h parse {<br />} + $h token list 1.0 end +} {0 {{Markup br}}} + +::tcltest::test html-3.26 {XHTML style / at the end of markup} { + set h [tkhtml_test_widget] + $h clear + $h parse {<br/>} + $h token list 1.0 end +} {0 {{Markup br}}} + +::tcltest::test html-3.27 {/ At the end of markup adds a second token} { + set h [tkhtml_test_widget] + $h clear + $h parse {<p />} + $h token list 1.0 end +} {0 {{Markup p} {Markup /p}}} + +::tcltest::test html-3.28 {/ at the end of markup adds a second token} { + set h [tkhtml_test_widget] + $h clear + $h parse {<p/>} + $h token list 1.0 end +} {0 {{Markup p} {Markup /p}}} + +::tcltest::test html-3.29 {/ not at the end of markup still work} { + set h [tkhtml_test_widget] + $h clear + $h parse "<A href=\"\" /privacy.html=\"/privacy.html\">\n" + $h token list 1.0 end +} {0 {{Markup a href {} /privacy.html /privacy.html} {Space 1 1}}} + +::tcltest::test html-3.30 {Incremental parsing} { + set h [tkhtml_test_widget] + $h clear + set txt {<a href="" /privacy.html="none"/>Hello&<p>} + set len [string length $txt] + for {set i 0} {$i<$len} {incr i} { + $h parse [string index $txt $i] + } + $h token list 1.0 end +} {0 {{Markup a href {} /privacy.html none} {Markup /a} {Text Hello&} {Markup p}}} + +::tcltest::test html-3.31 {Searching for anchors} { + set h [tkhtml_test_widget] + $h clear + $h parse { + <a name="one">One</a> + <a id="two">Two</a> + <a href="three">Three</a> + <a name="four" id="vier">Four</a> + } + update + $h names +} {0 {one two four}} diff --git a/tkhtml1/tests/page1/image1 b/tkhtml1/tests/page1/image1 Binary files differnew file mode 100644 index 0000000..31e96b6 --- /dev/null +++ b/tkhtml1/tests/page1/image1 diff --git a/tkhtml1/tests/page1/image10 b/tkhtml1/tests/page1/image10 Binary files differnew file mode 100644 index 0000000..80a8f81 --- /dev/null +++ b/tkhtml1/tests/page1/image10 diff --git a/tkhtml1/tests/page1/image11 b/tkhtml1/tests/page1/image11 Binary files differnew file mode 100644 index 0000000..e8cb01d --- /dev/null +++ b/tkhtml1/tests/page1/image11 diff --git a/tkhtml1/tests/page1/image12 b/tkhtml1/tests/page1/image12 Binary files differnew file mode 100644 index 0000000..c317bbd --- /dev/null +++ b/tkhtml1/tests/page1/image12 diff --git a/tkhtml1/tests/page1/image13 b/tkhtml1/tests/page1/image13 Binary files differnew file mode 100644 index 0000000..ac4b3cd --- /dev/null +++ b/tkhtml1/tests/page1/image13 diff --git a/tkhtml1/tests/page1/image14 b/tkhtml1/tests/page1/image14 Binary files differnew file mode 100644 index 0000000..c3b0255 --- /dev/null +++ b/tkhtml1/tests/page1/image14 diff --git a/tkhtml1/tests/page1/image2 b/tkhtml1/tests/page1/image2 Binary files differnew file mode 100644 index 0000000..da26d70 --- /dev/null +++ b/tkhtml1/tests/page1/image2 diff --git a/tkhtml1/tests/page1/image3 b/tkhtml1/tests/page1/image3 Binary files differnew file mode 100644 index 0000000..d91cdfa --- /dev/null +++ b/tkhtml1/tests/page1/image3 diff --git a/tkhtml1/tests/page1/image4 b/tkhtml1/tests/page1/image4 Binary files differnew file mode 100644 index 0000000..5fdf70c --- /dev/null +++ b/tkhtml1/tests/page1/image4 diff --git a/tkhtml1/tests/page1/image5 b/tkhtml1/tests/page1/image5 Binary files differnew file mode 100644 index 0000000..67cd14d --- /dev/null +++ b/tkhtml1/tests/page1/image5 diff --git a/tkhtml1/tests/page1/image6 b/tkhtml1/tests/page1/image6 Binary files differnew file mode 100644 index 0000000..9e05aa0 --- /dev/null +++ b/tkhtml1/tests/page1/image6 diff --git a/tkhtml1/tests/page1/image7 b/tkhtml1/tests/page1/image7 Binary files differnew file mode 100644 index 0000000..879656d --- /dev/null +++ b/tkhtml1/tests/page1/image7 diff --git a/tkhtml1/tests/page1/image8 b/tkhtml1/tests/page1/image8 Binary files differnew file mode 100644 index 0000000..8c647c4 --- /dev/null +++ b/tkhtml1/tests/page1/image8 diff --git a/tkhtml1/tests/page1/image9 b/tkhtml1/tests/page1/image9 Binary files differnew file mode 100644 index 0000000..3a77075 --- /dev/null +++ b/tkhtml1/tests/page1/image9 diff --git a/tkhtml1/tests/page1/index.html b/tkhtml1/tests/page1/index.html new file mode 100644 index 0000000..9efac7f --- /dev/null +++ b/tkhtml1/tests/page1/index.html @@ -0,0 +1,115 @@ +<HTML><HEAD><TITLE>Slashdot:News for Nerds. Stuff that Matters.</TITLE> </HEAD> +<BODY bgcolor="#000000" text="#000000" link="#006666" vlink="#000000"> +<center><a href="http://209.207.224.220/redir.pl?1463" target="_top"><img src="image1" alt="Click Here to enter the Sweepstakes" border="2" width="468" height="60"></a></center> <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0"><TR><TD WIDTH="1"><SCRIPT LANGUAGE="JAVASCRIPT"> +<!-- now="now" ="" new="new" Date();="Date();" tail="tail" ="" now.getTime();="now.getTime();" document.write("<IMG="document.write("<IMG" SRC="http://209.207.224.245/Slashdot/pc.gif?/slashhead.inc,"+" tail="tail" +="+" "=""" WIDTH="1" HEIGHT="1><BR>");" --> +</SCRIPT> +<NOSCRIPT> +<IMG SRC="image2" WIDTH="1" HEIGHT="1"> +</NOSCRIPT></TD></TR></TABLE><P> +<TABLE bgcolor="#FFFFFF" cellpadding="0" cellspacing="0" border="0" width="99%" align="center"> + <TR> + <TD valign="top" align="left" valign="top"><A href="http://slashdot.org/"><IMG src="image3" width="275" height="72" border="0" alt="Welcome to Slashdot"></A></TD> + <TD><A href="http://slashdot.org/search.pl?topic=linux"><IMG SRC="image4" width="60" height="70" border="0" alt="Linux"></A></TD> +<TD><A href="http://slashdot.org/search.pl?topic=news"><IMG SRC="image5" width="34" height="44" border="0" alt="News"></A></TD> +<TD><A href="http://slashdot.org/search.pl?topic=usa"><IMG SRC="image6" width="80" height="61" border="0" alt="United States"></A></TD> +<TD><A href="http://slashdot.org/search.pl?topic=ed"><IMG SRC="image7" width="87" height="64" border="0" alt="Education"></A></TD> +<TD><A href="http://slashdot.org/search.pl?topic=space"><IMG SRC="image8" width="73" height="59" border="0" alt="Space"></A></TD> + +</TR></TABLE> +<TABLE width="99%" align="center" cellpadding="0" cellspacing="0" border="0" bgcolor="#FFFFFF"><TR> +<TD valign="top" rowspan="5"><NOBR><FONT size="2"><B> + <A href="/faq.shtml">faq</A> <BR> + <A href="/code.shtml">code</A> <BR> + <A href="/awards.shtml">awards</A> <BR> + <A href="http://Andover.Net/privacy.html">privacy</A> <BR> + <A href="http://slashnet.org">slashNET</A> <BR> + <A href="/search.pl">older stuff</A> <BR> + <A href="http://cmdrtaco.net">rob's page</A> <BR> + <A href="/users.pl?op=preferences">preferences</A> <BR> + <A href="http://Andover.Net">andover.net</A> <BR> + <A href="/submit.pl">submit story</A> <BR> + <A href="/advertising.shtml">advertising</A> <BR> + <A href="/supporters.shtml">supporters</A> <BR> + <A href="/pollBooth.pl">past polls</A> <BR> + <A href="/topics.shtml">topics</A> <BR> + <A href="/about.shtml">about</A> <BR> + <A href="/jobs.shtml">jobs</A> <BR> + <A href="/hof.shtml">hof</A> + +</B></FONT></NOBR> + <P><TABLE border="0" cellpadding="1" cellspacing="0" align="center" bgcolor="#CCCCCC"><TR> + <TD><FONT size="2" color="#000000"><B> Sections</B></FONT></TD></TR> + <TR><TD><TABLE border="0" cellspacing="1" cellpadding="1" bgcolor="#FFFFFF" width="100%"><TR><TD><FONT color="#000000" size="2"><NOBR> +1/23<BR> +<B><A href="http://slashdot.org/index.pl?section=apache">apache</A></B><BR> +1/29 (3)<BR> +<B><A href="http://slashdot.org/index.pl?section=askslashdot">askslashdot</A></B><BR> +1/27<BR> +<B><A href="http://slashdot.org/index.pl?section=awards">awards</A></B><BR> +1/29 (2)<BR> +<B><A href="http://slashdot.org/index.pl?section=books">books</A></B><BR> +1/27<BR> +<B><A href="http://slashdot.org/index.pl?section=bsd">bsd</A></B><BR> +1/28 (2)<BR> +<B><A href="http://slashdot.org/index.pl?section=features">features</A></B><BR> +1/28 (2)<BR> +<B><A href="http://slashdot.org/index.pl?section=interviews">interviews</A></B><BR> +1/19<BR> +<B><A href="http://slashdot.org/index.pl?section=radio">radio</A></B><BR> +1/27 (2)<BR> +<B><A href="http://slashdot.org/index.pl?section=science">science</A></B><BR> +1/28 (3)<BR> +<B><A href="http://slashdot.org/index.pl?section=yro">yro</A></B><BR> </NOBR></FONT></TD></TR></TABLE><TR> + <TD><A href="http://andover.net"><FONT size="2" color="#000000"><B>Andover.Net</B></FONT></A></TD></TR> + <TR><TD><TABLE border="0" cellspacing="1" cellpadding="1" bgcolor="#FFFFFF"><TR><TD> +<FONT color="#000000" size="2"><NOBR><A href="http://www.andovernews.com">AndoverNews</A><BR><A href="http://www.askreggie.com">Ask Reggie</A><BR><A href="http://www.davecentral.com">DaveCentral</A><BR><A href="http://www.freecode.com">FreeCode</A><BR><A href="http://www.mediabuilder.com">MediaBuilder</A><BR> </NOBR></FONT></TD></TR></TABLE></TD></TR></TABLE></P> + <P></P> +</TD><TD valign="top" align="left"><FONT color="#000000"> <TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Who Bought Linux.Net?</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=linux"><IMG src="image4" width="60" height="70" border="0" align="right" hspace="20" vspace="10" alt="Linux"></A> <B>Posted by <A href="http://CmdrTaco.net">CmdrTaco</A> on Saturday January 29, @10:52AM</B><BR> <FONT size="2"><B>from the this-game-again dept.</B></FONT><BR> So Fred VanKampen (who has to hold the record for most money made by reselling two domain names) e-mailed us to say that the Domain Name for 'Linux.Net' has been sold. He won't say to whom, but it supposedly will be announced at LinuxWorld next week. Of course we have no idea what he got for the entry, but the rumors were that he made several million when he sold <A href="http://www.linux.com">Linux.com</A> to <A href="http://www.valinux.com">VA Linux</A>. Hopefully he'll take me for a ride in his yacht. ;) <P><B>( </B><A href="http://slashdot.org/articles/00/01/29/0837235.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/29/0837235&mode=thread&threshold=0">58</A> of <A href="http://slashdot.org/article.pl?sid=00/01/29/0837235&mode=thread&threshold=-1">62</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Book Reviews: E-Mails from (Over?) The Edge</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=news"><IMG src="image5" width="34" height="44" border="0" align="right" hspace="20" vspace="10" alt="News"></A> <B>Posted by <A href="http://hemos.net">Hemos</A> on Saturday January 29, @10:43AM</B><BR> <FONT size="2"><B>from the touching-story dept.</B></FONT><BR> I'd like to thank the author of this book for sending it to me. Nick's written a book that's touching and endearing, and one that's well worth reading for everyone who's ever had social struggles to deal with. As well, his involvement with the fine folks of <a href="http://www.thevenue.org">TheVenue</a>. I'll warn you - it's not a tech text. But it's still worth reading. Click below to read more. <P><B>( </B><A href="http://slashdot.org/books/00/01/24/1146250.shtml"><B>Read More...</B></A> | <A href="http://slashdot.org/article.pl?sid=00/01/24/1146250&mode=nocomment">6197 bytes in body</A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/24/1146250&mode=thread&threshold=0">6</A> of <A href="http://slashdot.org/article.pl?sid=00/01/24/1146250&mode=thread&threshold=-1">22</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Linux Kernel 2.3.41</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=linux"><IMG src="image4" width="60" height="70" border="0" align="right" hspace="20" vspace="10" alt="Linux"></A> <B>Posted by <A href="http://CmdrTaco.net">CmdrTaco</A> on Saturday January 29, @10:21AM</B><BR> <FONT size="2"><B>from the download-compile-reboot-repeat dept.</B></FONT><BR> <A href="mailto:bwhitehead@nospam.acm.org">sdriver</A> writes <I>"For those of us who enjoy *panic*, *oops*, and suddenly seeing their video BIOS... the newest version is out! Be the first on your block to submit a new patch! ;) "</I> If you don't know where to get it, you probably should stick to your warm and cuddly 2.2.x kernel *grin*. Now outta my way, I wanna crash my laptop! <P><B>( </B><A href="http://slashdot.org/articles/00/01/29/0834223.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/29/0834223&mode=thread&threshold=0">52</A> of <A href="http://slashdot.org/article.pl?sid=00/01/29/0834223&mode=thread&threshold=-1">57</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Congress Still Figuring Out E-Mail</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=usa"><IMG src="image6" width="80" height="61" border="0" align="right" hspace="20" vspace="10" alt="United States"></A> <B>Posted by <A href="mailto:roblimo@slashdot.org">Roblimo</A> on Saturday January 29, @07:28AM</B><BR> <FONT size="2"><B>from the voice-of-the-people-can-get-awfully-loud dept.</B></FONT><BR> Jett writes <I>" <A href="http://www.vote.com/">Vote.com</A> has <A href="http://www.vote.com/magazine/editorials/editorial1843752.phtml">an interesting article</A> in their Webmag Fifth Estate about how congressmen have responded to the popularity of e-mail in their daily operations. Quote: 'Of the 440 voting and non-voting House of Representatives members, 22 have no e-mail at all. Even House Speaker Dennis Hastert is wired only halfway -- his office receives e-mail, but does not respond to it. And while all U.S. senators have e-mail, they, like their House counterparts, routinely shun non-constituent mail -- even though they chair committees whose decisions affect the entire country.'"</I> <P><B>( </B><A href="http://slashdot.org/articles/00/01/28/2311232.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/28/2311232&mode=thread&threshold=0">66</A> of <A href="http://slashdot.org/article.pl?sid=00/01/28/2311232&mode=thread&threshold=-1">66</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Ask Slashdot: Sci Fi Literature 101?</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=ed"><IMG src="image7" width="87" height="64" border="0" align="right" hspace="20" vspace="10" alt="Education"></A> <B>Posted by <A href="http://exit118.com/">Cliff</A> on Saturday January 29, @06:56AM</B><BR> <FONT size="2"><B>from the recommendations-wanted dept.</B></FONT><BR> ohlaadee asks: <I>"My niece (she's 13) wants to start reading science fiction. I do too. I gave us both Asimov's </I>_The Foundation_<I> for Christmas. We'll read it together. I suppose we could spend the rest of our lives just reading Asimov, but I'm wondering what books and movies you folks would come up with? What does the /. recommended Science Fiction 101 list include?"</I> <P><B>( </B><A href="http://slashdot.org/askslashdot/00/01/22/1946244.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/22/1946244&mode=thread&threshold=0">345</A> of <A href="http://slashdot.org/article.pl?sid=00/01/22/1946244&mode=thread&threshold=-1">345</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Could Distributed.Net Help the Mars Polar Lander?</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=space"><IMG src="image8" width="73" height="59" border="0" align="right" hspace="20" vspace="10" alt="Space"></A> <B>Posted by <A href="mailto:roblimo@slashdot.org">Roblimo</A> on Saturday January 29, @03:35AM</B><BR> <FONT size="2"><B>from the food-for-thought dept.</B></FONT><BR> Anonymous Coward writes <I>"This official JPL <A href="http://mpfwww.jpl.nasa.gov/msp98/news/mpl000127.html">press release</A> describes the current attempt to listen for faint signals from the Mars Lander. They get three windows a day, and it takes 18 hours to process data because the signal is so weak (if it's really there). Too bad they don't have a deal with <A href="http://www.distributed.net"> distributed.net</A>."</I> Interesting thought. Is anyone at distributed.net or JPL interested in pursuing it? <P><B>( </B><A href="http://slashdot.org/articles/00/01/28/2318246.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/28/2318246&mode=thread&threshold=0">99</A> of <A href="http://slashdot.org/article.pl?sid=00/01/28/2318246&mode=thread&threshold=-1">102</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>iCrave TV Loses Battle against U.S. Broadcasters</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=tv"><IMG src="image10" width="50" height="50" border="0" align="right" hspace="20" vspace="10" alt="Television"></A> <B>Posted by <A href="mailto:roblimo@slashdot.org">Roblimo</A> on Saturday January 29, @12:21AM</B><BR> <FONT size="2"><B>from the shut-down-just-before-the-super-bowl dept.</B></FONT><BR> <A href="mailto:doran@brandx.net">Doran</A> writes <I>"C|Net has <a href="http://news.cnet.com/news/0-1004-200-1535528.html">this story</a> about how the Canadian company <a href="http://www.icravetv.com">iCraveTV.com</a> has lost its latest battle in U.S. courts over whether it can rebroadcast TV signals over the Web. The broadcasters say it's theft, while iCraveTV sez it's just doing what's legal for other cable TV companies in Canada (ie. rebroadcasting TV). Of course, by framing the streaming video iCraveTV is doing more than just rebroadcasting, they're also adding more commercial content, which the broadcasters feel dilutes their TV commercials. "</I> <P><B>( </B><A href="http://slashdot.org/articles/00/01/29/0010203.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/29/0010203&mode=thread&threshold=0">152</A> of <A href="http://slashdot.org/article.pl?sid=00/01/29/0010203&mode=thread&threshold=-1">170</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Win2k Security holes found</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=microsoft"><IMG src="image11" width="75" height="55" border="0" align="right" hspace="20" vspace="10" alt="Microsoft"></A> <B>Posted by <A href="mailto:heunique@slashdot.org">HeUnique</A> on Friday January 28, @04:58PM</B><BR> <FONT size="2"><B>from the and-it's-not-even-out-yet dept.</B></FONT><BR> According to a story posted by <a href="http://www.zdnn.com">ZDNN</a>, <a href="http://www.zdnet.com/zdnn/stories/news/0,4586,2429334,00.html?chkpt=zdnntop">two security holes</a> have been found on Windows 2000, and that's even before the official release of Windows 2000! Administrators who rush to incorporate the patch from MS beware - according to one of the talkback posts on ZDNN, the patch creates a new problem with Windows 2000 news server service. <P><B>( </B><A href="http://slashdot.org/articles/00/01/28/1653228.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/28/1653228&mode=thread&threshold=0">510</A> of <A href="http://slashdot.org/article.pl?sid=00/01/28/1653228&mode=thread&threshold=-1">534</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Encryption Debate at Mitnick Trial</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=encryption"><IMG src="image12" width="80" height="70" border="0" align="right" hspace="20" vspace="10" alt="Encryption"></A> <B>Posted by <A href="http://hemos.net">Hemos</A> on Friday January 28, @03:33PM</B><BR> <FONT size="2"><B>from the gimmie-the-data dept.</B></FONT><BR> A number of people have written about <A HREF="http://nytimes.com/library/tech/00/01/cyber/cyberlaw/28law.html">the latest twist</a> in the Mitnick case. Kevin wants to get his data back, but the government is refusing to do so until he gives them the key. Apparently, the government is unable to crack the encryption that he's got on it - you'd think after having the data for five years, they'd be able to brute-force the darn thing. It's a NYT article - free login required. <P><B>( </B><A href="http://slashdot.org/articles/00/01/28/1320253.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/28/1320253&mode=thread&threshold=0">504</A> of <A href="http://slashdot.org/article.pl?sid=00/01/28/1320253&mode=thread&threshold=-1">521</A> </B>comments <B>)</B> <P><TABLE width="99%" cellpadding="0" cellspacing="0" border="0"><TR><TD valign="top" bgcolor="#006666"><IMG src="image9" width="13" height="16" alt="" align="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Forum: Future Ports of Games to Linux</B></FONT></TD> </TR></TABLE><A href="http://slashdot.org/search.pl?topic=games"><IMG src="image13" width="80" height="56" border="0" align="right" hspace="20" vspace="10" alt="Games"></A> <B>Posted by <A href="http://CmdrTaco.net">CmdrTaco</A> on Friday January 28, @02:26PM</B><BR> <FONT size="2"><B>from the it's-been-awhile dept.</B></FONT><BR> It's been a long time since I posted an open forum like this, but I'm curious what people think on this one. What games do you most want to see ported to Linux in the next few months? Of course, for me personally it's StarCraft and Diablo 2, but I'm curious what games have come out or are due soon that people would most like to see a port of (and note that WINE doesn't count. ;) <P><B>( </B><A href="http://slashdot.org/articles/00/01/28/1257211.shtml"><B>Read More...</B></A> | <B><A href="http://slashdot.org/article.pl?sid=00/01/28/1257211&mode=thread&threshold=0">648</A> of <A href="http://slashdot.org/article.pl?sid=00/01/28/1257211&mode=thread&threshold=-1">652</A> </B>comments <B>)</B> <P></TD><TD width="210" align="center" valign="top"><TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B><A HREF="/index.pl?section=features"><FONT COLOR="#FFFFFF">Features</FONT></A></B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><A href="/vote.pl">Voting has begun</A> for the $100k <A href="/index.pl?section=awards">Slashdot Beanie Awards</A>. Talk amongst yourselves and choose who deserves the cash. <P>The latest installment of <A href="http://www.thesync.com/geeks">Geeks in Space</A> is up at <A href="http://www.thesync.com">The Sync</A>. Listen to CmdrTaco, Hemos, and Nate talk about the latest events to happen - or not happen in the computer world. <P>Perhaps you are seeking Jon Katz's series of articles related to recent events in Colorado. These articles include <A href="/article.pl?sid=99/04/25/1438249">Voices from the Hellmouth</A>, <A href="/article.pl?sid=99/04/27/0310247">More Stories from the Hellmouth</A> or <A href="/article.pl?sid=99/04/29/0124247">The Price of Being Different</A>, <P>For something different, try reading a little essay <A href="/article.pl?sid=99/03/31/0137221">Thoughts from the Furnace</A> about the internet, and flame. <p> And for a bit of an amusing take on the Open Source world, check out <a href="/article.pl?sid=99/08/24/1327256&mode=thread">Open Source as an Ant Farm</a> <P><B>Update: 01/03 03:10</B> by <B><A href="http://cowboyneal.org">CowboyNeal</a></B>: <P align="right"><B><A href="/features/">Past Features</A></B> <!-- end="end" features="features" block="block" --></FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B><A HREF="http://slashdot.org/index.pl?section=askslashdot"><FONT COLOR="#FFFFFF">Ask Slashdot</FONT></A></B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1946244">Sci Fi Literature 101?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/192226">Linux and Satellite Internet Services</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1843258">Open Defensive Patents?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1825252">Technologies That Shaped the Last Century?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1958212">Disk Repair Tools for Linux?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1955215">Why Can't the Command-Line be More Standardized?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1928235">Packet Radio Networking with PalmOS?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1817211">Cheap Rackmount Enclosures/Systems?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1950249">Open Source Software and Tax Breaks?</A> <li><A HREF="http://slashdot.org/article.pl?sid=00/01/22/1917207">Building an Upgradable Dual Processor System</A> <P> if you have a question for Ask Slashdot, send it to <A href="mailto:askslashdot@slashdot.org">askslashdot@slashdot.org</A></FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B><A HREF="/users.pl"><FONT COLOR="#FFFFFF">Slashdot Login</FONT></A></B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><FORM action="/users.pl" METHOD="POST"> <B>Nickname:</B><BR> <INPUT type="text" name="unickname" size="20" value=""><BR> <B>Password:</B><BR> <INPUT type="hidden" name="returnto" value="index.pl"> <INPUT type="password" name="upasswd" size="20"><BR> <INPUT type="submit" name="op" value="userlogin"> </FORM> Don't have an account yet? <A href="/users.pl">Go Create One</A>. A user account will allow you to customize all these <A href="/cheesyportal.shtml">nutty little boxes</A>, tailor the stories you see, as well as remember your comment viewing preferences.</FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Slashdot Poll</B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><FORM action="http://slashdot.org/pollBooth.pl"> <INPUT type="hidden" name="qid" value="techadvance"> <B>The Tech Advance I Most Want Is:</B><BR><INPUT type="radio" name="aid" value="1">Nanotechnology<BR><INPUT type="radio" name="aid" value="2">Cold Fusion<BR><INPUT type="radio" name="aid" value="3">Powerful Fuel Cells<BR><INPUT type="radio" name="aid" value="4">Hard Wiring my Body<BR><INPUT type="radio" name="aid" value="5">Universal Strong Crypto<BR><INPUT type="radio" name="aid" value="6">Interstellar Travel<BR><INPUT type="radio" name="aid" value="7">Cybernetic Body Armor<BR><INPUT type="radio" name="aid" value="8">ColecoVision<BR><INPUT type="submit" value="Vote"> [ <A href="http://slashdot.org/pollBooth.pl?qid=techadvance&aid=-1"><B>Results</B></A> | <A href="http://slashdot.org/pollBooth.pl?"><B>Polls</B></A> ] <BR>Comments:<B>656</B> | Votes:<B>29121</B></FORM> </FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Older Stuff</B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><P><B><A href="http://slashdot.org/index.pl?section=&issue=730512&mode=thread"><FONT size="4">Friday</FONT></A> January 28</B> <LI><A href="http://slashdot.org/articles/00/01/28/1110258.shtml">Abstract Programming and GPL Enforcement</A> (235) <LI><A href="http://slashdot.org/interviews/00/01/28/1225206.shtml">Interview: FreeDOS Leader Jim Hall Answers</A> (86) <LI><A href="http://slashdot.org/articles/00/01/28/116240.shtml">Open Source's Achilles Heel</A> (466) <LI><A href="http://slashdot.org/features/00/01/26/1915230.shtml">The Virtue of Communal Instincts</A> (237) <LI><A href="http://slashdot.org/articles/00/01/28/0723223.shtml">Gartner Group Debunking Open Source Myths</A> (165) <LI><A href="http://slashdot.org/yro/00/01/28/0917229.shtml">DoubleClick Taken to Court</A> (310) <LI><A href="http://slashdot.org/articles/00/01/28/0718209.shtml">Updated Slash & Server 51</A> (81) <LI><A href="http://slashdot.org/articles/00/01/28/089230.shtml">XMMS 1.0.0 Released</A> (128) <LI><A href="http://slashdot.org/askslashdot/00/01/22/192226.shtml">Linux and Satellite Internet Services</A> (138) <LI><A href="http://slashdot.org/articles/00/01/27/1811221.shtml">UN Wants to Combat Online Racism</A> (531) <P><B><A href="http://slashdot.org/index.pl?section=&issue=730511&mode=thread"><FONT size="4">Thursday</FONT></A> January 27</B> <LI><A href="http://slashdot.org/yro/00/01/27/2330205.shtml">Crackdowns, Fools and the MPAA</A> (351) <LI><A href="http://slashdot.org/articles/00/01/27/0832215.shtml">Heroes of Might and Magic III Demo Released</A> (157) <LI><A href="http://slashdot.org/science/00/01/27/1345241.shtml">Sandia Labs Venture Into Nanotechnology</A> (117) <LI><A href="http://slashdot.org/articles/00/01/27/0931237.shtml">CA Announces Program Ports to Linux</A> (195) <LI><A href="http://slashdot.org/interviews/00/01/27/1118251.shtml">Interview: Larry Augustin Finally Answers</A> (210) <LI><A href="http://slashdot.org/awards/00/01/27/0855252.shtml">Final Call for Voting in Slashdot's Beanie Awards</A> (178) <LI><A href="http://slashdot.org/features/00/01/26/197211.shtml">Transmeta Code Morphing != Just In Time</A> (449) <LI><A href="http://slashdot.org/books/00/01/24/1150256.shtml">Intrusion Detection</A> (65) <LI><A href="http://slashdot.org/science/00/01/27/0824239.shtml">Using Enzymes to Help Fight CO2 Build-Up</A> (165) <LI><A href="http://slashdot.org/articles/00/01/27/0712217.shtml">Jon Johansen on ABC World News Tonight</A> (415) <P align="right"><BR><A href="http://slashdot.org/search.pl?section=&min=30"><B>Older Articles</B></A><BR><A href="http://slashdot.org/index.pl?section=&mode=thread&issue=730512"><B>Yesterday's Edition</B></A> </FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B><A HREF="/index.pl?section=books"><FONT COLOR="#FFFFFF">Book Reviews</FONT></A></B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><p>Jon Katz, Resident Gasbag, has a new, very appropriate book coming out soon, <a href="http://www.thinkgeek.com">Geeks</a>. Preorder now and receive the book early. <p>For probably the best fiction read around, check out Neal Stephenson's <cite><a href="/article.pl?sid=99/06/23/139229&mode=thread">Cryptonomicon</a></cite>, an engaging read about WWII, cryptography and buried treasure. And data vaults. <p>If you've been doing a lot of work in Perl, you've probably figured out you really need <cite><a href="/article.pl?sid=99/05/10/2238254&mode=thread">Perl in a Nutshell</a></cite> or <cite><a href="/article.pl?sid=99/01/29/1035246&mode=thread">The Perl Cookbook</a></cite>. If you're still learning, grab <cite><a href="/books/older/980526096229.shtml">Programming Perl</a></cite>. <p>And if you want to learn more about how to become a better coder, grab <cite><a href="/article.pl?sid=99/06/28/1417229&mode=thread">The Unified Software Development Process</a></cite> or <cite><a href="/article.pl?sid=99/04/08/1512209&mode=thread">The Practice of Programming</cite></a> Additionally, check out <cite><a href="http://slashdot.org/article.pl?sid=99/09/16/1333202&mode=thread">Refactoring: Improving the Design of Existing Code</a></cite> . <p>Developing a large application? Grab Eric Greenberg's excellent <cite><a href="/article.pl?sid=99/07/13/1943258&mode=thread">Network Application Frameworks</cite></a>. <P>Visit <A href="/index.pl?section=books">Our Book Reviews Section</A> for more. <br> <B>Update: 11/12 05:19</B> by <B><A href="mailto:hemos@slashdot.org">H</A></B>:</FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B>Quick Links</B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><B>Cool Sites:</B> <LI><A href="http://www.linux.com">Linux.com</A> (What <B>is</B> Linux?) <LI><A href="http://everything.blockstackers.com">Everything</A> (Blow your Mind) <LI><A href="http://www.geekculture.com/geekycomics/Aftery2k/aftery2kmain.html">After Y2k</A> (<I>This</I> is Post-Apocalyptic?) <LI><A href="http://www.userfriendly.org">User Friendly</A> (Laugh) <LI><A href="http://themes.org">Themes.org</A> (Make X Perty) <P><B>Support Slashdot:</B> <LI><A href="http://www.thinkgeek.com">ThinkGeek</A> (Clothe Yourself in Slashdot) <LI><A href="http://cdnow.com/from=sr-302791">CDnow</A> (Support <A href="http://www.cdnow.com/gift/malda@slashdot.org">Rob's Who Habit</A>) <LI><A href="http://adfu.slashdot.org">Slashdot Advertiser Index</A></FONT></TD> </TR> </TABLE><P> <TABLE cellpadding="1" cellspacing="0" border="0" width="200" align="center"> <TR bgcolor="#006666"> <TD valign="top"><FONT size="4" color="#FFFFFF" face="arial,helvetica"><B><A HREF="http://freshmeat.net"><FONT COLOR="#FFFFFF">Freshmeat</FONT></A></B></FONT></TD> </TR><TR><TD bgcolor="#CCCCCC"><FONT color="#000000" size="2"><P><FONT size="4" color="#006666"><B>January</B></FONT><BR> <LI><A href="http://freshmeat.net/news/2000/01/29/949208399.html">We should get this out of the door now</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949159642.html">Is Linux for Crazies?</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949156343.html">SQN Linux 1.6</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949156277.html">Limo 0.3.2</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949156237.html">Fusion GS 1.3</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949145887.html">MMR 1.5.4</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949142835.html">KUPS 0.3.4</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949142815.html">3DSE patch for XMMS 4</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949139763.html">Linux 2.3.41</A> <LI><A href="http://freshmeat.net/news/2000/01/29/949139751.html">Free Code for Linux S/390</A> <FORM METHOD="post" ACTION="http://core.freshmeat.net/search.php3"> <FONT size="3" color="#006666"><B>Search Freshmeat:</B></FONT><BR> <INPUT TYPE="hidden" NAME="link" VALUE="freshmeat.net"> <INPUT TYPE="text" NAME="query"> </FORM> <P align="right"><A href="http://freshmeat.net"><B>More Meat...</B></A></FONT></TD> </TR> </TABLE><P> </FONT></TD> + </TR> + </TABLE><TABLE cellpadding="0" cellspacing="0" border="0" width="99%" align="center" bgcolor="ffffff"> + <TR> + <TD colspan="4" align="center"><IMG src="image14" alt="" width="80%" height="1" hspace="10" vspace="30"></TD> + </TR><TR> + <TD align="center"><FONT size="2" face="arial,helvetica"> + <FORM method="GET" action="http://slashdot.org/search.pl"> + <INPUT type="name" name="query" value="" width="20" size="20" length="20"> + <INPUT type="submit" value="Search"> + </FORM> + </FONT> + </TD> + <TD bgcolor="#ffffff" width="25"> </TD> + <TD align="center"> + <FONT size="2" face="arial,helvetica"><I>Wasn't there something about a PASCAL programmer knowing the value of +everything and the Wirth of nothing? +<TD> </TD></I></FONT> + </FONT> + </TD></TR> + <TR><TD colspan="4" align="center"> + <FONT size="1" color="#006666" face="arial,helvetica"> + + All trademarks and copyrights on this + page are owned by their respective owners. Comments + are owned by the Poster. + The Rest © 1997-2000 <A href="http://Andover.Net">Andover.Net</A>. +</FONT></CENTER> + </TD> + </TR> + </TABLE> + <CENTER> + <FONT size="2" color="#006666"> + + [ <A href="http://slashdot.org/"><Font color="#ffffff">home</FONT></A> | + <A href="http://slashdot.org/awards.shtml"><Font color="#ffffff">awards</FONT></A> | + <A href="http://slashdot.org/supporters.shtml"><FONT color="#ffffff">supporters</FONT></A> | + <A href="http://CmdrTaco.net"><FONT color="#ffffff">rob's homepage</FONT></A> | + <A href="http://slashdot.org/submit.pl"><FONT color="#ffffff">contribute story</FONT></A> | + <A href="http://slashdot.org/search.pl"><FONT color="#ffffff">older articles</FONT></A> | + <A href="http://Andover.Net"><FONT color="#ffffff">Andover.Net</FONT></A> | + <A href="http://slashdot.org/advertising.shtml"><FONT color="#ffffff">advertising</FONT></A> | + <A href="http://slashdot.org/pollBooth.pl"><FONT color="#ffffff">past polls</FONT></A> | + <A href="http://slashdot.org/about.shtml"><FONT color="#ffffff">about</FONT></A> | + <A href="http://slashdot.org/faq.shtml"><FONT color="#ffffff">faq</FONT></A> ] + </FONT> + </CENTER> +</BODY> +</HTML> diff --git a/tkhtml1/tests/page2/image1 b/tkhtml1/tests/page2/image1 Binary files differnew file mode 100644 index 0000000..2ed6ddc --- /dev/null +++ b/tkhtml1/tests/page2/image1 diff --git a/tkhtml1/tests/page2/image10 b/tkhtml1/tests/page2/image10 Binary files differnew file mode 100644 index 0000000..3021b68 --- /dev/null +++ b/tkhtml1/tests/page2/image10 diff --git a/tkhtml1/tests/page2/image11 b/tkhtml1/tests/page2/image11 Binary files differnew file mode 100644 index 0000000..41d1fe3 --- /dev/null +++ b/tkhtml1/tests/page2/image11 diff --git a/tkhtml1/tests/page2/image12 b/tkhtml1/tests/page2/image12 Binary files differnew file mode 100644 index 0000000..655a686 --- /dev/null +++ b/tkhtml1/tests/page2/image12 diff --git a/tkhtml1/tests/page2/image13 b/tkhtml1/tests/page2/image13 Binary files differnew file mode 100644 index 0000000..97d5950 --- /dev/null +++ b/tkhtml1/tests/page2/image13 diff --git a/tkhtml1/tests/page2/image14 b/tkhtml1/tests/page2/image14 Binary files differnew file mode 100644 index 0000000..6d73ad8 --- /dev/null +++ b/tkhtml1/tests/page2/image14 diff --git a/tkhtml1/tests/page2/image15 b/tkhtml1/tests/page2/image15 Binary files differnew file mode 100644 index 0000000..90cc3b2 --- /dev/null +++ b/tkhtml1/tests/page2/image15 diff --git a/tkhtml1/tests/page2/image16 b/tkhtml1/tests/page2/image16 Binary files differnew file mode 100644 index 0000000..93aa853 --- /dev/null +++ b/tkhtml1/tests/page2/image16 diff --git a/tkhtml1/tests/page2/image17 b/tkhtml1/tests/page2/image17 Binary files differnew file mode 100644 index 0000000..f46f030 --- /dev/null +++ b/tkhtml1/tests/page2/image17 diff --git a/tkhtml1/tests/page2/image18 b/tkhtml1/tests/page2/image18 Binary files differnew file mode 100644 index 0000000..3badd5e --- /dev/null +++ b/tkhtml1/tests/page2/image18 diff --git a/tkhtml1/tests/page2/image19 b/tkhtml1/tests/page2/image19 Binary files differnew file mode 100644 index 0000000..bd4f6d9 --- /dev/null +++ b/tkhtml1/tests/page2/image19 diff --git a/tkhtml1/tests/page2/image2 b/tkhtml1/tests/page2/image2 Binary files differnew file mode 100644 index 0000000..7566dda --- /dev/null +++ b/tkhtml1/tests/page2/image2 diff --git a/tkhtml1/tests/page2/image20 b/tkhtml1/tests/page2/image20 Binary files differnew file mode 100644 index 0000000..358fa95 --- /dev/null +++ b/tkhtml1/tests/page2/image20 diff --git a/tkhtml1/tests/page2/image21 b/tkhtml1/tests/page2/image21 Binary files differnew file mode 100644 index 0000000..c81aa52 --- /dev/null +++ b/tkhtml1/tests/page2/image21 diff --git a/tkhtml1/tests/page2/image22 b/tkhtml1/tests/page2/image22 Binary files differnew file mode 100644 index 0000000..6cbd630 --- /dev/null +++ b/tkhtml1/tests/page2/image22 diff --git a/tkhtml1/tests/page2/image23 b/tkhtml1/tests/page2/image23 Binary files differnew file mode 100644 index 0000000..e8173a7 --- /dev/null +++ b/tkhtml1/tests/page2/image23 diff --git a/tkhtml1/tests/page2/image24 b/tkhtml1/tests/page2/image24 Binary files differnew file mode 100644 index 0000000..bffd4b4 --- /dev/null +++ b/tkhtml1/tests/page2/image24 diff --git a/tkhtml1/tests/page2/image25 b/tkhtml1/tests/page2/image25 Binary files differnew file mode 100644 index 0000000..c656fa4 --- /dev/null +++ b/tkhtml1/tests/page2/image25 diff --git a/tkhtml1/tests/page2/image26 b/tkhtml1/tests/page2/image26 Binary files differnew file mode 100644 index 0000000..bc93fdb --- /dev/null +++ b/tkhtml1/tests/page2/image26 diff --git a/tkhtml1/tests/page2/image27 b/tkhtml1/tests/page2/image27 Binary files differnew file mode 100644 index 0000000..6ad0eff --- /dev/null +++ b/tkhtml1/tests/page2/image27 diff --git a/tkhtml1/tests/page2/image28 b/tkhtml1/tests/page2/image28 Binary files differnew file mode 100644 index 0000000..88f0d7c --- /dev/null +++ b/tkhtml1/tests/page2/image28 diff --git a/tkhtml1/tests/page2/image29 b/tkhtml1/tests/page2/image29 Binary files differnew file mode 100644 index 0000000..e070418 --- /dev/null +++ b/tkhtml1/tests/page2/image29 diff --git a/tkhtml1/tests/page2/image3 b/tkhtml1/tests/page2/image3 Binary files differnew file mode 100644 index 0000000..ac3fa33 --- /dev/null +++ b/tkhtml1/tests/page2/image3 diff --git a/tkhtml1/tests/page2/image30 b/tkhtml1/tests/page2/image30 Binary files differnew file mode 100644 index 0000000..4a41950 --- /dev/null +++ b/tkhtml1/tests/page2/image30 diff --git a/tkhtml1/tests/page2/image31 b/tkhtml1/tests/page2/image31 Binary files differnew file mode 100644 index 0000000..60f13ed --- /dev/null +++ b/tkhtml1/tests/page2/image31 diff --git a/tkhtml1/tests/page2/image32 b/tkhtml1/tests/page2/image32 Binary files differnew file mode 100644 index 0000000..04ddc4e --- /dev/null +++ b/tkhtml1/tests/page2/image32 diff --git a/tkhtml1/tests/page2/image33 b/tkhtml1/tests/page2/image33 Binary files differnew file mode 100644 index 0000000..c1ecfff --- /dev/null +++ b/tkhtml1/tests/page2/image33 diff --git a/tkhtml1/tests/page2/image34 b/tkhtml1/tests/page2/image34 Binary files differnew file mode 100644 index 0000000..3dfd5d7 --- /dev/null +++ b/tkhtml1/tests/page2/image34 diff --git a/tkhtml1/tests/page2/image35 b/tkhtml1/tests/page2/image35 Binary files differnew file mode 100644 index 0000000..aea44f3 --- /dev/null +++ b/tkhtml1/tests/page2/image35 diff --git a/tkhtml1/tests/page2/image36 b/tkhtml1/tests/page2/image36 Binary files differnew file mode 100644 index 0000000..baef0e0 --- /dev/null +++ b/tkhtml1/tests/page2/image36 diff --git a/tkhtml1/tests/page2/image37 b/tkhtml1/tests/page2/image37 Binary files differnew file mode 100644 index 0000000..6c6ba52 --- /dev/null +++ b/tkhtml1/tests/page2/image37 diff --git a/tkhtml1/tests/page2/image38 b/tkhtml1/tests/page2/image38 Binary files differnew file mode 100644 index 0000000..e298e04 --- /dev/null +++ b/tkhtml1/tests/page2/image38 diff --git a/tkhtml1/tests/page2/image39 b/tkhtml1/tests/page2/image39 Binary files differnew file mode 100644 index 0000000..e16e2f1 --- /dev/null +++ b/tkhtml1/tests/page2/image39 diff --git a/tkhtml1/tests/page2/image4 b/tkhtml1/tests/page2/image4 Binary files differnew file mode 100644 index 0000000..9e5e46b --- /dev/null +++ b/tkhtml1/tests/page2/image4 diff --git a/tkhtml1/tests/page2/image5 b/tkhtml1/tests/page2/image5 Binary files differnew file mode 100644 index 0000000..646a6d9 --- /dev/null +++ b/tkhtml1/tests/page2/image5 diff --git a/tkhtml1/tests/page2/image6 b/tkhtml1/tests/page2/image6 Binary files differnew file mode 100644 index 0000000..7df417c --- /dev/null +++ b/tkhtml1/tests/page2/image6 diff --git a/tkhtml1/tests/page2/image7 b/tkhtml1/tests/page2/image7 Binary files differnew file mode 100644 index 0000000..0e6ac10 --- /dev/null +++ b/tkhtml1/tests/page2/image7 diff --git a/tkhtml1/tests/page2/image8 b/tkhtml1/tests/page2/image8 Binary files differnew file mode 100644 index 0000000..ba7fb47 --- /dev/null +++ b/tkhtml1/tests/page2/image8 diff --git a/tkhtml1/tests/page2/image9 b/tkhtml1/tests/page2/image9 Binary files differnew file mode 100644 index 0000000..b1cad73 --- /dev/null +++ b/tkhtml1/tests/page2/image9 diff --git a/tkhtml1/tests/page2/index.html b/tkhtml1/tests/page2/index.html new file mode 100644 index 0000000..7eaf2d2 --- /dev/null +++ b/tkhtml1/tests/page2/index.html @@ -0,0 +1,433 @@ +<html> +<head> + <title>Tcl Resource Center</title> +</head> + +<body bgcolor="white" text="black"> + + <!-- MenuTopLevel Resource Software Extensions --> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td width="120" valign="TOP"><a href="/"><img src="image1" width="120" height="79" alt="Scriptics" border="0"></a></td> + <td valign="top" width="548"> + + <!-- Table to hold tabs --> + <table cellpadding="0" cellspacing="0" border="0" width="548"> + <tr> + <td valign="top" align="right" colspan="15" width="548"><a name="TOP"><img src="image2" width="548" height="9" alt="Tcl/Tk" border="0"></a></td> + </tr> + <tr> + <td valign="top" align="right" colspan="15" width="548"><img src="image3" width="482" height="34" alt="Scripting Solutions for eBusiness Integration" border="0"></td> + </tr> + <tr> + <td width="18" valign="TOP"><img src="image4" width="18" height="36" alt="" border="0"></td> + <td width="58"><a href="/products/" onMouseOver="msover(4, 'http://images.scriptics.com/images/ProductsMouseOff.gif') ; return true ;" onMouseOut="msover(4, 'http://images.scriptics.com/images/ProductsOff.gif') ; return true ;"><img src="image5" width="58" height="36" alt="Products" border="0"></a></td> + <td width="14" valign="TOP"><img src="image6" width="14" height="36" alt="" border="0"></td> + <td width="69"><a href="/customers/" onMouseOver="msover(6, 'http://images.scriptics.com/images/CustomersMouseOff.gif') ; return true ;" onMouseOut="msover(6, 'http://images.scriptics.com/images/CustomersOff.gif') ; return true ;"><img src="image7" width="69" height="36" alt="Customers" border="0"></a></td> + <td width="14" valign="TOP"><img src="image6" width="14" height="36" alt="" border="0"></td> + <td width="60"><a href="/partners/" onMouseOver="msover(8, 'http://images.scriptics.com/images/PartnersMouseOff.gif') ; return true ;" onMouseOut="msover(8, 'http://images.scriptics.com/images/PartnersOff.gif') ; return true ;"><img src="image8" width="60" height="36" alt="Partners" border="0"></a></td> + <td width="14" valign="TOP"><img src="image6" width="14" height="36" alt="" border="0"></td> + <td width="56"><a href="/services/" onMouseOver="msover(10, 'http://images.scriptics.com/images/ServicesMouseOff.gif') ; return true ;" onMouseOut="msover(10, 'http://images.scriptics.com/images/ServicesOff.gif') ; return true ;"><img src="image9" width="56" height="36" alt="Services" border="0"></a></td> + <td width="14" valign="TOP"><img src="image10" width="14" height="36" alt="" border="0"></td> + <td width="88"><a href="/resource/" onMouseOver="msover(12, 'http://images.scriptics.com/images/ResourceMouseOn.gif') ; return true ;" onMouseOut="msover(12, 'http://images.scriptics.com/images/ResourceOn.gif') ; return true ;"><img src="image11" width="88" height="36" alt="Tcl Resources" border="0"></a></td> + <td width="14" valign="TOP"><img src="image12" width="14" height="36" alt="" border="0"></td> + <td width="57"><a href="/company/" onMouseOver="msover(14, 'http://images.scriptics.com/images/CompanyMouseOff.gif') ; return true ;" onMouseOut="msover(14, 'http://images.scriptics.com/images/CompanyOff.gif') ; return true ;"><img src="image13" width="57" height="36" alt="Company" border="0"></a></td> + <td width="8" valign="TOP"><img src="image14" width="8" height="36" alt="" border="0"></td> + <td width="50" valign="TOP"><img src="image15" width="50" height="36" alt="" border="0"></td> + <td width="14" valign="TOP"><img src="image16" width="14" height="36" alt="" border="0"></td> + </tr> + </table> + </td> + </tr> + </table> <script language="Javascript"> + <!-- + function msover(num, file ) + { + old = (((navigator.appName=='Netscape') && + (parseInt(navigator.appVersion)<=3.0 ))) + if ( !old ) { + document.images[num].src=file + } + } + //--> + </SCRIPT> + +<!-- MenuSubLevel Resource Software Extensions Tk --> + +<table cellpadding="0" cellspacing="0" border="0"> + +<!-- Left Hand Column--> + +<tr><td valign="top" width="120"><table cellpadding="0" cellspacing="0" border="0" width="120"> + <tr> + <td width="120" valign="TOP"><img src="image17" width="120" height="4" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/resource/software/"><img src="image18" width="120" height="11" alt="Software" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image19" width="120" height="4" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/resource/software/tcltk/"><img src="image20" width="120" height="11" alt="Tcl/Tk Core" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image19" width="120" height="4" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/resource/software/applications/"><img src="image21" width="120" height="11" alt="Applications" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image22" width="120" height="4" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/resource/software/extensions/"><img src="image23" width="120" height="11" alt="Extensions" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image24" width="120" height="6" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/resource/software/patches/"><img src="image25" width="120" height="11" alt="Patches" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image19" width="120" height="4" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/resource/software/java/"><img src="image26" width="120" height="11" alt="Tcl & Java" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image19" width="120" height="4" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/resource/software/ports/"><img src="image27" width="120" height="11" alt="Tcl/Tk Ports" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image19" width="120" height="4" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/resource/software/tools/"><img src="image28" width="120" height="11" alt="Tools" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image29" width="120" height="6" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/resource/doc/"><img src="image30" width="120" height="11" alt="Documentation" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image31" width="120" height="5" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/resource/community/"><img src="image32" width="120" height="11" alt="Community" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image31" width="120" height="5" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/live/bydate"><img src="image33" width="120" height="11" alt="What's New" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image31" width="120" height="5" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/forms/urlnote.html"><img src="image34" width="120" height="11" alt="Add URL" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image31" width="120" height="5" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/live/keyword"><img src="image35" width="120" height="11" alt="Keyword Search" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image31" width="120" height="5" alt="" border="0"></td> + </tr> + <tr> + <td width="120" valign="TOP"><a href="/live/sitemap"><img src="image36" width="120" height="11" alt="Index" border="0"></a></td> + </tr> + <tr> + <td width="120" valign="TOP"><img src="image37" width="120" height="6" alt="" border="0"></td> + </tr> +</table><!-- End Left Column --></td><!-- Right Hand Column --><td valign="top" width="548" align="left"><table cellpadding="0" cellspacing="0" border="0" width="548"> + <tr> + <td width="295" valign="TOP"><img src="image38" width="295" height="42" alt="Resource" border="0"></td> + <td width="187" valign="bottom" align="right"><FORM action="/live/keyword"><img src="image39" width="46" height="24" alt="" border="0"><INPUT TYPE="TEXT" SIZE="10" MAXLENGTH="35" NAME="keywords"><INPUT type="IMAGE" border="0" img="img" src="http://images.scriptics.com/images/Go.gif" value="submit" width="33" height="24"></FORM> + </tr> + </table> + <!-- 2 Columns for spacer --> + <table cellpadding="0" cellspacing="0" border="0" width="548"> + <tr> + <!-- Spacer Column --> + <td valign="top" width="10"> + + </td> + + + <td valign="top" width="548"><font face="Geneva, Helvetica, Arial" size="2"><h1>Tcl Resource Center</h1> +<font size="+1"><a href="/resource/">Top</a>><a href="/resource/software/" ="">Software Central</a>><a href="/resource/software/extensions/" ="">Extensions</a>>Tk Widgets</font><font size="-1"><br>Viewed by name (<a href="/resource/software/extensions/tk/?sortby=date">By date</a>)</font><br> +<p>Tk is a toolkit for building graphical user interfaces with Tcl. + Your Tcl/Tk scripts run on UNIX, Windows, and Macintosh.<p> +<font face="Geneva, Helvetica, Arial"><ul></ul></font><dl> +<dt><b><a href="http://marge.phys.washington.edu/%7Ezager/blt80-unoff-exe.zip" ="">BLT 8.0 Unofficial zip and DLL</a></b> +<dd>This is a compiled version of BLT 8.0 "unofficial" for +the Windows platform. <a href="/live/annotate?url=http%3a%2f%2fmarge%2ephys%2ewashington%2eedu%2f%257Ezager%2fblt80%2dunoff%2dexe%2ezip">Edit</a> + <i><font size="-1">(September 24, 1999 06:31)</font></i><dt><b><a href="ftp://ftp.neosoft.com/languages/tcl/sorted/unknown/blt8.0p2-unoff.tgz" ="">BLT 8.0p2 Unofficial tar file</a><a name="bltunoff"></a></b> +<dd>This is a contributed patch to make BLT compatible with Tcl/Tk 8.0p2. While still "unofficial", it is widely used. + Make sure you get the 8.0p2 version because the 8.0 version does + not compile under windows. + There is also a <a href="ftp://ftp.neosoft.com/languages/sorted/devel/blt2.3-8.1.tar.gz">2.3-8.1 version</a> that has been patched to work with 8.1. + <a href="ftp://ftp.neosoft.com/languages/tcl/sorted/unknown/blt8.0p2-unoff.README">README file</a>. <a href="/live/annotate?url=ftp%3a%2f%2fftp%2eneosoft%2ecom%2flanguages%2ftcl%2fsorted%2funknown%2fblt8%2e0p2%2dunoff%2etgz">Edit</a> + <i><font size="-1">(August 30, 1999 06:38)</font></i><dt><b><a href="http://www.tcltk.com/blt/" ="">BLT Home Page</a></b> +<dd> + Author <b>George Howlett</b>, Version <b>2.3</b>, + Works with <b>Tk 4.1 through Tk 8.1</b> +<br><a href="ftp://ftp.tcltk.com/pub/blt/">Download</a>, <a href="ftp://ftp.tcltk.com/pub/blt/BLT2.3.tar.gz">BLT2.3.tar.gz</a>, <a href="ftp://ftp.tcltk.com/pub/blt/BLT2.4h.tar.gz">BLT2.4h.tar.gz</a>, <a href="ftp://ftp.tcltk.com/pub/blt/BLT2.4i.tar.gz">BLT2.4i.tar.gz</a>, <a href="ftp://ftp.tcltk.com/pub/blt/blt2.4i-for-8.0.exe">blt2.4i-for-8.0.exe</a>, <a href="ftp://ftp.tcltk.com/pub/blt/blt2.4i-for-8.1.exe">blt2.4i-for-8.1.exe</a><br>BLT is a set of widgets for Tk, including a graph widget, +bar chart, drag&drop, a simple command tracer, and much more. +The 2.4 release, which is still under development, works with 8.0 +or higher. +There are also an "<a href="#bltunoff">unofficial</a>" release for 8.0p2 +and 8.1a2 that were not done by the author. <a href="/live/annotate?url=http%3a%2f%2fwww%2etcltk%2ecom%2fblt%2f">Edit</a> + <i><font size="-1">(October 26, 1999 09:43)</font></i><dt><b><a href="http://www.unifix-online.com/BWidget/index.html" ="">BWidget</a></b> +<dd>A set of native Tk 8.x Widgets using Tcl8.x namespaces. +The ToolKit is available under Unix/X11 and Windows. +The BWidget(s) have a professional look&feel as in other +well known Toolkits (Tix or Incr Widget) but the concept is +radically different because everything is native +so no platform compilation, no compiled extension +library are needed. The code is 100 Pure Tcl/Tk. +More 30 components : Notebook, PageManager, Tree, PanedWindow, ButtonBox, +ScrollView, ComboBox, SpinBox, ListBox, SelectFont, SelectColor, +ProgressBare ... <a href="/live/annotate?url=http%3a%2f%2fwww%2eunifix%2donline%2ecom%2fBWidget%2findex%2ehtml">Edit</a> + <i><font size="-1">(September 06, 1999 09:58)</font></i><dt><b><a href="http://purl.oclc.org/net/nijtmans/dash.html" ="">Dash Patch for Tk</a></b> +<dd>This patch has many enhancements to the Tk and its canvas +widget, including dashed lines, smoothed polygons, +and performance enhancements. <a href="/live/annotate?url=http%3a%2f%2fpurl%2eoclc%2eorg%2fnet%2fnijtmans%2fdash%2ehtml">Edit</a> + <i><font size="-1">(November 21, 1999 06:33)</font></i><dt><b><a href="http://www.hwaci.com/sw/et" ="">Embedded Tk (et)</a></b> +<dd> + Author <b><a href="mailto:drh@acm.org" ="">Richard Hipp</a></b>, Version <b>8.0b5</b>, + Works with <b>Tk 4.0, 4.1, 4.2, 8.0</b> +<br>Download: <a href="http://www.hwaci.com/sw/et/et80b5.tar.gz">et80b5.tar.gz</a><br>Embedded Tk or ``ET'' is tool for making stand-alone executables out of a mixture of C or C++ and Tcl/Tk. +Using ET you can invoke a short Tcl/Tk script in the middle of a C routine, or you can invoke a C routine in the +middle of a Tcl/Tk script. ET also bundles external Tcl/Tk scripts (including the standard Tcl/Tk startup scripts) +into the executable so that the executable can be run on another binary-compatible computer that doesn't have +Tcl/Tk installed. <a href="/live/annotate?url=http%3a%2f%2fwww%2ehwaci%2ecom%2fsw%2fet">Edit</a> + <i><font size="-1">(August 19, 1999 15:35)</font></i><dt><b><a href="http://www.purl.org/net/hobbs/tcl/script/tkcon/" ="">Enhanced Tk Console (TkCon)</a></b> +<dd> + Author <b><a href="mailto:jeffrey.hobbs@oen.siemens.de" ="">Jeff Hobbs</a></b>, Version <b>1.3</b>, + Works with <b>Tk 4.1 through Tk 8.1</b> +<br>Download: <a href="http://www.purl.org/net/hobbs/tcl/script/tkcon/tkcon.tar.gz">tkcon.tar.gz</a><br>TkCon is a replacement for the standard console that comes with Tk (on Windows/Mac, but also works on + +Unix). The console itself provides many more features than the standard console. <a href="/live/annotate?url=http%3a%2f%2fwww%2epurl%2eorg%2fnet%2fhobbs%2ftcl%2fscript%2ftkcon%2f">Edit</a> + <i><font size="-1">(August 23, 1999 12:06)</font></i><dt><b><a href="http://www.scriptmeridian.org/projects/tk/" ="">Frontier-Tk ScriptMeridian project</a></b> +<dd>This project seeks to integrate the Tk toolkit +with the Frontier scripting language. <a href="/live/annotate?url=http%3a%2f%2fwww%2escriptmeridian%2eorg%2fprojects%2ftk%2f">Edit</a> + <i><font size="-1">(August 19, 1999 15:36)</font></i><dt><b><a href="http://purl.oclc.org/net/nijtmans/img.html" ="">Img image format extension</a></b> +<dd>This package enhances Tk, adding support for many other Image formats: +BMP, XBM, XPM, GIF (with transparency), PNG, +JPEG, TIFF and postscript. +This is implemented as a shared library that can be dynamically loaded into +Tcl/Tk. + <a href="/live/annotate?url=http%3a%2f%2fpurl%2eoclc%2eorg%2fnet%2fnijtmans%2fimg%2ehtml">Edit</a> + <i><font size="-1">(November 21, 1999 06:35)</font></i><dt><b><a href="http://purl.oclc.org/net/oakley/tcl/mclistbox/index.html" ="">mclistbox - a multi-column listbox widget</a></b> +<dd>mclistbox is a multi-column listbox that is +written in pure tcl and runs on all platforms +that support tcl/tk 8.0 or higher. This widget +requires no other extensions; it is completely +standalone. <a href="/live/annotate?url=http%3a%2f%2fpurl%2eoclc%2eorg%2fnet%2foakley%2ftcl%2fmclistbox%2findex%2ehtml">Edit</a> + <i><font size="-1">(August 19, 1999 15:37)</font></i><dt><b><a href="http://home.t-online.de/home/dshepherd/tkview.htm" ="">MFC views C++ class for embedding Tk</a></b> +<dd>The idea of embedding Tk in MFC windows always seemed very enticing but information was sparse and contradictory - on a + scale between "very easy" and "not yet possible". The only thing for it was to have a go and lo, it wasn't that hard after all. + CTkView is a C++ class which can be used in MFC SDI or MDI applications. An instance of CTkView hosts an embedded Tk + toplevel widget and performs some management chores for the widget so that it can size, update and react correctly to Windows + events. <a href="/live/annotate?url=http%3a%2f%2fhome%2et%2donline%2ede%2fhome%2fdshepherd%2ftkview%2ehtm">Edit</a> + <i><font size="-1">(August 19, 1999 15:38)</font></i><dt><b><a href="http://www.cs.umd.edu/hcil/pad++" ="">Pad++</a></b> +<dd> + Author <b><a href="mailto:pad-info@cs.umd.edu" ="">Ben Bederson et al</a></b>, Version <b>0.9p1</b>, + Works with <b>8.0</b> +<br>Download: <a href="http://www.cs.umd.edu/hcil/pad++/download.html">download.html</a><br>Pad++ is a Tk widget that provides a Zoomable User Interface (ZUI) that supports real-time interactive zoomable graphics in a fashion similar to the Tk Canvas widget. Pad++ supports tens of thousands of objects which include text, images, graphics, portals, lenses, simple html (and more), including transparency and rotation. <a href="/live/annotate?url=http%3a%2f%2fwww%2ecs%2eumd%2eedu%2fhcil%2fpad%2b%2b">Edit</a> + <i><font size="-1">(August 19, 1999 15:39)</font></i><dt><b><a href="http://home.t-online.de/home/sesam.com/freeware.htm" ="">Progressbar</a></b> +<dd>Progressbar is a megawidget written in pure tcl (ie: no compiling required - runs on all platforms Macintosh, Unix, Windows). +Its primary purpose is to show the progress of any action in percent. <a href="/live/annotate?url=http%3a%2f%2fhome%2et%2donline%2ede%2fhome%2fsesam%2ecom%2ffreeware%2ehtm">Edit</a> + <i><font size="-1">(January 24, 2000 09:19)</font></i><dt><b><a href="http://jfontain.free.fr/" ="">scwoop (Simple Composite Widget Object Oriented Package)</a></b> +<dd>Scwoop is a composite widget (also known as mega widget) extension to the great Tk widget library. Scwoop is +entirely written in Tcl using the stooop (Simple Tcl Only Object Oriented Programming) extension. <a href="/live/annotate?url=http%3a%2f%2fjfontain%2efree%2efr%2f">Edit</a> + <i><font size="-1">(January 09, 2000 02:10)</font></i><dt><b><a href="http://www2.clearlight.com/~oakley/tcl/supertext.html" ="">Supertext - tk text widget with unlimited undo</a></b> +<dd> + Author <b><a href="mailto:oakley@channelpoint.com" ="">Bryan Oakley</a></b>, Version <b>1.0b1</b>, + Works with <b>Tcl 8.0</b> +<br>Download: <a href="http://www2.clearlight.com/~oakley/tcl/supertext.tcl">supertext.tcl</a><br>Supertext is a package that provides a tk text widget with full undo and the ability to execute procedures both before and after a text +widget command has been processed. Supertext may be used as-is, or for the brave it may be used in place of the standard text +widget. <a href="/live/annotate?url=http%3a%2f%2fwww2%2eclearlight%2ecom%2f%7eoakley%2ftcl%2fsupertext%2ehtml">Edit</a> + <i><font size="-1">(August 23, 1999 12:06)</font></i><dt><b><a href="http://www.hwaci.com/sw/tk/nbpi.html" ="">Tabbed Notebook Widget</a></b> +<dd> + Author <b><a href="mailto:drh@acm.org" ="">Richard Hipp</a></b>, Version <b>1.0</b>, + Works with <b>Tk 4.1 or later.</b> +<br>Download: <a href="http://www.hwaci.com/sw/tk/notebook.tcl">notebook.tcl</a><br>This implements a tabbed notebook using +a canvas widget and embedded frames. +This is pure Tcl +code - not a C extension. <a href="/live/annotate?url=http%3a%2f%2fwww%2ehwaci%2ecom%2fsw%2ftk%2fnbpi%2ehtml">Edit</a> + <i><font size="-1">(August 23, 1999 12:08)</font></i><dt><b><a href="http://www.tcltk.com/ellson/ftp/Gdtclft2.0.README" ="">Tcl GD - graphics</a></b> +<dd> + Author <b>John Ellson and Spencer Thomas</b>, Version <b>2.0</b>, + Works with <b>8.0 and higher</b> +<br>Download: <a href="http://www.tcltk.com/ellson/ftp/Gdtclft2.0.tar.gz">Gdtclft2.0.tar.gz</a><br> + Thomas Boutell's Gd package provides a convenient way to generate + PNG images with a C program. If you prefer Tcl for CGI + applications, you'll want the TCL GD extension. <a href="/live/annotate?url=http%3a%2f%2fwww%2etcltk%2ecom%2fellson%2fftp%2fGdtclft2%2e0%2eREADME">Edit</a> + <i><font size="-1">(August 19, 1999 14:52)</font></i><dt><b><a href="http://www.stratasys.com/software/metagui" ="">The Meta-GUI Tools</a></b> +<dd>The Meta-GUI tools provide a framework for quickly building full +GUI applications. The GUI is rendered by a run-time engine +based on a hierarchical set of definitions you provide. At the bottom +of the hierarchy are abstract data types such as length, angle, +string, etc., and these are used to progressively build up frames, +dialogs, toolbars, menus, and operations. <a href="/live/annotate?url=http%3a%2f%2fwww%2estratasys%2ecom%2fsoftware%2fmetagui">Edit</a> + <i><font size="-1">(August 23, 1999 12:10)</font></i><dt><b><a href="http://jfontain.free.fr/" ="">Tkpiechart Home Page</a></b> +<dd>Tkpiechart is a Tcl-only extension that allows the programmer to create and dynamically update 2D or 3D pie +charts in a Tcl/Tk application. This uses the stooop package and builds +pie charts on a Tk canvas. <a href="/live/annotate?url=http%3a%2f%2fjfontain%2efree%2efr%2f">Edit</a> + <i><font size="-1">(January 09, 2000 02:12)</font></i><dt><b><a href="http://www.cygnus.com/~irox/tkprint/" ="">TkPrint</a></b> +<dd>TkPrint is an extension that allows you to print from a + Tk widget. <a href="/live/annotate?url=http%3a%2f%2fwww%2ecygnus%2ecom%2f%7eirox%2ftkprint%2f">Edit</a> + <i><font size="-1">(October 11, 1999 09:58)</font></i><dt><b><a href="http://www.purl.org/net/hobbs/tcl/capp/" ="">TkTable Home Page</a></b> +<dd>The TkTable widget. The <code>table</code> command creates a +2-dimensional grid of cells. The table can use a Tcl array variable or Tcl + +command for data storage and retrieval. <a href="/live/annotate?url=http%3a%2f%2fwww%2epurl%2eorg%2fnet%2fhobbs%2ftcl%2fcapp%2f">Edit</a> + <i><font size="-1">(November 18, 1999 09:25)</font></i><dt><b><a href="http://ftp.austintx.net/users/jatucker/TkTextmatrix/default.htm" ="">TkTextMatrix (spreadsheet)</a></b> +<dd> + Author <b><a href="mailto:jatucker@austin.dsccc.com" ="">John Arthur Tucker</a></b>, Version <b>4.1</b>, + Works with <b>Tk 4.1</b> +<br>Download: <a href="http://ftp.austintx.net/users/jatucker/TkTextmatrix/download.htm">download.htm</a>, <a href="http://ftp.austintx.net/users/jatucker/TkTextmatrix/textmatrix4.1.tar.gz">textmatrix4.1.tar.gz</a><br>A Tcl/Tk spreadsheet widget, TkTextmatrix, which is implemented in C++ and is + basically a Tk Canvas widget plus extra behavior for manipulating rows and columns of cell + items many times faster than with a plain Tk Canvas. It actually inserts text nearly as fast + as the Tk Text widget. If you work with or are interested in creating your own Tcl/Tk widgets + in C++, you might want to take a look at the C++ widget library included with this + distribution. <a href="/live/annotate?url=http%3a%2f%2fftp%2eaustintx%2enet%2fusers%2fjatucker%2fTkTextmatrix%2fdefault%2ehtm">Edit</a> + <i><font size="-1">(August 23, 1999 12:14)</font></i><dt><b><a href="http://www.cs.umd.edu/~bederson/Togl.html" ="">ToGL - a Tk Open GL widget</a></b> +<dd>Togl is a Tk widget for OpenGL rendering. Togl is based on OGLTK, originally written by Benjamin Bederson at the +University of New Mexico (who has since moved to the University of Maryland). Togl adds the new features: +<ul> +<li> color-index mode support including color allocation functions +<li> support for requesting stencil, accumulation, alpha buffers, etc +<li> multiple OpenGL drawing widgets +<li> OpenGL extension testing from Tcl +<li> simple, portable font support +<li> overlay plane support +</ul> +Togl allows one to create and manage a special Tk/OpenGL widget with Tcl and render into it with a C program. That is, +a typical Togl program will have Tcl code for managing the user interface and a C program for computations and +OpenGL rendering. <a href="/live/annotate?url=http%3a%2f%2fwww%2ecs%2eumd%2eedu%2f%7ebederson%2fTogl%2ehtml">Edit</a> + <i><font size="-1">(August 23, 1999 12:14)</font></i><dt><b><a href="http://www.hwaci.com/sw/tk/treepi.html" ="">Tree Widget</a></b> +<dd>This implements a tree display in a canvas widget. +It is similar in layout to that of the +Windows explorer file viewer. This is pure Tcl +code - not a C extension. <a href="/live/annotate?url=http%3a%2f%2fwww%2ehwaci%2ecom%2fsw%2ftk%2ftreepi%2ehtml">Edit</a> + <i><font size="-1">(September 29, 1999 14:37)</font></i><dt><b><a href="http://www.du.edu/~mschwart/tcl-tk.htm" ="">Windows Extensions for Tcl/Tk (Michael Schwartz)</a></b> +<dd>This site has pointers to several extensions specific to the +Windows platform. The extensions provide printing, +a MAPI interface to send email, and an interface to manipulate +.INI files, among other things. <a href="/live/annotate?url=http%3a%2f%2fwww%2edu%2eedu%2f%7emschwart%2ftcl%2dtk%2ehtm">Edit</a> + <i><font size="-1">(October 07, 1999 10:50)</font></i><dt><b><a href="http://www.tcltk.com/iwidgets/" ="">[incr Widgets] Home Page</a></b> +<dd>[incr Widgets] is a set of megawidgets (combo boxes, etc.) that are +upon the [incr Tcl] object system and the [incr Tk] megawidget +framework. This comes bundled with the +<a href="http://www.tcltk.com/itcl/">[incr Tcl]</a> distributions. <a href="/live/annotate?url=http%3a%2f%2fwww%2etcltk%2ecom%2fiwidgets%2f">Edit</a> + <i><font size="-1">(September 05, 1999 16:08)</font></i><dt><b><a href="http://www1.clearlight.com/~oakley/tcl/combobox/index.html" ="">combobox</a></b> +<dd> + Author <b><a href="mailto:oakley@channelpoint.com" ="">Bryan Oakley</a></b>, Version <b>1.03</b>, + Works with <b>8.x</b> +<br>Download: <a href="http://www1.clearlight.com/~oakley/tcl/combobox/combobox.tcl">combobox.tcl</a><br>combobox is a pure-tcl implementation of a combobox widget. It is +entirely self contained and does not require any other OO or megawidget +extension. It supports both editable and non-editable entries, and +provides the ability to call a procedure anytime the value of the combobox +changes. <a href="/live/annotate?url=http%3a%2f%2fwww1%2eclearlight%2ecom%2f%7eoakley%2ftcl%2fcombobox%2findex%2ehtml">Edit</a> + <i><font size="-1">(August 23, 1999 12:15)</font></i><dt><b><a href="http://www.multimania.com/droche/rnotebook/index.html" ="">Rnotebook</a></b> +<dd> + Author <b><a href="mailto:dan@lectra.com" ="">Daniel Roche</a></b>, Version <b>1.0</b>, + Works with <b>8.0 or higher</b> +<br>Download: <a href="http://www.multimania.com/droche/rnotebook/index.html">index.html</a><br>This implements a resizeable notebook +widget in pure tcl/tk <a href="/live/annotate?url=http%3a%2f%2fwww%2emultimania%2ecom%2fdroche%2frnotebook%2findex%2ehtml">Edit</a> + <i><font size="-1">(August 19, 1999 15:39)</font></i><dt><b><a href="http://www.tregar.com/samdi.html" ="">saMDI v1.0a1 Multi-Document Interface Extension</a></b> +<dd>A multi-document interface (MDI) extension for TCL/Tk 8.0. +This is a common interface format in Microsoft Windows that lets a parent window contain multiple child windows. +In effect you get a window manager inside a window! +Uses and includes the STOOOP object-oriented extension by +Jean-Luc Fontaine. +saMDI v1.0a1 GPL Copyright 1998 Sam Tregar. <a href="/live/annotate?url=http%3a%2f%2fwww%2etregar%2ecom%2fsamdi%2ehtml">Edit</a> + <i><font size="-1">(August 23, 1999 12:07)</font></i><dt><b><a href="http://tix.mne.com/htdocs/tix/index.html" ="">Tix Support Site</a></b> +<dd> + Author <b><a href="mailto:tix@mne.com" ="">Ioi Lam, (adopted by Gregg Squires)</a></b>, Version <b>4.1</b>, + Works with <b>Tcl 7.4 through Tcl 8.0</b> +<br><a href="ftp://ftp.tix.mne.com/pub/tix/">Download</a>, <a href="ftp://ftp.tix.mne.com/pub/tix/Tix4.1.0.006.tar.gz">Tix4.1.0.006.tar.gz</a>, <a href="ftp://ftp.tix.mne.com/pub/tix/Tix41p6.zip">Tix41p6.zip</a>, <a href="ftp://ftp.tix.mne.com/pub/tix/win41p6bin.zip">win41p6bin.zip</a><br><b>Tix has found a new home!</b> + <br> + Tix provides over 40 new Tk including the +combo box, file selection dialogs, paned widget, +notebook, hierarchical list, directory tree, and more. + <a href="/live/annotate?url=http%3a%2f%2ftix%2emne%2ecom%2fhtdocs%2ftix%2findex%2ehtml">Edit</a> + <i><font size="-1">(August 23, 1999 12:11)</font></i><dt><b><a href="ftp://ftp.archive.eso.org/pub/tree" ="">Tk Tree Widget (C++)</a></b> +<dd>Tk Tree widget for Tcl8.0.3. + +This version contains (optional) support for \[incr Tcl\] and \[incr Tk\] +version 3.0. +<br> +With the tree widget, you can display a tree in a Tk canvas. The nodes +can be made up of any number of canvas items or even other Tk widgets. +You create the objects that make up a node and the line that connects +it to its parent and pass them to the tree widget. After this the tree +widget manages the positions of the nodes and end points of the tree +lines. Operations are available for inserting, moving and removing +nodes and subtrees and for querrying the position of a node in the +tree. The tree can be displayed horizontally or vertically. + <a href="/live/annotate?url=ftp%3a%2f%2fftp%2earchive%2eeso%2eorg%2fpub%2ftree">Edit</a> + <i><font size="-1">(August 25, 1999 03:14)</font></i><dt><b><a href="http://www.purl.org/net/hobbs/tcl/script/widget/" ="">widget, simple megawidget package</a></b> +<dd> + Author <b><a href="mailto:jeffrey.hobbs@oen.siemens.de" ="">Jeffrey Hobbs</a></b>, Version <b>0.9</b>, + Works with <b>Tcl/Tk 8.0 or higher</b> +<br>Download: <a href="http://www.purl.org/net/hobbs/tcl/script/widget/widget-0.9.tar.gz">widget-0.9.tar.gz</a><br>This is a package of + megawidgets (i.e., compound widgets) that work almost exactly like Tk widgets. + You can also build your own new megawidgets. +Includes: combobox, hierarchy, console, progressbar, +tabnotebook, validating entry, pane geometry manager, baloon help. <a href="/live/annotate?url=http%3a%2f%2fwww%2epurl%2eorg%2fnet%2fhobbs%2ftcl%2fscript%2fwidget%2f">Edit</a> + <i><font size="-1">(August 23, 1999 12:16)</font></i></dl> +<hr><p><center><font size="-1" face="Geneva, Helvetica, Arial"><br><a href="#TOP"><b>Top</b></a><br><!-- key ResourceSoftwareExtensions --><a href="/">Home</a> + | <a href="/products/">Products</a> + | <a href="/customers/">Customers</a> + | <a href="/partners/">Partners</a> + | <a href="/services/">Services</a> + | <a href="/resource/">Tcl Resources</a> + | <a href="/company/">Company</a> +<br><a href="/live/keyword">Search</a> + | <a href="/live/map">Site Map</a> + | <a href="/company/feedback.html?url=%2fresource%2fsoftware%2fextensions%2ftk%2f">Feedback</a> + | <a href="/company/contact.html">Contact Us</a> + | <a href="mailto:info@scriptics.com">info@scriptics.com</a> + + <SCRIPT LANGUAGE="Javascript"> +<!-- + browser = (((navigator.appName == "Netscape") &&(parseInt(navigator.appVersion) >= 3 )) || ((navigator.appName =="Microsoft Internet Explorer") && (parseInt(navigator.appVersion) >= 4 ))) + + if ( browser ) + { + over = new MakeImageArray(10) + over[0].src = "http://images.scriptics.com/images/ProductsMouseOff.gif" + over[1].src = "http://images.scriptics.com/images/CustomersMouseOff.gif" + over[2].src = "http://images.scriptics.com/images/PartnersMouseOff.gif" + over[3].src = "http://images.scriptics.com/images/ServicesMouseOff.gif" + over[4].src = "http://images.scriptics.com/images/ResourceMouseOff.gif" + over[5].src = "http://images.scriptics.com/images/CompanyMouseOff.gif" + over[6].src = "http://images.scriptics.com/images/homeMainRollover1.gif" + over[7].src = "http://images.scriptics.com/images/homeMainRollover2.gif" + over[8].src = "http://images.scriptics.com/images/homeMainRollover3.gif" + over[9].src = "http://images.scriptics.com/images/homeMainRollover3.gif" + + } + + function MakeImageArray(n) { + this.length = n + for (var i = 0; i<=n; i++)="i++)" {="{" this[i]="this[i]" ="" new="new" Image()="Image()" }="}" return="return" this="this" }="}" //="//" --="--"> + </SCRIPT><br> + <font size="2"> + © 1998-2000 Scriptics Corporation. All rights reserved. + <a href="/legal_notice.html">Legal Notice</a> | <A href="" /privacy.html="/privacy.html"> + Privacy Statement</a> + </td></tr></table></td></tr></table> +</Body> +</Html>
\ No newline at end of file diff --git a/tkhtml1/tests/page3/image1 b/tkhtml1/tests/page3/image1 Binary files differnew file mode 100644 index 0000000..814d1e8 --- /dev/null +++ b/tkhtml1/tests/page3/image1 diff --git a/tkhtml1/tests/page3/image10 b/tkhtml1/tests/page3/image10 Binary files differnew file mode 100644 index 0000000..45001fa --- /dev/null +++ b/tkhtml1/tests/page3/image10 diff --git a/tkhtml1/tests/page3/image11 b/tkhtml1/tests/page3/image11 Binary files differnew file mode 100644 index 0000000..7c4c170 --- /dev/null +++ b/tkhtml1/tests/page3/image11 diff --git a/tkhtml1/tests/page3/image12 b/tkhtml1/tests/page3/image12 Binary files differnew file mode 100644 index 0000000..903e734 --- /dev/null +++ b/tkhtml1/tests/page3/image12 diff --git a/tkhtml1/tests/page3/image13 b/tkhtml1/tests/page3/image13 Binary files differnew file mode 100644 index 0000000..226d4f6 --- /dev/null +++ b/tkhtml1/tests/page3/image13 diff --git a/tkhtml1/tests/page3/image14 b/tkhtml1/tests/page3/image14 Binary files differnew file mode 100644 index 0000000..8e8c718 --- /dev/null +++ b/tkhtml1/tests/page3/image14 diff --git a/tkhtml1/tests/page3/image2 b/tkhtml1/tests/page3/image2 Binary files differnew file mode 100644 index 0000000..2ddeb32 --- /dev/null +++ b/tkhtml1/tests/page3/image2 diff --git a/tkhtml1/tests/page3/image3 b/tkhtml1/tests/page3/image3 Binary files differnew file mode 100644 index 0000000..1651ba7 --- /dev/null +++ b/tkhtml1/tests/page3/image3 diff --git a/tkhtml1/tests/page3/image4 b/tkhtml1/tests/page3/image4 Binary files differnew file mode 100644 index 0000000..b565c8d --- /dev/null +++ b/tkhtml1/tests/page3/image4 diff --git a/tkhtml1/tests/page3/image5 b/tkhtml1/tests/page3/image5 Binary files differnew file mode 100644 index 0000000..e1268b8 --- /dev/null +++ b/tkhtml1/tests/page3/image5 diff --git a/tkhtml1/tests/page3/image6 b/tkhtml1/tests/page3/image6 Binary files differnew file mode 100644 index 0000000..1a6b260 --- /dev/null +++ b/tkhtml1/tests/page3/image6 diff --git a/tkhtml1/tests/page3/image7 b/tkhtml1/tests/page3/image7 Binary files differnew file mode 100644 index 0000000..cec7aa0 --- /dev/null +++ b/tkhtml1/tests/page3/image7 diff --git a/tkhtml1/tests/page3/image8 b/tkhtml1/tests/page3/image8 Binary files differnew file mode 100644 index 0000000..ad0d748 --- /dev/null +++ b/tkhtml1/tests/page3/image8 diff --git a/tkhtml1/tests/page3/image9 b/tkhtml1/tests/page3/image9 Binary files differnew file mode 100644 index 0000000..46ade30 --- /dev/null +++ b/tkhtml1/tests/page3/image9 diff --git a/tkhtml1/tests/page3/index.html b/tkhtml1/tests/page3/index.html new file mode 100644 index 0000000..ce92e8a --- /dev/null +++ b/tkhtml1/tests/page3/index.html @@ -0,0 +1,2787 @@ +<html><body bgcolor="white"> +<hr> +<h1 align="center">Embedding Tcl in C/C++ Applications</h1> + + <table width="100%"> + <tr><td valign="top" align="left" width="46%"> + <b>Presented At:</b> + <blockquote> + The Tcl2K Conference<br> + Austin, Texas<br> + <nobr>9:00am, February 15, 2000</nobr><br> + </blockquote> + </td> + <td width="5%"> </td> + <td valign="top" align="left" width="46%"> + <b>Instructor:</b> + <blockquote> + D. Richard Hipp<br> + drh@hwaci.com<br> + http://www.hwaci.com/drh/<br> + 704.948.4565 + </blockquote> + </td></tr> + </table><p> + <center><table border="2"> + <tr><td> + <p align="center"> + Copies of these notes, example source code,<br>and other + resources related to this tutorial<br>are available online at + <a href="http://www.hwaci.com/tcl2k/"> + http://www.hwaci.com/tcl2k/</a></p> + <p align="center"><small>$Id$</small></p></td></tr> + </table> + </center> +</p> + +<br clear="both"><p><hr></p> +<h2 align="center">Tutorial Outline</h2> +<p><ul><li>Introduction</li> +<li>Building It Yourself</li> +<ul><li>"Hello, World!" using Tcl</li> +<li>Tcl scripts as C strings</li> +<li>Adding new Tcl commands</li> +<li>A tour of the Tcl API</li> +<li>Tcl initialization scripts</li> +<li>Adding Tk</li> +</ul><li>Tools Survey</li> +<li>Mktclapp</li> +<ul><li>"Hello World" using mktclapp</li> +<li>Adding C code</li> +<li>Other Features</li> +<li>Invoking Tcl from C</li> +<li>Running mktclapp directly</li> +<li>Real-world examples</li> +</ul><li>Summary</li> +</ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Embedding Tcl in C/C++ Applications</h2> +<p><ul><li>You know how to program in Tcl/Tk</li></ul><ul><li>You know how to program in C/C++</li></ul><ul><li>This tutorial is about how to do both at the same time.</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Why Mix C With Tcl/Tk?</h2> +<p><ul><li>Use C for the things C is good at and Tcl for the things + Tcl is good at.</li></ul><ul><li>Generate standalone executables. + <ul><li>Eliminate the need to install Tcl/Tk.</li> + <li>Prevent problems when the wrong version of Tcl/Tk is installed.</li> + </ul></li></ul><ul><li>Prevent end users from changing the source code. + <ul><li>Keeps users from creating new bugs.</li> + <li>Protects proprietary code.</li> + </ul></li></ul><ul><li>Office politics</li></ul><ul><li>Use Tcl/Tk as a portability layer for a large C program</li></ul><ul><li>Use Tcl as a testing interface</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Why Mix C With Tcl/Tk?</h2> +<p><blockquote><big><b> + "Use C for the things C is good at and use Tcl/Tk for the things + Tcl/Tk is good at." + </b></blockquote></p><p> + + <table width="100%"> + <tr><td valign="top" align="left" width="46%"> + <b>C is good at:</b> + <ul> + <li>Speed</li> + <li>Complex data structures</li> + <li>Computation</li> + <li>Interacting with hardware</li> + <li>Byte-by-byte data analysis</li> + </ul> + </td> + <td width="5%"> </td> + <td valign="top" align="left" width="46%"> + <b>Tcl/Tk is good at:</b> + <ul> + <li>Building a user interface</li> + <li>Manipulation of strings</li> + <li>Portability</li> + <li>Opening sockets</li> + <li>Handling events</li> + </ul> + </td></tr> + </table> +<br clear="both"><p><hr></p> +<h2 align="center">Programming Models</h2> +<table width="100%"> +<tr><td valign="top" width="49%"> + + <p><b>Mainstream Tcl Programming Model:</b></p> +</td> +<td width="2%"> </td> +<td valign="top" width="49%"> + + <p><b>Embedded Tcl Programming Model: </b></p> +</td></tr> +<tr><td valign="top" width="49%"> + + <ul><li>Add bits of C code to a large Tcl program</li></ul> +</td> +<td width="2%"> </td> +<td valign="top" width="49%"> + + <ul><li>Add bits of Tcl code to a large C program</li></ul> +</td></tr> +<tr><td valign="top" width="49%"> + + <ul><li>Main Tcl script loads extensions written in C</li></ul> +</td> +<td width="2%"> </td> +<td valign="top" width="49%"> + + <ul><li>Main C procedure invokes the Tcl interpreter</li></ul> +</td></tr> +<tr><td valign="top" width="49%"> + + <ul><li>Tcl/Tk is a programming language</li></ul> +</td> +<td width="2%"> </td> +<td valign="top" width="49%"> + + <ul><li>Tcl/Tk is a C library</li></ul> +</td></tr> +<tr><td valign="top" width="49%"> + + <center><img src="image1"><br> + Most of the Tcl2K conference is about</center> +</td> +<td width="2%"> </td> +<td valign="top" width="49%"> + + <center><img src="image1"><br> + This tutorial is about</center> +</td></tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">"Hello, World!" Using The Tcl Library</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h></tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Always include <tcl.h></td> +</tr> +<tr><td valign="center"> +<small><tt>int main(int argc, char **argv){<br> + Tcl_Interp *interp;</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> interp = Tcl_CreateInterp();</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Create a new Tcl interpreter</td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Eval(interp, "puts {Hello, World!}");</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Execute a Tcl command.</td> +</tr> +<tr><td valign="center"> +<small><tt> return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Compiling "Hello, World!"</h2> +<p><p><b>Unix:</b></p> + <blockquote><tt> + $ gcc hello.c -ltcl -lm -ldl<br> + $ ./a.out<br> + Hello, World!</tt></blockquote> + + <p><b>Windows using Cygwin:</b></p> + <blockquote><tt> + C:> gcc hello.c -ltcl80 -lm<br> + C:> a.exe<br> + Hello, World!</tt></blockquote> + + <p><b>Windows using Mingw32:</b></p> + <blockquote><tt> + C:> gcc -mno-cygwin hello.c -ltcl82 -lm<br> + </tt></blockquote> +<table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>Also works with VC++</b></td></tr></table></p> +<br clear="both"><p><hr></p> +<h2 align="center">Where Does <tt>-ltcl</tt> Come From On Unix?</h2> +<p><p>Build it yourself using these steps:</p></p><p> +<p><ul><li>Get tcl8.2.2.tar.gz from Scriptics</li></ul><ul><li><tt>zcat tcl8.2.2.tar.gz | tar vx </tt></li></ul><ul><li><tt>cd tcl8.2.2/unix</tt></li></ul><ul><li><tt>./configure --disable-shared</tt></li></ul><ul><li><tt>make</tt></li></ul><ul><li>Move <b>libtcl8.2.a</b> to your lib directory.</li></ul><ul><li>Copy <b>../generic/tcl.h</b> into /usr/include.</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">What Other Libraries Are Required For Unix?</h2> +<p><ul><li>The sequence of <b>-l</b> options after <b>-ltcl</b> + varies from system to system</li></ul><ul><li>Observe what libraries the TCL makefile inserts when + it is building <b>tclsh</b></li></ul><ul><li>Examples in this talk are for RedHat Linux 6.0 for Intel</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">How To Compile Under Unix Without Installing Tcl</h2> +<p><p>Specify the *.a file directly:</p> + <blockquote><pre> + $ gcc -I../tcl8.2.2/generic hello.c \ + ../tcl8.2.2/unix/libtcl8.2.a -lm -ldl + $ strip a.out + $ ./a.out + Hello, World!</pre></blockquote> + + <p>Or, tell the C compiler where to look for *.a files:</p> + <blockquote><pre> + $ gcc -I../tcl8.2.2/generic hello.c \ + -L../tcl8.2.2/unix -ltcl -lm -ldl + $ strip a.out + $ ./a.out + Hello, World!</pre></blockquote> +<table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>The <tt>-I../tcl8.2.2</tt> argument + tells the compiler where to + find <tt><tcl.h></tt>.</p></b></td></tr></table></p> +<br clear="both"><p><hr></p> +<h2 align="center">What's "Cygwin"?</h2> +<p><ul><li>An implementation of GCC/G++ and all development tools + for Windows95/98/NT/2000</li></ul><ul><li>Available for free download at + <blockquote> + <tt>http://sourceware.cygnus.com/cygwin/</tt> + </blockquote></li></ul><ul><li>Also available shrink-wrapped at your local software retailer or + online at + <blockquote> + <tt>http://www.cygnus.com/cygwin/index.html</tt> + </blockquote></li></ul><ul><li>Programs compiled using Cygwin require a special + DLL (<b>cygwin1.dll</b>) that provides a POSIX system API</li></ul><ul><li>Cygwin1.dll cannot be shipped with proprietary programs + without purchasing a license from Cygnus.</li></ul><ul><li>Mingw32 is the same compiler as Cygwin, but generates + binaries that do not use cygwin1.dll</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Where Does <tt>-ltcl82</tt> Come From On Windows?</h2> +<p><p>Build it like this:</p></p><p> +<p><ul><li>Get <b>tcl82.lib</b> and <b>tcl82.dll</b> from Scriptics.</li></ul><ul><li><tt>echo EXPORTS >tcl82.def</tt></li></ul><ul><li><tt>nm tcl82.lib | grep 'T _' | sed 's/.* T _//' >>tcl82.def</tt></li></ul><ul><li><tt>dlltool --def tcl82.def --dllname tcl82.dll --output-lib libtcl82.a</tt></li></ul><ul><li>Move <b>libtcl82.a</b> to the lib directory and <b>tcl82.dll</b> + to the bin directory.</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Where Does Your Code Go?</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> + <br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;<br> + interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> /* Your application code goes here */</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Insert C code here to do whatever it is your program is + suppose to do</td> +</tr> +<tr><td valign="center"> +<small><tt> return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Building A Simple TCLSH</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> + <br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;<br> + char *z;<br> + char zLine[2000];<br> + interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> while( fgets(zLine,sizeof(zLine),stdin) ){</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Get one line of input</td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Eval(interp, zLine);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Execute the input as Tcl.</td> +</tr> +<tr><td valign="center"> +<small><tt> z = Tcl_GetStringResult(interp);<br> + if( z[0] ){<br> + printf("¸üÿ¿PX¶\n", z);<br> + }</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Print result if not empty</td> +</tr> +<tr><td valign="center"> +<small><tt> }<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>What if user types more than 2000 characters?</b></td></tr></table> +</p> + +<br clear="both"><p><hr></p> +<h2 align="center">Building A Simple TCLSH</h2> +<p>Use TCL to handle input. Allows input lines of unlimited length.</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> + <br> +/* Tcl code to implement the<br> +** input loop */<br> +static char zLoop[] = <br> + "while {![eof stdin]} {\n"</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> " set line [gets stdin]\n"</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Get one line of input</td> +</tr> +<tr><td valign="center"> +<small><tt> " set result [eval $line]\n"</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Execute input as Tcl</td> +</tr> +<tr><td valign="center"> +<small><tt> " if {$result!=\"\"} {puts $result}\n"</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Print result</td> +</tr> +<tr><td valign="center"> +<small><tt> "}\n"<br> +;<br> + <br> +<br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;<br> + interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Eval(interp, zLoop);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Run the Tcl input loop</td> +</tr> +<tr><td valign="center"> +<small><tt> return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>But what about commands that span multiple lines of input?</b></td></tr></table> +</p> + +<br clear="both"><p><hr></p> +<h2 align="center">Better Handling Of Command-Line Input</h2> +<p>The file "input.tcl"</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>set line {}<br> +while {![eof stdin]} {</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> if {$line!=""} {<br> + puts -nonewline "> "<br> + } else {<br> + puts -nonewline "% "<br> + }<br> + flush stdout</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Prompt for user input. The prompt is normally "%" + but changes to ">" if the current line is a continuation.</td> +</tr> +<tr><td valign="center"> +<small><tt> append line [gets stdin]<br> + if {[info complete $line]} {</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> if {[catch {uplevel #0 $line} result]} {</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">If the command is complete, execute it.</td> +</tr> +<tr><td valign="center"> +<small><tt> puts stderr "Error: $result"<br> + } elseif {$result!=""} {<br> + puts $result<br> + }<br> + set line {}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> } else {<br> + append line \n<br> + }</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">If the command is incomplete, append a newline and get + another line of text.</td> +</tr> +<tr><td valign="center"> +<small><tt>}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Better Handling Of Command-Line Input</h2> +<p>The file "input.c"</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> + <br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;<br> + interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Eval(interp, "source input.tcl");</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Read and execute the input loop</td> +</tr> +<tr><td valign="center"> +<small><tt> return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>But now the program is not standalone!</b></td></tr></table> +</p> + +<br clear="both"><p><hr></p> +<h2 align="center">Converting Scripts Into C Strings</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>static char zInputLoop[] = <br> + "set line {}\n"<br> + "while {![eof stdin]} {\n"<br> + " if {$line!=\"\"} {\n"<br> + " puts -nonewline \"> \"\n"<br> + " } else {\n"<br> + " puts -nonewline \"% \"\n"<br> + " }\n"<br> + " flush stdout\n"<br> + " append line [gets stdin]\n"<br> + " if {[info complete $line]} {\n"<br> + " if {[catch {uplevel #0 $line} result]} {\n"<br> + " puts stderr \"Error: $result\"\n"<br> + " } elseif {$result!=\"\"} {\n"<br> + " puts $result\n"<br> + " }\n"<br> + " set line {}\n"<br> + " } else {\n"<br> + " append line \\n\n"<br> + " }\n"<br> + "}\n"<br> +;</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Compile Tcl Scripts Into C Programs</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> +</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt><br> +static char zInputLoop[] = <br> + /* Actual code omitted */<br> +;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Copy and paste the converted Tcl script here</td> +</tr> +<tr><td valign="center"> +<small><tt><br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;<br> + interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Eval(interp, zInputLoop);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Execute the Tcl code</td> +</tr> +<tr><td valign="center"> +<small><tt> return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Converting Scripts To Strings<br>Using SED Or TCLSH</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>sed -e 's/\\/\\\\/g' \ </tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Convert <b>\</b> into <b>\\</b></td> +</tr> +<tr><td valign="center"> +<small><tt> -e 's/"/\\"/g' \ </tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Convert <b>"</b> into <b>\"</b></td> +</tr> +<tr><td valign="center"> +<small><tt> -e 's/^/ "/' \ </tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Add <b>"</b> to start of each line</td> +</tr> +<tr><td valign="center"> +<small><tt> -e 's/$/\\n"/' input.tcl</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Add <b>\n"</b> to end of each line</td> +</tr> +<tr><td valign="center"> +<small><tt><br> + <br> +<br> + <br> +<br> +while {![eof stdin]} {<br> + set line [gets stdin]</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> regsub -all {\} $line {&&} line</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Convert <b>\</b> into <b>\\</b></td> +</tr> +<tr><td valign="center"> +<small><tt> regsub -all {"} $line {\"} line</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Convert <b>"</b> into <b>\"</b></td> +</tr> +<tr><td valign="center"> +<small><tt> puts "\"$line\\n\""</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Add <b>"</b> in front and <b>\n"</b> at the end</td> +</tr> +<tr><td valign="center"> +<small><tt>}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Converting Scripts Into C Strings</h2> +<p>You may want to save space by removing comments and extra whitespace + from scripts.</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>static char zInputLoop[] = <br> + "set line {}\n"<br> + "while {![eof stdin]} {\n"<br> + "if {$line!=\"\"} {\n"<br> + "puts -nonewline \"> \"\n"<br> + "} else {\n"<br> + "puts -nonewline \"% \"\n"<br> + "}\n"<br> + "flush stdout\n"<br> + "append line [gets stdin]\n"<br> + "if {[info complete $line]} {\n"<br> + "if {[catch {uplevel #0 $line} result]} {\n"<br> + "puts stderr \"Error: $result\"\n"<br> + "} elseif {$result!=\"\"} {\n"<br> + "puts $result\n"<br> + "}\n"<br> + "set line {}\n"<br> + "} else {\n"<br> + "append line \\n\n"<br> + "}\n"<br> + "}\n"<br> +;</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Converting Scripts To Strings</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>sed -e 's/\\/\\\\/g' \ <br> + -e 's/"/\\"/g' \ </tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> -e '/^ *#/d' \ </tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Delete lines that begin with #</td> +</tr> +<tr><td valign="center"> +<small><tt> -e '/^ *$/d' \ </tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Delete blank lines</td> +</tr> +<tr><td valign="center"> +<small><tt> -e 's/^ */ "/' \ </tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Delete leading spaces</td> +</tr> +<tr><td valign="center"> +<small><tt> -e 's/$/\\n"/' input.tcl<br> + <br> +<br> + <br> +<br> + <br> +while {![eof stdin]} {<br> + set line [gets stdin]</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> set line [string trimleft $line]</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Remove leading space</td> +</tr> +<tr><td valign="center"> +<small><tt> if {$line==""} continue</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Delete blank lines</td> +</tr> +<tr><td valign="center"> +<small><tt> if {[string index $line 0]=="#"} {<br> + continue<br> + }</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Delete lines starting with #</td> +</tr> +<tr><td valign="center"> +<small><tt> regsub -all {\} $line {&&} line<br> + regsub -all {"} $line {\"} line<br> + puts "\"$line\\n\""<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Removing Comments Or Leading Space<br>Will Break Some Tcl Scripts!</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>image create bitmap smiley -data {</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>#define smile_width 15<br> +#define smile_height 15</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">These lines begin with # but are not comment</td> +</tr> +<tr><td valign="center"> +<small><tt>static unsigned char smile_bits[] = {<br> + 0xc0, 0x01, 0x30, 0x06, 0x0c, 0x18,<br> + 0x04, 0x10, 0x22, 0x22, 0x52, 0x25,<br> + 0x01, 0x40, 0x01, 0x40, 0x01, 0x40,<br> + 0x12, 0x24, 0xe2, 0x23, 0x04, 0x10,<br> + 0x0c, 0x18, 0x30, 0x06, 0xc0, 0x01};<br> +}<br> + <br> +<br> + <br> +text .t<br> +pack .t<br> +.t insert end [string trim {</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>She walks in beauty, like the night<br> + Of cloudless climes and starry skies;<br> +And all that's best of dark and bright<br> + Meet in her aspect and her eyes;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Indentation is deleted on lines 2 + and 4</td> +</tr> +<tr><td valign="center"> +<small><tt>}] <br> + <br> +</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>Problems like these are rare</b></td></tr></table> +</p> + +<br clear="both"><p><hr></p> +<h2 align="center">Adding A "continue" Command</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>set line {}<br> +while {![eof stdin]} {<br> + if {$line!=""} {<br> + puts -nonewline "> "<br> + } else {<br> + puts -nonewline "% "<br> + }<br> + flush stdout<br> + append line [gets stdin]<br> + if {[info complete $line]} {</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> if {[lindex $line 0]=="continue"} {<br> + break;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Break out of the loop if the command + is "continue"</td> +</tr> +<tr><td valign="center"> +<small><tt> } elseif {[catch {uplevel #0 $line} result]} {<br> + puts stderr "Error: $result"<br> + } elseif {$result!=""} {<br> + puts $result<br> + }<br> + set line {}<br> + } else {<br> + append line \n<br> + }<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Stop For Tcl Input At Various Points<br>In A C Program</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> + <br> +static char zInputLoop[] = <br> + /* Tcl Input loop as a C string */<br> +;<br> + <br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;<br> + interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> /* Application C code */</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Do some computation</td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Eval(interp, zInputLoop);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Stop for some Tcl input</td> +</tr> +<tr><td valign="center"> +<small><tt> /* More application C code */</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Do more computation</td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Eval(interp, zInputLoop);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Stop for more Tcl input</td> +</tr> +<tr><td valign="center"> +<small><tt> /* Finish up the application */</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Finish the computation</td> +</tr> +<tr><td valign="center"> +<small><tt> return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Using Tcl For Testing</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> + <br> +static char zInputLoop[] = <br> + /* Tcl Input loop as a C string */<br> +;<br> + <br> +</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>int main(int argc, char **argv){<br> +#ifdef TESTING<br> + Tcl_Interp *interp;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Create interpreter only if TESTING + is defined</td> +</tr> +<tr><td valign="center"> +<small><tt> interp = Tcl_CreateInterp();<br> +#endif<br> + /* Application C code */</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>#ifdef TESTING<br> + Tcl_Eval(interp, zInputLoop);<br> +#endif</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Accept command-line input only if TESTING + is defined</td> +</tr> +<tr><td valign="center"> +<small><tt> /* More application C code */<br> +#ifdef TESTING<br> + Tcl_Eval(interp, zInputLoop);<br> +#endif<br> + /* Finish up the application */<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Creating A New Tcl Command In C</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> + <br> +int NewCmd(</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> void *clientData,<br> + Tcl_Interp *interp,<br> + int argc,<br> + char **argv</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">The Tcl command is implemented as + a C function with four arguments.</td> +</tr> +<tr><td valign="center"> +<small><tt>){<br> + printf("Hello, World!\n");</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> return TCL_OK;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Returns TCL_OK or TCL_ERROR</td> +</tr> +<tr><td valign="center"> +<small><tt>}<br> + <br> +static char zInputLoop[] = <br> + /* Tcl code omitted... */<br> +;<br> + <br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;<br> + interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_CreateCommand(interp, "helloworld",<br> + NewCmd, 0, 0);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Tell the interpreter which C function to call when the + "helloworld" Tcl command is executed</td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Eval(interp, zInputLoop);<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Linkage From Tcl To C</h2> +<p><p align="center"><img src="image4"></p></p><p><ul><li>3rd parameter of Tcl_CreateCommand() is a pointer to the C subroutine + that implements the command.</li></ul><ul><li>4th parameter to Tcl_CreateCommand() becomes the 1st parameter to + the C routine whenever the Tcl command is executed.</li></ul><ul><li>1st parameter to Tcl_CreateCommand() must be a valid Tcl interpreter. + The same pointer appears as the second parameter to the C routine + whenever the Tcl command is executed.</li></ul></p> + +<br clear="both"><p><hr></p> +<h2 align="center">Linkage From Tcl To C</h2> +<p><p align="center"><img src="image5"></p></p><p><ul><li>5th parameter of Tcl_CreateCommand() is a pointer to the C subroutine + that is called when the Tcl command is deleted.</li></ul><ul><li>4th parameter to Tcl_CreateCommand() becomes the 1st parameter to + the C routine.</li></ul></p> + +<br clear="both"><p><hr></p> +<h2 align="center">When To Use A Delete Proc</h2> +<p>Examples of where the delete proc is used in standard Tcl/Tk:</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>button .b -text Hello<br> +pack .b</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>rename .b {}</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Deleting the <b>.b</b> command causes the button to be destroyed</td> +</tr> +<tr><td valign="center"> +<small><tt><br> + <br> +</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>image create photo smiley \ <br> + -file smiley.gif</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>rename smiley {}</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Deleting the <b>smiley</b> command destroys the image and reclaims the + memory used to hold the image</td> +</tr> +</table> +<p><ul><li>Always use a delete proc if the clientData is a pointer to + malloced memory or some other resource that needs freeing</li></ul><ul><li>Delete procs are never used in the Tcl core but are used + extensively in Tk</li></ul></p> + +<br clear="both"><p><hr></p> +<h2 align="center">Linkage From Tcl To C</h2> +<p>The <tt>argc</tt> and <tt>argv</tt> parameters work just like in + <tt>main()</tt></p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>helloworld one {two three} four</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center"><tt>argc = 4<br> + argv[0] = "helloworld"<br> + argv[1] = "one"<br> + argv[2] = "two three"<br> + argv[3] = "four"<br> + argv[4] = NULL</tt></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">A Short-Cut</h2> +<p>In a program with many new Tcl commands implemented in C, it becomes + tedious to type the same four parameters over and over again. So + we define a short-cut.</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#define TCLARGS \ <br> + void *clientData, \ <br> + Tcl_Interp *interp, \ <br> + int argc, \ <br> + char *argv</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Define TCLARGS once in a header file</td> +</tr> +<tr><td valign="center"> +<small><tt> <br> + <br> + </tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>int NewCmd(TCLARGS){</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Use the TCLARGS macro to define new C functions + that implement Tcl commands.</td> +</tr> +<tr><td valign="center"> +<small><tt> /* implementation... */<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>For brevity, we will use the TCLARGS macro during the + rest of this talk.</b></td></tr></table> +</p> + +<br clear="both"><p><hr></p> +<h2 align="center">Returning A Value From C Back To Tcl</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>int NewCmd(TCLARGS){</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Note that the C function returns an "int"</td> +</tr> +<tr><td valign="center"> +<small><tt> return TCL_OK;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Return value is TCL_OK or TCL_ERROR</td> +</tr> +<tr><td valign="center"> +<small><tt>}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p><ul><li>TCL_OK and TCL_ERROR are defined in <tcl.h></li></ul><ul><li>Other valid return values TCL_RETURN, TCL_BREAK and TCL_CONTINUE + are rarely used</li></ul><ul><li>Common mistake: forgetting to return TCL_OK</li></ul></p> + +<br clear="both"><p><hr></p> +<h2 align="center">Returning A Value From C Back To Tcl</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>int NewCmd(TCLARGS){</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_SetResult(interp,"Hello!",TCL_STATIC);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Set the result to "Hello!"</td> +</tr> +<tr><td valign="center"> +<small><tt> return TCL_OK;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p><ul><li>Result should be the text of an error message if you + return TCL_ERROR.</li></ul><ul><li>3rd argument to Tcl_SetResult() can be TCL_STATIC, + TCL_DYNAMIC, TCL_VOLATILE, or a function pointer.</li></ul><ul><li>Also consider using Tcl_AppendResult().</li></ul><ul><li>Direct access to <tt>interp->result</tt> is deprecated.</li></ul><ul><li>See the man pages for details.</li></ul></p> + +<br clear="both"><p><hr></p> +<h2 align="center">The Tcl_Obj Interface</h2> +<p><ul><li>A new way to write Tcl commands in C code</li></ul><ul><li>First introduced in Tcl8.0</li></ul><ul><li>Can be much faster, especially for lists or numeric values.</li></ul><ul><li>Able to handle arbitrary binary data.</li></ul><ul><li>More difficult to program.</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">The Tcl_Obj Interface</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>int NewObjCmd(<br> + void *clientData,<br> + Tcl_Interp *interp,<br> + int objc,</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Obj *const* objv</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">4th parameter is an array Tcl_Objs, not an array of strings</td> +</tr> +<tr><td valign="center"> +<small><tt>){<br> + /* Implementation... */<br> + return TCL_OK;<br> +}<br> + <br> +static char zInputLoop[] = <br> + /* Tcl code omitted... */<br> +;<br> + <br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;<br> + interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_CreateObjCommand(interp, "newcmd",<br> + NewObjCmd, 0, 0);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Use a different function to register the command</td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Eval(interp, zInputLoop);<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">The Tcl_Obj Interface</h2> +<p><ul><li>There are countless access methods for reading information from and + placing information in Tcl_Objs. Always use the access methods.</li></ul><ul><li>Details provided at Lee Bernhard's talk this afternoon.</li></ul><ul><li>Definitely use Tcl_Objs if you are writing a new Tcl extension.</li></ul><ul><li>Tcl_Objs address some of the weaknesses of Tcl relative to C/C++. + <ul> + <li> Tcl_Objs are faster </li> + <li> Tcl_Objs work with binary data </li> + </ul> + But C/C++ is faster still and better for working with binary data.</li></ul><ul><li>When mixing C/C++ with Tcl/Tk the benefits of Tcl_Objs are + less important. Using Tcl_Objs in this context may not be + worth the extra trouble.</li></ul><ul><li>This talk will focus on the string interface.</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Nickel Tour Of The Tcl API</h2> +<p><p><b>Memory allocation functions</b></p> +<center><table width="90%"><tr> +<td width="32%" valign="top"><small><tt> + Tcl_Alloc<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_Free<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_Realloc<br> +</tt></small></td> +</table></center><p><b>Functions useful in the implementation of new Tcl commands</b></p> +<center><table width="90%"><tr> +<td width="32%" valign="top"><small><tt> + Tcl_AppendElement<br> + Tcl_AppendResult<br> + Tcl_GetBoolean<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_GetDouble<br> + Tcl_GetInt<br> + Tcl_GetStringResult<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_ResetResult<br> + Tcl_SetResult<br> +</tt></small></td> +</table></center><p><b>Functions for controlling the Tcl interpreter</b></p> +<center><table width="90%"><tr> +<td width="32%" valign="top"><small><tt> + Tcl_CreateCommand<br> + Tcl_CreateInterp<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_CreateObjCommand<br> + Tcl_DeleteCommand<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_DeleteInterp<br> + Tcl_Exit<br> +</tt></small></td> +</table></center></p> +<br clear="both"><p><hr></p> +<h2 align="center">Nickel Tour Of The Tcl API</h2> +<p><p><b>I/O functions</b></p> +<center><table width="90%"><tr> +<td width="32%" valign="top"><small><tt> + Tcl_Close<br> + Tcl_Eof<br> + Tcl_Flush<br> + Tcl_GetChannel<br> + Tcl_GetChannelMode<br> + Tcl_GetChannelName<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_Gets<br> + Tcl_OpenCommandChannel<br> + Tcl_OpenFileChannel<br> + Tcl_OpenTcpClient<br> + Tcl_OpenTcpServer<br> + Tcl_Read<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_Seek<br> + Tcl_Tell<br> + Tcl_Ungets<br> + Tcl_Write<br> + Tcl_WriteChars<br> +</tt></small></td> +</table></center><p><b>Names and meanings of system error codes</b></p> +<center><table width="90%"><tr> +<td width="32%" valign="top"><small><tt> + Tcl_ErrnoId<br> + Tcl_ErrnoMsg<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_GetErrno<br> + Tcl_SetErrno<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_SignalId<br> + Tcl_SignalMsg<br> +</tt></small></td> +</table></center></p> +<br clear="both"><p><hr></p> +<h2 align="center">Nickel Tour Of The Tcl API</h2> +<p><p><b>General Operating System Calls</b></p> +<center><table width="90%"><tr> +<td width="32%" valign="top"><small><tt> + Tcl_Access<br> + Tcl_Chdir<br> + Tcl_GetCwd<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_GetHostName<br> + Tcl_GetNameOfExecutable<br> + Tcl_Sleep<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_Stat<br> +</tt></small></td> +</table></center><p><b>String Manipulation And Comparison</b></p> +<center><table width="90%"><tr> +<td width="32%" valign="top"><small><tt> + Tcl_Concat<br> + Tcl_Merge<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_SplitList<br> + Tcl_StringCaseMatch<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_StringMatch<br> +</tt></small></td> +</table></center><p><b>Dynamically Resizable Strings</b></p> +<center><table width="90%"><tr> +<td width="49%" valign="top"><small><tt> + Tcl_DStringAppend<br> + Tcl_DStringAppendElement<br> + Tcl_DStringEndSublist<br> + Tcl_DStringInit<br> + Tcl_DStringLength<br> +</tt></small></td> +<td width="49%" valign="top"><small><tt> + Tcl_DStringResult<br> + Tcl_DStringSetLength<br> + Tcl_DStringStartSublist<br> + Tcl_DStringValue<br> +</tt></small></td> +</table></center></p> +<br clear="both"><p><hr></p> +<h2 align="center">Nickel Tour Of The Tcl API</h2> +<p><p><b>Event Handlers</b></p> +<center><table width="90%"><tr> +<td width="49%" valign="top"><small><tt> + Tcl_CancelIdleCall<br> + Tcl_CreateChannelHandler<br> + Tcl_CreateTimerHandler<br> + Tcl_DeleteChannelHandler<br> +</tt></small></td> +<td width="49%" valign="top"><small><tt> + Tcl_DeleteTimerHandler<br> + Tcl_DoOneEvent<br> + Tcl_DoWhenIdle<br> +</tt></small></td> +</table></center><p><b>Functions For Reading And Writing Tcl Variables</b></p> +<center><table width="90%"><tr> +<td width="32%" valign="top"><small><tt> + Tcl_GetVar<br> + Tcl_GetVar2<br> + Tcl_LinkVar<br> + Tcl_SetVar<br> + Tcl_SetVar2<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_TraceVar<br> + Tcl_TraceVar2<br> + Tcl_UnlinkVar<br> + Tcl_UnsetVar<br> + Tcl_UnsetVar2<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_UntraceVar<br> + Tcl_UntraceVar2<br> + Tcl_UpdateLinkedVar<br> +</tt></small></td> +</table></center><p><b>Functions For Executing Tcl Code</b></p> +<center><table width="90%"><tr> +<td width="32%" valign="top"><small><tt> + Tcl_Eval<br> + Tcl_EvalFile<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_EvalObj<br> + Tcl_GlobalEval<br> +</tt></small></td> +<td width="32%" valign="top"><small><tt> + Tcl_GlobalEvalObj<br> + Tcl_VarEval<br> +</tt></small></td> +</table></center></p> +<br clear="both"><p><hr></p> +<h2 align="center">Nickel Tour Of The Tcl API</h2> +<p><p><b>Functions For Dealing With Unicode</b></p> +<center><table width="90%"><tr> +<td width="49%" valign="top"><small><tt> + Tcl_NumUtfChars<br> + Tcl_UniCharAtIndex<br> + Tcl_UniCharIsAlnum<br> + Tcl_UniCharIsAlpha<br> + Tcl_UniCharIsControl<br> + Tcl_UniCharIsDigit<br> + Tcl_UniCharIsGraph<br> + Tcl_UniCharIsLower<br> + Tcl_UniCharIsPrint<br> + Tcl_UniCharIsPunct<br> + Tcl_UniCharIsSpace<br> + Tcl_UniCharIsUpper<br> + Tcl_UniCharIsWordChar<br> + Tcl_UniCharLen<br> + Tcl_UniCharNcmp<br> + Tcl_UniCharToLower<br> + Tcl_UniCharToTitle<br> +</tt></small></td> +<td width="49%" valign="top"><small><tt> + Tcl_UniCharToUpper<br> + Tcl_UniCharToUtf<br> + Tcl_UniCharToUtfDString<br> + Tcl_UtfAtIndex<br> + Tcl_UtfBackslash<br> + Tcl_UtfCharComplete<br> + Tcl_UtfFindFirst<br> + Tcl_UtfFindLast<br> + Tcl_UtfNcasecmp<br> + Tcl_UtfNcmp<br> + Tcl_UtfNext<br> + Tcl_UtfPrev<br> + Tcl_UtfToLower<br> + Tcl_UtfToTitle<br> + Tcl_UtfToUniChar<br> + Tcl_UtfToUniCharDString<br> + Tcl_UtfToUpper<br> +</tt></small></td> +</table></center> + <p><b>Functions For Dealing With Tcl_Objs</b></p> + <blockquote><i>Too numerous to list...</i></blockquote></p> +<br clear="both"><p><hr></p> +<h2 align="center">Documentation Of The Tcl API</h2> +<p><ul><li>Tcl comes with excellent man pages</li></ul><ul><li>"Use the source, Luke"</li></ul><ul><li>See <tt>tclDecl.h</tt> for a list of API functions</li></ul><ul><li>The header comments on the implementation of API functions usually + gives a good description of what the function does and how it should + be used.</li></ul><ul><li>Most API functions are used within Tcl and Tk. Use grep to locate + examples.</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Initialization Scripts</h2> +<p><ul><li>Run the mini TCLSH implemented above and execute the <tt>parray</tt> command</li></ul><ul><li>It doesn't work! What's wrong? </p></li></li></ul><ul><li><tt>parray</tt> is really a Tcl proc that is read in when the + interpreter is initialized. </p></li></li></ul><ul><li><tt>parray</tt> (and several other commands) are stored in a + handful of "Initialization Scripts" </p></li></li></ul><ul><li>All the initialization scripts are stored in the + "Tcl Library" - a directory on the host + computer. </p></li></li></ul><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>Invoke the Tcl_Init() function to locate and read the + Tcl initialization scripts.</b></td></tr></table></p> +<br clear="both"><p><hr></p> +<h2 align="center">The <tt>Tcl_Init()</tt> Function</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> + <br> +static char zInputLoop[] = <br> + /* Tcl code omitted... */<br> +;<br> + <br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;<br> + interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Init(interp);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Locate and read the initialization scripts</td> +</tr> +<tr><td valign="center"> +<small><tt> /* Call Tcl_CreateCommand()? */<br> + Tcl_Eval(interp, zInputLoop);<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>But Tcl_Init() can fail. We need to check its return value...</b></td></tr></table> +</p> + +<br clear="both"><p><hr></p> +<h2 align="center">The <tt>Tcl_Init()</tt> Function</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> + <br> +static char zInputLoop[] = <br> + /* Tcl code omitted... */<br> +;<br> + <br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;<br> + interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> if( Tcl_Init(interp)!=TCL_OK ){<br> + fprintf(stderr,"Tcl_Init() failed: ¸üÿ¿PX¶",<br> + Tcl_GetStringResult(interp));<br> + }</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Print error message if Tcl_Init() fails</td> +</tr> +<tr><td valign="center"> +<small><tt> /* Call Tcl_CreateCommand()? */<br> + Tcl_Eval(interp, zInputLoop);<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>But now the program is not standalone.</b></td></tr></table> +</p> + +<br clear="both"><p><hr></p> +<h2 align="center">How <tt>Tcl_Init()</tt> Works</h2> +<p><ul><li>Computes the value of variable <tt>tcl_libPath</tt>.</li></ul><ul><li>Invokes the procedure named "<tt>tclInit</tt>"</li></ul><ul><li>A default <tt>tclInit</tt> procedure is built into Tcl. + You can define an alternative <tt>tclInit</tt> procedure + prior to calling <tt>Tcl_Init()</tt>.</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">The Default <tt>initTcl</tt> Procedure</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>set errors {}<br> +set dirs {}<br> +if {[info exists tcl_library]} {<br> + lappend dirs $tcl_library<br> +} else {<br> + if {[info exists env(TCL_LIBRARY)]} {<br> + lappend dirs $env(TCL_LIBRARY)<br> + }<br> + lappend dirs $tclDefaultLibrary<br> + unset tclDefaultLibrary<br> + set dirs [concat $dirs $tcl_libPath]<br> +}<br> +foreach i $dirs {<br> + set tcl_library $i<br> + set tclfile [file join $i init.tcl]<br> + if {[file exists $tclfile]} {<br> + if {![catch {uplevel #0 [list source $tclfile]} msg]} {<br> + return<br> + } else {<br> + append errors "$tclfile: $msg\n$errorInfo\n"<br> + }<br> + }<br> +}<br> +error "Can't find a usable init.tcl ..."</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">The Default Initialization Sequence</h2> +<p><ul><li>The <tt>tclInit</tt> procedure locates and sources the <tt>init.tcl</tt> + script. The directory that contains <tt>init.tcl</tt> is stored in + the <tt>tcl_library</tt> variable.</li></ul><ul><li>The <tt>init.tcl</tt> script creates an <tt>unknown</tt> procedure. + The <tt>unknown</tt> procedure will run whenever Tcl encounters an + unknown command.</li></ul><ul><li>The <tt>unknown</tt> procedure consults the file <tt>tclIndex</tt> in the + <tt>tcl_library</tt> directory to see if the command is defined by one of + the initialization scripts.</li></ul><ul><li>The <tt>unknown</tt> procedure sources any needed initialization scripts + and retries the command.</li></ul><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>Commands defined in the initialization scripts are loaded + on demand.</b></td></tr></table></p> +<br clear="both"><p><hr></p> +<h2 align="center">Standalone Initialization Techniques</h2> +<p><p><b>Manually execute all initialization scripts</b></p> +<ul><li>Convert all initialization scripts into C strings and + put them in the executable.</li></ul><ul><li>Call <tt>Tcl_Eval()</tt> on each initialization script and omit the + call to <tt>Tcl_Init()</tt></li></ul><ul><li>Or, redefine <tt>tclInit</tt> so that it does not attempt to source + <tt>init.tcl</tt> then call <tt>Tcl_Eval()</tt> on each initialization + script after <tt>Tcl_Init()</tt> returns.</li></ul><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>This approach is not recommended</b></td></tr></table></p> +<br clear="both"><p><hr></p> +<h2 align="center">Standalone Initialization Techniques</h2> +<p><p><b>Redefining the builtin <tt>source</tt> command</b></p> +<ul><li>Convert all initialization scripts into C strings and + put them in the executable.</li></ul><ul><li>Create a new <tt>source</tt> command that + calls <tt>Tcl_Eval()</tt> on the appropriate built-in string + instead of reading from the disk.</li></ul><ul><li>Read from disk if the named file is not one that is built in.</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Redefining <tt>source</tt></h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>static char zInitTcl[] = "...";<br> +static char zParrayTcl[] = "...";</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Scripts <tt>init.tcl</tt> and <tt>parray.tcl</tt></td> +</tr> +<tr><td valign="center"> +<small><tt><br> +int NewSourceCmd(TCLARGS){</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> if( !strcmp(argv[1],"/builtin/init.tcl") )<br> + return Tcl_Eval(interp, zInitTcl);<br> + if( !strcmp(argv[1],"/builtin/parray.tcl") )<br> + return Tcl_Eval(interp, zParrayTcl);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Call <tt>Tcl_Eval()</tt> on builtin strings if the names match</td> +</tr> +<tr><td valign="center"> +<small><tt> return Tcl_EvalFile(interp, argv[1]);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Call <tt>Tcl_EvalFile()</tt> if no match</td> +</tr> +<tr><td valign="center"> +<small><tt>}<br> + <br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> setenv("TCL_LIBRARY","/builtin");</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Causes <tt>tclInit</tt> to look for <tt>init.tcl</tt> in <tt>/builtin</tt></td> +</tr> +<tr><td valign="center"> +<small><tt> interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_CreateCommand(interp, "source",<br> + NewSourceCmd, 0, 0);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Redefine <tt>source</tt></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Init(interp);<br> + Tcl_Eval(interp, zInputLoop);<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Redefining <tt>source</tt></h2> +<p><ul><li>This approach works for all versions of Tcl and Tk.</li></ul><ul><li>Also need to redefine the "<tt>file exists</tt>" Tcl command since it + too is used by <tt>tclInit</tt>.</li></ul><ul><li>To verify that the program is really standalone, remove the call + to <tt>Tcl_EvalFile()</tt>.</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Standalone Initialization Techniques</h2> +<p><p><b>Use the <tt>Tcl</tt>*<tt>InsertProc()</tt> functions</b></p> +<ul><li>Three routines that overload basic file I/O operations: + <ul> + <li> <tt>TclStatInsertProc()</tt> </li> + <li> <tt>TclAccessInsertProc()</tt> </li> + <li> <tt>TclOpenFileChannelInsertProc()</tt> </li> + </ul></li></ul><ul><li>Allows us to implement a virtual filesystem that overlays the + real filesystem.</li></ul><ul><li>The virtual filesystem contains all the initialization scripts + as compiled-in strings. The initialization scripts look like + they are resident on disk even though they are built in.</li></ul><ul><li>These functions first appeared in Tcl8.0.3. + Presumably to support TclPro Wrapper.</li></ul><ul><li>The only documentation is comments on the code. + See the Tcl source file <tt>generic/tclIOUtil.c</tt></li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">The <tt>TclStatInsertProc()</tt> Function</h2> +<p><ul><li>Sole argument is a pointer to a function whose interface is the + same as <tt>stat()</tt></li></ul><ul><li>Functions are stacked. Tcl tries each <tt>stat</tt> function on the + list, beginning with the most recently inserted, until one succeeds.</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">The <tt>TclStatInsertProc()</tt> Function</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tclInt.h></tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Rather than <tt><tcl.h></tt>!</td> +</tr> +<tr><td valign="center"> +<small><tt><br> +static int<br> +BltinFileStat(char *path,struct stat *buf){<br> + char *zData;<br> + int nData;</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> zData = FindBuiltinFile(path, 0, &nData);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Check if <tt>path</tt> is a builtin</td> +</tr> +<tr><td valign="center"> +<small><tt> if( zData==0 ){<br> + return -1;<br> + }</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Fail if <tt>path</tt> is not a builtin</td> +</tr> +<tr><td valign="center"> +<small><tt> memset(buf, 0, sizeof(*buf));<br> + buf->st_mode = 0400;<br> + buf->st_size = nData;</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> return 0;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Success if it is builtin</td> +</tr> +<tr><td valign="center"> +<small><tt>}<br> + <br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> TclStatInsertProc(BltinFileStat);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Register new <tt>stat</tt> function</td> +</tr> +<tr><td valign="center"> +<small><tt> interp = Tcl_CreateInterp();<br> + Tcl_Init(interp);<br> + Tcl_Eval(interp, zInputLoop);<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">The <tt>TclAccessInsertProc()</tt> Function</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tclInt.h></tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Rather than <tt><tcl.h></tt>!</td> +</tr> +<tr><td valign="center"> +<small><tt><br> +/* BltinFileStat() not shown... */<br> + <br> +static int<br> +BltinFileAccess(char *path, int mode){<br> + char *zData;</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> if( mode & 3 ) return -1;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">All builtins are read-only</td> +</tr> +<tr><td valign="center"> +<small><tt> zData = FindBuiltinFile(path, 0, &nData);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Check if <tt>path</tt> is a builtin</td> +</tr> +<tr><td valign="center"> +<small><tt> if( zData==0 ) return -1;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Fail if <tt>path</tt> is not a builtin</td> +</tr> +<tr><td valign="center"> +<small><tt> return 0;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Success if it is builtin</td> +</tr> +<tr><td valign="center"> +<small><tt>}<br> + <br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> TclStatInsertProc(BltinFileStat);<br> + TclAccessInsertProc(BltinFileAccess);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Register new <tt>stat</tt> and <tt>access</tt> functions</td> +</tr> +<tr><td valign="center"> +<small><tt> interp = Tcl_CreateInterp();<br> + Tcl_Init(interp);<br> + Tcl_Eval(interp, zInputLoop);<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">The <tt>TclOpenFileChannelInsertProc()</tt> Function</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>static Tcl_Channel BuiltinFileOpen(<br> + Tcl_Interp *interp, /* The TCL interpreter doing the open */<br> + char *zFilename, /* Name of the file to open */<br> + char *modeString, /* Mode string for the open (ignored) */<br> + int permissions /* Permissions for a newly created file (ignored) */<br> +){<br> + char *zData;<br> + BuiltinFileStruct *p;<br> + int nData;<br> + char zName[50];<br> + Tcl_Channel chan;<br> + static int count = 1;<br> + <br> + zData = FindBuiltinFile(zFilename, 1, &nData);<br> + if( zData==0 ) return NULL;<br> + p = (BuiltinFileStruct*)Tcl_Alloc( sizeof(BuiltinFileStruct) );<br> + if( p==0 ) return NULL;<br> + p->zData = zData;<br> + p->nData = nData;<br> + p->cursor = 0;<br> + sprintf(zName,"etbi_bffffc7c_8049b04",((int)BuiltinFileOpen)>>12,count++);<br> + chan = Tcl_CreateChannel(&builtinChannelType, zName, <br> + (ClientData)p, TCL_READABLE);<br> + return chan;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">The <tt>TclOpenFileChannelInsertProc()</tt> Function</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>static Tcl_ChannelType builtinChannelType = {<br> + "builtin", /* Type name. */<br> + NULL, /* Always non-blocking.*/<br> + BuiltinFileClose, /* Close proc. */<br> + BuiltinFileInput, /* Input proc. */<br> + BuiltinFileOutput, /* Output proc. */<br> + BuiltinFileSeek, /* Seek proc. */<br> + NULL, /* Set option proc. */<br> + NULL, /* Get option proc. */<br> + BuiltinFileWatch, /* Watch for events on console. */<br> + BuiltinFileHandle, /* Get a handle from the device. */<br> +};</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p> + <p>For additional information see:</p> + <ul> + <li>The man page for <tt>Tcl_CreateChannel()</tt></li> + <li>Tk source code file <tt>generic/tkConsole.c</tt></li> + </ul> +</p> + +<br clear="both"><p><hr></p> +<h2 align="center">Initializing Tk</h2> +<p><ul><li>All the same initialization script issues as Tcl</li></ul><ul><li>Tk initialization scripts are in a different directory + than the Tcl initialization scripts - the "Tk Library"</li></ul><ul><li>Call <tt>Tk_Init()</tt> after <tt>Tcl_Init()</tt></li></ul><ul><li>Must have an event loop or Tk will not work!</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Implementing An Event Loop</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>button .b -text Hello -command exit<br> +pack .b</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Create a Tk interface</td> +</tr> +<tr><td valign="center"> +<small><tt><br> +</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>bind . <Destroy> {<br> + if {![winfo exists .]} exit<br> +}</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Close the application when the main window + is destroyed</td> +</tr> +<tr><td valign="center"> +<small><tt><br> +</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>while 1 {vwait forever}</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">The event loop</td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">"Hello, World!" Using Tk</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tk.h><br> + <br> +</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>static char zHello[] = </tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">The application code</td> +</tr> +<tr><td valign="center"> +<small><tt> "button .b "<br> + "-text {Hello, World} "<br> + "-command exit\n"<br> + "pack .b\n";<br> + <br> +</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>static char zEventLoop[] =</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">The event loop</td> +</tr> +<tr><td valign="center"> +<small><tt> "bind . <Destroy> {\n"<br> + " if {![winfo exists .]} exit\n"<br> + "}\n"<br> + "while 1 {vwait forever}\n";<br> + <br> +<br> +int main(int argc, char **argv){<br> + Tcl_Interp *interp;<br> + interp = Tcl_CreateInterp();</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Init(interp);<br> + Tk_Init(interp);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">We really should check the return values of the init functions...</td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Eval(interp, zHello);</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_Eval(interp, zEventLoop);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">The event loop never returns</td> +</tr> +<tr><td valign="center"> +<small><tt> /*NOTREACHED*/<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Compiling "Hello, World!" For Tk</h2> +<p><p><b>Unix:</b></p> + <blockquote><pre> + $ gcc hello.c -ltk -L/usr/X11R6/lib \ + -lX11 -ltcl -lm -ldl + $ ./a.out</pre></blockquote> + + <p><b>Windows using Cygwin:</b></p> + <blockquote><pre> + C:> gcc hello.c -mwindows -ltk80 -ltcl80 -lm + C:> a.exe</pre></blockquote> + + <p><b>Windows using Mingw32:</b></p> + <blockquote><pre> + C:> gcc -mno-cygwin hello.c -mwindows \ + -ltk82 -ltcl82 -lm + C:> a.exe</pre></blockquote></p> +<br clear="both"><p><hr></p> +<h2 align="center">Making The Program Standalone</h2> +<p><p>To make a Tcl application standalone you have to convert the following + initialization scripts to C strings and compile them into the + executable:</p> + <table><tr> + <td valign="top"><tt> + auto.tcl<br> + history.tcl<br> + init.tcl + </tt></td> + <td valign="top"><tt> + ldAout.tcl<br> + package.tcl + </tt></td> + <td valign="top"><tt> + parray.tcl<br> + safe.tcl + </tt></td> + <td valign="top"><tt> + tclIndex<br> + word.tcl + </tt></td> + </tr></table> + + <p>To make a Tk application standalone requires these additional + initialization scripts from the Tk Library:</p> + <table><tr> + <td valign="top"><tt> + bgerror.tcl<br> + button.tcl<br> + clrpick.tcl<br> + comdlg.tcl<br> + console.tcl<br> + dialog.tcl + </tt></td> + <td valign="top"><tt> + entry.tcl<br> + focus.tcl<br> + listbox.tcl<br> + menu.tcl<br> + msgbox.tcl<br> + optMenu.tcl + </tt></td> + <td valign="top"><tt> + palette.tcl<br> + safetk.tcl<br> + scale.tcl<br> + scrlbar.tcl<br> + tclIndex<br> + tearoff.tcl + </tt></td> + <td valign="top"><tt> + text.tcl<br> + tk.tcl<br> + tkfbox.tcl<br> + xmfbox.tcl + </tt></td> + </tr></table> + + <p>Total of about 13K lines and 400K bytes of text or 9K lines and + 250K bytes if you strip comments and leading spaces</p></p> +<br clear="both"><p><hr></p> +<h2 align="center">A Review Of The Features We Want</h2> +<p><ol type="A"> + <li value="1"> + Combine C/C++ with Tcl/Tk into a single executable.</dd> + </li></ol> + + <ol type="A"> + <li value="2"> + The executable should be standalone. It must not depend + on files not normally found on the system. + </li></ol> + + <ol type="A"> + <li value="3"> + It should be difficult for end users to alter the program + (and introduce bugs). + </li></ol></p> +<br clear="both"><p><hr></p> +<h2 align="center">Available Programming Aids</h2> +<p><p>Several tools are available. The chart below shows which tools + help achieve which objectives.</p> + + <center><table border="2"> + <tr> + <td></td> + <td colspan="3" align="center"> + <b>Features The Tool Helps To Achieve</b></td> + </tr> + <tr> + <td align="center"><b>Tool Name</b></td> + <td align="center">Mix C and Tcl</td> + <td align="center">Standalone</td> + <td align="center">Hide Source</td> + </tr> + <tr> + <td>SWIG</td> + <td align="center"><img src="image6"></td> + <td> </td> + <td> </td> + </tr> + <tr> + <td>TclPro Wrapper</td> + <td> </td> + <td align="center"><img src="image6"></td> + <td align="center"><img src="image6"></td> + </tr> + <tr> + <td>FreeWrap</td> + <td> </td> + <td align="center"><img src="image6"></td> + <td align="center"><img src="image6"></td> + </tr> + <tr> + <td>Wrap</td> + <td> </td> + <td align="center"><img src="image6"></td> + <td> </td> + </tr> + <tr> + <td>mktclapp</td> + <td align="center"><img src="image6"></td> + <td align="center"><img src="image6"></td> + <td align="center"><img src="image6"></td> + </tr> + </table></center></p> +<br clear="both"><p><hr></p> +<h2 align="center">SWIG</h2> +<table><tr><td valign="top"><img src="image7"></td> +<td valign="top"><p><ul><li>Creates an interface between an existing C/C++ library and a high-level + programming language. Support for: + <ul> + <li> Tcl/Tk </li> + <li> Perl </li> + <li> Python </li> + <li> Java </li> + <li> Eiffel </li> + <li> Guile </li> + </ul></li></ul><ul><li>No changes required to C/C++ code. Can be used with legacy libraries.</li></ul><ul><li>Generates an extension, not a standalone binary</li></ul><ul><li>The tutorial on SWIG was yesterday afternoon.</li></ul><ul><li>http://www.swig.org/</li></ul></p></td></tr></table> + +<br clear="both"><p><hr></p> +<h2 align="center">Wrapper Programs</h2> +<table><tr><td valign="top"><img src="image8"></td> +<td valign="top"><p><ul><li>Convert a pure Tcl/Tk program into a standalone binary</li></ul><ul><li>Several wrapper programs are available: + <ul> + <li> TclPro Wrapper - http://www.scriptics.com/ </li> + <li> FreeWrap - http://www.albany.net/~dlabelle/freewrap/freewrap.html </li> + <li> Wrap - http://members1.chello.nl/~j.nijtmans/wrap.html </li> + </ul></li></ul><ul><li>No C compiler required!</li></ul><ul><li>TclPro will convert Tcl script into bytecode so that it cannot be + easily read by the end user. FreeWrap encrypts the scripts.</li></ul><ul><li>FreeWrap uses compression on its executable. + Wrap uses compression on both the executable and on the bundled script files.</li></ul><ul><li>Usually include extensions like winico and/or BLT</li></ul></p></td></tr></table> + +<br clear="both"><p><hr></p> +<h2 align="center">mktclapp</h2> +<table><tr><td valign="top"><img src="image9"></td> +<td valign="top"><p><ul><li>Mix C/C++ with Tcl/Tk into a standalone binary</li></ul> +<ul><li><tt>mktclapp</tt> generates an application initialization file + that contains Tcl scripts as strings and makes all necessary calls + to <tt>Tcl_Init</tt>, <tt>Tcl_CreateCommand</tt>, + <tt>Tcl</tt>*<tt>InsertProc</tt>, etc.</li></ul><ul><li>Features to make it easier to write new Tcl command in C</li></ul><ul><li><tt>xmktclapp.tcl</tt> provides a GUI interface to <tt>mktclapp</tt></li></ul><ul><li>http://www.hwaci.com/sw/mktclapp/</li></ul></p></td></tr></table> + +<br clear="both"><p><hr></p> +<h2 align="center">"Hello, World!" Using Mktclapp</h2> +<p><ul><li>Download <tt>mktclapp.c</tt> and <tt>xmktclapp.tcl</tt> from + http://www.hwaci.com/sw/mktclapp/</li></ul><ul><li>Compile <tt>mktclapp</tt>: + <blockquote><pre> + cc -o mktclapp mktclapp.c + </pre></blockquote></li></ul><ul><li>Create "Hello, World!" as a Tcl script in file <tt>hw.tcl</tt>: + <blockquote><pre> + button .b -text {Hello, World!} -command exit + pack .b + </pre></blockquote></li></ul><ul><li>Launch xmktclapp: + <blockquote><pre> + wish xmktclapp.tcl + </pre></blockquote></li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">"Hello, World!" Using Mktclapp</h2> +<table width="100%"><tr><td valign="top"><p><ul><li>Set "Command Line Input?" to "None"</li></ul><ul><li>Set "Standalone?" to "Yes"</li></ul><ul><li>Enter "<tt>hw.mta</tt>" for the Configuration File</li></ul><ul><li>Enter "<tt>hw.c</tt>" for the Output C File</li></ul></p></td> +<td valign="top" align="right"><img src="image10"></td></tr></table> + +<br clear="both"><p><hr></p> +<h2 align="center">"Hello, World!" Using Mktclapp</h2> +<table width="100%"><tr><td valign="top"><p><ul><li>Go to the "Tcl Scripts" page</li></ul><ul><li>Press "Insert" and add <tt>hw.tcl</tt> to the list of + Tcl scripts</li></ul><ul><li>Change the "Startup Script" to be <tt>hw.tcl</tt>.</li></ul><ul><li>Select File/Build and File/Exit</li></ul></p></td> +<td valign="top" align="right"><img src="image11"></td></tr></table> + +<br clear="both"><p><hr></p> +<h2 align="center">"Hello, World!" Using Mktclapp</h2> +<p><ul><li>Mktclapp generates <tt>hw.c</tt>. + Compile it something like this: + <pre> + cc hw.c -ltk -L/usr/X11R6/lib -lX11 -ltcl -lm -ldl + </pre></li></ul><ul><li>Or, if using Cygwin: + <pre> + gcc hw.c -mwindows -ltk80 -ltcl80 -lm + </pre></li></ul><ul><li>Or, if using Mingw32: + <pre> + gcc -mno-cygwin hw.c -mwindows -ltk82 -ltcl82 -lm + </pre></li></ul><ul><li>And you're done!</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Adding C Code To Your Program</h2> +<p>Put the new C code in a new source file named "<tt>add.c</tt>"</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include "hw.h"</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Generated by mktclapp</td> +</tr> +<tr><td valign="center"> +<small><tt></tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>int ET_COMMAND_add(ET_TCLARGS){</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center"><tt>ET_TCLARGS</tt> is a macro defined in <tt>hw.h</tt></td> +</tr> +<tr><td valign="center"> +<small><tt> int a, b;<br> + char zResult[30];<br> + a = atoi(argv[1]);<br> + b = atoi(argv[2]);<br> + sprintf(zResult, "-1073742724", a+b);<br> + Tcl_SetResult(interp, zResult, TCL_VOLATILE);<br> + return TCL_OK;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Adding C Code To Your Program</h2> +<table width="100%"><tr><td valign="top"><p><ul><li>Go to the "C/C++ Modules" page of xmktclapp.tcl</li></ul> +<ul><li>Press "Insert" and add <tt>add.c</tt> to the list of + C/C++ modules</p></li></ul></li></ul><ul><li>Select File/Build and File/Exit</li></ul></p></td> +<td valign="top" align="right"><img src="image12"></td></tr></table> + +<br clear="both"><p><hr></p> +<h2 align="center">Adding C Code To Your Program</h2> +<p><ul><li>Compile as follows: + <pre> + cc add.c hw.c -ltk -L/usr/X11R6/lib -ltcl -lm -ldl + </pre></li></ul><ul><li>Or construct a Makefile that compiles <tt>add.c</tt> into <tt>add.o</tt> + and <tt>hw.c</tt> into <tt>hw.o</tt> and then links them.</li></ul><ul><li>Compile the same way for Windows except use the usual Windows + libraries and options...</li></ul><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>Don't have to worry with <tt>Tcl_CreateCommand()</tt> - Mktclapp takes + care of that automatically.</b></td></tr></table></p> +<br clear="both"><p><hr></p> +<h2 align="center">Checking Parameters In The <tt>add</tt> Command</h2> +<p>Modify <tt>add.c</tt> to insure the <tt>add</tt> command + is called with exactly two integer arguments</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include "hw.h"<br> + <br> +int ET_COMMAND_add(ET_TCLARGS){<br> + int a, b;<br> + char zResult[30];</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> if( argc!=3 ){<br> + Tcl_AppendResult(interp,<br> + "wrong # args: should be: \"",<br> + argv[0], " VALUE VALUE\"", 0);<br> + return TCL_ERROR;<br> + }</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Report an error if there are not exactly + 2 arguments</td> +</tr> +<tr><td valign="center"> +<small><tt> if( Tcl_GetInt(interp, argv[1], &a)!=TCL_OK ){<br> + return TCL_ERROR;<br> + }</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Report an error if the first argument is + not an integer</td> +</tr> +<tr><td valign="center"> +<small><tt> if( Tcl_GetInt(interp, argv[2], &b)!=TCL_OK ){<br> + return TCL_ERROR;<br> + }</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Do the same for the second argument</td> +</tr> +<tr><td valign="center"> +<small><tt> sprintf(zResult, "-1073742724", a+b);<br> + Tcl_SetResult(interp, zResult, TCL_VOLATILE);<br> + return TCL_OK;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Using The Tcl_Obj Interface</h2> +<p>In the file <tt>objadd.c</tt> put this code:</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include "hw.h"</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt><br> +int ET_OBJCOMMAND_add2(ET_OBJARGS){<br> + int a, b;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Use "<tt>ET_OBJCOMMAND</tt>" instead of "<tt>ET_COMMAND</tt>" and + "<tt>ET_OBJARGS</tt>" instead of "<tt>ET_TCLARGS</tt>"</td> +</tr> +<tr><td valign="center"> +<small><tt> if( objc!=3 ){<br> + Tcl_WrongNumArgs(interp, 1, objv,<br> + "number number");<br> + return TCL_ERROR;<br> + }</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">A special routine for "wrong # args" error</td> +</tr> +<tr><td valign="center"> +<small><tt> if( Tcl_GetIntFromObj(interp, objv[1], &a) ){</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Instead of <tt>Tcl_GetInt</tt></td> +</tr> +<tr><td valign="center"> +<small><tt> return TCL_ERROR;<br> + }<br> + if( Tcl_GetIntFromObj(interp, objv[2], &b) ){<br> + return TCL_ERROR;<br> + }</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_SetIntObj(Tcl_GetObjResult(interp), a+b);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Result stored as integer, not a string</td> +</tr> +<tr><td valign="center"> +<small><tt> return TCL_OK;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Speed Of Tcl_Obj Versus "char*" Interfaces</h2> +<p><ul><li>Compile both <tt>add</tt> and <tt>add2</tt> into the same executable.</li></ul><ul><li>Compare their speeds: + <pre> + time {add 123456 654321} 10000 + <font color="blue">26 microseconds per iteration</font> + time {add2 123456 654321} 10000 + <font color="blue">4 microseconds per iteration</font> + </pre></li></ul><ul><li>The Tcl_Obj version is 650 faster!</li></ul><ul><li>Replace the addition with a "real" computation that takes + 10 milliseconds.</li></ul><ul><li>Now the Tcl_Obj version is only 0.2 faster!</li></ul><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>In many real-world problems, the Tcl_Obj interface has no noticeable + speed advantage over the string interface.</b></td></tr></table></p> +<br clear="both"><p><hr></p> +<h2 align="center">More About Built-in Tcl Scripts</h2> +<table><tr><td valign="top"><img src="image11"></td> +<td valign="top"><p><ul><li>Comments and leading white-space are removed from the + script by default. Use the "Don't Strip Comments" + button to change this.</li></ul><ul><li>The file name must exactly match the name that is + used by the <tt>source</tt> command.</li></ul></p></td></tr></table> + +<br clear="both"><p><hr></p> +<h2 align="center">Locations Of Libraries</h2> +<table><tr><td valign="top"><img src="image13"></td> +<td valign="top"><p><ul><li>Tells mktclapp where to look for script libraries.</li></ul><ul><li>All Tcl scripts in the indicated directories are + compiled into the <tt>appinit.c</tt> file.</li></ul><ul><li>Comments and extra white-space are removed. + There is no way to turn this off.</li></ul></p></td></tr></table> + +<br clear="both"><p><hr></p> +<h2 align="center">Built-in Binary Data Files</h2> +<table><tr><td valign="top"><img src="image14"></td> +<td valign="top"><p><ul><li>Arbitrary files become part of the virtual filesystem</li></ul><ul><li>No comment or white-space removal is attempted</li></ul><ul><li>Useful for images or other binary data</li></ul></p></td></tr></table> + +<br clear="both"><p><hr></p> +<h2 align="center">New Commands In Namespaces</h2> +<p>Two underscores (__) are replaced by two colons (::) in + command names, thus giving the ability to define new commands + in a namespace</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <hw.h></tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt><br> +int ET_COMMAND_adder__add(ET_TCLARGS){<br> + int a, b;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Creates the Tcl command called "<tt>adder::add</tt>"</td> +</tr> +<tr><td valign="center"> +<small><tt> char *zResult[30];<br> + if( argc!=3 ){<br> + Tcl_AppendResult(interp,<br> + "wrong # args: should be: \"",<br> + argv[0], " VALUE VALUE\"", 0);<br> + return TCL_ERROR;<br> + }<br> + if( Tcl_GetInt(interp, argv[1], &a)!=TCL_OK ){<br> + return TCL_ERROR;<br> + }<br> + if( Tcl_GetInt(interp, argv[1], &b)!=TCL_OK ){<br> + return TCL_ERROR;<br> + }<br> + sprintf(zResult, "-1073742724", a+b);<br> + Tcl_SetResult(interp, zResult, TCL_VOLATILE);<br> + return TCL_OK;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Adding Your Own <tt>main()</tt></h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>int main(int argc, char **argv){<br> + /* Application specific initialization */</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Et_Init(argc, argv);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Never returns!</td> +</tr> +<tr><td valign="center"> +<small><tt> /*NOTREACHED*/<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p><table><tr><td valign="top"><img src="image3"></td> +<td valign="top"><b>The "Autofork" feature is disabled if you supply your own <tt>main()</tt></b></td></tr></table> +</p> + +<br clear="both"><p><hr></p> +<h2 align="center">Initializing The Tcl Interpreter</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> + <br> +int counter = 0;<br> + <br> +int main(int argc, char **argv){<br> + Et_Init(argc, argv);<br> + /*NOTREACHED*/<br> + return 0;<br> +}<br> + <br> +int Et_AppInit(Tcl_Interp *interp){</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> if( Blt_Init(Interp) ){<br> + return TCL_ERROR;<br> + }</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Example: Initialize an extension</td> +</tr> +<tr><td valign="center"> +<small><tt> Tcl_LinkVar(interp, "counter", &counter,<br> + TCL_LINK_INT);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Or link a C variable to a Tcl variable</td> +</tr> +<tr><td valign="center"> +<small><tt> return TCL_OK;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Return TCL_OK if successful</td> +</tr> +<tr><td valign="center"> +<small><tt>}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Writing Your Own Event Loop</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> +</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt>void Et_CustomMainLoop(Tcl_Interp *interp){</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Replaces the default event loop</td> +</tr> +<tr><td valign="center"> +<small><tt> return;</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Ex: Return without handling any events.</td> +</tr> +<tr><td valign="center"> +<small><tt>}<br> + <br> +int main(int argc, char **argv){</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Et_Init(argc, argv);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">This now returns after initializing Tcl</td> +</tr> +<tr><td valign="center"> +<small><tt> /* Application code here */<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Writing Your Own Event Loop</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include <tcl.h><br> + <br> +void Et_CustomMainLoop(Tcl_Interp *interp){</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> for(;;){<br> + Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);<br> + /* Other processing... */<br> + }</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Intermix processing and event handling</td> +</tr> +<tr><td valign="center"> +<small><tt>}<br> + <br> +int main(int argc, char **argv){</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +<tr><td valign="center"> +<small><tt> Et_Init(argc, argv);</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Never returns</td> +</tr> +<tr><td valign="center"> +<small><tt> /*NOTREACHED*/<br> + return 0;<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Mktclapp Initialization Sequence</h2> +<p><ul><li>Initialization starts when the <tt>Et_Init()</tt> + function is called either by client code or by + the <tt>main()</tt> that mktclapp generates</li></ul><ul><li>Create the main Tcl interpreter</li></ul><ul><li>Construct the virtual filesystem overlay by redefining + the <tt>source</tt> command and by using the + <tt>Tcl</tt>*<tt>InsertProc()</tt> functions</li></ul><ul><li>Call <tt>Et_PreInit()</tt> if the client defines it</li></ul><ul><li>Call <tt>Tcl_Init()</tt> and <tt>Tk_Init()</tt></li></ul><ul><li>Call <tt>Tcl_CreateCommand()</tt> and <tt>Tcl_CreateObjCommand()</tt> + for every <tt>ET_COMMAND_</tt>* and <tt>ET_OBJCOMMAND_</tt>* function + in the client code</li></ul><ul><li>Call <tt>Et_AppInit()</tt> if the client defines it</li></ul><ul><li>Run the main Tcl script if there is one</li></ul><ul><li>Call <tt>Et_CustomMainLoop()</tt> if defined by client code or + else run the built-in event loop</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Invoking Tcl From C</h2> +<p><ul><li>Use one of the built-in evaluation functions: + <center><table width="80%"> + <tr><td valign="top" width="50%"><ul> + <li> Tcl_Eval() </li> + <li> Tcl_VarEval() </li> + <li> Tcl_EvalFile() </li> + <li> Tcl_GlobalEval() </li> + </ul></td> + <td valign="top" width="50%"><ul> + <li> Tcl_EvalObj() </li> + <li> Tcl_GlobalEvalObj() </li> + </ul></td></tr> + </table></center></li></ul><ul><li>Mktclapp provides evaluation functions with variable argument + lists as in <tt>printf()</tt>: + <ul> + <li> Et_EvalF() </li> + <li> Et_GlobalEvalF() </li> + </ul></li></ul><ul><li>Mktclapp provides a global variable <tt>Et_Interp</tt> which is + a pointer to the main interpreter</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Invoking Tcl From C</h2> +<p>Example: A C function that pops up an error message dialog box</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include "appinit.h"<br> + <br> +void ErrMsg(char *zMsg){<br> + Tcl_SetVar(Et_Interp, "zMsg", zMsg, TCL_GLOBAL_ONLY);<br> + Tcl_GlobalEval(Et_Interp, <br> + "tk_messageBox -icon error -msg $zMsg -type ok");<br> + Tcl_UnsetVar(Et_Interp, "zMsg", TCL_GLOBAL_ONLY);<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Invoking Tcl From C</h2> +<p>The same C function implemented using <tt>Et_EvalF()</tt> instead + of <tt>Tcl_GlobalEval()</tt></p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include "appinit.h"<br> + <br> +void ErrMsg(char *zMsg){<br> + Et_EvalF(Et_Interp, <br> + "tk_messageBox -icon error -msg {¸üÿ¿PX¶} -type ok",<br> + zMsg);<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p> + <ul><li> + Suppose the function is called as follows: + <blockquote> + <tt>ErrMsg("Syntax error near \"}\"");</tt> + </blockquote> + </li></ul> + + <ul><li> + The command that gets executed is: + <pre> + tk_messageBox -icon error -msg \ + {Syntax error near "}"} -type ok + </pre> + </li></ul> + + <ul><li> + But this is an ill-formed Tcl command! + </li></ul> +</p> + +<br clear="both"><p><hr></p> +<h2 align="center">Invoking Tcl From C</h2> +<p>Use the "<tt></tt>" format to generate a quoted string</p><p> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt>#include "appinit.h"<br> + <br> +void ErrMsg(char *zMsg){<br> + Et_EvalF(Et_Interp, <br> + "tk_messageBox -icon error -msg \"%\" -type ok",<br> + zMsg);<br> +}</tt></small></td> +<td></td><td></td><td></td><td></td> +</tr> +</table> +<p><ul><li>The <tt></tt> puts a backslash before all characters that + are special to Tcl</li></ul><ul><li>The Tcl command becomes: + <pre> + tk_messageBox -icon error -msg \ + "Syntax error near \"\}\"" -type ok + </pre></li></ul></p> + +<br clear="both"><p><hr></p> +<h2 align="center">Other Functions Provided By Mktclapp</h2> +<p><ul><li><tt>void Et_ResultF(Tcl_Interp*, ...);</tt></li></ul><ul><li><tt>char *Et_DStringAppendF(Tcl_DString*, ...);</tt></li></ul><ul><li><tt>int Et_AppendObjF(Tcl_Obj*, ...);</tt></li></ul><ul><li><tt>char *mprintf(const char *format, ...);<br> + char *vmprintf(const char *format, va_list);</tt></li></ul><ul><li><tt>void Et_NewBuiltinFile(char *filename, char *data, int amt);</tt></li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Operating Mktclapp From The Command Line</h2> +<p><ul><li>Generate the <tt>appinit.h</tt> header file like this: + <blockquote> + <tt>mktclapp -header >appinit.h</tt> + </blockquote></li></ul><ul><li>Generate the <tt>appinit.c</tt> file like this: + <blockquote> + <tt>mktclapp -f appinit.mta >appinit.c</tt> + </blockquote></li></ul><ul><li>The <tt>*.mta</tt> file is just a list of command-line options</li></ul><ul><li>Enter + <blockquote> + <tt>mktclapp -help</tt> + </blockquote> + to get a list of available options</li></ul><ul><li>Look at MTA files generated by xmktclapp.tcl for examples</li></ul></p> +<br clear="both"><p><hr></p> +<h2 align="center">Format Of An MTA File</h2> +<table cellspacing="0" cellpadding="0" border="0"> +<tr><td valign="center"> +<small><tt># Configuration file generated by xmktclapp<br> +# Hand editing is not recommended<br> +#</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Comments begin with one #</td> +</tr> +<tr><td valign="center"> +<small><tt>## Autofork No<br> +## CFile:add.c 1<br> +## CFile:objadd.c 1<br> +## CmdLine Console<br> +## ConfigFile hw.mta<br> +## Data:check.gif 1<br> +## MainScript hw.tcl<br> +## Mode Tcl/Tk<br> +## NoSource No<br> +## OutputFile hw.c<br> +## Shroud No<br> +## Standalone Yes<br> +## TclFile:hw.tcl 1<br> +## TclLib /usr/lib/tcl8.0<br> +## TkLib /usr/lib/tk8.0</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">Lines beginning with two #s are used + by xmktclapp.tcl and ignored by mktclapp</td> +</tr> +<tr><td valign="center"> +<small><tt>-console<br> +-main-script "hw.tcl"<br> +-tcl-library "/usr/lib/tcl8.0"<br> +-tk-library "/usr/lib/tk8.0"<br> +"add.c"<br> +"objadd.c"<br> +-i "check.gif"<br> +-strip-tcl "hw.tcl"</tt></small></td> +<td> </td> +<td valign="center"><img src="image2"></td> +<td> </td> +<td valign="center">All other lines are read by mktclapp and + ignored by xmktclapp.tcl</td> +</tr> +</table> + +<br clear="both"><p><hr></p> +<h2 align="center">Summary</h2> +<p><ul><li>Use Tcl for the things Tcl is good at and use C/C++ for the things that + C/C++ is good at</li></ul><ul><li>Use wrapper programs to make pure Tcl programs standalone</li></ul><ul><li>Use mktclapp to combine Tcl/Tk with C/C++ into a standalone</li></ul></p> +<br clear="both"><p><hr></p> diff --git a/tkhtml1/tests/page4/image1 b/tkhtml1/tests/page4/image1 Binary files differnew file mode 100644 index 0000000..da26d70 --- /dev/null +++ b/tkhtml1/tests/page4/image1 diff --git a/tkhtml1/tests/page4/image2 b/tkhtml1/tests/page4/image2 Binary files differnew file mode 100644 index 0000000..e176a96 --- /dev/null +++ b/tkhtml1/tests/page4/image2 diff --git a/tkhtml1/tests/page4/image3 b/tkhtml1/tests/page4/image3 Binary files differnew file mode 100644 index 0000000..e829d37 --- /dev/null +++ b/tkhtml1/tests/page4/image3 diff --git a/tkhtml1/tests/page4/image4 b/tkhtml1/tests/page4/image4 Binary files differnew file mode 100644 index 0000000..f14ea13 --- /dev/null +++ b/tkhtml1/tests/page4/image4 diff --git a/tkhtml1/tests/page4/image5 b/tkhtml1/tests/page4/image5 Binary files differnew file mode 100644 index 0000000..4ef6277 --- /dev/null +++ b/tkhtml1/tests/page4/image5 diff --git a/tkhtml1/tests/page4/image6 b/tkhtml1/tests/page4/image6 Binary files differnew file mode 100644 index 0000000..1adb261 --- /dev/null +++ b/tkhtml1/tests/page4/image6 diff --git a/tkhtml1/tests/page4/image7 b/tkhtml1/tests/page4/image7 Binary files differnew file mode 100644 index 0000000..ba0d26e --- /dev/null +++ b/tkhtml1/tests/page4/image7 diff --git a/tkhtml1/tests/page4/image8 b/tkhtml1/tests/page4/image8 Binary files differnew file mode 100644 index 0000000..8b81d58 --- /dev/null +++ b/tkhtml1/tests/page4/image8 diff --git a/tkhtml1/tests/page4/image9 b/tkhtml1/tests/page4/image9 Binary files differnew file mode 100644 index 0000000..f0a352f --- /dev/null +++ b/tkhtml1/tests/page4/image9 diff --git a/tkhtml1/tests/page4/index.html b/tkhtml1/tests/page4/index.html new file mode 100644 index 0000000..99530ce --- /dev/null +++ b/tkhtml1/tests/page4/index.html @@ -0,0 +1,768 @@ +<!DOCTYPE HTML="HTML" PUBLIC="PUBLIC" "-//W3C//DTD=""-//W3C//DTD" HTML="HTML" 4.0="4.0" Transitional//EN"="Transitional//EN""> +<HTML> +<HEAD> +<TITLE>[fm] welcome to freshmeat.net</TITLE> +<STYLE TYPE="text/css"><!-- A:link {text-decoration: none}A:visited{text-decoration:none}A:active{text-decoration:none}--></STYLE> +</HEAD> +<BODY MARGINWIDTH="0" MARGINHEIGHT="0" LEFTMARGIN="0" RIGHTMARGIN="0" TOPMARGIN="0" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#336699" VLINK="#336699" ALINK="#336699"> +<BR><CENTER><TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0"><TR><TD WIDTH="1"><SCRIPT LANGUAGE="JAVASCRIPT"> +<!-- +now = new Date(); +tail = now.getTime(); +document.write("<IMG SRC='http://209.207.224.246/FreshMeat/Core/pc.gif?/index.php3," + tail + "' WIDTH=1 HEIGHT=1><BR>"); +//--> +</SCRIPT> +<NOSCRIPT> +<IMG SRC="image1" WIDTH="1" HEIGHT="1"><BR> +</NOSCRIPT></TD></TR></TABLE> +<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0"><TR><TD WIDTH="468"><SCRIPT LANGUAGE="JAVASCRIPT"> +<!-- +now = new Date(); +tail = now.getTime(); +AltText = "\"Please click here.\""; +document.write("<A HREF='http://ads.freshmeat.net/cgi-bin/ad_click.pl?index,tsof0001en'>") +document.write("<IMG SRC='http://ads.freshmeat.net/tsof0001en.gif?" + tail + "' WIDTH=468 HEIGHT=60 ALT=" + AltText + "></A><BR>"); +//--> +</SCRIPT> +<NOSCRIPT> +<A HREF="http://ads.freshmeat.net/cgi-bin/ad_click.pl?index,tsof0001en"><IMG SRC="image2" WIDTH="468" HEIGHT="60" ALT="Please click here."></A><BR> +</NOSCRIPT></TD></TR></TABLE> + +<TABLE CELLSPACING="0" CELLPADDING="2" BORDER="0" WIDTH="97%"><TR> +<TD ALIGN="left" VALIGN="bottom"><A HREF="/"><IMG SRC="image3" BORDER="0" ALT="freshmeat.net" WIDTH="300" HEIGHT="65"></A></TD> +<TD VALIGN="bottom" ALIGN="left" ROWSPAN="2"><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<FORM METHOD="get" ACTION="/search.php3"> +<SMALL>find: <INPUT TYPE="text" SIZE="15" NAME="query"></SMALL></FORM></FONT></TD> +<TD ALIGN="right" VALIGN="bottom"><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<A HREF="http://www.linux.com"><FONT COLOR="#000000"><B><SMALL>linux.com partner</SMALL></B></FONT></A><BR> +<TABLE CELLSPACING="0" CELLPADDING="1" BORDER="0" WIDTH="100%"><TR> +<TD ALIGN="right"><SMALL><NOBR><FONT FACE="Lucida,Verdana,Helvetica,Arial"><B><A HREF="/">news</A> |<BR> +<A HREF="/appindex/">appindex</A> |<BR> +<A HREF="/editorials/">editorials</A> |</B></FONT></NOBR></SMALL></TD> +<TD ALIGN="right"><SMALL><NOBR><FONT FACE="Lucida,Verdana,Helvetica,Arial"><B><A HREF="/lounge/">lounge</A> |<BR> +<A HREF="/contrib.php3">contribute</A> |<BR> +<A HREF="/feedback.php3">feedback</A> |</B></FONT></NOBR></SMALL></TD> +<TD ALIGN="right"><SMALL><NOBR><FONT FACE="Lucida,Verdana,Helvetica,Arial"><B><A HREF="/about.php3">about</A> |<BR> +<A HREF="/awards.php3">awards</A> |<BR> +<A HREF="/faq.php3">FAQ</A> |</B></FONT></NOBR></SMALL></TD> +</TR></TABLE></TD> +</TR></TABLE> +<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"> +<TR BGCOLOR="#000000"><TD><IMG SRC="image4" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE> +<TABLE CELLSPACING="0" CELLPADDING="3" BORDER="0" WIDTH="100%" BGCOLOR="#BBDDFF"> +<TR><TD ALIGN="center" VALIGN="top"> +<BR> +<FONT FACE="Lucida,Verdana,Helvetica,Arial"> + + +<SMALL><B>sort by: [ <A HREF="/news/2000/01/29/">date</A> | <A HREF="/news/list.php3?day=/2000/01/29/&orderby=name">name</A> | <A HREF="/news/list.php3?day=/2000/01/29/&orderby=urgency">urgency</A> ]</B></SMALL><BR></TD><TD> </TD></TR><TR><TD VALIGN="top" ALIGN="center"><FONT FACE="Lucida,Verdana,Helvetica,Arial"><TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">We should get this out of the door now</FONT></B><BR> +<SMALL><B><A HREF="mailto:scoop@freshmeat.net">scoop</A> - January 29th 2000, 23:59 EST</B></SMALL> +<P>Everyone else is talking about it, so we should announce it ourselves
+before you start to think it's a government hoax. <A HREF="http://server51.freshmeat.net/">Server 51</A> is our new hosting service for Open Source projects, based on Super Cool Space Alien Technology(TM). We hadn't planned to announce it quite so soon, and it's still in the alpha stage as we work day and night at integrating SCSAT with our terrestrial systems, but feel free to take a look around and see what's going on. When we're out of the testing stage and ready to make room for your project, we'll send word via your implants. Be listening.
+
+
+ +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949208399.html">comments (8)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>Category: freshmeat +</SMALL></B></FONT></FONT></TD><TD ALIGN="right"> + <A HREF="http://server51.freshmeat.net"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">Is Linux for Crazies?</FONT></B><BR> +<SMALL><B><A HREF="mailto:jeff.covey@pobox.com">jeff covey</A> - January 29th 2000, 23:59 EST</B></SMALL> +<P>Ray Woodcock writes: "In terms relevant to Linux, this freshmeat
+editorial glances at the tendency of mainstream viewpoints to dismiss
+other viewpoints as 'fringe,' the propensity of dissident movements to
+splinter into factions before they can effectively counter their
+primary adversaries, and the difficulty of creating stability without
+squelching curiosity." +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949208340.html">comments (2), 2065 words in body</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>Category: Editorial +</SMALL></B></FONT></FONT></TD><TD ALIGN="right"> + +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">RabbIT 2.0.2</FONT></B><BR> +<SMALL><B><A HREF="mailto:d94-rol@nada.kth.se">Ernimril</A> - January 29th 2000, 18:29 EST</B></SMALL> +<DIV ALIGN="justify"><P>RabbIt is the mutating, caching webproxy which is used to speed up surfing over slow links like modems. It does this by removing advertising and background images and scaling down images to low quality JPEGs. RabbIT is written in Java and should be able to run on any platform. It does depend upon an image converter if imagescaleing is on. The recommended image converter is "convert" from the ImageMagick package.</DIV> +<P><B>Changes:</B> Fixes have been made for a few bugs concerning keep alive and the HTTP response header, a bug with NT and cache directories, a bug concerning requests without a response body, a bug in GZIPHandler that caused it to not gzip already compressed (gzip or compress) streams, a bug in HTTPHeader regarding response phrases that are multiline, and a few bugs in ImageHandler and NCache. GZIPHandler has been built as an intermediate(*) to FilterHandler (this means that it is possible to gzip text/plain, etc., without filtering those streams) uuencoding has been added to the Coder, RabbIT now uses HTTP/1.1, HTMLParser now compiles cleanly with Jikes, and GeneralHeader has been created to allow for HTTPFooter (which is useful when sending chunked data). +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949188564.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: freely distributable</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/daemons/proxy.html"><FONT COLOR="#FFFFFF">Daemons/Proxy</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/902659138/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/902659138/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/1998/08/09/902659138.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">nmpg 1.1.3</FONT></B><BR> +<SMALL><B><A HREF="mailto:narkos@linuxmail.org">Joel Lindau</A> - January 29th 2000, 18:18 EST</B></SMALL> +<DIV ALIGN="justify"><P>nmpg is a small command-driven frontend and network-jukebox for mpg123.</DIV> +<P><B>Changes:</B> Bugfixes, better memory managment, a new .nmpgrc parser, and new options. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949187896.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: OpenSource</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/console/sound.html"><FONT COLOR="#FFFFFF">Console/Sound</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/935430877/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/935430877/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/935430877/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/08/23/935430877.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">mod_dtcl 0.7.3</FONT></B><BR> +<SMALL><B><A HREF="mailto:davidw@prosa.it">David Welton</A> - January 29th 2000, 18:11 EST</B></SMALL> +<DIV ALIGN="justify"><P>Mod_dtcl is a free/open source implementation of server-parsed Tcl under Apache. It allows you to tightly integrate HTML with Tcl, a widely-used scripting language with many years of development invested in it. There are also many external Tcl modules that you can load into mod_dtcl, to create images, access databases, etc.</DIV> +<P><B>Changes:</B> A major overhaul of header handling and internal buffering, and the addition of the ability to handle binary data. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949187471.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/web/development.html"><FONT COLOR="#FFFFFF">Web/Development</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/917925309/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/917925309/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/917925309/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/02/01/917925309.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">CoreLinux++ 0.4.6</FONT></B><BR> +<SMALL><B><A HREF="mailto:frankc@users.sourceforge.net">Frank V. Castellucci</A> - January 29th 2000, 18:07 EST</B></SMALL> +<DIV ALIGN="justify"><P>CoreLinux++ is an initiative to normalize methods and conventions for OOA/OOD/C++ development for Linux, materialized in a set of Open Source C++ class libraries (libcorelinux++ and libcoreframework++) to support common patterns and exploit the C++ standards.</DIV> +<P><B>Changes:</B> This release adds AbstractFactory and AssociativeIterator analysis, design, implementations, test code, a CVS daily tarball, a Patch Submission facility and updated FAQ, Web Pages, and defect reporting guidelines. +<P><B>Urgency:</B> medium +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949187233.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: LGPL</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/development/libraries.html"><FONT COLOR="#FFFFFF">Development/Libraries</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/944077775/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/944077775/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/944077775/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/12/01/944077775.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">scribe 0.2</FONT></B><BR> +<SMALL><B><A HREF="mailto:kahlage@logoncafe.net">ChromeBob</A> - January 29th 2000, 12:12 EST</B></SMALL> +<DIV ALIGN="justify"><P>scribe writes functions prototypes for your C code, so you don't have to. It also compares unique functions between source code files and will 'extern' when appropriate. C++ methods support is also planned.</DIV> +<P><B>Changes:</B> A fix for an fflush() bug and better documentation. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949165962.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/development/tools.html"><FONT COLOR="#FFFFFF">Development/Tools</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/946661656/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/946661656/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/1999/12/31/946661656.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">E theme updater 0.1</FONT></B><BR> +<SMALL><B><A HREF="mailto:hallvar@ii.uib.no">Hallvar Helleseth</A> - January 29th 2000, 12:04 EST</B></SMALL> +<DIV ALIGN="justify"><P>E theme Updater is a bash script to automatically update all of your Enlightenment themes from e.themes.org.</DIV> +<P><B>Changes:</B> Initial release. + +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949165472.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/console/misc.html"><FONT COLOR="#FFFFFF">Console/Misc</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/949164501/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/949164501/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/2000/01/29/949164501.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">Powertweak-Linux 0.1.7</FONT></B><BR> +<SMALL><B><A HREF="mailto:dave@denial.force9.co.uk">Dave Jones</A> - January 29th 2000, 12:03 EST</B></SMALL> +<DIV ALIGN="justify"><P>Powertweak-Linux is a port of the Microsoft Windows tool of the same name rewritten from the ground up. Its main function is to tune your system to its optimal performance settings. Currently, it tunes PCI chipsets and can set /proc/sys entries.</DIV> +<P><B>Changes:</B> A major GUI overhaul, the ability to generate configuration files, extended PCI information tabs, extra information support for the Matrox G200, and numerous other bugfixes & improvements. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949165416.html">comments (2)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/console/system.html"><FONT COLOR="#FFFFFF">Console/System</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/930836224/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/930836224/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/930836224/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/07/01/930836224.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">Pexeso Beta</FONT></B><BR> +<SMALL><B><A HREF="mailto:pavolkrigler@pobox.sk">Pavol Krigler</A> - January 29th 2000, 11:55 EST</B></SMALL> +<DIV ALIGN="justify"><P>pexeso is a simple graphic card game for one or two players.</DIV> +<P><B>Changes:</B> Initial public release. + +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164956.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: Freeware</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/console/games.html"><FONT COLOR="#FFFFFF">Console/Games</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/949141436/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/949141436/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/2000/01/29/949141436.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">XZX 2.9.2</FONT></B><BR> +<SMALL><B><A HREF="mailto:Erik.Kunze@fantasy.muc.de">E. Kunze</A> - January 29th 2000, 11:54 EST</B></SMALL> +<DIV ALIGN="justify"><P>XZX is a portable emulator of ZX Spectrum 48K/128K/+3 (8-bit home computers made by Sir Clive Sinclair) and Pentagon/Scorpion (Spectrum clones made in Russia) for machines running UNIX and the X Window system. XZX is completely written in C and emulates Spectrum 48K, 128K, +2 and +3, Pentagon and Scorpion, Interface I with up to 8 microdrives, Multiface 128 and Multiface 3, BetaDisk 128 interface by Technology Research Ltd with 4 disk drives, +D interface by Miles Gordon Technology with 2 disk drives, Kempston mouse, Kempston joystick and built-in machine code monitor.</DIV> +<P><B>Changes:</B> Lots of feature improvement and bug fixes. Most parts of the audio support has been rewritten for different UNICES. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164896.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: Shareware</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/x11/emulators.html"><FONT COLOR="#FFFFFF">X11/Emulators</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/936956384/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/936956384/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/936956384/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/09/10/936956384.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">DistroLib 0.4</FONT></B><BR> +<SMALL><B><A HREF="mailto:phir@gcu-squad.org">PhiR</A> - January 29th 2000, 11:54 EST</B></SMALL> +<DIV ALIGN="justify"><P>DistroLib is an abstraction library designed to make the development of distributed application easier. Its main target is currently compute-bound tasks based on a one server, many clients model (much like distributed.net), but it is quite generic and could be used for any client/server app. It is lightweight, easy-to-use, and relies heavily on threads.</DIV> +<P><B>Changes:</B> Important bug fixes and command history support. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164869.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/development/libraries.html"><FONT COLOR="#FFFFFF">Development/Libraries</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/942588431/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/942588431/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/942588431/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/11/14/942588431.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">ToutDoux 1.1.7</FONT></B><BR> +<SMALL><B><A HREF="mailto:yeupou@altern.org">yeupou</A> - January 29th 2000, 11:54 EST</B></SMALL> +<DIV ALIGN="justify"><P>ToutDoux is a project manager which lets you design a plan of action using a tree structure, with translations in French and English.</DIV> +<P><B>Changes:</B> A new menu and XML standard for save files. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164843.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/gnome/tools.html"><FONT COLOR="#FFFFFF">GNOME/Tools</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/944433411/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/944433411/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/1999/12/05/944433411.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">goMP 1.0.3</FONT></B><BR> +<SMALL><B><A HREF="mailto:dioxine@poulet.org">Gautier</A> - January 29th 2000, 11:52 EST</B></SMALL> +<DIV ALIGN="justify"><P>goMP is a set of CGI scripts that allows you to remotely control, via a Web browser, a computer acting as an MP3 jukebox. This program is very useful for someone who's got a dedicated computer with a lot of MP3 files but that doesn't have any output and input devices except network and sound card. It's main advantages are built-in cataloging, fast access to music, and no special software needed on the client side.</DIV> +<P><B>Changes:</B> Bugfixes, a password-protected config page, basic search function, easier installation thanks to an install script, and relocation of HTML docs and CGIs to a subdirectory. +<P><B>Urgency:</B> medium +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164772.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: Artistic</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/web/tools.html"><FONT COLOR="#FFFFFF">Web/Tools</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/948492962/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/948492962/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/948492962/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/2000/01/21/948492962.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">APSEND 1.40</FONT></B><BR> +<SMALL><B><A HREF="mailto:sventek@gmx.net">M.K.</A> - January 29th 2000, 11:50 EST</B></SMALL> +<DIV ALIGN="justify"><P>APSEND is a TCP/IP packet sender to test firewalls and other network applications. It also includes a syn flood option, the land DoS attack, and a DoS attack against tcpdump running on a UNIX-based system. Future updates will include support for a scripting language to construct TCP packets and a few more options and protocols like UDP and ICMP. A port of APSEND from Perl to C is planned as well.</DIV> +<P><B>Changes:</B> The stream attack, bugfixes, and rewrites for parts of the code. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164633.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/console/networking.html"><FONT COLOR="#FFFFFF">Console/Networking</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/941654429/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/941654429/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/941654429/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/11/03/941654429.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">ecasound 1.6.12r10</FONT></B><BR> +<SMALL><B><A HREF="mailto:kaiv@wakkanet.fi">Kai Vehmanen</A> - January 29th 2000, 11:48 EST</B></SMALL> +<DIV ALIGN="justify"><P>Ecasound is a software package designed for multitrack audio processing. It can be used for simple tasks like audio playback, recording and format conversions, as well as for multitrack effect processing, mixing, recording and signal recycling. Ecasound supports a wide range of audio inputs, outputs and effect algorithms. Ecasound has a chain-based design that allows effects to be easily combined both in series and in parallel. Oscillators and MIDI-CCs can be used for controlling effect parameters. Includes a versatile console mode interface, a Qt-based X-interface and various command-line utils suitable for batch processing.</DIV> +<P><B>Changes:</B> Support for 24- and 32-bit audio formats and for ALSA 0.5, multichannel noisegate, a new 2nd order lowpass filter, some ia-mode commands, and various bugfixes and low-level improvements. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164529.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/console/sound.html"><FONT COLOR="#FFFFFF">Console/Sound</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/931819147/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/931819147/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/931819147/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/07/12/931819147.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">SCEZ 20000129</FONT></B><BR> +<SMALL><B><A HREF="mailto:m032@mbsks.franken.de">endergone Zwiebeltuete</A> - January 29th 2000, 11:46 EST</B></SMALL> +<DIV ALIGN="justify"><P>SCEZ is a library that should make the handling of smart cards (not memory cards) and card readers as simple as possible and be at the same time small and easily portable. Currently supported are Dumb Mouse, CT-API and Towitoko readers and Schlumberger Cryptoflex, Gemplus GPK4000, GSM SIM and Telesec SigG cards. A PKCS#15 implementation is in the design phase. There are ports to PalmOS and MS-Windows available.</DIV> +<P><B>Changes:</B> More card and reader drivers, and an application to read out GSM SIM card (phone book and SMS) and write it to the card. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164394.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: BSD type</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/development/libraries.html"><FONT COLOR="#FFFFFF">Development/Libraries</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/939677525/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/939677525/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/1999/10/11/939677525.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">Comicq 0.2.0</FONT></B><BR> +<SMALL><B><A HREF="mailto:terminal6@submail.net">Terminal6</A> - January 29th 2000, 11:45 EST</B></SMALL> +<DIV ALIGN="justify"><P>COMICQ is a command line ICQ messaging tool that allows a user to connect to ICQ using your UIN and password, then sends a message to the destination UIN.</DIV> +<P><B>Changes:</B> Several bugfixes, icq99a compliance, and a new option --ip that allows you to get any user's IP by their UIN. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164350.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/console/communication.html"><FONT COLOR="#FFFFFF">Console/Communication</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/948389309/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/948389309/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="/appindex/2000/01/20/948389309.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">senv 0.2</FONT></B><BR> +<SMALL><B><A HREF="mailto:kojak@ids.pl">Zbyszek Sobiecki</A> - January 29th 2000, 11:44 EST</B></SMALL> +<DIV ALIGN="justify"><P>Senv allows you to run programs with a specified environment. It can set uid, gid, root directory, working directory, limits, and environment variables. It is useful in init scripts and as a shell for users for setting resource limits and environment variables. You can create sets of configurations and specify the one to use from command line.</DIV> +<P><B>Changes:</B> Login shell limits and environment setting for users, permanent resource limits for specified groups of users and environment variables, and other minor bugfixes. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949164259.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: GPL</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/console/administration.html"><FONT COLOR="#FFFFFF">Console/Administration</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/944953892/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/changelog/944953892/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/12/11/944953892.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="97%" BORDER="0" BGCOLOR="#000000"><TR><TD COLSPAN="2"> +<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#FFFFFF"> +<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B><FONT SIZE="+2">XZX 2.9.2</FONT></B><BR> +<SMALL><B><A HREF="mailto:Erik.Kunze@fantasy.muc.de">E. Kunze</A> - January 29th 2000, 10:55 EST</B></SMALL> +<DIV ALIGN="justify"><P>XZX is a portable emulator of ZX Spectrum 48K/128K/+3 (8-bit home computers made by Sir Clive Sinclair) and Pentagon/Scorpion (Spectrum clones made in Russia) for machines running UNIX and the X Window system. XZX is completely written in C and emulates Spectrum 48K, 128K, +2 and +3, Pentagon and Scorpion, Interface I with up to 8 microdrives, Multiface 128 and Multiface 3, BetaDisk 128 interface by Technology Research Ltd with 4 disk drives, +D interface by Miles Gordon Technology with 2 disk drives, Kempston mouse, Kempston joystick and built-in machine code monitor.</DIV> +<P><B>Changes:</B> Lots of feature improvement and bug fixes. Most parts of the audio support has been rewritten for different UNICES. +<P><B>Urgency:</B> low +<P ALIGN="right"><B>[ <A HREF="/news/2000/01/29/949161354.html">comments (0)</A> ]</B> +</FONT></TD></TR></TABLE></TD></TR><TR><TD VALIGN="middle"> + <FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#FFFFFF"><B><SMALL>License: Shareware</SMALL></B><BR> +<B><SMALL> Category: <A HREF="/appindex/x11/emulators.html"><FONT COLOR="#FFFFFF">X11/Emulators</FONT></A></SMALL></B></FONT></FONT></TD><TD ALIGN="right"> +<A HREF="http://apps.freshmeat.net/download/936956384/"><IMG SRC="image6" WIDTH="21" HEIGHT="21" BORDER="0" ALT="download"></A> <A HREF="http://apps.freshmeat.net/homepage/936956384/"><IMG SRC="image5" WIDTH="21" HEIGHT="21" BORDER="0" ALT="homepage"></A> <A HREF="http://apps.freshmeat.net/changelog/936956384/"><IMG SRC="image8" WIDTH="21" HEIGHT="21" BORDER="0" ALT="changelog"></A> <A HREF="/appindex/1999/09/10/936956384.html"><IMG SRC="image7" WIDTH="21" HEIGHT="21" BORDER="0" ALT="appindex record"></A> +</TD></TR></TABLE> +<HR WIDTH="0" SIZE="0"> + + +<P><SMALL><CENTER><B>[ <A HREF="/news/2000/01/29/">full page for today</A> | <A HREF="/news/2000/01/28/">yesterday's edition</A> ]</SMALL></B></CENTER></FONT></TD><TD WIDTH="27%" VALIGN="top" ALIGN="center"><FONT FACE="Lucida,Verdana,Helvetica,Arial"> + +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">navigator</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="/news/2000/01/29/"><FONT COLOR="#000000">full page for today</FONT></A><BR> +- <A HREF="/news/2000/01/28/"><FONT COLOR="#000000">yesterday's edition</FONT></A><BR> +- <A HREF="news://news.freshmeat.net/"><FONT COLOR="#000000"><B>new:</B> fm news via NNTP</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">eye catcher</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<B>Free Shirts</B><BR>We give away a free freshmeat t-shirt every week for the best comment added to an application announcement or story posted on freshmeat. +<P><B>#freshmeat</B><BR>If you want to chat about what's new on freshmeat and hang out with other fm lounge lizards and the fm staff, head over to #freshmeat on irc.freshmeat.net, part of <A HREF="http://openprojects.nu/">The Open Projects Network</A>. + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">site notes</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="/news/2000/01/29/949208399.html"><FONT COLOR="#000000">We should get this out of the door now (Jan 29th)</FONT></A><BR> +- <A HREF="/news/2000/01/01/946704535.html"><FONT COLOR="#000000">freshmeat Y2K report (Jan 01st)</FONT></A><BR> +- <A HREF="/news/1999/08/16/934862340.html"><FONT COLOR="#000000">Assorted freshmeat notes (Aug 16th)</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">recent editorials</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="/news/2000/01/29/949208340.html"><FONT COLOR="#000000">Is Linux for Crazies? (Jan 29th)</FONT></A><BR> +- <A HREF="/news/2000/01/22/948603540.html"><FONT COLOR="#000000">A New Business Plan for Free Software (Jan 22nd)</FONT></A><BR> +- <A HREF="/news/2000/01/15/947998740.html"><FONT COLOR="#000000">Is Linux Going to Reunite the UNIX Market? (Jan 15th)</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">andover.net</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +<BR><CENTER><A HREF="http://andover.net"><IMG SRC="image9" BORDER="0" WIDTH="150" HEIGHT="43" ALT="Mirror Logo"></A></CENTER><P> +- <A HREF="http://www.animfactory.com/"><FONT COLOR="#000000">Animation Factory</FONT></A><BR> +- <A HREF="http://www.davecentral.com/"><FONT COLOR="#000000">DaveCentral</FONT></A><BR> +- <A HREF="http://www.freecode.com/"><FONT COLOR="#000000">FreeCode</FONT></A><BR> +- <A HREF="http://www.InternetTrafficReport.com/"><FONT COLOR="#000000">Internet Traffic Report</FONT></A><BR> +- <A HREF="http://www.ITManagersJournal.com/"><FONT COLOR="#000000">IT Manager's Journal</FONT></A><BR> +- <A HREF="http://www.mediabuilder.com/"><FONT COLOR="#000000">MediaBuilder</FONT></A><BR> +- <A HREF="http://slashdot.org/"><FONT COLOR="#000000">Slashdot</FONT></A><BR> +- <A HREF="http://www.slaughterhouse.com/"><FONT COLOR="#000000">Slaughterhouse</FONT></A><BR> +- <A HREF="http://www.techmailings.com/"><FONT COLOR="#000000">TechMailings</FONT></A><BR> +- <A HREF="http://www.techsightings.com/"><FONT COLOR="#000000">TechSightings</FONT></A><BR> +<BR><CENTER><B>E-Commerce</B></CENTER><P> +- <A HREF="http://www.thinkgeek.com"><FONT COLOR="#000000">ThinkGeek (Stuff for smart masses)</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000">supported sites</FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="http://www.userfriendly.org"><FONT COLOR="#000000">Userfriendly.org</FONT></A><BR> +- <A HREF="http://www.securityfocus.com"><FONT COLOR="#000000">SecurityFocus</FONT></A><BR> +- <A HREF="http://copyleft.net"><FONT COLOR="#000000">copyleft</FONT></A><BR> +- <A HREF="http://filewatcher.org"><FONT COLOR="#000000">Filewatcher</FONT></A><BR> +- <A HREF="http://www.linux.com"><FONT COLOR="#000000">Linux.com</FONT></A><BR> +- <A HREF="http://www.linuxtelephony.org"><FONT COLOR="#000000">LinuxTelephony</FONT></A><BR> +- <A HREF="http://www.linuxtoday.com"><FONT COLOR="#000000">LinuxToday</FONT></A><BR> +- <A HREF="http://openprojects.nu/services/irc.html"><FONT COLOR="#000000">Openprojects</FONT></A><BR> +- <A HREF="http://www.32bitsonline.com"><FONT COLOR="#000000">32bitsonline</FONT></A><BR> +- <A HREF="http://www.gnu.org"><FONT COLOR="#000000">The GNU Project</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="/news/2000/01/29/"><font color="#000000">saturday</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="/news/2000/01/29/949208399.html"><FONT COLOR="#000000">We should get this out of the door now</FONT></A><BR> +- <A HREF="/news/2000/01/29/949208340.html"><FONT COLOR="#000000">Is Linux for Crazies?</FONT></A><BR> +- <A HREF="/news/2000/01/29/949188564.html"><FONT COLOR="#000000">RabbIT 2.0.2</FONT></A><BR> +- <A HREF="/news/2000/01/29/949187896.html"><FONT COLOR="#000000">nmpg 1.1.3</FONT></A><BR> +- <A HREF="/news/2000/01/29/949187471.html"><FONT COLOR="#000000">mod_dtcl 0.7.3</FONT></A><BR> +- <A HREF="/news/2000/01/29/949187233.html"><FONT COLOR="#000000">CoreLinux++ 0.4.6</FONT></A><BR> +- <A HREF="/news/2000/01/29/949165962.html"><FONT COLOR="#000000">scribe 0.2</FONT></A><BR> +- <A HREF="/news/2000/01/29/949165472.html"><FONT COLOR="#000000">E theme updater 0.1</FONT></A><BR> +- <A HREF="/news/2000/01/29/949165416.html"><FONT COLOR="#000000">Powertweak-Linux 0.1.7</FONT></A><BR> +- <A HREF="/news/2000/01/29/949164956.html"><FONT COLOR="#000000">Pexeso Beta</FONT></A><BR> +- <A HREF="/news/2000/01/29/949164896.html"><FONT COLOR="#000000">XZX 2.9.2</FONT></A><BR> +- <A HREF="/news/2000/01/29/949164869.html"><FONT COLOR="#000000">DistroLib 0.4</FONT></A><BR> +- <A HREF="/news/2000/01/29/949164843.html"><FONT COLOR="#000000">ToutDoux 1.1.7</FONT></A><BR> +- <A HREF="/news/2000/01/29/949164772.html"><FONT COLOR="#000000">goMP 1.0.3</FONT></A><BR> +- <A HREF="/news/2000/01/29/949164633.html"><FONT COLOR="#000000">APSEND 1.40</FONT></A><BR> +- <A HREF="/news/2000/01/29/949164529.html"><FONT COLOR="#000000">ecasound 1.6.12r10</FONT></A><BR> +- <A HREF="/news/2000/01/29/949164394.html"><FONT COLOR="#000000">SCEZ 20000129</FONT></A><BR> +- <A HREF="/news/2000/01/29/949164350.html"><FONT COLOR="#000000">Comicq 0.2.0</FONT></A><BR> +- <A HREF="/news/2000/01/29/949164259.html"><FONT COLOR="#000000">senv 0.2</FONT></A><BR> +- <A HREF="/news/2000/01/29/949161354.html"><FONT COLOR="#000000">XZX 2.9.2</FONT></A><BR> +- <A HREF="/news/2000/01/29/949161036.html"><FONT COLOR="#000000">log4j 0.7.5</FONT></A><BR> +- <A HREF="/news/2000/01/29/949156343.html"><FONT COLOR="#000000">SQN Linux 1.6</FONT></A><BR> +- <A HREF="/news/2000/01/29/949156277.html"><FONT COLOR="#000000">Limo 0.3.2</FONT></A><BR> +- <A HREF="/news/2000/01/29/949156237.html"><FONT COLOR="#000000">Fusion GS 1.3</FONT></A><BR> +- <A HREF="/news/2000/01/29/949145887.html"><FONT COLOR="#000000">MMR 1.5.4</FONT></A><BR> +- <A HREF="/news/2000/01/29/949142835.html"><FONT COLOR="#000000">KUPS 0.3.4</FONT></A><BR> +- <A HREF="/news/2000/01/29/949142815.html"><FONT COLOR="#000000">3DSE patch for XMMS 4</FONT></A><BR> +- <A HREF="/news/2000/01/29/949139763.html"><FONT COLOR="#000000">Linux 2.3.41</FONT></A><BR> +- <A HREF="/news/2000/01/29/949139751.html"><FONT COLOR="#000000">Free Code for Linux S/390</FONT></A><BR> +- <A HREF="/news/2000/01/29/949135979.html"><FONT COLOR="#000000">CircleMUD 3.0 beta patchlevel 17</FONT></A><BR> +- <A HREF="/news/2000/01/29/949135938.html"><FONT COLOR="#000000">NiL Isn't Liero 000128</FONT></A><BR> +- <A HREF="/news/2000/01/29/949135913.html"><FONT COLOR="#000000">OpenSSH Unix Port 1.2.2</FONT></A><BR> +- <A HREF="/news/2000/01/29/949135889.html"><FONT COLOR="#000000">KBoxes! 1.3</FONT></A><BR> +- <A HREF="/news/2000/01/29/949135867.html"><FONT COLOR="#000000">phpLanParty 0.23</FONT></A><BR> +- <A HREF="/news/2000/01/29/949135509.html"><FONT COLOR="#000000">DGen/SDL 1.20</FONT></A><BR> +- <A HREF="/news/2000/01/29/949135482.html"><FONT COLOR="#000000">EdcomLib 1.0 alpha 5</FONT></A><BR> +- <A HREF="/news/2000/01/29/949135309.html"><FONT COLOR="#000000">Etherboot 4.4.2</FONT></A><BR> +- <A HREF="/news/2000/01/29/949135205.html"><FONT COLOR="#000000">BLADE 0.18.0</FONT></A><BR> +- <A HREF="/news/2000/01/29/949135115.html"><FONT COLOR="#000000">Sapphire 0.13.7</FONT></A><BR> +- <A HREF="/news/2000/01/29/949135070.html"><FONT COLOR="#000000">ippl 1.99.3</FONT></A><BR> +- <A HREF="/news/2000/01/29/949134977.html"><FONT COLOR="#000000">Saint 1.5patch1</FONT></A><BR> +- <A HREF="/news/2000/01/29/949134943.html"><FONT COLOR="#000000">Zircon 1.18.232</FONT></A><BR> +- <A HREF="/news/2000/01/29/949134927.html"><FONT COLOR="#000000">nmap 2.3BETA14</FONT></A><BR> +- <A HREF="/news/2000/01/29/949134901.html"><FONT COLOR="#000000">xterm patch #124</FONT></A><BR> +- <A HREF="/news/2000/01/29/949134817.html"><FONT COLOR="#000000">MyThreads-Links v0.5.2</FONT></A><BR> +- <A HREF="/news/2000/01/29/949134633.html"><FONT COLOR="#000000">sudo 1.6.2p1</FONT></A><BR> +- <A HREF="/news/2000/01/29/949134552.html"><FONT COLOR="#000000">MIT Photonic-Bands 0.10</FONT></A><BR> +- <A HREF="/news/2000/01/29/949134246.html"><FONT COLOR="#000000">Launcher 0.86</FONT></A><BR> +- <A HREF="/news/2000/01/29/949134179.html"><FONT COLOR="#000000">nano 0.8.1</FONT></A><BR> +- <A HREF="/news/2000/01/29/949134103.html"><FONT COLOR="#000000">Gtk-- 1.1.8</FONT></A><BR> +- <A HREF="/news/2000/01/29/949134049.html"><FONT COLOR="#000000">tkchooser 0.65</FONT></A><BR> +- <A HREF="/news/2000/01/29/949133420.html"><FONT COLOR="#000000">XShipWars 1.33a</FONT></A><BR> +- <A HREF="/news/2000/01/29/949133280.html"><FONT COLOR="#000000">Lamerpad 0.1</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="/news/2000/01/28/"><font color="#000000">friday</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="/news/2000/01/28/949117833.html"><FONT COLOR="#000000">fsv 0.9</FONT></A><BR> +- <A HREF="/news/2000/01/28/949117711.html"><FONT COLOR="#000000">popsneaker 0.1.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949114716.html"><FONT COLOR="#000000">eyep-updater.sh 1.0</FONT></A><BR> +- <A HREF="/news/2000/01/28/949113240.html"><FONT COLOR="#000000">W3Mail 0.5.0</FONT></A><BR> +- <A HREF="/news/2000/01/28/949113214.html"><FONT COLOR="#000000">The Urgent Decision 0.9.9</FONT></A><BR> +- <A HREF="/news/2000/01/28/949112269.html"><FONT COLOR="#000000">LTSP 1.02</FONT></A><BR> +- <A HREF="/news/2000/01/28/949112198.html"><FONT COLOR="#000000">Production BASIC 0.2.12</FONT></A><BR> +- <A HREF="/news/2000/01/28/949112123.html"><FONT COLOR="#000000">Postfix 19991231-pl03</FONT></A><BR> +- <A HREF="/news/2000/01/28/949109732.html"><FONT COLOR="#000000">Mp3 Commander 0.7</FONT></A><BR> +- <A HREF="/news/2000/01/28/949109324.html"><FONT COLOR="#000000">iManager 1.0.1b</FONT></A><BR> +- <A HREF="/news/2000/01/28/949108399.html"><FONT COLOR="#000000">Eterm 0.9</FONT></A><BR> +- <A HREF="/news/2000/01/28/949108308.html"><FONT COLOR="#000000">dqd_dirindex 1.0</FONT></A><BR> +- <A HREF="/news/2000/01/28/949108087.html"><FONT COLOR="#000000">Tidings 1.0.4</FONT></A><BR> +- <A HREF="/news/2000/01/28/949108026.html"><FONT COLOR="#000000">localscan 2.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949107922.html"><FONT COLOR="#000000">WMKeyboard 0.3</FONT></A><BR> +- <A HREF="/news/2000/01/28/949107834.html"><FONT COLOR="#000000">fcmp 1.0.2</FONT></A><BR> +- <A HREF="/news/2000/01/28/949107767.html"><FONT COLOR="#000000">Akkord 0.3.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949107649.html"><FONT COLOR="#000000">HiM 0.1.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949106305.html"><FONT COLOR="#000000">cdrecord 1.8</FONT></A><BR> +- <A HREF="/news/2000/01/28/949103400.html"><FONT COLOR="#000000">eMixer 0.05.5</FONT></A><BR> +- <A HREF="/news/2000/01/28/949103187.html"><FONT COLOR="#000000">FreeVSD 1.4.0</FONT></A><BR> +- <A HREF="/news/2000/01/28/949103096.html"><FONT COLOR="#000000">Common C++ Libraries 0.0</FONT></A><BR> +- <A HREF="/news/2000/01/28/949095155.html"><FONT COLOR="#000000">Moonshine 1.0beta2</FONT></A><BR> +- <A HREF="/news/2000/01/28/949095112.html"><FONT COLOR="#000000">swim 0.3.5</FONT></A><BR> +- <A HREF="/news/2000/01/28/949095009.html"><FONT COLOR="#000000">Xmame/xmess 0.36b15.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949094448.html"><FONT COLOR="#000000">pcmcia-cs 3.1.9</FONT></A><BR> +- <A HREF="/news/2000/01/28/949091509.html"><FONT COLOR="#000000">gPS 0.5.2</FONT></A><BR> +- <A HREF="/news/2000/01/28/949091415.html"><FONT COLOR="#000000">Snort 1.5.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949090436.html"><FONT COLOR="#000000">Pygmy Linux 0.7 beta</FONT></A><BR> +- <A HREF="/news/2000/01/28/949090237.html"><FONT COLOR="#000000">Intro to Bash Programming HOWTO 0.3</FONT></A><BR> +- <A HREF="/news/2000/01/28/949084379.html"><FONT COLOR="#000000">GNU Pth 1.3b2</FONT></A><BR> +- <A HREF="/news/2000/01/28/949084356.html"><FONT COLOR="#000000">Laonux 0.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949084304.html"><FONT COLOR="#000000">x-wvdial 0.12</FONT></A><BR> +- <A HREF="/news/2000/01/28/949084188.html"><FONT COLOR="#000000">Intro to Bash Programming HOWTO 0.3</FONT></A><BR> +- <A HREF="/news/2000/01/28/949084106.html"><FONT COLOR="#000000">Catalog 1.02</FONT></A><BR> +- <A HREF="/news/2000/01/28/949084062.html"><FONT COLOR="#000000">harvest 1.5.20-kj-0.9</FONT></A><BR> +- <A HREF="/news/2000/01/28/949068306.html"><FONT COLOR="#000000">wmseti 0.3.0a</FONT></A><BR> +- <A HREF="/news/2000/01/28/949057272.html"><FONT COLOR="#000000">RIG 1.02</FONT></A><BR> +- <A HREF="/news/2000/01/28/949057019.html"><FONT COLOR="#000000">FreeAddr 0.2</FONT></A><BR> +- <A HREF="/news/2000/01/28/949056939.html"><FONT COLOR="#000000">GtkAda 1.2.5</FONT></A><BR> +- <A HREF="/news/2000/01/28/949056664.html"><FONT COLOR="#000000">dot.conf 0.6.0</FONT></A><BR> +- <A HREF="/news/2000/01/28/949055099.html"><FONT COLOR="#000000">dep.pl 1.28.0</FONT></A><BR> +- <A HREF="/news/2000/01/28/949054980.html"><FONT COLOR="#000000">Prae's Scripts 1.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949044301.html"><FONT COLOR="#000000">Project Clock 0.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949044285.html"><FONT COLOR="#000000">Xtheater 0.2.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949040013.html"><FONT COLOR="#000000">i-no Chart 0.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949039945.html"><FONT COLOR="#000000">spliff 0.8.1</FONT></A><BR> +- <A HREF="/news/2000/01/28/949038953.html"><FONT COLOR="#000000">Regexx 0.95</FONT></A><BR> +- <A HREF="/news/2000/01/28/949038316.html"><FONT COLOR="#000000">RBook 0.5.0</FONT></A><BR> +- <A HREF="/news/2000/01/28/949036742.html"><FONT COLOR="#000000">RIG 1.01</FONT></A><BR> +- <A HREF="/news/2000/01/28/949036714.html"><FONT COLOR="#000000">wchat 1.2.0</FONT></A><BR> +- <A HREF="/news/2000/01/28/949036428.html"><FONT COLOR="#000000">PCCS MySQLDatabase Admin Tool 1.2.2</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="/news/2000/01/27/"><font color="#000000">thursday</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="/news/2000/01/27/949033332.html"><FONT COLOR="#000000">CADUBI 1.1b1</FONT></A><BR> +- <A HREF="/news/2000/01/27/949032987.html"><FONT COLOR="#000000">Angus' Chess Clock 0.8.1</FONT></A><BR> +- <A HREF="/news/2000/01/27/949032555.html"><FONT COLOR="#000000">MP3 Report Generator 1.0.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/949032518.html"><FONT COLOR="#000000">4DOM 0.9.2</FONT></A><BR> +- <A HREF="/news/2000/01/27/949032386.html"><FONT COLOR="#000000">4XSLT 0.8.2</FONT></A><BR> +- <A HREF="/news/2000/01/27/949031346.html"><FONT COLOR="#000000">OpenNaken 1.10</FONT></A><BR> +- <A HREF="/news/2000/01/27/949025747.html"><FONT COLOR="#000000">iManager 1.0b</FONT></A><BR> +- <A HREF="/news/2000/01/27/949025168.html"><FONT COLOR="#000000">QuakeForge 0.1.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/949023271.html"><FONT COLOR="#000000">pylice 0.7.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/949023250.html"><FONT COLOR="#000000">Solfege 0.6.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/949023151.html"><FONT COLOR="#000000">xinetd 2.1.8.7p1</FONT></A><BR> +- <A HREF="/news/2000/01/27/949022849.html"><FONT COLOR="#000000">jac 0.13</FONT></A><BR> +- <A HREF="/news/2000/01/27/949022803.html"><FONT COLOR="#000000">Xmms 1.0.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/949022319.html"><FONT COLOR="#000000">KSrnd 0.97</FONT></A><BR> +- <A HREF="/news/2000/01/27/949021877.html"><FONT COLOR="#000000">getpg / UW-IMAP 0.54</FONT></A><BR> +- <A HREF="/news/2000/01/27/949021849.html"><FONT COLOR="#000000">getpg 0.53</FONT></A><BR> +- <A HREF="/news/2000/01/27/949021824.html"><FONT COLOR="#000000">setserial 2.17</FONT></A><BR> +- <A HREF="/news/2000/01/27/949021250.html"><FONT COLOR="#000000">Pan 0.7.3</FONT></A><BR> +- <A HREF="/news/2000/01/27/949021216.html"><FONT COLOR="#000000">jwhois 2.4.1</FONT></A><BR> +- <A HREF="/news/2000/01/27/949021126.html"><FONT COLOR="#000000">Kmp3 1.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/949020964.html"><FONT COLOR="#000000">xPine 0.0.12</FONT></A><BR> +- <A HREF="/news/2000/01/27/949019905.html"><FONT COLOR="#000000">Avenger's News System 2.1 Alpha</FONT></A><BR> +- <A HREF="/news/2000/01/27/949019709.html"><FONT COLOR="#000000">RIG 1.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/949019321.html"><FONT COLOR="#000000">scroller 1.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/949018347.html"><FONT COLOR="#000000">Perl EyeP Client 0.1</FONT></A><BR> +- <A HREF="/news/2000/01/27/949017796.html"><FONT COLOR="#000000">sfront 0.54</FONT></A><BR> +- <A HREF="/news/2000/01/27/949017631.html"><FONT COLOR="#000000">XFrisk 1.2</FONT></A><BR> +- <A HREF="/news/2000/01/27/949016202.html"><FONT COLOR="#000000">Moffy 0.0.1</FONT></A><BR> +- <A HREF="/news/2000/01/27/949015348.html"><FONT COLOR="#000000">Solid POP3 0.14</FONT></A><BR> +- <A HREF="/news/2000/01/27/949014200.html"><FONT COLOR="#000000">php3guest 1.5</FONT></A><BR> +- <A HREF="/news/2000/01/27/949013630.html"><FONT COLOR="#000000">crUD 01.27.2000</FONT></A><BR> +- <A HREF="/news/2000/01/27/949013380.html"><FONT COLOR="#000000">crUD 01.27.2000</FONT></A><BR> +- <A HREF="/news/2000/01/27/949012979.html"><FONT COLOR="#000000">Free Pascal Compiler 0.99.14</FONT></A><BR> +- <A HREF="/news/2000/01/27/949012771.html"><FONT COLOR="#000000">gtk-font-hack 0.2-gtk-1.2.6</FONT></A><BR> +- <A HREF="/news/2000/01/27/949009233.html"><FONT COLOR="#000000">Linux 2.2.15pre5</FONT></A><BR> +- <A HREF="/news/2000/01/27/949005620.html"><FONT COLOR="#000000">krunseti 0.2.1</FONT></A><BR> +- <A HREF="/news/2000/01/27/948996446.html"><FONT COLOR="#000000">CompuPic 5.0.1036</FONT></A><BR> +- <A HREF="/news/2000/01/27/948995905.html"><FONT COLOR="#000000">gfontview 0.3.3</FONT></A><BR> +- <A HREF="/news/2000/01/27/948995819.html"><FONT COLOR="#000000">authlocal 1.0.2</FONT></A><BR> +- <A HREF="/news/2000/01/27/948995600.html"><FONT COLOR="#000000">bigwig 1.1</FONT></A><BR> +- <A HREF="/news/2000/01/27/948995501.html"><FONT COLOR="#000000">CAFire 0.0.11</FONT></A><BR> +- <A HREF="/news/2000/01/27/948995429.html"><FONT COLOR="#000000">ANVLOGIN 2.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/948994944.html"><FONT COLOR="#000000">sawmill.el 1.9</FONT></A><BR> +- <A HREF="/news/2000/01/27/948994810.html"><FONT COLOR="#000000">Perlsh 20000127</FONT></A><BR> +- <A HREF="/news/2000/01/27/948994776.html"><FONT COLOR="#000000">sitescooper 2.1.2</FONT></A><BR> +- <A HREF="/news/2000/01/27/948994691.html"><FONT COLOR="#000000">MHDns 1.4</FONT></A><BR> +- <A HREF="/news/2000/01/27/948994419.html"><FONT COLOR="#000000">JChemPaint 0.5</FONT></A><BR> +- <A HREF="/news/2000/01/27/948994364.html"><FONT COLOR="#000000">Filesystems HOWTO 0.7.3</FONT></A><BR> +- <A HREF="/news/2000/01/27/948994343.html"><FONT COLOR="#000000">KSnes9x 1.2</FONT></A><BR> +- <A HREF="/news/2000/01/27/948993513.html"><FONT COLOR="#000000">Mozilla M13</FONT></A><BR> +- <A HREF="/news/2000/01/27/948993439.html"><FONT COLOR="#000000">edna 0.3</FONT></A><BR> +- <A HREF="/news/2000/01/27/948993409.html"><FONT COLOR="#000000">GMasqdialer 0.99.8</FONT></A><BR> +- <A HREF="/news/2000/01/27/948993341.html"><FONT COLOR="#000000">spliff 0.8</FONT></A><BR> +- <A HREF="/news/2000/01/27/948992808.html"><FONT COLOR="#000000">MultiSeti 0.3</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970667.html"><FONT COLOR="#000000">rude 0.50</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970605.html"><FONT COLOR="#000000">cgi-util++ 0.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970479.html"><FONT COLOR="#000000">Cricket 0.72</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970458.html"><FONT COLOR="#000000">nuni 0.04</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970379.html"><FONT COLOR="#000000">Ksetiwatch 0.3.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970358.html"><FONT COLOR="#000000">SiteMgrYAP 0.1.2</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970322.html"><FONT COLOR="#000000">phpLanParty 0.21</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970285.html"><FONT COLOR="#000000">Glitter Newsreader 0.1</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970263.html"><FONT COLOR="#000000">Fastresolve 2.4</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970164.html"><FONT COLOR="#000000">ColdSync 1.1.2</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970080.html"><FONT COLOR="#000000">DDD 3.2</FONT></A><BR> +- <A HREF="/news/2000/01/27/948970032.html"><FONT COLOR="#000000">X Northern Captain 4.2.1</FONT></A><BR> +- <A HREF="/news/2000/01/27/948969919.html"><FONT COLOR="#000000">abcde 1.0.2</FONT></A><BR> +- <A HREF="/news/2000/01/27/948969659.html"><FONT COLOR="#000000">Gnapster 1.3.2</FONT></A><BR> +- <A HREF="/news/2000/01/27/948969551.html"><FONT COLOR="#000000">xmix 1.0 Alpha</FONT></A><BR> +- <A HREF="/news/2000/01/27/948969488.html"><FONT COLOR="#000000">gtktetcolor 0.3</FONT></A><BR> +- <A HREF="/news/2000/01/27/948969412.html"><FONT COLOR="#000000">muttzilla 0.40</FONT></A><BR> +- <A HREF="/news/2000/01/27/948969395.html"><FONT COLOR="#000000">muttzilla 0.40</FONT></A><BR> +- <A HREF="/news/2000/01/27/948969337.html"><FONT COLOR="#000000">asp2php 0.73.6</FONT></A><BR> +- <A HREF="/news/2000/01/27/948969217.html"><FONT COLOR="#000000">mod_ticket 1.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/948969078.html"><FONT COLOR="#000000">MegaHAL for Eggdrop .01</FONT></A><BR> +- <A HREF="/news/2000/01/27/948968456.html"><FONT COLOR="#000000">Jetty 2.3.5</FONT></A><BR> +- <A HREF="/news/2000/01/27/948968386.html"><FONT COLOR="#000000">xlpotdb 1.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/948968341.html"><FONT COLOR="#000000">Koala Complete MUD Server 0.1.1a</FONT></A><BR> +- <A HREF="/news/2000/01/27/948968255.html"><FONT COLOR="#000000">mcountd 0.4</FONT></A><BR> +- <A HREF="/news/2000/01/27/948967933.html"><FONT COLOR="#000000">cdbackup 0.5.0</FONT></A><BR> +- <A HREF="/news/2000/01/27/948967908.html"><FONT COLOR="#000000">The Java SSH/Telnet Application/Applet 2.0 RC1</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://slashdot.org"><font color="#000000">slashdot</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="http://slashdot.org/article.pl?sid=00/01/29/1534255"><FONT COLOR="#000000">Petition Apple for Linux QuickTime</FONT></A><BR> +- <A HREF="http://slashdot.org/article.pl?sid=00/01/29/1223249"><FONT COLOR="#000000">GNUstep 0.6.5 freeze</FONT></A><BR> +- <A HREF="http://slashdot.org/article.pl?sid=00/01/28/2324203"><FONT COLOR="#000000">YETI@Home</FONT></A><BR> +- <A HREF="http://slashdot.org/article.pl?sid=00/01/29/1024215"><FONT COLOR="#000000">Documents Unsealed in Microsoft/Caldera Case</FONT></A><BR> +- <A HREF="http://slashdot.org/article.pl?sid=00/01/29/0837235"><FONT COLOR="#000000">Who Bought Linux.Net?</FONT></A><BR> +- <A HREF="http://slashdot.org/article.pl?sid=00/01/24/1146250"><FONT COLOR="#000000">E-Mails from (Over?) The Edge</FONT></A><BR> +- <A HREF="http://slashdot.org/article.pl?sid=00/01/29/0834223"><FONT COLOR="#000000">Linux Kernel 2.3.41</FONT></A><BR> +- <A HREF="http://slashdot.org/article.pl?sid=00/01/28/2311232"><FONT COLOR="#000000">Congress Still Figuring Out E-Mail</FONT></A><BR> +- <A HREF="http://slashdot.org/article.pl?sid=00/01/22/1946244"><FONT COLOR="#000000">Sci Fi Literature 101?</FONT></A><BR> +- <A HREF="http://slashdot.org/article.pl?sid=00/01/28/2318246"><FONT COLOR="#000000">Could Distributed.Net Help the Mars Polar Lander?</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://www.securityfocus.com"><font color="#000000">securityfocus</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.zdnet.com/zdnn/stories/news/0,4586,2429334,00.html?chkpt=zdnntop"><FONT COLOR="#000000">Win2000 security hole a 'major threat'</FONT></A><BR> +- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.computerworld.com/home/print.nsf/all/000128e45a"><FONT COLOR="#000000">Visa acknowledges cracker break-ins</FONT></A><BR> +- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.zdnet.com/sr/stories/column/0,4712,2429536,00.html"><FONT COLOR="#000000">What's Wrong With Microsoft Security?</FONT></A><BR> +- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.zdnet.com/pcweek/stories/news/0,4153,2429334,00.html"><FONT COLOR="#000000">Microsoft posts first Win2K security patch</FONT></A><BR> +- <A HREF="http://www.securityfocus.com/level2/?go=tools&id=1018"><FONT COLOR="#000000">Libnids 1.12</FONT></A><BR> +- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.theregister.co.uk/000127-000005.html"><FONT COLOR="#000000">New hack attack is greater threat than imagined</FONT></A><BR> +- <A HREF="http://www.securityfocus.com/level2/?go=news&id=http://www.mercurycenter.com/svtech/news/indepth/docs/hacker012700.htm"><FONT COLOR="#000000">Student charged with hacking</FONT></A><BR> +- <A HREF="http://www.securityfocus.com/level2/?go=library&id=63"><FONT COLOR="#000000">Building and Managing Virtual Private Networks (book)</FONT></A><BR> +- <A HREF="http://www.securityfocus.com/level2/?go=library&id=111"><FONT COLOR="#000000">Threats, Vulnerabilities and Real-Worl Responses: The Foundations of the TruSecure Process</FONT></A><BR> +- <A HREF="http://www.securityfocus.com/level2/?go=library&id=1701"><FONT COLOR="#000000">The Hundredth Window : Protecting Your Privacy and Security in the Age of the Internet (boo</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://www.bebits.com"><font color="#000000">bebits</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="http://www.bebits.com/app/706/"><FONT COLOR="#000000">Pe 3.0a3</FONT></A><BR> +- <A HREF="http://www.bebits.com/app/757/"><FONT COLOR="#000000">Rarscript 1.5</FONT></A><BR> +- <A HREF="http://www.bebits.com/app/736/"><FONT COLOR="#000000">CD Manager 0.66a beta</FONT></A><BR> +- <A HREF="http://www.bebits.com/app/174/"><FONT COLOR="#000000">TraX 1.1</FONT></A><BR> +- <A HREF="http://www.bebits.com/app/785/"><FONT COLOR="#000000">BeMath 1.2.2</FONT></A><BR> +- <A HREF="http://www.bebits.com/app/784/"><FONT COLOR="#000000">simple blackjack 1</FONT></A><BR> +- <A HREF="http://www.bebits.com/app/758/"><FONT COLOR="#000000">HtmlTree 0.5.3</FONT></A><BR> +- <A HREF="http://www.bebits.com/app/783/"><FONT COLOR="#000000">Yacp 0.1</FONT></A><BR> +- <A HREF="http://www.bebits.com/app/222/"><FONT COLOR="#000000">TicTacToe 1.5</FONT></A><BR> +- <A HREF="http://www.bebits.com/app/706/"><FONT COLOR="#000000">Pe 3.0a2</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://linuxtoday.com"><font color="#000000">linuxtoday</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="http://linuxtoday.com/story.php3?sn=15878"><FONT COLOR="#000000">Linux Journal: KDE--The Next Generation</FONT></A><BR> +- <A HREF="http://linuxtoday.com/story.php3?sn=15876"><FONT COLOR="#000000">Kernel Cousin gimp-devel #11 Is Out</FONT></A><BR> +- <A HREF="http://linuxtoday.com/story.php3?sn=15875"><FONT COLOR="#000000">Infoworld: Corel Linux OS ideal for the desktop</FONT></A><BR> +- <A HREF="http://linuxtoday.com/story.php3?sn=15874"><FONT COLOR="#000000">Technology Evaluation: IBM Jumps on the Linux Bandwagon with Both Feet, Sort Of</FONT></A><BR> +- <A HREF="http://linuxtoday.com/story.php3?sn=15873"><FONT COLOR="#000000">Tobias Hövekamp: European Union acknowledges</FONT></A><BR> +- <A HREF=""><FONT COLOR="#000000">&</FONT></A><BR> +- <A HREF=""><FONT COLOR="#000000">#34;Open Source Software</FONT></A><BR> +- <A HREF=""><FONT COLOR="#000000">&</FONT></A><BR> +- <A HREF=""><FONT COLOR="#000000">#34;</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://www.linuxtelephony.org"><font color="#000000">linuxtelephony</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="http://www.linuxtelephony.org/article.cgi?i=208&r=0"><FONT COLOR="#000000">Traverse Technologies releases NETspider-U in US</FONT></A><BR> +- <A HREF="http://www.linuxtelephony.org/article.cgi?i=207&r=0"><FONT COLOR="#000000">Quicknet releases new GPL'd Linux Drivers!</FONT></A><BR> +- <A HREF="http://www.linuxtelephony.org/article.cgi?i=206&r=0"><FONT COLOR="#000000">Natural Microsystems Delivers Carrier-Class Linux</FONT></A><BR> +- <A HREF="http://www.linuxtelephony.org/article.cgi?i=205&r=0"><FONT COLOR="#000000">Quicknet is hiring programmers of all kinds!</FONT></A><BR> +- <A HREF="http://www.linuxtelephony.org/article.cgi?i=204&r=0"><FONT COLOR="#000000">Babylon MLPPP Software Released under GPL</FONT></A><BR> +- <A HREF="http://www.linuxtelephony.org/article.cgi?i=202&r=0"><FONT COLOR="#000000">Linux Telephony Server Project?</FONT></A><BR> +- <A HREF="http://www.linuxtelephony.org/article.cgi?i=203&r=0"><FONT COLOR="#000000">Vovida Networks to Hire Telephony Software Engineers</FONT></A><BR> +- <A HREF="http://www.linuxtelephony.org/article.cgi?i=200&r=0"><FONT COLOR="#000000">SPIRO-Linux Introduces Web-Enabled Phone Administration</FONT></A><BR> +- <A HREF="http://www.linuxtelephony.org/article.cgi?i=199&r=0"><FONT COLOR="#000000">LinuxTelephony sponsors area at LinuxFest 2000</FONT></A><BR> +- <A HREF="http://www.linuxtelephony.org/article.cgi?i=198&r=0"><FONT COLOR="#000000">GSM-Mobile Switching Center (MSC) with Linux-PC</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="0" BGCOLOR="#000000" WIDTH="97%"><TR><TD> +<TABLE WIDTH="100%" BORDER="0" CELLSPACING="1" CELLPADDING="3"> +<TR><TD ALIGN="center" BGCOLOR="#EEEEEE"><B><FONT FACE="Lucida,Verdana,Helvetica,Arial"><FONT COLOR="#000000"><a href="http://www.32bitsonline.com"><font color="#000000">32bitsonline</font></a></FONT></FONT></B></TD></TR><TR><TD BGCOLOR="#FFFFFF"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"> +- <A HREF="http://www.32bitsonline.com/article.php3?file=issues/200001/homeworld&page=1 +"><FONT COLOR="#000000">Game: Homeworld</FONT></A><BR> +- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001271a&page=1 +"><FONT COLOR="#000000">DVD Lawsuit Spreads Its Own 'Trade Secrets'</FONT></A><BR> +- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001272&page=1 +"><FONT COLOR="#000000">Register.com Adds 'One-step' Domain Registration</FONT></A><BR> +- <A HREF="http://www.32bitsonline.com/article.php3?file=issues/200001/webevent&page=1 +"><FONT COLOR="#000000">WebEvent: Keeping you organized</FONT></A><BR> +- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001273a&page=1 +"><FONT COLOR="#000000">Y2K Officers Defend $100 Bil Investment</FONT></A><BR> +- <A HREF="http://www.32bitsonline.com/article.php3?file=issues/200001/jan2000_john_berger&page=1 +"><FONT COLOR="#000000">DON'T BE FOOLED</FONT></A><BR> +- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001274&page=1 +"><FONT COLOR="#000000">Microsoft Scorns Think-Tank's Breakup Idea</FONT></A><BR> +- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001275a&page=1 +"><FONT COLOR="#000000">Yahoo Accused Of Stalking Internet Users</FONT></A><BR> +- <A HREF="http://www.32bitsonline.com/news.php3?news=news/200001/nb200001276a&page=1 +"><FONT COLOR="#000000">eToys.com Settles Spat With Swiss Artist Group</FONT></A><BR> +- <A HREF="http://www.32bitsonline.com/ +"><FONT COLOR="#000000">[more articles/news]</FONT></A><BR> + </FONT></SMALL></TD></TR></TABLE></TD></TR></TABLE><P> +<BR><BR></FONT> +</TD></TR></TABLE> +<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"> +<TR BGCOLOR="#000000"><TD><IMG SRC="image4" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE> +</CENTER> +<TABLE CELLSPACING="0" CELLPADDING="2" WIDTH="100%" BORDER="0"><TR> +<TD VALIGN="top" ALIGN="center"><FONT FACE="Lucida,Verdana,Helvetica,Arial"><SMALL>copyright © 1997-2000 <A HREF="http://andover.net">Andover.Net</A> - +icons courtesy of <A HREF="mailto:tigert@gimp.org">tigert@gimp.org</A> - +code revision <A HREF="http://freshmeat.net/ChangeLog">20000101</A> - +our <A HREF="http://www.andover.net/privacy.html">privacy policy</A></SMALL></FONT></TD> +</TR></TABLE> +</BODY> +</HTML> + + diff --git a/tkhtml1/tools/getpage.c b/tkhtml1/tools/getpage.c new file mode 100644 index 0000000..2b2bc56 --- /dev/null +++ b/tkhtml1/tools/getpage.c @@ -0,0 +1,171 @@ +/* +** This is a simple program used to retrieve an HTML document using +** HTTP. The program also fetches all images that the document +** references. +*/ +#include <stdio.h> +#include <stdlib.h> +#include "getpage.h" + +#define stricmp strcasecmp + + +/* +** Each image to be loaded is an instance of the following structure. +*/ +typedef struct Image Image; +struct Image { + char *zUrl; /* The URL for this image */ + char *zLocal; /* The local filename */ + Image *pNext; /* Next in a list of them all */ +}; + +static FILE *html; /* Html output to this file. */ +static int nImage = 0; /* Number of images loaded so far */ +static Image *pImage; /* List of all images */ +static global_nErr = 0; /* System wide errors */ +static char baseUrl[1000];/* The base URL */ +static int quiet = 0; /* The quiet flag */ + +/* +** Make sure the given URL is loaded as a local file. Return the +** name of the local file. +*/ +static char *GetImage(char *zUrl){ + Image *p; + for(p=pImage; p; p=p->pNext){ + if( strcmp(p->zUrl,zUrl)==0 ){ + return p->zLocal; + } + } + p = malloc( sizeof(*p) + strlen(zUrl) + 100 ); + p->zUrl = (char*)&p[1]; + strcpy(p->zUrl, zUrl); + p->zLocal = &p->zUrl[strlen(zUrl)+1]; + sprintf(p->zLocal,"image%d", ++nImage); + p->pNext = pImage; + pImage = p; + HttpFetch(zUrl, p->zLocal, quiet, 0, 0); + return p->zLocal; +} + +/* +** Print a usage comment and exit +*/ +void usage(char *argv0){ + fprintf(stderr,"Usage: %s URL\n",argv0); + exit(1); +} + +/* +** Handle anything that isn't markup +*/ +static void WordHandler(const char *zText, void *notUsed){ + fprintf(html, zText); +} + +/* +** Handle all markup that we don't care about. +*/ +static void DefaultMarkup(int argc, const char **argv, void *notUsed){ + int i; + fprintf(html,"<%s",argv[0]); + for(i=1; i<argc-1; i+=2){ + fprintf(html," %s=\"%s\"", argv[i], argv[i+1]); + } + fprintf(html,">"); +} + +/* +** Handler for <IMG> markup +*/ +static void ImageMarkup(int argc, const char **argv, void *notUsed){ + int i; + for(i=1; i<argc-1; i+=2){ + if( stricmp(argv[i],"src")==0 ){ + const char *azUrl[2]; + char *zResolved; + azUrl[0] = argv[i+1]; + azUrl[1] = 0; + zResolved = ResolveUrl(baseUrl, azUrl); + if( !quiet ){ + printf("Resolved: (%s) (%s) -> (%s)\n",baseUrl, azUrl[0], zResolved); + } + argv[i+1] = GetImage(zResolved); + /* printf("%s -> %s -> argv[i+1]\n",argv[i+1], zResolved); */ + free(zResolved); + } + } + DefaultMarkup(argc, argv, 0); +} + +/* +** Handler for <BASE> markup +*/ +static void BaseMarkup(int argc, const char **argv, void *notUsed){ + int i; + for(i=1; i<argc-1; i+=2){ + if( stricmp(argv[i],"href")==0 ){ + if( !quiet ){ + printf("Base Href=%s\n",argv[i+1]); + } + sprintf(baseUrl,"%.*s", sizeof(baseUrl), argv[i+1]); + } + } +} + +/* +** Name of a temporary file +*/ +static char zTemp[] = "index.html.orig"; + +/* +** The main routine +*/ +int main(int argc, char **argv){ + int i; /* Loop counter */ + int nErr; /* Number of errors */ + int rc; /* Result code */ + char *zUrl = 0; /* The URL */ + FILE *in; /* For reading the raw html */ + + if( argc<2 ) usage(argv[0]); + zUrl = 0; + for(i=1; i<argc; i++){ + if( strcmp(argv[i],"-quiet")==0 ){ + quiet = 1; + }else if( argv[i][0]=='-' ){ + usage(argv[0]); + }else{ + zUrl = argv[i]; + } + } + if( zUrl==0 ) usage(argv[0]); + rc = HttpFetch(zUrl, zTemp, quiet, sizeof(baseUrl), baseUrl); + if( rc!=200 ){ + unlink(zTemp); + fprintf(stderr,"Unable to fetch base page %s\n", zUrl); + exit(1); + } + in = fopen(zTemp,"r"); + /* unlink(zTemp); */ + if( in==0 ){ + perror("can't reopen temporary file!"); + exit(1); + } + html = fopen("index.html","w"); + if( html==0 ){ + perror("can't open output file \"index.html\""); + exit(1); + } + SgmlWordHandler(WordHandler); + SgmlSpaceHandler(WordHandler); + SgmlCommentHandler(WordHandler); + SgmlDefaultMarkupHandler(DefaultMarkup); + SgmlHandler("img", ImageMarkup); + SgmlHandler("base", BaseMarkup); + SgmlParse(in, 0); + fclose(in); + fclose(html); + return global_nErr; +} diff --git a/tkhtml1/tools/httpget.c b/tkhtml1/tools/httpget.c new file mode 100644 index 0000000..3532147 --- /dev/null +++ b/tkhtml1/tools/httpget.c @@ -0,0 +1,188 @@ +/* +** This file contains code to fetch a single URL into a local file. +*/ +#include <stdio.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <linux/in.h> +#include "httpget.h" + +#define strnicmp strncasecmp + +/* +** Get a URL using HTTP. Return the result code. If a Location: field +** appears in the header, write it into zLocation[]. Location[] should +** be at least 200 characters in size. +*/ +static int +HttpTryOnce(char *zUrl, char *zLocalFile, int quiet, char *zLocation){ + int i, j; + int nErr = 0; /* Number of errors */ + char *zPath; /* Pathname to send as second argument to GET */ + int iPort; /* TCP port for the server */ + struct hostent *pHost; /* Name information */ + int s; /* The main communications socket */ + int c; /* A character read from the remote side */ + int n; /* Number of characters in header */ + int rc = 200; /* The result code */ + FILE *sock; /* FILE corresponding to file descriptor s */ + FILE *out; /* Write output here */ + int last_was_nl; /* TRUE if last character received was '\n' */ + struct sockaddr_in addr; /* The address structure */ + int nByte = 0; + char zIpAddr[400]; /* The IP address of the server to print */ + char zMsg[1000]; /* Space to hold error messages */ + char zLine[1000]; /* A single line of the header */ + + out = fopen(zLocalFile, "w"); + if( out==0 ){ + sprintf(zMsg, "can't open output fule \"%.100s\"", zLocalFile); + perror(zMsg); + return 1; + } + + i = 0; + if( strnicmp(zUrl,"http:",5)==0 ){ i = 5; } + while( zUrl[i]=='/' ){ i++; } + j = 0; + while( zUrl[i] && zUrl[i]!=':' && zUrl[i]!='/' ){ + if( j<sizeof(zIpAddr)-1 ){ zIpAddr[j++] = zUrl[i]; } + i++; + } + zIpAddr[j] = 0; + if( zUrl[i]==':' ){ + iPort = 0; + i++; + while( isdigit(zUrl[i]) ){ + iPort = iPort*10 + zUrl[i] - '0'; + i++; + } + }else{ + iPort = 80; + } + zPath = &zUrl[i]; + + addr.sin_family = AF_INET; + addr.sin_port = htons(iPort); + *(int*)&addr.sin_addr = inet_addr(zIpAddr); + if( -1 == *(int*)&addr.sin_addr ){ + pHost = gethostbyname(zIpAddr); + if( pHost==0 ){ + fprintf(stderr,"can't resolve host name: %s\n",zIpAddr); + return 1; + } + memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length); + if( !quiet ){ + fprintf(stderr,"Address resolution: %s -> %d.%d.%d.%d\n",zIpAddr, + pHost->h_addr_list[0][0]&0xff, + pHost->h_addr_list[0][1]&0xff, + pHost->h_addr_list[0][2]&0xff, + pHost->h_addr_list[0][3]&0xff); + } + } + s = socket(AF_INET,SOCK_STREAM,0); + if( s<0 ){ + sprintf(zMsg,"can't open socket to %.100s", zIpAddr); + perror(zMsg); + fclose(out); + return 1; + } + if( connect(s,(struct sockaddr*)&addr,sizeof(addr))<0 ){ + sprintf(zMsg,"can't connect to host %.100s", zIpAddr); + perror(zMsg); + fclose(out); + return 1; + } + sock = fdopen(s,"r+"); + if( *zPath==0 ) zPath = "/"; + fprintf(sock,"GET %s HTTP/1.0\r\n",zPath); + fprintf(sock,"User-Agent: Mozilla/2.0 (X11; U; Linux 0.99p17 i486)\r\n"); + if( iPort!=80 ){ + fprintf(sock,"Host: %s:%d\r\n", zIpAddr, iPort); + }else{ + fprintf(sock,"Host: %s\r\n", zIpAddr); + } + fprintf(sock,"Accept: image/gif, image/x-xbitmap, image/jpeg, */*\r\n"); + fprintf(sock,"\r\n"); + fflush(sock); + n = 0; + rc = 0; + while( (c=getc(sock))!=EOF && (c!='\n' || !last_was_nl) ){ + if( c=='\r' ) continue; + last_was_nl = (c=='\n'); + if( last_was_nl ){ + zLine[n] = 0; + if( strncmp(zLine,"Location:",9)==0 && zLocation ){ + int j, k; + for(j=9; isspace(zLine[j]); j++){} + k = 0; + while( zLine[j] && !isspace(zLine[j]) && k<199 ){ + zLocation[k++] = zLine[j++]; + } + zLocation[k] = 0; + if( !quiet ) fprintf(stderr,"Location: %s\n", zLocation); + }else if( rc==0 ){ + sscanf(zLine,"HTTP/%*d.%*d %d ",&rc); + if( !quiet ) fprintf(stderr,"Status: %d\n", rc); + } + } + if( n<sizeof(zLine)-1 ){ zLine[n++] = c; } + if( last_was_nl ){ n = 0; } + } + if( rc==0 ) rc = 200; + if( !quiet ){ + fprintf(stderr, "Reading %s...", zUrl); + } + while( (c=getc(sock))!=EOF ){ + nByte++; + putc(c,out); + } + if( !quiet ){ + fprintf(stderr, " %d bytes\n", nByte); + } + fclose(sock); + fclose(out); + return rc; +} + +/* +** Get the file. Take up to 7 redirects. +*/ +int HttpFetch( + char *zUrl, /* Fetch this URL */ + char *zLocalFile, /* Write to this file */ + int quiet, /* Be quiet if true */ + int nActual, /* Size of zActual[] */ + char *zActual /* Write actual URL retrieved here */ +){ + int i; + int rc; + char *zOriginalUrl = zUrl; + char zLocation[300]; + + for(i=0; i<7; i++){ + if( !quiet ) fprintf(stderr,"HTTP: %s -> %s\n", zUrl, zLocalFile); + rc = HttpTryOnce(zUrl, zLocalFile, quiet, zLocation); + if( rc==301 || rc==302 ){ + char *z; + const char *az[2]; + az[0] = zLocation; + az[1] = 0; + z = ResolveUrl(zUrl, az); + if( zUrl!=zOriginalUrl ){ + free(zUrl); + } + zUrl = z; + }else{ + break; + } + } + if( nActual>0 && zActual!=0 ){ + sprintf(zActual, "%.*s", nActual, zUrl); + } + if( zUrl!=zOriginalUrl ){ + free(zUrl); + } + return rc; +} diff --git a/tkhtml1/tools/makeheaders.c b/tkhtml1/tools/makeheaders.c new file mode 100644 index 0000000..6d05935 --- /dev/null +++ b/tkhtml1/tools/makeheaders.c @@ -0,0 +1,3129 @@ +/* +** This program scans C and C++ source files and automatically generates +** appropriate header files. +** %Z% %P% %I% %G% %Z% +*/ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <memory.h> +#include <sys/stat.h> +#include <assert.h> +#ifndef WIN32 +# include <unistd.h> +#else +# include <string.h> +#endif + +/* +** Macros for debugging. +*/ +#ifdef DEBUG +static int debugMask = 0; +# define debug0(F,M) if( (F)&debugMask ){ fprintf(stderr,M); } +# define debug1(F,M,A) if( (F)&debugMask ){ fprintf(stderr,M,A); } +# define debug2(F,M,A,B) if( (F)&debugMask ){ fprintf(stderr,M,A,B); } +# define debug3(F,M,A,B,C) if( (F)&debugMask ){ fprintf(stderr,M,A,B,C); } +# define PARSER 0x00000001 +# define DECL_DUMP 0x00000002 +# define TOKENIZER 0x00000004 +#else +# define debug0(Flags, Format) +# define debug1(Flags, Format, A) +# define debug2(Flags, Format, A, B) +# define debug3(Flags, Format, A, B, C) +#endif + +/* +** The following macros are purely for the purpose of testing this +** program on itself. They don't really contribute to the code. +*/ +#define INTERFACE 1 +#define EXPORT_INTERFACE 1 +#define EXPORT + +/* +** Each token in a source file is represented by an instance of +** the following structure. Tokens are collected onto a list. +*/ +typedef struct Token Token; +struct Token { + const char *zText; /* The text of the token */ + int nText; /* Number of characters in the token's text */ + int eType; /* The type of this token */ + int nLine; /* The line number on which the token starts */ + Token *pComment; /* Most recent block comment before this token */ + Token *pNext; /* Next token on the list */ + Token *pPrev; /* Previous token on the list */ +}; + +/* +** During tokenization, information about the state of the input +** stream is held in an instance of the following structure +*/ +typedef struct InStream InStream; +struct InStream { + const char *z; /* Complete text of the input */ + int i; /* Next character to read from the input */ + int nLine; /* The line number for character z[i] */ +}; + +/* +** Each declaration in the C or C++ source files is parsed out and stored as +** an instance of the following structure. +** +** A "forward declaration" is a declaration that an object exists that +** doesn't tell about the objects structure. A typical forward declaration +** is: +** +** struct Xyzzy; +** +** Not every object has a forward declaration. If it does, thought, the +** forward declaration will be contained in the zFwd field for C and +** the zFwdCpp for C++. The zDecl field contains the complete +** declaration text. +*/ +typedef struct Decl Decl; +struct Decl { + char *zName; /* Name of the object being declared. The appearance + ** of this name is a source file triggers the declaration + ** to be added to the header for that file. */ + char *zFile; /* File from which extracted. */ + char *zIf; /* Surround the declaration with this #if */ + char *zFwd; /* A forward declaration. NULL if there is none. */ + char *zFwdCpp; /* Use this forward declaration for C++. */ + char *zDecl; /* A full declaration of this object */ + struct Include *pInclude; /* #includes that come before this declaration */ + int flags; /* See the "Properties" below */ + Token *pComment; /* A block comment associated with this declaration */ + Token tokenCode; /* Implementation of functions and procedures */ + Decl *pSameName; /* Next declaration with the same "zName" */ + Decl *pSameHash; /* Next declaration with same hash but different zName */ + Decl *pNext; /* Next declaration with a different name */ +}; + +/* +** Properties associated with declarations. +** +** DP_Forward and DP_Declared are used during the generation of a single +** header file in order to prevent duplicate declarations and definitions. +** DP_Forward is set after the object has been given a forward declaration +** and DP_Declared is set after the object gets a full declarations. +** (Example: A forward declaration is "typedef struct Abc Abc;" and the +** full declaration is "struct Abc { int a; float b; };".) +** +** The DP_Export and DP_Local flags are more permanent. They mark objects +** that have EXPORT scope and LOCAL scope respectively. If both of these +** marks are missing, then the object has library scope. The meanings of +** the scopes are as follows: +** +** LOCAL scope The object is only usable within the file in +** which it is declared. +** +** library scope The object is visible and usable within other +** files in the same project. By if the project is +** a library, then the object is not visible to users +** of the library. (i.e. the object does not appear +** in the output when using the -H option.) +** +** EXPORT scope The object is visible and usable everywhere. +** +** The DP_Flag is a temporary use flag that is used during processing to +** prevent an infinite loop. It's use is localized. +** +** The DP_Cplusplus, DP_ExternCReqd and DP_ExternReqd flags are permanent +** and are used to specify what type of declaration the object requires. +*/ +#define DP_Forward 0x001 /* Has a forward declaration in this file */ +#define DP_Declared 0x002 /* Has a full declaration in this file */ +#define DP_Export 0x004 /* Export this declaration */ +#define DP_Local 0x008 /* Declare in its home file only */ +#define DP_Flag 0x010 /* Use to mark a subset of a Decl list + ** for special processing */ +#define DP_Cplusplus 0x020 /* Has C++ linkage and cannot appear in a + ** C header file */ +#define DP_ExternCReqd 0x040 /* Prepend 'extern "C"' in a C++ header. + ** Prepend nothing in a C header */ +#define DP_ExternReqd 0x080 /* Prepend 'extern "C"' in a C++ header if + ** DP_Cplusplus is not also set. If DP_Cplusplus + ** is set or this is a C header then + ** prepend 'extern' */ + +/* +** Convenience macros for dealing with declaration properties +*/ +#define DeclHasProperty(D,P) (((D)->flags&(P))==(P)) +#define DeclHasAnyProperty(D,P) (((D)->flags&(P))!=0) +#define DeclSetProperty(D,P) (D)->flags |= (P) +#define DeclClearProperty(D,P) (D)->flags &= ~(P) + +/* +** These are state properties of the parser. Each of the values is +** distinct from the DP_ values above so that both can be used in +** the same "flags" field. +** +** Be careful not to confuse PS_Export with DP_Export or +** PS_Local with DP_Local. Their names are similar, but the meanings +** of these flags are very different. +*/ +#define PS_Extern 0x000800 /* "extern" has been seen */ +#define PS_Export 0x001000 /* If between "#if EXPORT_INTERFACE" + ** and "#endif" */ +#define PS_Export2 0x002000 /* If "EXPORT" seen */ +#define PS_Typedef 0x004000 /* If "typedef" has been seen */ +#define PS_Static 0x008000 /* If "static" has been seen */ +#define PS_Interface 0x010000 /* If within #if INTERFACE..#endif */ +#define PS_Method 0x020000 /* If "::" token has been seen */ +#define PS_Local 0x040000 /* If within #if LOCAL_INTERFACE..#endif */ +#define PS_Local2 0x080000 /* If "LOCAL" seen. */ + +/* +** The following set of flags are ORed into the "flags" field of +** a Decl in order to identify what type of object is being +** declared. +*/ +#define TY_Class 0x00100000 +#define TY_Subroutine 0x00200000 +#define TY_Macro 0x00400000 +#define TY_Typedef 0x00800000 +#define TY_Variable 0x01000000 +#define TY_Structure 0x02000000 +#define TY_Union 0x04000000 +#define TY_Enumeration 0x08000000 +#define TY_Defunct 0x10000000 /* Used to erase a declaration */ + +/* +** Each nested #if (or #ifdef or #ifndef) is stored in a stack of +** instances of the following structure. +*/ +typedef struct Ifmacro Ifmacro; +struct Ifmacro { + int nLine; /* Line number where this macro occurs */ + char *zCondition; /* Text of the condition for this macro */ + Ifmacro *pNext; /* Next down in the stack */ + int flags; /* Can hold PS_Export, PS_Interface or PS_Local flags */ +}; + +/* +** When parsing a file, we need to keep track of what other files have +** be #include-ed. For each #include found, we create an instance of +** the following structure. +*/ +typedef struct Include Include; +struct Include { + char *zFile; /* The name of file include. Includes "" or <> */ + char *zIf; /* If not NULL, #include should be enclosed in #if */ + char *zLabel; /* A unique label used to test if this #include has + * appeared already in a file or not */ + Include *pNext; /* Previous include file, or NULL if this is the first */ +}; + +/* +** Identifiers found in a source file that might be used later to provoke +** the copying of a declaration into the corresponding header file are +** stored in a hash table as instances of the following structure. +*/ +typedef struct Ident Ident; +struct Ident { + char *zName; /* The text of this identifier */ + Ident *pCollide; /* Next identifier with the same hash */ + Ident *pNext; /* Next identifier in a list of them all */ +}; + +/* +** A complete table of identifiers is stored in an instance of +** the next structure. +*/ +#define IDENT_HASH_SIZE 2237 +typedef struct IdentTable IdentTable; +struct IdentTable { + Ident *pList; /* List of all identifiers in this table */ + Ident *apTable[IDENT_HASH_SIZE]; /* The hash table */ +}; + +/* +** The following structure holds all information for a single +** source file named on the command line of this program. +*/ +typedef struct InFile InFile; +struct InFile { + char *zSrc; /* Name of input file */ + char *zHdr; /* Name of the generated .h file for this input. + ** Will be NULL if input is to be scanned only */ + int flags; /* One or more DP_, PS_ and/or TY_ flags */ + InFile *pNext; /* Next input file in the list of them all */ + IdentTable idTable; /* All identifiers in this input file */ +}; + +/* +** An unbounded string is able to grow without limit. We use these +** to construct large in-memory strings from lots of smaller components. +*/ +typedef struct String String; +struct String { + int nAlloc; /* Number of bytes allocated */ + int nUsed; /* Number of bytes used (not counting null terminator) */ + char *zText; /* Text of the string */ +}; + +/* +** The following structure contains a lot of state information used +** while generating a .h file. We put the information in this structure +** and pass around a pointer to this structure, rather than pass around +** all of the information separately. This helps reduce the number of +** arguments to generator functions. +*/ +typedef struct GenState GenState; +struct GenState { + String *pStr; /* Write output to this string */ + IdentTable *pTable; /* A table holding the zLabel of every #include that + * has already been generated. Used to avoid + * generating duplicate #includes. */ + const char *zIf; /* If not NULL, then we are within a #if with + * this argument. */ + int nErr; /* Number of errors */ + const char *zFilename; /* Name of the source file being scanned */ + int flags; /* Various flags (DP_ and PS_ flags above) */ +}; + +/* +** The following text line appears at the top of every file generated +** by this program. By recognizing this line, the program can be sure +** never to read a file that it generated itself. +*/ +const char zTopLine[] = + "/* \aThis file was automatically generated. Do not edit! */\n"; +#define nTopLine (sizeof(zTopLine)-1) + +/* +** The name of the file currently being parsed. +*/ +static char *zFilename; + +/* +** The stack of #if macros for the file currently being parsed. +*/ +static Ifmacro *ifStack = 0; + +/* +** A list of all files that have been #included so far in a file being +** parsed. +*/ +static Include *includeList = 0; + +/* +** The last block comment seen. +*/ +static Token *blockComment = 0; + +/* +** The following flag is set if the -doc flag appears on the +** command line. +*/ +static int doc_flag = 0; + +/* +** If the following flag is set, then makeheaders will attempt to +** generate prototypes for static functions and procedures. +*/ +static int proto_static = 0; + +/* +** A list of all declarations. The list is held together using the +** pNext field of the Decl structure. +*/ +static Decl *pDeclFirst; /* First on the list */ +static Decl *pDeclLast; /* Last on the list */ + +/* +** A hash table of all declarations +*/ +#define DECL_HASH_SIZE 3371 +static Decl *apTable[DECL_HASH_SIZE]; + +/* +** The TEST macro must be defined to something. Make sure this is the +** case. +*/ +#ifndef TEST +# define TEST 0 +#endif + +#ifdef NOT_USED +/* +** We do our own assertion macro so that we can have more control +** over debugging. +*/ +#define Assert(X) if(!(X)){ CantHappen(__LINE__); } +#define CANT_HAPPEN CantHappen(__LINE__) +static void CantHappen(int iLine){ + fprintf(stderr,"Assertion failed on line %d\n",iLine); + *(char*)1 = 0; /* Force a core-dump */ +} +#endif + +/* +** Memory allocation functions that are guaranteed never to return NULL. +*/ +static void *SafeMalloc(int nByte){ + void *p = malloc( nByte ); + if( p==0 ){ + fprintf(stderr,"Out of memory. Can't allocate %d bytes.\n",nByte); + exit(1); + } + return p; +} +static void SafeFree(void *pOld){ + if( pOld ){ + free(pOld); + } +} +static void *SafeRealloc(void *pOld, int nByte){ + void *p; + if( pOld==0 ){ + p = SafeMalloc(nByte); + }else{ + p = realloc(pOld, nByte); + if( p==0 ){ + fprintf(stderr, + "Out of memory. Can't enlarge an allocation to %d bytes\n",nByte); + exit(1); + } + } + return p; +} +static char *StrDup(const char *zSrc, int nByte){ + char *zDest; + if( nByte<=0 ){ + nByte = strlen(zSrc); + } + zDest = SafeMalloc( nByte + 1 ); + strncpy(zDest,zSrc,nByte); + zDest[nByte] = 0; + return zDest; +} + +/* +** Return TRUE if the character X can be part of an identifier +*/ +#define ISALNUM(X) ((X)=='_' || isalnum(X)) + +/* +** Routines for dealing with unbounded strings. +*/ +static void StringInit(String *pStr){ + pStr->nAlloc = 0; + pStr->nUsed = 0; + pStr->zText = 0; +} +static void StringReset(String *pStr){ + SafeFree(pStr->zText); + StringInit(pStr); +} +static void StringAppend(String *pStr, const char *zText, int nByte){ + if( nByte<=0 ){ + nByte = strlen(zText); + } + if( pStr->nUsed + nByte >= pStr->nAlloc ){ + if( pStr->nAlloc==0 ){ + pStr->nAlloc = nByte + 100; + pStr->zText = SafeMalloc( pStr->nAlloc ); + }else{ + pStr->nAlloc = pStr->nAlloc*2 + nByte; + pStr->zText = SafeRealloc(pStr->zText, pStr->nAlloc); + } + } + strncpy(&pStr->zText[pStr->nUsed],zText,nByte); + pStr->nUsed += nByte; + pStr->zText[pStr->nUsed] = 0; +} +#define StringGet(S) ((S)->zText?(S)->zText:"") + +/* +** Compute a hash on a string. The number returned is a non-negative +** value between 0 and 2**31 - 1 +*/ +static int Hash(const char *z, int n){ + int h = 0; + if( n<=0 ){ + n = strlen(z); + } + while( n-- ){ + h = h ^ (h<<5) ^ *z++; + } + if( h<0 ) h = -h; + return h; +} + +/* +** Given an identifier name, try to find a declaration for that +** identifier in the hash table. If found, return a pointer to +** the Decl structure. If not found, return 0. +*/ +static Decl *FindDecl(const char *zName, int len){ + int h; + Decl *p; + + if( len<=0 ){ + len = strlen(zName); + } + h = Hash(zName,len) % DECL_HASH_SIZE; + p = apTable[h]; + while( p && (strncmp(p->zName,zName,len)!=0 || p->zName[len]!=0) ){ + p = p->pSameHash; + } + return p; +} + +/* +** Install the given declaration both in the hash table and on +** the list of all declarations. +*/ +static void InstallDecl(Decl *pDecl){ + int h; + Decl *pOther; + + h = Hash(pDecl->zName,0) % DECL_HASH_SIZE; + pOther = apTable[h]; + while( pOther && strcmp(pDecl->zName,pOther->zName)!=0 ){ + pOther = pOther->pSameHash; + } + if( pOther ){ + pDecl->pSameName = pOther->pSameName; + pOther->pSameName = pDecl; + }else{ + pDecl->pSameName = 0; + pDecl->pSameHash = apTable[h]; + apTable[h] = pDecl; + } + pDecl->pNext = 0; + if( pDeclFirst==0 ){ + pDeclFirst = pDeclLast = pDecl; + }else{ + pDeclLast->pNext = pDecl; + pDeclLast = pDecl; + } +} + +/* +** Look at the current ifStack. If anything declared at the current +** position must be surrounded with +** +** #if STUFF +** #endif +** +** Then this routine computes STUFF and returns a pointer to it. Memory +** to hold the value returned is obtained from malloc(). +*/ +static char *GetIfString(void){ + Ifmacro *pIf; + char *zResult = 0; + int hasIf = 0; + String str; + + for(pIf = ifStack; pIf; pIf=pIf->pNext){ + if( pIf->zCondition==0 || *pIf->zCondition==0 ) continue; + if( !hasIf ){ + hasIf = 1; + StringInit(&str); + }else{ + StringAppend(&str," && ",4); + } + StringAppend(&str,pIf->zCondition,0); + } + if( hasIf ){ + zResult = StrDup(StringGet(&str),0); + StringReset(&str); + }else{ + zResult = 0; + } + return zResult; +} + +/* +** Create a new declaration and put it in the hash table. Also +** return a pointer to it so that we can fill in the zFwd and zDecl +** fields, and so forth. +*/ +static Decl *CreateDecl( + const char *zName, /* Name of the object being declared. */ + int nName /* Length of the name */ +){ + Decl *pDecl; + + pDecl = SafeMalloc( sizeof(Decl) + nName + 1); + memset(pDecl,0,sizeof(Decl)); + pDecl->zName = (char*)&pDecl[1]; + sprintf(pDecl->zName,"%.*s",nName,zName); + pDecl->zFile = zFilename; + pDecl->pInclude = includeList; + pDecl->zIf = GetIfString(); + InstallDecl(pDecl); + return pDecl; +} + +/* +** Insert a new identifier into an table of identifiers. Return TRUE if +** a new identifier was inserted and return FALSE if the identifier was +** already in the table. +*/ +static int IdentTableInsert( + IdentTable *pTable, /* The table into which we will insert */ + const char *zId, /* Name of the identifiers */ + int nId /* Length of the identifier name */ +){ + int h; + Ident *pId; + + if( nId<=0 ){ + nId = strlen(zId); + } + h = Hash(zId,nId) % IDENT_HASH_SIZE; + for(pId = pTable->apTable[h]; pId; pId=pId->pCollide){ + if( strncmp(zId,pId->zName,nId)==0 && pId->zName[nId]==0 ){ + /* printf("Already in table: %.*s\n",nId,zId); */ + return 0; + } + } + pId = SafeMalloc( sizeof(Ident) + nId + 1 ); + pId->zName = (char*)&pId[1]; + sprintf(pId->zName,"%.*s",nId,zId); + pId->pNext = pTable->pList; + pTable->pList = pId; + pId->pCollide = pTable->apTable[h]; + pTable->apTable[h] = pId; + /* printf("Add to table: %.*s\n",nId,zId); */ + return 1; +} + +/* +** Check to see if the given value is in the given IdentTable. Return +** true if it is and false if it is not. +*/ +static int IdentTableTest( + IdentTable *pTable, /* The table in which to search */ + const char *zId, /* Name of the identifiers */ + int nId /* Length of the identifier name */ +){ + int h; + Ident *pId; + + if( nId<=0 ){ + nId = strlen(zId); + } + h = Hash(zId,nId) % IDENT_HASH_SIZE; + for(pId = pTable->apTable[h]; pId; pId=pId->pCollide){ + if( strncmp(zId,pId->zName,nId)==0 && pId->zName[nId]==0 ){ + return 1; + } + } + return 0; +} + +/* +** Remove every identifier from the given table. Reset the table to +** its initial state. +*/ +static void IdentTableReset(IdentTable *pTable){ + Ident *pId, *pNext; + + for(pId = pTable->pList; pId; pId = pNext){ + pNext = pId->pNext; + SafeFree(pId); + } + memset(pTable,0,sizeof(IdentTable)); +} + +#ifdef DEBUG +/* +** Print the name of every identifier in the given table, one per line +*/ +static void IdentTablePrint(IdentTable *pTable, FILE *pOut){ + Ident *pId; + + for(pId = pTable->pList; pId; pId = pId->pNext){ + fprintf(pOut,"%s\n",pId->zName); + } +} +#endif + +/* +** Read an entire file into memory. Return a pointer to the memory. +** +** The memory is obtained from SafeMalloc and must be freed by the +** calling function. +** +** If the read fails for any reason, 0 is returned. +*/ +static char *ReadFile(const char *zFilename){ + struct stat sStat; + FILE *pIn; + char *zBuf; + int n; + + if( stat(zFilename,&sStat)!=0 +#ifndef WIN32 + || !S_ISREG(sStat.st_mode) +#endif + ){ + return 0; + } + pIn = fopen(zFilename,"r"); + if( pIn==0 ){ + return 0; + } + zBuf = SafeMalloc( sStat.st_size + 1 ); + n = fread(zBuf,1,sStat.st_size,pIn); + zBuf[n] = 0; + fclose(pIn); + return zBuf; +} + +/* +** Write the contents of a string into a file. Return the number of +** errors +*/ +static int WriteFile(const char *zFilename, const char *zOutput){ + FILE *pOut; + pOut = fopen(zFilename,"w"); + if( pOut==0 ){ + return 1; + } + fwrite(zOutput,1,strlen(zOutput),pOut); + fclose(pOut); + return 0; +} + +/* +** Major token types +*/ +#define TT_Space 1 /* Contiguous white space */ +#define TT_Id 2 /* An identifier */ +#define TT_Preprocessor 3 /* Any C preprocessor directive */ +#define TT_Comment 4 /* Either C or C++ style comment */ +#define TT_Number 5 /* Any numeric constant */ +#define TT_String 6 /* String or character constants. ".." or '.' */ +#define TT_Braces 7 /* All text between { and a matching } */ +#define TT_EOF 8 /* End of file */ +#define TT_Error 9 /* An error condition */ +#define TT_BlockComment 10 /* A C-Style comment at the left margin that + * spans multple lines */ +#define TT_Other 0 /* None of the above */ + +/* +** Get a single low-level token from the input file. Update the +** file pointer so that it points to the first character beyond the +** token. +** +** A "low-level token" is any token except TT_Braces. A TT_Braces token +** consists of many smaller tokens and is assembled by a routine that +** calls this one. +** +** The function returns the number of errors. An error is an +** unterminated string or character literal or an unterminated +** comment. +** +** Profiling shows that this routine consumes about half the +** CPU time on a typical run of makeheaders. +*/ +static int GetToken(InStream *pIn, Token *pToken){ + int i; + const char *z; + int cStart; + int c; + int startLine; /* Line on which a structure begins */ + int nlisc = 0; /* True if there is a new-line in a ".." or '..' */ + int nErr = 0; /* Number of errors seen */ + + z = pIn->z; + i = pIn->i; + pToken->nLine = pIn->nLine; + pToken->zText = &z[i]; + switch( z[i] ){ + case 0: + pToken->eType = TT_EOF; + pToken->nText = 0; + break; + + case '#': + if( i==0 || z[i-1]=='\n' || (i>1 && z[i-1]=='\r' && z[i-2]=='\n')){ + /* We found a preprocessor statement */ + pToken->eType = TT_Preprocessor; + i++; + while( z[i]!=0 && z[i]!='\n' ){ + if( z[i]=='\\' ){ + i++; + if( z[i]=='\n' ) pIn->nLine++; + } + i++; + } + pToken->nText = i - pIn->i; + }else{ + /* Just an operator */ + pToken->eType = TT_Other; + pToken->nText = 1; + } + break; + + case ' ': + case '\t': + case '\r': + case '\f': + case '\n': + while( isspace(z[i]) ){ + if( z[i]=='\n' ) pIn->nLine++; + i++; + } + pToken->eType = TT_Space; + pToken->nText = i - pIn->i; + break; + + case '\\': + pToken->nText = 2; + pToken->eType = TT_Other; + if( z[i+1]=='\n' ){ + pIn->nLine++; + pToken->eType = TT_Space; + }else if( z[i+1]==0 ){ + pToken->nText = 1; + } + break; + + case '\'': + case '\"': + cStart = z[i]; + startLine = pIn->nLine; + do{ + i++; + c = z[i]; + if( c=='\n' ){ + if( !nlisc ){ + fprintf(stderr, + "%s:%d: (warning) Newline in string or character literal.\n", + zFilename, pIn->nLine); + nlisc = 1; + } + pIn->nLine++; + } + if( c=='\\' ){ + i++; + c = z[i]; + if( c=='\n' ){ + pIn->nLine++; + } + }else if( c==cStart ){ + i++; + c = 0; + }else if( c==0 ){ + fprintf(stderr, "%s:%d: Unterminated string or character literal.\n", + zFilename, startLine); + nErr++; + } + }while( c ); + pToken->eType = TT_String; + pToken->nText = i - pIn->i; + break; + + case '/': + if( z[i+1]=='/' ){ + /* C++ style comment */ + while( z[i] && z[i]!='\n' ){ i++; } + pToken->eType = TT_Comment; + pToken->nText = i - pIn->i; + }else if( z[i+1]=='*' ){ + /* C style comment */ + int isBlockComment = i==0 || z[i-1]=='\n'; + i += 2; + startLine = pIn->nLine; + while( z[i] && (z[i]!='*' || z[i+1]!='/') ){ + if( z[i]=='\n' ){ + pIn->nLine++; + if( isBlockComment ){ + if( z[i+1]=='*' || z[i+2]=='*' ){ + isBlockComment = 2; + }else{ + isBlockComment = 0; + } + } + } + i++; + } + if( z[i] ){ + i += 2; + }else{ + isBlockComment = 0; + fprintf(stderr,"%s:%d: Unterminated comment\n", + zFilename, startLine); + nErr++; + } + pToken->eType = isBlockComment==2 ? TT_BlockComment : TT_Comment; + pToken->nText = i - pIn->i; + }else{ + /* A divide operator */ + pToken->eType = TT_Other; + pToken->nText = 1; + } + break; + + case '0': + if( z[i+1]=='x' || z[i+1]=='X' ){ + /* A hex constant */ + i += 2; + while( isxdigit(z[i]) ){ i++; } + }else{ + /* An octal constant */ + while( isdigit(z[i]) ){ i++; } + } + pToken->eType = TT_Number; + pToken->nText = i - pIn->i; + break; + + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + while( isdigit(z[i]) ){ i++; } + if( (c=z[i])=='.' ){ + i++; + while( isdigit(z[i]) ){ i++; } + c = z[i]; + if( c=='e' || c=='E' ){ + i++; + if( ((c=z[i])=='+' || c=='-') && isdigit(z[i+1]) ){ i++; } + while( isdigit(z[i]) ){ i++; } + c = z[i]; + } + if( c=='f' || c=='F' || c=='l' || c=='L' ){ i++; } + }else if( c=='e' || c=='E' ){ + i++; + if( ((c=z[i])=='+' || c=='-') && isdigit(z[i+1]) ){ i++; } + while( isdigit(z[i]) ){ i++; } + }else if( c=='L' || c=='l' ){ + i++; + c = z[i]; + if( c=='u' || c=='U' ){ i++; } + }else if( c=='u' || c=='U' ){ + i++; + c = z[i]; + if( c=='l' || c=='L' ){ i++; } + } + pToken->eType = TT_Number; + pToken->nText = i - pIn->i; + break; + + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': + case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': + case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': + case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': + case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': + case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': + case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': + case 'X': case 'Y': case 'Z': case '_': + while( isalnum(z[i]) || z[i]=='_' ){ i++; }; + pToken->eType = TT_Id; + pToken->nText = i - pIn->i; + break; + + default: + pToken->eType = TT_Other; + pToken->nText = 1; + break; + } + pIn->i += pToken->nText; + return nErr; +} + +/* +** This routine recovers the next token from the input file which is +** not a space or a comment or any text between an "#if 0" and "#endif". +** +** This routine returns the number of errors encountered. An error +** is an unterminated token or unmatched "#if 0". +** +** Profiling shows that this routine uses about a quarter of the +** CPU time in a typical run. +*/ +static int GetNonspaceToken(InStream *pIn, Token *pToken){ + int nIf = 0; + int inZero = 0; + const char *z; + int value; + int startLine; + int nErr = 0; + + startLine = pIn->nLine; + while( 1 ){ + nErr += GetToken(pIn,pToken); + /* printf("%04d: Type=%d nIf=%d [%.*s]\n", + pToken->nLine,pToken->eType,nIf,pToken->nText, + pToken->eType!=TT_Space ? pToken->zText : "<space>"); */ + pToken->pComment = blockComment; + switch( pToken->eType ){ + case TT_Comment: + case TT_Space: + break; + + case TT_BlockComment: + if( doc_flag ){ + blockComment = SafeMalloc( sizeof(Token) ); + *blockComment = *pToken; + } + break; + + case TT_EOF: + if( nIf ){ + fprintf(stderr,"%s:%d: Unterminated \"#if\"\n", + zFilename, startLine); + nErr++; + } + return nErr; + + case TT_Preprocessor: + z = &pToken->zText[1]; + while( *z==' ' || *z=='\t' ) z++; + if( sscanf(z,"if %d",&value)==1 && value==0 ){ + nIf++; + inZero = 1; + }else if( inZero ){ + if( strncmp(z,"if",2)==0 ){ + nIf++; + }else if( strncmp(z,"endif",5)==0 ){ + nIf--; + if( nIf==0 ) inZero = 0; + } + }else{ + return nErr; + } + break; + + default: + if( !inZero ){ + return nErr; + } + break; + } + } + /* NOT REACHED */ +} + +/* +** This routine looks for identifiers (strings of contiguous alphanumeric +** characters) within a preprocessor directive and adds every such string +** found to the given identifier table +*/ +static void FindIdentifiersInMacro(Token *pToken, IdentTable *pTable){ + Token sToken; + InStream sIn; + int go = 1; + + sIn.z = pToken->zText; + sIn.i = 1; + sIn.nLine = 1; + while( go && sIn.i < pToken->nText ){ + GetToken(&sIn,&sToken); + switch( sToken.eType ){ + case TT_Id: + IdentTableInsert(pTable,sToken.zText,sToken.nText); + break; + + case TT_EOF: + go = 0; + break; + + default: + break; + } + } +} + +/* +** This routine gets the next token. Everything contained within +** {...} is collapsed into a single TT_Braces token. Whitespace is +** omitted. +** +** If pTable is not NULL, then insert every identifier seen into the +** IdentTable. This includes any identifiers seen inside of {...}. +** +** The number of errors encountered is returned. An error is an +** unterminated token. +*/ +static int GetBigToken(InStream *pIn, Token *pToken, IdentTable *pTable){ + const char *z, *zStart; + int iStart; + int nBrace; + int c; + int nLine; + int nErr; + + nErr = GetNonspaceToken(pIn,pToken); + switch( pToken->eType ){ + case TT_Id: + if( pTable!=0 ){ + IdentTableInsert(pTable,pToken->zText,pToken->nText); + } + return nErr; + + case TT_Preprocessor: + if( pTable!=0 ){ + FindIdentifiersInMacro(pToken,pTable); + } + return nErr; + + case TT_Other: + if( pToken->zText[0]=='{' ) break; + return nErr; + + default: + return nErr; + } + + z = pIn->z; + iStart = pIn->i; + zStart = pToken->zText; + nLine = pToken->nLine; + nBrace = 1; + while( nBrace ){ + nErr += GetNonspaceToken(pIn,pToken); + /* printf("%04d: nBrace=%d [%.*s]\n",pToken->nLine,nBrace, + pToken->nText,pToken->zText); */ + switch( pToken->eType ){ + case TT_EOF: + fprintf(stderr,"%s:%d: Unterminated \"{\"\n", + zFilename, nLine); + nErr++; + pToken->eType = TT_Error; + return nErr; + + case TT_Id: + if( pTable ){ + IdentTableInsert(pTable,pToken->zText,pToken->nText); + } + break; + + case TT_Preprocessor: + if( pTable!=0 ){ + FindIdentifiersInMacro(pToken,pTable); + } + break; + + case TT_Other: + if( (c = pToken->zText[0])=='{' ){ + nBrace++; + }else if( c=='}' ){ + nBrace--; + } + break; + + default: + break; + } + } + pToken->eType = TT_Braces; + pToken->nText = 1 + pIn->i - iStart; + pToken->zText = zStart; + pToken->nLine = nLine; + return nErr; +} + +/* +** This routine frees up a list of Tokens. The pComment tokens are +** not cleared by this. So we leak a little memory when using the -doc +** option. So what. +*/ +static void FreeTokenList(Token *pList){ + Token *pNext; + while( pList ){ + pNext = pList->pNext; + SafeFree(pList); + pList = pNext; + } +} + +/* +** Tokenize an entire file. Return a pointer to the list of tokens. +** +** Space for each token is obtained from a separate malloc() call. The +** calling function is responsible for freeing this space. +** +** If pTable is not NULL, then fill the table with all identifiers seen in +** the input file. +*/ +static Token *TokenizeFile(const char *zFile, IdentTable *pTable){ + InStream sIn; + Token *pFirst = 0, *pLast = 0, *pNew; + int nErr = 0; + + sIn.z = zFile; + sIn.i = 0; + sIn.nLine = 1; + blockComment = 0; + + while( sIn.z[sIn.i]!=0 ){ + pNew = SafeMalloc( sizeof(Token) ); + nErr += GetBigToken(&sIn,pNew,pTable); + debug3(TOKENIZER, "Token on line %d: [%.*s]\n", + pNew->nLine, pNew->nText<50 ? pNew->nText : 50, pNew->zText); + if( pFirst==0 ){ + pFirst = pLast = pNew; + pNew->pPrev = 0; + }else{ + pLast->pNext = pNew; + pNew->pPrev = pLast; + pLast = pNew; + } + if( pNew->eType==TT_EOF ) break; + } + if( pLast ) pLast->pNext = 0; + blockComment = 0; + if( nErr ){ + FreeTokenList(pFirst); + pFirst = 0; + } + + return pFirst; +} + +#if TEST==1 +/* +** Use the following routine to test or debug the tokenizer. +*/ +void main(int argc, char **argv){ + char *zFile; + Token *pList, *p; + IdentTable sTable; + + if( argc!=2 ){ + fprintf(stderr,"Usage: %s filename\n",*argv); + exit(1); + } + memset(&sTable,0,sizeof(sTable)); + zFile = ReadFile(argv[1]); + if( zFile==0 ){ + fprintf(stderr,"Can't read file \"%s\"\n",argv[1]); + exit(1); + } + pList = TokenizeFile(zFile,&sTable); + for(p=pList; p; p=p->pNext){ + int j; + switch( p->eType ){ + case TT_Space: + printf("%4d: Space\n",p->nLine); + break; + case TT_Id: + printf("%4d: Id %.*s\n",p->nLine,p->nText,p->zText); + break; + case TT_Preprocessor: + printf("%4d: Preprocessor %.*s\n",p->nLine,p->nText,p->zText); + break; + case TT_Comment: + printf("%4d: Comment\n",p->nLine); + break; + case TT_BlockComment: + printf("%4d: Block Comment\n",p->nLine); + break; + case TT_Number: + printf("%4d: Number %.*s\n",p->nLine,p->nText,p->zText); + break; + case TT_String: + printf("%4d: String %.*s\n",p->nLine,p->nText,p->zText); + break; + case TT_Other: + printf("%4d: Other %.*s\n",p->nLine,p->nText,p->zText); + break; + case TT_Braces: + for(j=0; j<p->nText && j<30 && p->zText[j]!='\n'; j++){} + printf("%4d: Braces %.*s...}\n",p->nLine,j,p->zText); + break; + case TT_EOF: + printf("%4d: End of file\n",p->nLine); + break; + default: + printf("%4d: type %d\n",p->nLine,p->eType); + break; + } + } + FreeTokenList(pList); + SafeFree(zFile); + IdentTablePrint(&sTable,stdout); +} +#endif + +#ifdef DEBUG +/* +** For debugging purposes, write out a list of tokens. +*/ +static void PrintTokens(Token *pFirst, Token *pLast){ + int needSpace = 0; + int c; + + pLast = pLast->pNext; + while( pFirst!=pLast ){ + switch( pFirst->eType ){ + case TT_Preprocessor: + printf("\n%.*s\n",pFirst->nText,pFirst->zText); + needSpace = 0; + break; + + case TT_Id: + case TT_Number: + printf("%s%.*s", needSpace ? " " : "", pFirst->nText, pFirst->zText); + needSpace = 1; + break; + + default: + c = pFirst->zText[0]; + printf("%s%.*s", + (needSpace && (c=='*' || c=='{')) ? " " : "", + pFirst->nText, pFirst->zText); + needSpace = pFirst->zText[0]==','; + break; + } + pFirst = pFirst->pNext; + } +} +#endif + +/* +** Convert a sequence of tokens into a string and return a pointer +** to that string. Space to hold the string is obtained from malloc() +** and must be freed by the calling function. +** +** The characters ";\n" are always appended. +*/ +static char *TokensToString(Token *pFirst, Token *pLast){ + char *zReturn; + String str; + int needSpace = 0; + int c; + + StringInit(&str); + pLast = pLast->pNext; + while( pFirst!=pLast ){ + switch( pFirst->eType ){ + case TT_Preprocessor: + StringAppend(&str,"\n",1); + StringAppend(&str,pFirst->zText,pFirst->nText); + StringAppend(&str,"\n",1); + needSpace = 0; + break; + + case TT_Id: + if( pFirst->nText==6 && pFirst->zText[0]=='E' + && strncmp(pFirst->zText,"EXPORT",6)==0 ){ + break; + } + /* Fall thru to the next case */ + case TT_Number: + if( needSpace ){ + StringAppend(&str," ",1); + } + StringAppend(&str,pFirst->zText,pFirst->nText); + needSpace = 1; + break; + + default: + c = pFirst->zText[0]; + if( needSpace && (c=='*' || c=='{') ){ + StringAppend(&str," ",1); + } + StringAppend(&str,pFirst->zText,pFirst->nText); + /* needSpace = pFirst->zText[0]==','; */ + needSpace = 0; + break; + } + pFirst = pFirst->pNext; + } + StringAppend(&str,";\n",2); + zReturn = StrDup(StringGet(&str),0); + StringReset(&str); + return zReturn; +} + +/* +** This routine is called when we see one of the keywords "struct", +** "enum", "union" or "class". This might be the beginning of a +** type declaration. This routine will process the declaration and +** remove the declaration tokens from the input stream. +** +** If this is a type declaration that is immediately followed by a +** semicolon (in other words it isn't also a variable definition) +** then set *pReset to ';'. Otherwise leave *pReset at 0. The +** *pReset flag causes the parser to skip ahead to the next token +** that begins with the value placed in the *pReset flag, if that +** value is different from 0. +*/ +static int ProcessTypeDecl(Token *pList, int flags, int *pReset){ + Token *pName, *pEnd; + Decl *pDecl; + String str; + int need_to_collapse = 1; + + *pReset = 0; + if( pList==0 || pList->pNext==0 || pList->pNext->eType!=TT_Id ){ + return 0; + } + pName = pList->pNext; + + /* Catch the case of "struct Foo;" and skip it. */ + if( pName->pNext && pName->pNext->zText[0]==';' ){ + *pReset = ';'; + return 0; + } + + for(pEnd=pName->pNext; pEnd && pEnd->eType!=TT_Braces; pEnd=pEnd->pNext){ + switch( pEnd->zText[0] ){ + case '(': + case '*': + case '[': + case '=': + case ';': + return 0; + } + } + if( pEnd==0 ){ + return 0; + } + + /* + ** At this point, we know we have a type declaration that is bounded + ** by pList and pEnd and has the name pName. + */ + + /* + ** If the braces are followed immedately by a semicolon, then we are + ** dealing a type declaration only. There is not variable definition + ** following the type declaration. So reset... + */ + if( pEnd->pNext==0 || pEnd->pNext->zText[0]==';' ){ + *pReset = ';'; + need_to_collapse = 0; + }else{ + need_to_collapse = 1; + } + + if( proto_static==0 && (flags & (PS_Local|PS_Export|PS_Interface))==0 ){ + /* Ignore these objects unless they are explicitly declared as interface, + ** or unless the "-local" command line option was specified. */ + *pReset = ';'; + return 0; + } + +#ifdef DEBUG + if( debugMask & PARSER ){ + printf("**** Found type: %.*s %.*s...\n", + pList->nText, pList->zText, pName->nText, pName->zText); + PrintTokens(pList,pEnd); + printf(";\n"); + } +#endif + pDecl = CreateDecl(pName->zText,pName->nText); + if( (flags & PS_Static) || !(flags & (PS_Interface|PS_Export)) ){ + DeclSetProperty(pDecl,DP_Local); + } + switch( *pList->zText ){ + case 'c': DeclSetProperty(pDecl,TY_Class); break; + case 's': DeclSetProperty(pDecl,TY_Structure); break; + case 'e': DeclSetProperty(pDecl,TY_Enumeration); break; + case 'u': DeclSetProperty(pDecl,TY_Union); break; + default: /* Can't Happen */ break; + } + + /* The object has a full declaration only if it is contained within + ** "#if INTERFACE...#endif" or "#if EXPORT_INTERFACE...#endif" or + ** "#if LOCAL_INTERFACE...#endif". Otherwise, we only give it a + ** forward declaration. + */ + if( flags & (PS_Local | PS_Export | PS_Interface) ){ + pDecl->zDecl = TokensToString(pList,pEnd); + }else{ + pDecl->zDecl = 0; + } + pDecl->pComment = pList->pComment; + StringInit(&str); + StringAppend(&str,"typedef ",0); + StringAppend(&str,pList->zText,pList->nText); + StringAppend(&str," ",0); + StringAppend(&str,pName->zText,pName->nText); + StringAppend(&str," ",0); + StringAppend(&str,pName->zText,pName->nText); + StringAppend(&str,";\n",2); + pDecl->zFwd = StrDup(StringGet(&str),0); + StringReset(&str); + StringInit(&str); + StringAppend(&str,pList->zText,pList->nText); + StringAppend(&str," ",0); + StringAppend(&str,pName->zText,pName->nText); + StringAppend(&str,";\n",2); + pDecl->zFwdCpp = StrDup(StringGet(&str),0); + StringReset(&str); + if( flags & PS_Export ){ + DeclSetProperty(pDecl,DP_Export); + }else if( flags & PS_Local ){ + DeclSetProperty(pDecl,DP_Local); + } + + /* Here's something weird. ANSI-C doesn't allow a forward declaration + ** of an enumeration. So we have to build the typedef into the + ** definition. + */ + if( pDecl->zDecl && DeclHasProperty(pDecl, TY_Enumeration) ){ + StringInit(&str); + StringAppend(&str,pDecl->zDecl,0); + StringAppend(&str,pDecl->zFwd,0); + SafeFree(pDecl->zDecl); + SafeFree(pDecl->zFwd); + pDecl->zFwd = 0; + pDecl->zDecl = StrDup(StringGet(&str),0); + StringReset(&str); + } + + if( pName->pNext->zText[0]==':' ){ + DeclSetProperty(pDecl,DP_Cplusplus); + } + if( pName->nText==5 && strncmp(pName->zText,"class",5)==0 ){ + DeclSetProperty(pDecl,DP_Cplusplus); + } + + /* + ** Remove all but pList and pName from the input stream. + */ + if( need_to_collapse ){ + while( pEnd!=pName ){ + Token *pPrev = pEnd->pPrev; + pPrev->pNext = pEnd->pNext; + pEnd->pNext->pPrev = pPrev; + SafeFree(pEnd); + pEnd = pPrev; + } + } + return 0; +} + +/* +** Given a list of tokens that declare something (a function, procedure, +** variable or typedef) find the token which contains the name of the +** thing being declared. +** +** Algorithm: +** +** The name is: +** +** 1. The first identifier that is followed by a "[", or +** +** 2. The first identifier that is followed by a "(" where the +** "(" is followed by another identifier, or +** +** 3. The first identifier followed by "::", or +** +** 4. If none of the above, then the last identifier. +** +** In all of the above, certain reserved words (like "char") are +** not considered identifiers. +*/ +static Token *FindDeclName(Token *pFirst, Token *pLast){ + Token *pName = 0; + Token *p; + int c; + + if( pFirst==0 || pLast==0 ){ + return 0; + } + pLast = pLast->pNext; + for(p=pFirst; p && p!=pLast; p=p->pNext){ + if( p->eType==TT_Id ){ + static IdentTable sReserved; + static int isInit = 0; + static char *aWords[] = { "char", "class", + "const", "double", "enum", "extern", "EXPORT", "ET_PROC", + "float", "int", "long", + "register", "static", "struct", "sizeof", "signed", "typedef", + "union", "volatile", "virtual", "void", }; + + if( !isInit ){ + int i; + for(i=0; i<sizeof(aWords)/sizeof(aWords[0]); i++){ + IdentTableInsert(&sReserved,aWords[i],0); + } + isInit = 1; + } + if( !IdentTableTest(&sReserved,p->zText,p->nText) ){ + pName = p; + } + }else if( p==pFirst ){ + continue; + }else if( (c=p->zText[0])=='[' && pName ){ + break; + }else if( c=='(' && p->pNext && p->pNext->eType==TT_Id && pName ){ + break; + }else if( c==':' && p->zText[1]==':' && pName ){ + break; + } + } + return pName; +} + +/* +** This routine is called when we see a function or procedure definition. +** We make an entry in the declaration table that is a prototype for this +** function or procedure. +*/ +static int ProcessProcedureDef(Token *pFirst, Token *pLast, int flags){ + Token *pName; + Decl *pDecl; + Token *pCode; + + if( pFirst==0 || pLast==0 ){ + return 0; + } + if( flags & PS_Method ){ + return 0; + } + if( (flags & PS_Static)!=0 && !proto_static ){ + return 0; + } + pCode = pLast; + while( pLast && pLast!=pFirst && pLast->zText[0]!=')' ){ + pLast = pLast->pPrev; + } + if( pLast==0 || pLast==pFirst || pFirst->pNext==pLast ){ + fprintf(stderr,"%s:%d: Unrecognized syntax.\n", + zFilename, pFirst->nLine); + return 1; + } + if( flags & (PS_Interface|PS_Export|PS_Local) ){ + fprintf(stderr,"%s:%d: Missing \"inline\" on function or procedure.\n", + zFilename, pFirst->nLine); + return 1; + } + pName = FindDeclName(pFirst,pLast); + if( pName==0 ){ + fprintf(stderr,"%s:%d: Malformed function or procedure definition.\n", + zFilename, pFirst->nLine); + return 1; + } + + /* + ** At this point we've isolated a procedure declaration between pFirst + ** and pLast with the name pName. + */ +#ifdef DEBUG + if( debugMask & PARSER ){ + printf("**** Found routine: %.*s on line %d...\n", pName->nText, + pName->zText, pFirst->nLine); + PrintTokens(pFirst,pLast); + printf(";\n"); + } +#endif + pDecl = CreateDecl(pName->zText,pName->nText); + pDecl->pComment = pFirst->pComment; + if( pCode && pCode->eType==TT_Braces ){ + pDecl->tokenCode = *pCode; + } + DeclSetProperty(pDecl,TY_Subroutine); + pDecl->zDecl = TokensToString(pFirst,pLast); + if( (flags & (PS_Static|PS_Local2))!=0 ){ + DeclSetProperty(pDecl,DP_Local); + }else if( (flags & (PS_Export2))!=0 ){ + DeclSetProperty(pDecl,DP_Export); + } + + if( flags & DP_Cplusplus ){ + DeclSetProperty(pDecl,DP_Cplusplus); + }else{ + DeclSetProperty(pDecl,DP_ExternCReqd); + } + + return 0; +} + +/* +** This routine is called whenever we see the "inline" keyword. We +** need to seek-out the inline function or procedure and make a +** declaration out of the entire definition. +*/ +static int ProcessInlineProc(Token *pFirst, int flags, int *pReset){ + Token *pName; + Token *pEnd; + Decl *pDecl; + + for(pEnd=pFirst; pEnd; pEnd = pEnd->pNext){ + if( pEnd->zText[0]=='{' || pEnd->zText[0]==';' ){ + *pReset = pEnd->zText[0]; + break; + } + } + if( pEnd==0 ){ + *pReset = ';'; + fprintf(stderr,"%s:%d: incomplete inline procedure definition\n", + zFilename, pFirst->nLine); + return 1; + } + pName = FindDeclName(pFirst,pEnd); + if( pName==0 ){ + fprintf(stderr,"%s:%d: malformed inline procedure definition\n", + zFilename, pFirst->nLine); + return 1; + } + +#ifdef DEBUG + if( debugMask & PARSER ){ + printf("**** Found inline routine: %.*s on line %d...\n", + pName->nText, pName->zText, pFirst->nLine); + PrintTokens(pFirst,pEnd); + printf("\n"); + } +#endif + pDecl = CreateDecl(pName->zText,pName->nText); + pDecl->pComment = pFirst->pComment; + DeclSetProperty(pDecl,TY_Subroutine); + pDecl->zDecl = TokensToString(pFirst,pEnd); + if( (flags & (PS_Static|PS_Local|PS_Local2)) ){ + DeclSetProperty(pDecl,DP_Local); + }else if( flags & (PS_Export|PS_Export2) ){ + DeclSetProperty(pDecl,DP_Export); + } + + if( flags & DP_Cplusplus ){ + DeclSetProperty(pDecl,DP_Cplusplus); + }else{ + DeclSetProperty(pDecl,DP_ExternCReqd); + } + + return 0; +} + +/* +** Determine if the tokens between pFirst and pEnd form a variable +** definition or a function prototype. Return TRUE if we are dealing +** with a variable defintion and FALSE for a prototype. +** +** pEnd is the token that ends the object. It can be either a ';' or +** a '='. If it is '=', then assume we have a variable definition. +** +** If pEnd is ';', then the determination is more difficult. We have +** to search for an occurance of an ID followed immediately by '('. +** If found, we have a prototype. Otherwise we are dealing with a +** variable definition. +*/ +static int isVariableDef(Token *pFirst, Token *pEnd){ + if( pEnd && pEnd->zText[0]=='=' ){ + return 1; + } + while( pFirst && pFirst!=pEnd && pFirst->pNext && pFirst->pNext!=pEnd ){ + if( pFirst->eType==TT_Id && pFirst->pNext->zText[0]=='(' ){ + return 0; + } + pFirst = pFirst->pNext; + } + return 1; +} + + +/* +** This routine is called whenever we encounter a ";" or "=". The stuff +** between pFirst and pLast constitutes either a typedef or a global +** variable definition. Do the right thing. +*/ +static int ProcessDecl(Token *pFirst, Token *pEnd, int flags){ + Token *pName; + Decl *pDecl; + int isLocal = 0; + int isVar; + int nErr = 0; + + if( pFirst==0 || pEnd==0 ){ + return 0; + } + if( flags & PS_Typedef ){ + if( (flags & (PS_Export2|PS_Local2))!=0 ){ + fprintf(stderr,"%s:%d: \"EXPORT\" or \"LOCAL\" ignored before typedef.\n", + zFilename, pFirst->nLine); + nErr++; + } + if( (flags & (PS_Interface|PS_Export|PS_Local|DP_Cplusplus))==0 ){ + /* It is illegal to duplicate a typedef in C (but OK in C++). + ** So don't record typedefs that aren't within a C++ file or + ** within #if INTERFACE..#endif */ + return nErr; + } + if( (flags & (PS_Interface|PS_Export|PS_Local))==0 && proto_static==0 ){ + /* Ignore typedefs that are not with "#if INTERFACE..#endif" unless + ** the "-local" command line option is used. */ + return nErr; + } + if( (flags & (PS_Interface|PS_Export))==0 ){ + /* typedefs are always local, unless within #if INTERFACE..#endif */ + isLocal = 1; + } + }else if( flags & (PS_Static|PS_Local2) ){ + if( proto_static==0 && (flags & PS_Local2)==0 ){ + /* Don't record static variables unless the "-local" command line + ** option was specified or the "LOCAL" keyword is used. */ + return nErr; + } + while( pFirst!=0 && pFirst->pNext!=pEnd && + ((pFirst->nText==6 && strncmp(pFirst->zText,"static",6)==0) + || (pFirst->nText==5 && strncmp(pFirst->zText,"LOCAL",6)==0)) + ){ + /* Lose the initial "static" or local from local variables. + ** We'll prepend "extern" later. */ + pFirst = pFirst->pNext; + isLocal = 1; + } + if( pFirst==0 || !isLocal ){ + return nErr; + } + }else if( flags & PS_Method ){ + /* Methods are declared by their class. Don't declare separately. */ + return nErr; + } + isVar = (flags & (PS_Typedef|PS_Method))==0 && isVariableDef(pFirst,pEnd); + if( isVar && (flags & (PS_Interface|PS_Export|PS_Local))!=0 + && (flags & PS_Extern)==0 ){ + fprintf(stderr,"%s:%d: Can't define a variable in this context\n", + zFilename, pFirst->nLine); + nErr++; + } + pName = FindDeclName(pFirst,pEnd->pPrev); + if( pName==0 ){ + fprintf(stderr,"%s:%d: Can't find a name for the object declared here.\n", + zFilename, pFirst->nLine); + return nErr+1; + } + +#ifdef DEBUG + if( debugMask & PARSER ){ + if( flags & PS_Typedef ){ + printf("**** Found typedef %.*s at line %d...\n", + pName->nText, pName->zText, pName->nLine); + }else if( isVar ){ + printf("**** Found variable %.*s at line %d...\n", + pName->nText, pName->zText, pName->nLine); + }else{ + printf("**** Found prototype %.*s at line %d...\n", + pName->nText, pName->zText, pName->nLine); + } + PrintTokens(pFirst,pEnd->pPrev); + printf(";\n"); + } +#endif + + pDecl = CreateDecl(pName->zText,pName->nText); + if( (flags & PS_Typedef) ){ + DeclSetProperty(pDecl, TY_Typedef); + }else if( isVar ){ + DeclSetProperty(pDecl,DP_ExternReqd | TY_Variable); + if( !(flags & DP_Cplusplus) ){ + DeclSetProperty(pDecl,DP_ExternCReqd); + } + }else{ + DeclSetProperty(pDecl, TY_Subroutine); + if( !(flags & DP_Cplusplus) ){ + DeclSetProperty(pDecl,DP_ExternCReqd); + } + } + pDecl->pComment = pFirst->pComment; + pDecl->zDecl = TokensToString(pFirst,pEnd->pPrev); + if( isLocal || (flags & (PS_Local|PS_Local2))!=0 ){ + DeclSetProperty(pDecl,DP_Local); + }else if( flags & (PS_Export|PS_Export2) ){ + DeclSetProperty(pDecl,DP_Export); + } + if( flags & DP_Cplusplus ){ + DeclSetProperty(pDecl,DP_Cplusplus); + } + return nErr; +} + +/* +** Push an if condition onto the if stack +*/ +static void PushIfMacro( + const char *zPrefix, /* A prefix, like "define" or "!" */ + const char *zText, /* The condition */ + int nText, /* Number of characters in zText */ + int nLine, /* Line number where this macro occurs */ + int flags /* Either 0, PS_Interface, PS_Export or PS_Local */ +){ + Ifmacro *pIf; + int nByte; + + nByte = sizeof(Ifmacro); + if( zText ){ + if( zPrefix ){ + nByte += strlen(zPrefix) + 2; + } + nByte += nText + 1; + } + pIf = SafeMalloc( nByte ); + if( zText ){ + pIf->zCondition = (char*)&pIf[1]; + if( zPrefix ){ + sprintf(pIf->zCondition,"%s(%.*s)",zPrefix,nText,zText); + }else{ + sprintf(pIf->zCondition,"%.*s",nText,zText); + } + }else{ + pIf->zCondition = 0; + } + pIf->nLine = nLine; + pIf->flags = flags; + pIf->pNext = ifStack; + ifStack = pIf; +} + +/* +** This routine is called to handle all preprocessor directives. +** +** This routine will recompute the value of *pPresetFlags to be the +** logical or of all flags on all nested #ifs. The #ifs that set flags +** are as follows: +** +** conditional flag set +** ------------------------ -------------------- +** #if INTERFACE PS_Interface +** #if EXPORT_INTERFACE PS_Export +** #if LOCAL_INTERFACE PS_Local +** +** For example, if after processing the preprocessor token given +** by pToken there is an "#if INTERFACE" on the preprocessor +** stack, then *pPresetFlags will be set to PS_Interface. +*/ +static int ParsePreprocessor(Token *pToken, int flags, int *pPresetFlags){ + const char *zCmd; + int nCmd; + const char *zArg; + int nArg; + int nErr = 0; + Ifmacro *pIf; + + zCmd = &pToken->zText[1]; + while( isspace(*zCmd) && *zCmd!='\n' ){ + zCmd++; + } + if( !isalpha(*zCmd) ){ + return 0; + } + nCmd = 1; + while( isalpha(zCmd[nCmd]) ){ + nCmd++; + } + + if( nCmd==5 && strncmp(zCmd,"endif",5)==0 ){ + /* + ** Pop the if stack + */ + pIf = ifStack; + if( pIf==0 ){ + fprintf(stderr,"%s:%d: extra '#endif'.\n",zFilename,pToken->nLine); + return 1; + } + ifStack = pIf->pNext; + SafeFree(pIf); + }else if( nCmd==6 && strncmp(zCmd,"define",6)==0 ){ + /* + ** Record a #define if we are in PS_Interface or PS_Export + */ + Decl *pDecl; + if( !(flags & (PS_Local|PS_Interface|PS_Export)) ){ return 0; } + zArg = &zCmd[6]; + while( *zArg && isspace(*zArg) && *zArg!='\n' ){ + zArg++; + } + if( *zArg==0 || *zArg=='\n' ){ return 0; } + for(nArg=0; ISALNUM(zArg[nArg]); nArg++){} + if( nArg==0 ){ return 0; } + pDecl = CreateDecl(zArg,nArg); + pDecl->pComment = pToken->pComment; + DeclSetProperty(pDecl,TY_Macro); + pDecl->zDecl = SafeMalloc( pToken->nText + 2 ); + sprintf(pDecl->zDecl,"%.*s\n",pToken->nText,pToken->zText); + if( flags & PS_Export ){ + DeclSetProperty(pDecl,DP_Export); + }else if( flags & PS_Local ){ + DeclSetProperty(pDecl,DP_Local); + } + }else if( nCmd==7 && strncmp(zCmd,"include",7)==0 ){ + /* + ** Record an #include if we are in PS_Interface or PS_Export + */ + Include *pInclude; + char *zIf; + + if( !(flags & (PS_Interface|PS_Export)) ){ return 0; } + zArg = &zCmd[7]; + while( *zArg && isspace(*zArg) ){ zArg++; } + for(nArg=0; !isspace(zArg[nArg]); nArg++){} + if( (zArg[0]=='"' && zArg[nArg-1]!='"') + ||(zArg[0]=='<' && zArg[nArg-1]!='>') + ){ + fprintf(stderr,"%s:%d: malformed #include statement.\n", + zFilename,pToken->nLine); + return 1; + } + zIf = GetIfString(); + if( zIf ){ + pInclude = SafeMalloc( sizeof(Include) + nArg*2 + strlen(zIf) + 10 ); + pInclude->zFile = (char*)&pInclude[1]; + pInclude->zLabel = &pInclude->zFile[nArg+1]; + sprintf(pInclude->zFile,"%.*s",nArg,zArg); + sprintf(pInclude->zLabel,"%.*s:%s",nArg,zArg,zIf); + pInclude->zIf = &pInclude->zLabel[nArg+1]; + SafeFree(zIf); + }else{ + pInclude = SafeMalloc( sizeof(Include) + nArg + 1 ); + pInclude->zFile = (char*)&pInclude[1]; + sprintf(pInclude->zFile,"%.*s",nArg,zArg); + pInclude->zIf = 0; + pInclude->zLabel = pInclude->zFile; + } + pInclude->pNext = includeList; + includeList = pInclude; + }else if( nCmd==2 && strncmp(zCmd,"if",2)==0 ){ + /* + ** Push an #if. Watch for the special cases of INTERFACE + ** and EXPORT_INTERFACE and LOCAL_INTERFACE + */ + zArg = &zCmd[2]; + while( *zArg && isspace(*zArg) && *zArg!='\n' ){ + zArg++; + } + if( *zArg==0 || *zArg=='\n' ){ return 0; } + nArg = pToken->nText + (int)pToken->zText - (int)zArg; + if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){ + PushIfMacro(0,0,0,pToken->nLine,PS_Interface); + }else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){ + PushIfMacro(0,0,0,pToken->nLine,PS_Export); + }else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){ + PushIfMacro(0,0,0,pToken->nLine,PS_Local); + }else{ + PushIfMacro(0,zArg,nArg,pToken->nLine,0); + } + }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){ + /* + ** Push an #ifdef. + */ + zArg = &zCmd[5]; + while( *zArg && isspace(*zArg) && *zArg!='\n' ){ + zArg++; + } + if( *zArg==0 || *zArg=='\n' ){ return 0; } + nArg = pToken->nText + (int)pToken->zText - (int)zArg; + PushIfMacro("defined",zArg,nArg,pToken->nLine,0); + }else if( nCmd==6 && strncmp(zCmd,"ifndef",6)==0 ){ + /* + ** Push an #ifndef. + */ + zArg = &zCmd[6]; + while( *zArg && isspace(*zArg) && *zArg!='\n' ){ + zArg++; + } + if( *zArg==0 || *zArg=='\n' ){ return 0; } + nArg = pToken->nText + (int)pToken->zText - (int)zArg; + PushIfMacro("!defined",zArg,nArg,pToken->nLine,0); + }else if( nCmd==4 && strncmp(zCmd,"else",4)==0 ){ + /* + ** Invert the #if on the top of the stack + */ + if( ifStack==0 ){ + fprintf(stderr,"%s:%d: '#else' without an '#if'\n",zFilename, + pToken->nLine); + return 1; + } + pIf = ifStack; + if( pIf->zCondition ){ + ifStack = ifStack->pNext; + PushIfMacro("!",pIf->zCondition,strlen(pIf->zCondition),pIf->nLine,0); + SafeFree(pIf); + }else{ + pIf->flags = 0; + } + }else{ + /* + ** This directive can be safely ignored + */ + return 0; + } + + /* + ** Recompute the preset flags + */ + *pPresetFlags = 0; + for(pIf = ifStack; pIf; pIf=pIf->pNext){ + *pPresetFlags |= pIf->flags; + } + + return nErr; +} + +/* +** Parse an entire file. Return the number of errors. +** +** pList is a list of tokens in the file. Whitespace tokens have been +** eliminated, and text with {...} has been collapsed into a +** single TT_Brace token. +** +** initFlags are a set of parse flags that should always be set for this +** file. For .c files this is normally 0. For .h files it is PS_Interface. +*/ +static int ParseFile(Token *pList, int initFlags){ + int nErr = 0; + Token *pStart = 0; + int flags = initFlags; + int presetFlags = initFlags; + int resetFlag = 0; + + includeList = 0; + while( pList ){ + switch( pList->eType ){ + case TT_EOF: + goto end_of_loop; + + case TT_Preprocessor: + nErr += ParsePreprocessor(pList,flags,&presetFlags); + pStart = 0; + presetFlags |= initFlags; + flags = presetFlags; + break; + + case TT_Other: + switch( pList->zText[0] ){ + case ';': + nErr += ProcessDecl(pStart,pList,flags); + pStart = 0; + flags = presetFlags; + break; + + case '=': + nErr += ProcessDecl(pStart,pList,flags); + pStart = 0; + while( pList && pList->zText[0]!=';' ){ + pList = pList->pNext; + } + if( pList==0 ) goto end_of_loop; + flags = presetFlags; + break; + + case ':': + if( pList->zText[1]==':' ){ + flags |= PS_Method; + } + break; + + default: + break; + } + break; + + case TT_Braces: + nErr += ProcessProcedureDef(pStart,pList,flags); + pStart = 0; + flags = presetFlags; + break; + + case TT_Id: + if( pStart==0 ){ + pStart = pList; + flags = presetFlags; + } + resetFlag = 0; + switch( pList->zText[0] ){ + case 'c': + if( pList->nText==5 && strncmp(pList->zText,"class",5)==0 ){ + nErr += ProcessTypeDecl(pList,flags,&resetFlag); + } + break; + + case 'E': + if( pList->nText==6 && strncmp(pList->zText,"EXPORT",6)==0 ){ + flags |= PS_Export2; + /* pStart = 0; */ + } + break; + + case 'e': + if( pList->nText==4 && strncmp(pList->zText,"enum",4)==0 ){ + if( pList->pNext && pList->pNext->eType==TT_Braces ){ + pList = pList->pNext; + }else{ + nErr += ProcessTypeDecl(pList,flags,&resetFlag); + } + }else if( pList->nText==6 && strncmp(pList->zText,"extern",6)==0 ){ + pList = pList->pNext; + if( pList && pList->nText==3 && strncmp(pList->zText,"\"C\"",3)==0 ){ + pList = pList->pNext; + flags &= ~DP_Cplusplus; + }else{ + flags |= PS_Extern; + } + pStart = pList; + } + break; + + case 'i': + if( pList->nText==6 && strncmp(pList->zText,"inline",6)==0 ){ + nErr += ProcessInlineProc(pList,flags,&resetFlag); + } + break; + + case 'L': + if( pList->nText==5 && strncmp(pList->zText,"LOCAL",5)==0 ){ + flags |= PS_Local2; + pStart = pList; + } + break; + + case 's': + if( pList->nText==6 && strncmp(pList->zText,"struct",6)==0 ){ + if( pList->pNext && pList->pNext->eType==TT_Braces ){ + pList = pList->pNext; + }else{ + nErr += ProcessTypeDecl(pList,flags,&resetFlag); + } + }else if( pList->nText==6 && strncmp(pList->zText,"static",6)==0 ){ + flags |= PS_Static; + } + break; + + case 't': + if( pList->nText==7 && strncmp(pList->zText,"typedef",7)==0 ){ + flags |= PS_Typedef; + } + break; + + case 'u': + if( pList->nText==5 && strncmp(pList->zText,"union",5)==0 ){ + if( pList->pNext && pList->pNext->eType==TT_Braces ){ + pList = pList->pNext; + }else{ + nErr += ProcessTypeDecl(pList,flags,&resetFlag); + } + } + break; + + default: + break; + } + if( resetFlag!=0 ){ + while( pList && pList->zText[0]!=resetFlag ){ + pList = pList->pNext; + } + if( pList==0 ) goto end_of_loop; + pStart = 0; + flags = presetFlags; + } + break; + + case TT_Number: + break; + + default: + pStart = pList; + flags = presetFlags; + break; + } + pList = pList->pNext; + } + end_of_loop: + + /* Verify that all #ifs have a matching "#endif" */ + while( ifStack ){ + Ifmacro *pIf = ifStack; + ifStack = pIf->pNext; + fprintf(stderr,"%s:%d: This '#if' has no '#endif'\n",zFilename, + pIf->nLine); + SafeFree(pIf); + } + + return nErr; +} + +/* +** Reset the DP_Forward and DP_Declared flags on all Decl structures. +** Set both flags for anything that is tagged as local and isn't +** in the file zFilename so that it won't be printing in other files. +*/ +static void ResetDeclFlags(char *zFilename){ + Decl *pDecl; + + for(pDecl = pDeclFirst; pDecl; pDecl = pDecl->pNext){ + DeclClearProperty(pDecl,DP_Forward|DP_Declared); + if( DeclHasProperty(pDecl,DP_Local) && pDecl->zFile!=zFilename ){ + DeclSetProperty(pDecl,DP_Forward|DP_Declared); + } + } +} + +/* +** Forward declaration of the ScanText() function. +*/ +static void ScanText(const char*, GenState *pState); + +/* +** The output in pStr is currently within an #if CONTEXT where context +** is equal to *pzIf. (*pzIf might be NULL to indicate that we are +** not within any #if at the moment.) We are getting ready to output +** some text that needs to be within the context of "#if NEW" where +** NEW is zIf. Make an appropriate change to the context. +*/ +static void ChangeIfContext( + const char *zIf, /* The desired #if context */ + GenState *pState /* Current state of the code generator */ +){ + if( zIf==0 ){ + if( pState->zIf==0 ) return; + StringAppend(pState->pStr,"#endif\n",0); + pState->zIf = 0; + }else{ + if( pState->zIf ){ + if( strcmp(zIf,pState->zIf)==0 ) return; + StringAppend(pState->pStr,"#endif\n",0); + pState->zIf = 0; + } + ScanText(zIf, pState); + if( pState->zIf!=0 ){ + StringAppend(pState->pStr,"#endif\n",0); + } + StringAppend(pState->pStr,"#if ",0); + StringAppend(pState->pStr,zIf,0); + StringAppend(pState->pStr,"\n",0); + pState->zIf = zIf; + } +} + +/* +** Add to the string pStr a #include of every file on the list of +** include files pInclude. The table pTable contains all files that +** have already been #included at least once. Don't add any +** duplicates. Update pTable with every new #include that is added. +*/ +static void AddIncludes( + Include *pInclude, /* Write every #include on this list */ + GenState *pState /* Current state of the code generator */ +){ + if( pInclude ){ + if( pInclude->pNext ){ + AddIncludes(pInclude->pNext,pState); + } + if( IdentTableInsert(pState->pTable,pInclude->zLabel,0) ){ + ChangeIfContext(pInclude->zIf,pState); + StringAppend(pState->pStr,"#include ",0); + StringAppend(pState->pStr,pInclude->zFile,0); + StringAppend(pState->pStr,"\n",1); + } + } +} + +/* +** Add to the string pStr a declaration for the object described +** in pDecl. +** +** If pDecl has already been declared in this file, detect that +** fact and abort early. Do not duplicate a declaration. +** +** If the needFullDecl flag is false and this object has a forward +** declaration, then supply the forward declaration only. A later +** call to CompleteForwardDeclarations() will finish the declaration +** for us. But if needFullDecl is true, we must supply the full +** declaration now. Some objects do not have a forward declaration. +** For those objects, we must print the full declaration now. +** +** Because it is illegal to duplicate a typedef in C, care is taken +** to insure that typedefs for the same identifier are only issued once. +*/ +static void DeclareObject( + Decl *pDecl, /* The thing to be declared */ + GenState *pState, /* Current state of the code generator */ + int needFullDecl /* Must have the full declaration. A forward + * declaration isn't enough */ +){ + Decl *p; /* The object to be declared */ + int flag; + int isCpp; /* True if generating C++ */ + int doneTypedef = 0; /* True if a typedef has been done for this object */ + + /* + ** For any object that has a forward declaration, go ahead and do the + ** forward declaration first. + */ + isCpp = (pState->flags & DP_Cplusplus) != 0; + for(p=pDecl; p; p=p->pSameName){ + if( p->zFwd ){ + if( !DeclHasProperty(p,DP_Forward) ){ + DeclSetProperty(p,DP_Forward); + if( strncmp(p->zFwd,"typedef",7)==0 ){ + if( doneTypedef ) continue; + doneTypedef = 1; + } + ChangeIfContext(p->zIf,pState); + StringAppend(pState->pStr,isCpp ? p->zFwdCpp : p->zFwd,0); + } + } + } + + /* + ** Early out if everything is already suitably declared. + ** + ** This is a very important step because it prevents us from + ** executing the code the follows in a recursive call to this + ** function with the same value for pDecl. + */ + flag = needFullDecl ? DP_Declared|DP_Forward : DP_Forward; + for(p=pDecl; p; p=p->pSameName){ + if( !DeclHasProperty(p,flag) ) break; + } + if( p==0 ){ + return; + } + + /* + ** Make sure we have all necessary #includes + */ + for(p=pDecl; p; p=p->pSameName){ + AddIncludes(p->pInclude,pState); + } + + /* + ** Go ahead an mark everything as being declared, to prevent an + ** infinite loop thru the ScanText() function. At the same time, + ** we decide which objects need a full declaration and mark them + ** with the DP_Flag bit. We are only able to use DP_Flag in this + ** way because we know we'll never execute this far into this + ** function on a recursive call with the same pDecl. Hence, recursive + ** calls to this function (through ScanText()) can never change the + ** value of DP_Flag out from under us. + */ + for(p=pDecl; p; p=p->pSameName){ + if( !DeclHasProperty(p,DP_Declared) + && (p->zFwd==0 || needFullDecl) + && p->zDecl!=0 + ){ + DeclSetProperty(p,DP_Forward|DP_Declared|DP_Flag); + }else{ + DeclClearProperty(p,DP_Flag); + } + } + + /* + ** Call ScanText() recusively (this routine is called from ScanText()) + ** to include declarations required to come before these declarations. + */ + for(p=pDecl; p; p=p->pSameName){ + if( DeclHasProperty(p,DP_Flag) ){ + if( p->zDecl[0]=='#' ){ + ScanText(&p->zDecl[1],pState); + }else{ + ScanText(p->zDecl,pState); + } + } + } + + /* + ** Output the declarations. Do this in two passes. First + ** output everything that isn't a typedef. Then go back and + ** get the typedefs by the same name. + */ + for(p=pDecl; p; p=p->pSameName){ + if( DeclHasProperty(p,DP_Flag) && !DeclHasProperty(p,TY_Typedef) ){ + if( DeclHasAnyProperty(p,TY_Enumeration) ){ + if( doneTypedef ) continue; + doneTypedef = 1; + } + ChangeIfContext(p->zIf,pState); + if( !isCpp && DeclHasAnyProperty(p,DP_ExternReqd) ){ + StringAppend(pState->pStr,"extern ",0); + }else if( isCpp && DeclHasProperty(p,DP_Cplusplus|DP_ExternReqd) ){ + StringAppend(pState->pStr,"extern ",0); + }else if( isCpp && DeclHasAnyProperty(p,DP_ExternCReqd|DP_ExternReqd) ){ + StringAppend(pState->pStr,"extern \"C\" ",0); + } + StringAppend(pState->pStr,p->zDecl,0); + if( !isCpp && DeclHasProperty(p,DP_Cplusplus) ){ + fprintf(stderr, + "%s: C code ought not reference the C++ object \"%s\"\n", + pState->zFilename, p->zName); + pState->nErr++; + } + DeclClearProperty(p,DP_Flag); + } + } + for(p=pDecl; p && !doneTypedef; p=p->pSameName){ + if( DeclHasProperty(p,DP_Flag) ){ + /* This has to be a typedef */ + doneTypedef = 1; + ChangeIfContext(p->zIf,pState); + StringAppend(pState->pStr,p->zDecl,0); + } + } +} + +/* +** This routine scans the input text given, and appends to the +** string in pState->pStr the text of any declarations that must +** occur before the text in zText. +** +** If an identifier in zText is immediately followed by '*', then +** only forward declarations are needed for that identifier. If the +** identifier name is not followed immediately by '*', we must supply +** a full declaration. +*/ +static void ScanText( + const char *zText, /* The input text to be scanned */ + GenState *pState /* Current state of the code generator */ +){ + int nextValid = 0; /* True is sNext contains valid data */ + InStream sIn; /* The input text */ + Token sToken; /* The current token being examined */ + Token sNext; /* The next non-space token */ + + sIn.z = zText; + sIn.i = 0; + sIn.nLine = 1; + while( sIn.z[sIn.i]!=0 ){ + if( nextValid ){ + sToken = sNext; + nextValid = 0; + }else{ + GetNonspaceToken(&sIn,&sToken); + } + if( sToken.eType==TT_Id ){ + int needFullDecl; /* True if we need to provide the full declaration, + ** not just the forward declaration */ + Decl *pDecl; /* The declaration having the name in sToken */ + + /* + ** See if there is a declaration in the database with the name given + ** by sToken. + */ + pDecl = FindDecl(sToken.zText,sToken.nText); + if( pDecl==0 ) continue; + + /* + ** If we get this far, we've found an identifier that has a + ** declaration in the database. Now see if we the full declaration + ** or just a forward declaration. + */ + GetNonspaceToken(&sIn,&sNext); + if( sNext.zText[0]=='*' ){ + needFullDecl = 0; + }else{ + needFullDecl = 1; + nextValid = sNext.eType==TT_Id; + } + + /* + ** Generate the needed declaration. + */ + DeclareObject(pDecl,pState,needFullDecl); + }else if( sToken.eType==TT_Preprocessor ){ + sIn.i -= sToken.nText - 1; + } + } +} + +/* +** Provide a full declaration to any object which so far has had only +** a foward declaration. +*/ +static void CompleteForwardDeclarations(GenState *pState){ + Decl *pDecl; + int progress; + + do{ + progress = 0; + for(pDecl=pDeclFirst; pDecl; pDecl=pDecl->pNext){ + if( DeclHasProperty(pDecl,DP_Forward) + && !DeclHasProperty(pDecl,DP_Declared) + ){ + DeclareObject(pDecl,pState,1); + progress = 1; + assert( DeclHasProperty(pDecl,DP_Declared) ); + } + } + }while( progress ); +} + +/* +** Generate an include file for the given source file. Return the number +** of errors encountered. +** +** if nolocal_flag is true, then we do not generate declarations for +** objected marked DP_Local. +*/ +static int MakeHeader(InFile *pFile, FILE *report, int nolocal_flag){ + int nErr = 0; + GenState sState; + String outStr; + IdentTable includeTable; + Ident *pId; + char *zNewVersion; + char *zOldVersion; + + if( pFile->zHdr==0 || *pFile->zHdr==0 ) return 0; + sState.pStr = &outStr; + StringInit(&outStr); + StringAppend(&outStr,zTopLine,nTopLine); + sState.pTable = &includeTable; + memset(&includeTable,0,sizeof(includeTable)); + sState.zIf = 0; + sState.nErr = 0; + sState.zFilename = pFile->zSrc; + sState.flags = pFile->flags & DP_Cplusplus; + ResetDeclFlags(nolocal_flag ? "no" : pFile->zSrc); + for(pId = pFile->idTable.pList; pId; pId=pId->pNext){ + Decl *pDecl = FindDecl(pId->zName,0); + if( pDecl ){ + DeclareObject(pDecl,&sState,1); + } + } + CompleteForwardDeclarations(&sState); + ChangeIfContext(0,&sState); + nErr += sState.nErr; + zOldVersion = ReadFile(pFile->zHdr); + zNewVersion = StringGet(&outStr); + if( report ) fprintf(report,"%s: ",pFile->zHdr); + if( zOldVersion==0 ){ + if( report ) fprintf(report,"updated\n"); + if( WriteFile(pFile->zHdr,zNewVersion) ){ + fprintf(stderr,"%s: Can't write to file\n",pFile->zHdr); + nErr++; + } + }else if( strncmp(zOldVersion,zTopLine,nTopLine)!=0 ){ + if( report ) fprintf(report,"error!\n"); + fprintf(stderr, + "%s: Can't overwrite this file because it wasn't previously\n" + "generated by 'makeheaders'.\n", pFile->zHdr); + nErr++; + }else if( strcmp(zOldVersion,zNewVersion)!=0 ){ + if( report ) fprintf(report,"updated\n"); + if( WriteFile(pFile->zHdr,zNewVersion) ){ + fprintf(stderr,"%s: Can't write to file\n",pFile->zHdr); + nErr++; + } + }else if( report ){ + fprintf(report,"unchanged\n"); + } + SafeFree(zOldVersion); + IdentTableReset(&includeTable); + StringReset(&outStr); + return nErr; +} + +/* +** Generate a global header file -- a header file that contains all +** declarations. If the forExport flag is true, then only those +** objects that are exported are included in the header file. +*/ +static int MakeGlobalHeader(int forExport){ + GenState sState; + String outStr; + IdentTable includeTable; + Decl *pDecl; + + sState.pStr = &outStr; + StringInit(&outStr); + /* StringAppend(&outStr,zTopLine,nTopLine); */ + sState.pTable = &includeTable; + memset(&includeTable,0,sizeof(includeTable)); + sState.zIf = 0; + sState.nErr = 0; + sState.zFilename = "(all)"; + sState.flags = 0; + ResetDeclFlags(0); + for(pDecl=pDeclFirst; pDecl; pDecl=pDecl->pNext){ + if( forExport==0 || DeclHasProperty(pDecl,DP_Export) ){ + DeclareObject(pDecl,&sState,1); + } + } + ChangeIfContext(0,&sState); + printf("%s",StringGet(&outStr)); + IdentTableReset(&includeTable); + StringReset(&outStr); + return 0; +} + +#ifdef DEBUG +/* +** Return the number of characters in the given string prior to the +** first newline. +*/ +static int ClipTrailingNewline(char *z){ + int n = strlen(z); + while( n>0 && (z[n-1]=='\n' || z[n-1]=='\r') ){ n--; } + return n; +} + +/* +** Dump the entire declaration list for debugging purposes +*/ +static void DumpDeclList(void){ + Decl *pDecl; + + for(pDecl = pDeclFirst; pDecl; pDecl=pDecl->pNext){ + printf("**** %s from file %s ****\n",pDecl->zName,pDecl->zFile); + if( pDecl->zIf ){ + printf("If: [%.*s]\n",ClipTrailingNewline(pDecl->zIf),pDecl->zIf); + } + if( pDecl->zFwd ){ + printf("Decl: [%.*s]\n",ClipTrailingNewline(pDecl->zFwd),pDecl->zFwd); + } + if( pDecl->zDecl ){ + printf("Def: [%.*s]\n",ClipTrailingNewline(pDecl->zDecl),pDecl->zDecl); + } + if( pDecl->flags ){ + static struct { + int mask; + char *desc; + } flagSet[] = { + { TY_Class, "class" }, + { TY_Enumeration, "enum" }, + { TY_Structure, "struct" }, + { TY_Union, "union" }, + { TY_Variable, "variable" }, + { TY_Subroutine, "function" }, + { TY_Typedef, "typedef" }, + { TY_Macro, "macro" }, + { DP_Export, "export" }, + { DP_Local, "local" }, + { DP_Cplusplus, "C++" }, + }; + int i; + printf("flags:"); + for(i=0; i<sizeof(flagSet)/sizeof(flagSet[0]); i++){ + if( flagSet[i].mask & pDecl->flags ){ + printf(" %s", flagSet[i].desc); + } + } + printf("\n"); + } + if( pDecl->pInclude ){ + Include *p; + printf("includes:"); + for(p=pDecl->pInclude; p; p=p->pNext){ + printf(" %s",p->zFile); + } + printf("\n"); + } + } +} +#endif + +/* +** When the "-doc" command-line option is used, this routine is called +** to print all of the database information to standard output. +*/ +static void DocumentationDump(void){ + Decl *pDecl; + static struct { + int mask; + char flag; + } flagSet[] = { + { TY_Class, 'c' }, + { TY_Enumeration, 'e' }, + { TY_Structure, 's' }, + { TY_Union, 'u' }, + { TY_Variable, 'v' }, + { TY_Subroutine, 'f' }, + { TY_Typedef, 't' }, + { TY_Macro, 'm' }, + { DP_Export, 'x' }, + { DP_Local, 'l' }, + { DP_Cplusplus, '+' }, + }; + + for(pDecl = pDeclFirst; pDecl; pDecl=pDecl->pNext){ + int i; + int nLabel = 0; + char *zDecl; + char zLabel[50]; + for(i=0; i<sizeof(flagSet)/sizeof(flagSet[0]); i++){ + if( DeclHasProperty(pDecl,flagSet[i].mask) ){ + zLabel[nLabel++] = flagSet[i].flag; + } + } + if( nLabel==0 ) continue; + zLabel[nLabel] = 0; + zDecl = pDecl->zDecl; + if( zDecl==0 ) zDecl = pDecl->zFwd; + printf("%s %s %s %d %d %d %d %d %d\n", + pDecl->zName, + zLabel, + pDecl->zFile, + (int)(pDecl->pComment ? (int)pDecl->pComment/sizeof(Token) : 0), + (int)(pDecl->pComment ? pDecl->pComment->nText+1 : 0), + (int)(pDecl->zIf ? strlen(pDecl->zIf)+1 : 0), + (int)(zDecl ? strlen(zDecl) : 0), + (int)(pDecl->pComment ? pDecl->pComment->nLine : 0), + pDecl->tokenCode.nText ? pDecl->tokenCode.nText+1 : 0 + ); + if( pDecl->pComment ){ + printf("%.*s\n",pDecl->pComment->nText, pDecl->pComment->zText); + } + if( pDecl->zIf ){ + printf("%s\n",pDecl->zIf); + } + if( zDecl ){ + printf("%s",zDecl); + } + if( pDecl->tokenCode.nText ){ + printf("%.*s\n",pDecl->tokenCode.nText, pDecl->tokenCode.zText); + } + } +} + +/* +** Given the complete text of an input file, this routine prints a +** documentation record for the header comment at the beginning of the +** file (if the file has a header comment.) +*/ +void PrintModuleRecord(const char *zFile, const char *zFilename){ + int i; + static int addr = 5; + while( isspace(*zFile) ){ zFile++; } + if( *zFile!='/' || zFile[1]!='*' ) return; + for(i=2; zFile[i] && (zFile[i-1]!='/' || zFile[i-2]!='*'); i++){} + if( zFile[i]==0 ) return; + printf("%s M %s %d %d 0 0 0\n%.*s\n", + zFilename, zFilename, addr, i+1, i, zFile); + addr += 4; +} + + +/* +** Given an input argument to the program, construct a new InFile +** object. +*/ +static InFile *CreateInFile(char *zArg, int *pnErr){ + int nSrc; + char *zSrc; + InFile *pFile; + int i; + + /* + ** Get the name of the input file to be scanned + */ + zSrc = zArg; + for(nSrc=0; zSrc[nSrc] && zArg[nSrc]!=':'; nSrc++){} + pFile = SafeMalloc( sizeof(InFile) ); + memset(pFile,0,sizeof(InFile)); + pFile->zSrc = StrDup(zSrc,nSrc); + + /* Figure out if we are dealing with C or C++ code. Assume any + ** file with ".c" or ".h" is C code and all else is C++. + */ + if( nSrc>2 && zSrc[nSrc-2]=='.' && (zSrc[nSrc-1]=='c' || zSrc[nSrc-1]=='h')){ + pFile->flags &= ~DP_Cplusplus; + }else{ + pFile->flags |= DP_Cplusplus; + } + + /* + ** If a separate header file is specified, use it + */ + if( zSrc[nSrc]==':' ){ + int nHdr; + char *zHdr; + zHdr = &zSrc[nSrc+1]; + for(nHdr=0; zHdr[nHdr] && zHdr[nHdr]!=':'; nHdr++){} + pFile->zHdr = StrDup(zHdr,nHdr); + } + + /* Look for any 'c' or 'C' in the suffix of the file name and change + ** that character to 'h' or 'H' respectively. If no 'c' or 'C' is found, + ** then assume we are dealing with a header. + */ + else{ + int foundC = 0; + pFile->zHdr = StrDup(zSrc,nSrc); + for(i = nSrc-1; i>0 && pFile->zHdr[i]!='.'; i--){ + if( pFile->zHdr[i]=='c' ){ + foundC = 1; + pFile->zHdr[i] = 'h'; + }else if( pFile->zHdr[i]=='C' ){ + foundC = 1; + pFile->zHdr[i] = 'H'; + } + } + if( !foundC ){ + SafeFree(pFile->zHdr); + pFile->zHdr = 0; + } + } + + /* + ** If pFile->zSrc contains no 'c' or 'C' in its extension, it + ** must be a header file. In that case, we need to set the + ** PS_Interface flag. + */ + pFile->flags |= PS_Interface; + for(i=nSrc-1; i>0 && zSrc[i]!='.'; i--){ + if( zSrc[i]=='c' || zSrc[i]=='C' ){ + pFile->flags &= ~PS_Interface; + break; + } + } + + /* Done! + */ + return pFile; +} + +/* MS-Windows and MS-DOS both have the following serious OS bug: the +** length of a command line is severely restricted. But this program +** occasionally requires long command lines. Hence the following +** work around. +** +** If the parameters "-f FILENAME" appear anywhere on the command line, +** then the named file is scanned for additional command line arguments. +** These arguments are substituted in place of the "FILENAME" argument +** in the original argument list. +** +** This first parameter to this routine is the index of the "-f" +** parameter in the argv[] array. The argc and argv are passed by +** pointer so that they can be changed. +** +** Parsing of the parameters in the file is very simple. Parameters +** can be separated by any amount of white-space (including newlines +** and carriage returns.) There are now quoting characters of any +** kind. The length of a token is limited to about 1000 characters. +*/ +static void AddParameters(int index, int *pArgc, char ***pArgv){ + int argc = *pArgc; /* The original argc value */ + char **argv = *pArgv; /* The original argv value */ + int newArgc; /* Value for argc after inserting new arguments */ + char **zNew; /* The new argv after this routine is done */ + char *zFile; /* Name of the input file */ + int nNew = 0; /* Number of new entries in the argv[] file */ + int nAlloc = 0; /* Space allocated for zNew[] */ + int i; /* Loop counter */ + int n; /* Number of characters in a new argument */ + int c; /* Next character of input */ + int startOfLine = 1; /* True if we are where '#' can start a comment */ + FILE *in; /* The input file */ + char zBuf[1000]; /* A single argument is accumulated here */ + + if( index+1==argc ) return; + zFile = argv[index+1]; + in = fopen(zFile,"r"); + if( in==0 ){ + fprintf(stderr,"Can't open input file \"%s\"\n",zFile); + exit(1); + } + c = ' '; + while( c!=EOF ){ + while( c!=EOF && isspace(c) ){ + if( c=='\n' ){ + startOfLine = 1; + } + c = getc(in); + if( startOfLine && c=='#' ){ + while( c!=EOF && c!='\n' ){ + c = getc(in); + } + } + } + n = 0; + while( c!=EOF && !isspace(c) ){ + if( n<sizeof(zBuf)-1 ){ zBuf[n++] = c; } + startOfLine = 0; + c = getc(in); + } + zBuf[n] = 0; + if( n>0 ){ + nNew++; + if( nNew + argc > nAlloc ){ + if( nAlloc==0 ){ + nAlloc = 100 + argc; + zNew = malloc( sizeof(char*) * nAlloc ); + }else{ + nAlloc *= 2; + zNew = realloc( zNew, sizeof(char*) * nAlloc ); + } + } + if( zNew ){ + int j = nNew + index; + zNew[j] = malloc( n + 1 ); + if( zNew[j] ){ + strcpy( zNew[j], zBuf ); + } + } + } + } + newArgc = argc + nNew - 1; + for(i=0; i<=index; i++){ + zNew[i] = argv[i]; + } + for(i=nNew + index + 1; i<newArgc; i++){ + zNew[i] = argv[i + 1 - nNew]; + } + zNew[newArgc] = 0; + *pArgc = newArgc; + *pArgv = zNew; +} + +#ifdef NOT_USED +/* +** Return the time that the given file was last modified. If we can't +** locate the file (because, for example, it doesn't exist), then +** return 0. +*/ +static unsigned int ModTime(const char *zFilename){ + unsigned int mTime = 0; + struct stat sStat; + if( stat(zFilename,&sStat)==0 ){ + mTime = sStat.st_mtime; + } + return mTime; +} +#endif + +/* +** Print a usage comment for this program. +*/ +static void Usage(const char *argv0, const char *argvN){ + fprintf(stderr,"%s: Illegal argument \"%s\"\n",argv0,argvN); + fprintf(stderr,"Usage: %s [options] filename...\n" + "Options:\n" + " -h Generate a single .h to standard output.\n" + " -H Like -h, but only output EXPORT declarations.\n" + " -v (verbose) Write status information to the screen.\n" + " -doc Generate no header files. Instead, output information\n" + " that can be used by an automatic program documentation\n" + " and cross-reference generator.\n" + " -local Generate prototypes for \"static\" functions and\n" + " procedures.\n" + " -f FILE Read additional command-line arguments from the file named\n" + " \"FILE\".\n" +#ifdef DEBUG + " -! MASK Set the debugging mask to the number \"MASK\".\n" +#endif + " -- Treat all subsequent comment-line parameters as filenames,\n" + " even if they begin with \"-\".\n", + argv0 + ); +} + +/* +** The following text contains a few simple #defines that we want +** to be available to every file. +*/ +static char zInit[] = + "#define INTERFACE 0\n" + "#define EXPORT_INTERFACE 0\n" + "#define LOCAL_INTERFACE 0\n" + "#define EXPORT\n" + "#define LOCAL static\n" +; + +#if TEST==0 +int main(int argc, char **argv){ + int i; /* Loop counter */ + int nErr = 0; /* Number of errors encountered */ + Token *pList; /* List of input tokens for one file */ + InFile *pFileList = 0;/* List of all input files */ + InFile *pTail; /* Last file on the list */ + InFile *pFile; /* for looping over the file list */ + int h_flag = 0; /* True if -h is present. Output unified header */ + int H_flag = 0; /* True if -H is present. Output EXPORT header */ + int v_flag = 0; /* Verbose */ + int noMoreFlags; /* True if -- has been seen. */ + FILE *report; /* Send progress reports to this, if not NULL */ + + noMoreFlags = 0; + for(i=1; i<argc; i++){ + if( argv[i][0]=='-' && !noMoreFlags ){ + switch( argv[i][1] ){ + case 'h': h_flag = 1; break; + case 'H': H_flag = 1; break; + case 'v': v_flag = 1; break; + case 'd': doc_flag = 1; proto_static = 1; break; + case 'l': proto_static = 1; break; + case 'f': AddParameters(i, &argc, &argv); break; + case '-': noMoreFlags = 1; break; +#ifdef DEBUG + case '!': i++; debugMask = strtol(argv[i],0,0); break; +#endif + default: Usage(argv[0],argv[i]); return 1; + } + }else{ + pFile = CreateInFile(argv[i],&nErr); + if( pFile ){ + if( pFileList ){ + pTail->pNext = pFile; + pTail = pFile; + }else{ + pFileList = pTail = pFile; + } + } + } + } + if( h_flag && H_flag ){ + h_flag = 0; + } + if( v_flag ){ + report = (h_flag || H_flag) ? stderr : stdout; + }else{ + report = 0; + } + if( nErr>0 ){ + return nErr; + } + for(pFile=pFileList; pFile; pFile=pFile->pNext){ + char *zFile; + + zFilename = pFile->zSrc; + if( zFilename==0 ) continue; + zFile = ReadFile(zFilename); + if( zFile==0 ){ + fprintf(stderr,"Can't read input file \"%s\"\n",zFilename); + nErr++; + continue; + } + if( strncmp(zFile,zTopLine,nTopLine)==0 ){ + pFile->zSrc = 0; + }else{ + if( report ) fprintf(report,"Reading %s...\n",zFilename); + pList = TokenizeFile(zFile,&pFile->idTable); + if( pList ){ + nErr += ParseFile(pList,pFile->flags); + FreeTokenList(pList); + }else if( zFile[0]==0 ){ + fprintf(stderr,"Input file \"%s\" is empty.\n", zFilename); + nErr++; + }else{ + fprintf(stderr,"Errors while processing \"%s\"\n", zFilename); + nErr++; + } + } + if( !doc_flag ) SafeFree(zFile); + if( doc_flag ) PrintModuleRecord(zFile,zFilename); + } + if( nErr>0 ){ + return nErr; + } +#ifdef DEBUG + if( debugMask & DECL_DUMP ){ + DumpDeclList(); + return nErr; + } +#endif + if( doc_flag ){ + DocumentationDump(); + return nErr; + } + zFilename = "--internal--"; + pList = TokenizeFile(zInit,0); + if( pList==0 ){ + return nErr+1; + } + ParseFile(pList,PS_Interface); + FreeTokenList(pList); + if( h_flag || H_flag ){ + nErr += MakeGlobalHeader(H_flag); + }else{ + for(pFile=pFileList; pFile; pFile=pFile->pNext){ + if( pFile->zSrc==0 ) continue; + nErr += MakeHeader(pFile,report,0); + } + } + return nErr; +} +#endif diff --git a/tkhtml1/tools/maketokens.tcl b/tkhtml1/tools/maketokens.tcl new file mode 100644 index 0000000..95cd34e --- /dev/null +++ b/tkhtml1/tools/maketokens.tcl @@ -0,0 +1,94 @@ +#!/bin/sh +# This script is a replacement for the maketokens.sh shell script. +# The shell script required GNU awk. This script should work with +# any old version of tclsh. +# \ +exec tclsh "$0" ${1+"$@"} + +if {$argc!=1} { + puts stderr "Usage: $argv0 tokenlist.txt >htmltokens.c" + exit 1 +} +if {[catch {open [lindex $argv 0] r} f]} { + puts stderr "$argv0: can not open \"[lindex $argv 0]\": $f" + exit 1 +} +set tokenlist {} +while {![eof $f]} { + set line [string trim [gets $f]] + if {$line==""} continue + if {[string index $line 0]=="#"} continue + if {[llength $line]!=2 && [llength $line]!=3} continue + lappend tokenlist [lindex $line 0] + lappend tokenlist [lindex $line 1] + lappend tokenlist [lindex $line 2] +} +close $f + +global tcl_platform +if {$tcl_platform(platform) == "windows"} { + fconfigure stdout -translation lf +} + +puts {/* DO NOT EDIT +** The code in this file was automatically generated. +*/ +#include <tk.h> +#include "htmltokens.h" +#if INTERFACE +struct HtmlTokenMap { + char *zName; /* Name of a markup */ + Html_16 type; /* Markup type code */ + Html_16 extra; /* Extra space needed above HtmlBaseElement */ + HtmlTokenMap *pCollide; /* Hash table collision chain */ +}; +#define Html_Text 1 +#define Html_Space 2 +#define Html_Unknown 3 +#define Html_Block 4 +#define HtmlIsMarkup(X) ((X)->base.type>Html_Block) +} + +set count 5 +set fmt {#define %-20s %d} + +foreach {name start end} $tokenlist { + set upr [string toupper $name] + puts [format $fmt Html_$upr $count] + incr count + if {$end!=""} { + puts [format $fmt Html_End$upr $count] + incr count + } +} + +puts [format $fmt Html_TypeCount [expr $count-1]] +puts "#define HTML_MARKUP_HASH_SIZE [expr $count+11]" +puts "#define HTML_MARKUP_COUNT [expr $count-5]" +puts "#endif /* INTERFACE */" +puts "HtmlTokenMap HtmlMarkupMap\[\] = {" + +set fmt " { %-15s %-25s %-30s }," + +foreach {name start end} $tokenlist { + set upr [string toupper $name] + set nm "\"$name\"," + set val Html_$upr, + if {$start=="0"} { + set size "0," + } else { + set size "sizeof($start)," + } + puts [format $fmt $nm $val $size] + if {$end==""} continue + set nm "\"/$name\"," + set val Html_End$upr, + if {$end=="0"} { + set size "0," + } else { + set size "sizeof($end)," + } + puts [format $fmt $nm $val $size] +} + +puts "};" diff --git a/tkhtml1/tools/sgmlparse.c b/tkhtml1/tools/sgmlparse.c new file mode 100644 index 0000000..d85806e --- /dev/null +++ b/tkhtml1/tools/sgmlparse.c @@ -0,0 +1,207 @@ +/* +** This file contains code used to tokenize SGML. +*/ +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> +#include "sgmlparse.h" + +#define stricmp strcasecmp + +/* These three pointers define certain special handlers. All whitespace +** is sent to xSpaceHandler. Non-whitespace is given to xWordHandler. +** Any markup that isn't specifically directed elsewhere is given +** to xDefaultMarkupHandlers. +*/ +static void (*xSpaceHandler)(const char*,void*); +static void (*xWordHandler)(const char*,void*); +static void (*xCommentHandler)(const char*,void*); +static void (*xDefaultMarkupHandler)(int, const char**, void*); + +/* Each handler is stored in a hash table as an instance of the +** following structure. +*/ +typedef struct sgHandler Handler; +struct sgHandler { + char *zName; /* Name of markup to handle */ + void (*xHandler)(int, const char**, void*); /* Routine to do the work */ + Handler *pCollide; /* Next handler with same hash */ +}; + +/* The size of the handler hash table. +** For best results, this should be a prime number which is larger than +** the number of markups in the hash table. +*/ +#define SGML_HASH_SIZE 203 + +/* The handler hash table */ +static Handler *apHandler[SGML_HASH_SIZE]; + +/* Hash a handler name */ +static int SgmlHash(const char *zName){ + int h = 0; + char c; + while( (c=*zName)!=0 ){ + if( isupper(c) ) c = tolower(c); + h = h<<5 ^ h ^ c; + zName++; + } + if( h<0 ) h = -h; + return h % SGML_HASH_SIZE; +} + +/* Given a pointer to an input file, read and parse that file +** as if it were SGML. +** +** This is not a true SGML parser because it handles some unusual +** cases differently, and ignores the & operator completely. +*/ +void SgmlParse(FILE *in, void *pArg){ + int c; + int i, j; + int argc; + Handler *pHandler; + char *argv[100]; + char zBuf[10000]; + + c = getc(in); + while( c!=EOF ){ + if( isspace(c) ){ + /* Case 1: spaces */ + zBuf[0] = c; + i = 1; + while( i<sizeof(zBuf)-2 && (c=getc(in))!=EOF && isspace(c) ){ + zBuf[i++] = c; + } + zBuf[i] = 0; + /* Dispose of space */ + if( xSpaceHandler ){ + (*xSpaceHandler)(zBuf,pArg); + } + }else if( c=='<' ){ + int cQuote = 0; + i = 0; + zBuf[i++] = c; + while( (c=getc(in))!=EOF && (cQuote || c!='>') ){ + if( i<sizeof(zBuf)-3 ) zBuf[i++] = c; + if( cQuote ){ + if( cQuote==c ) cQuote = 0; + }else if( c=='"' || c=='\'' ){ + cQuote = c; + } + } + if( c=='>' ) c = getc(in); + zBuf[i] = 0; + if( strncmp(zBuf,"<!--",4)==0 ){ + zBuf[i++] = '>'; + zBuf[i] = 0; + if( xCommentHandler ){ + (*xCommentHandler)(zBuf,pArg); + } + continue; + } + argc = 0; + argv[0] = &zBuf[1]; + for(j=1; zBuf[j] && !isspace(zBuf[j]); j++){} + if( zBuf[j] ){ + zBuf[j++] = 0; + while( argc<(sizeof(argv)/sizeof(argv[0])) - 4 && zBuf[j] ){ + while( isspace(zBuf[j]) ) j++; + argv[++argc] = &zBuf[j]; + while( zBuf[j] && !isspace(zBuf[j]) && zBuf[j]!='=' ) j++; + if( zBuf[j]!='=' ){ + argv[argc+1] = argv[argc]; + argc++; + if( zBuf[j] ) zBuf[j++] = 0; + continue; + } + zBuf[j++] = 0; + if( zBuf[j]=='"' || zBuf[j]=='\'' ){ + cQuote = zBuf[j++]; + }else{ + cQuote = 0; + } + argv[++argc] = &zBuf[j]; + if( cQuote ){ + while( zBuf[j] && zBuf[j]!=cQuote ) j++; + }else{ + while( zBuf[j] && !isspace(zBuf[j]) ) j++; + } + if( zBuf[j] ) zBuf[j++] = 0; + } + } + argv[++argc] = 0; + /* Despose of a markup */ + pHandler = apHandler[SgmlHash(argv[0])]; + while( pHandler && stricmp(pHandler->zName,argv[0])!=0 ){ + pHandler = pHandler->pCollide; + } + if( pHandler ){ + if( pHandler->xHandler ){ + (*pHandler->xHandler)(argc,(const char**)argv,pArg); + } + }else if( xDefaultMarkupHandler ){ + (*xDefaultMarkupHandler)(argc,(const char**)argv,pArg); + } + }else{ + zBuf[0] = c; + i = 1; + while( i<sizeof(zBuf)-2 && (c=getc(in))!=EOF && c!='<' && !isspace(c) ){ + zBuf[i++] = c; + } + zBuf[i] = 0; + /* Dispose of a word */ + if( xWordHandler ){ + (*xWordHandler)(zBuf,pArg); + } + } + } +} + +/* +** Clear out the handler hash table +*/ +void SgmlHandlerReset(void){ + Handler *pHandler; + int i; + + for(i=0; i<SGML_HASH_SIZE; i++){ + Handler *pNext; + for(pHandler=apHandler[i]; pHandler; pHandler=pNext){ + pNext = pHandler->pCollide; + free(pHandler); + } + apHandler[i] = 0; + } +} + +/* Install a new handler +*/ +void SgmlHandler(const char *zName, void (*xFunc)(int,const char**,void*)){ + int h = SgmlHash(zName); + extern void *malloc(); + Handler *pNew = malloc( sizeof(Handler) + strlen(zName) + 1 ); + if( pNew==0 ) return; + pNew->zName = (char*)&pNew[1]; + strcpy(pNew->zName,zName); + pNew->pCollide = apHandler[h]; + pNew->xHandler = xFunc; + apHandler[h] = pNew; +} + +/* Install the default handlers +*/ +void SgmlWordHandler(void (*xWord)(const char*,void*)){ + xWordHandler = xWord; +} +void SgmlSpaceHandler(void (*xSpace)(const char*,void*)){ + xSpaceHandler = xSpace; +} +void SgmlCommentHandler(void (*xComment)(const char*,void*)){ + xCommentHandler = xComment; +} +void SgmlDefaultMarkupHandler(void (*xMarkup)(int,const char**,void*)){ + xDefaultMarkupHandler = xMarkup; +} diff --git a/tkhtml1/tools/url.c b/tkhtml1/tools/url.c new file mode 100644 index 0000000..677cbba --- /dev/null +++ b/tkhtml1/tools/url.c @@ -0,0 +1,268 @@ +/* +** This file contains code use for resolving relative URLs +*/ +#include <stdlib.h> +#include "url.h" + +#if INTERFACE +/* +** A parsed URI is held in an instance of the following structure. +** Each component is recorded in memory obtained from malloc(). +** +** The examples are from the URI +** +** http://192.168.1.1:8080/cgi-bin/printenv?name=xyzzy&addr=none#frag +*/ +typedef struct Url Url; +struct Url { + char *zScheme; /* Ex: "http" */ + char *zAuthority; /* Ex: "192.168.1.1:8080" */ + char *zPath; /* Ex: "cgi-bin/printenv" */ + char *zQuery; /* Ex: "name=xyzzy&addr=none" */ + char *zFragment; /* Ex: "frag" */ +}; +#endif + +/* +** Return the length of the next component of the URL in z[] given +** that the component starts at z[0]. The initial sequence of the +** component must be zInit[]. The component is terminated by any +** character in zTerm[]. The length returned is 0 if the component +** doesn't exist. The length includes the zInit[] string, but not +** the termination character. +** +** Component zInit zTerm +** ---------- ------- ------- +** scheme "" ":/?#" +** authority "//" "/?#" +** path "/" "?#" +** query "?" "#" +** fragment "#" "" +*/ +static int ComponentLength(const char *z, const char *zInit, const char *zTerm){ + int i, n; + for(n=0; zInit[n]; n++){ + if( zInit[n]!=z[n] ) return 0; + } + while( z[n] ){ + for(i=0; zTerm[i]; i++){ + if( z[n]==zTerm[i] ) return n; + } + n++; + } + return n; +} + +/* +** Duplicate a string of length n. +*/ +static char *StrNDup(const char *z, int n){ + char *zResult; + if( n<=0 ){ + n = strlen(z); + } + zResult = malloc( n + 1 ); + if( zResult ){ + memcpy(zResult, z, n); + zResult[n] = 0; + } + return zResult; +} + +/* +** Parse a text URI into an Url structure. +*/ +Url *ParseUrl(const char *zUri){ + Url *p; + int n; + + p = malloc( sizeof(*p) ); + if( p==0 ) return 0; + memset(p, 0, sizeof(*p)); + if( zUri==0 || zUri[0]==0 ) return p; + while( isspace(zUri[0]) ){ zUri++; } + n = ComponentLength(zUri, "", ":/?# "); + if( n>0 && zUri[n]==':' ){ + p->zScheme = StrNDup(zUri, n); + zUri += n+1; + } + n = ComponentLength(zUri, "//", "/?# "); + if( n>0 ){ + p->zAuthority = StrNDup(&zUri[2], n-2); + zUri += n; + } + n = ComponentLength(zUri, "", "?# "); + if( n>0 ){ + p->zPath = StrNDup(zUri, n); + zUri += n; + } + n = ComponentLength(zUri, "?", "# "); + if( n>0 ){ + p->zQuery = StrNDup(&zUri[1], n-1); + zUri += n; + } + n = ComponentLength(zUri, "#", " "); + if( n>0 ){ + p->zFragment = StrNDup(&zUri[1], n-1); + } + return p; +} + +/* +** Delete an Url structure. +*/ +void FreeUrl(Url *p){ + if( p==0 ) return; + if( p->zScheme ) free(p->zScheme); + if( p->zAuthority ) free(p->zAuthority); + if( p->zPath ) free(p->zPath); + if( p->zQuery ) free(p->zQuery); + if( p->zFragment ) free(p->zFragment); + free(p); +} + +/* +** Create a string to hold the given URI. Memory to hold the string +** is obtained from malloc() and must be freed by the calling +** function. +*/ +char *BuildUrl(Url *p){ + int n = 1; + char *z; + if( p->zScheme ) n += strlen(p->zScheme)+1; + if( p->zAuthority ) n += strlen(p->zAuthority)+2; + if( p->zPath ) n += strlen(p->zPath)+1; + if( p->zQuery ) n += strlen(p->zQuery)+1; + if( p->zFragment ) n += strlen(p->zFragment)+1; + z = malloc( n ); + if( z==0 ) return 0; + n = 0; + if( p->zScheme ){ + sprintf(z, "%s:", p->zScheme); + n = strlen(z); + } + if( p->zAuthority ){ + sprintf(&z[n], "//%s", p->zAuthority); + n += strlen(&z[n]); + } + if( p->zPath ){ + sprintf(&z[n], "%s", p->zPath); + n += strlen(&z[n]); + } + if( p->zQuery ){ + sprintf(&z[n], "?%s", p->zQuery); + n += strlen(&z[n]); + } + if( p->zFragment ){ + sprintf(&z[n], "#%s", p->zFragment); + } + return z; +} + +/* +** Replace the string in *pzDest with the string in zSrc +*/ +static void ReplaceStr(char **pzDest, const char *zSrc){ + if( *pzDest!=0 ) free(*pzDest); + if( zSrc==0 ){ + *pzDest = 0; + }else{ + *pzDest = StrNDup(zSrc, -1); + } +} + +/* +** Remove leading and trailing spaces from the given string. Return +** a new string obtained from malloc(). +*/ +static char *Trim(char *z){ + int i; + char *zNew; + while( isspace(*z) ) z++; + i = strlen(z); + zNew = malloc( i+1 ); + if( zNew==0 ) return 0; + strcpy(zNew, z); + if( i>0 && isspace(zNew[i-1]) ){ + i--; + zNew[i] = 0; + } + return zNew; +} + +/* +** Resolve a sequence of URLs. Return the result in space obtained +** from malloc(). +*/ +char *ResolveUrl( + char *zBase, /* The base URL */ + const char **azSeries /* A list of relatives. NULL terminated */ +){ + Url *base; + Url *term; + char *z; + + base = ParseUrl(zBase); + while( azSeries[0] ){ + term = ParseUrl(azSeries[0]); + azSeries++; + if( term->zScheme==0 && term->zAuthority==0 && term->zPath==0 + && term->zQuery==0 && term->zFragment ){ + ReplaceStr(&base->zFragment, term->zFragment); + }else if( term->zScheme ){ + Url temp; + temp = *term; + *term = *base; + *base = temp; + }else if( term->zAuthority ){ + ReplaceStr(&base->zAuthority, term->zAuthority); + ReplaceStr(&base->zPath, term->zPath); + ReplaceStr(&base->zQuery, term->zQuery); + ReplaceStr(&base->zFragment, term->zFragment); + }else if( term->zPath && term->zPath[0]=='/' ){ + ReplaceStr(&base->zPath, term->zPath); + ReplaceStr(&base->zQuery, term->zQuery); + ReplaceStr(&base->zFragment, term->zFragment); + }else if( term->zPath && base->zPath ){ + char *zBuf; + int i, j; + zBuf = malloc( strlen(base->zPath) + strlen(term->zPath) + 2 ); + if( zBuf ){ + sprintf(zBuf,"%s", base->zPath); + for(i=strlen(zBuf)-1; i>=0 && zBuf[i]!='/'; i--){ zBuf[i] = 0; } + strcat(zBuf, term->zPath); + for(i=0; zBuf[i]; i++){ + if( zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]=='/' ){ + strcpy(&zBuf[i+1], &zBuf[i+3]); + i--; + continue; + } + if( zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]==0 ){ + zBuf[i+1] = 0; + continue; + } + if( i>0 && zBuf[i]=='/' && zBuf[i+1]=='.' && zBuf[i+2]=='.' + && (zBuf[i+3]=='/' || zBuf[i+3]==0) ){ + for(j=i-1; j>=0 && zBuf[j]!='/'; j--){} + if( zBuf[i+3] ){ + strcpy(&zBuf[j+1], &zBuf[i+4]); + }else{ + zBuf[j+1] = 0; + } + i = j-1; + if( i<-1 ) i = -1; + continue; + } + } + free(base->zPath); + base->zPath = zBuf; + } + ReplaceStr(&base->zQuery, term->zQuery); + ReplaceStr(&base->zFragment, term->zFragment); + } + FreeUrl(term); + } + z = BuildUrl(base); + FreeUrl(base); + return z; +} |