Import exactly the files of the teapot-2.3.0 distribution
146
CMakeLists.txt
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
project(Teapot)
|
||||||
|
|
||||||
|
set(Teapot_VERSION_MAJOR 2)
|
||||||
|
set(Teapot_VERSION_MINOR 3)
|
||||||
|
set(Teapot_VERSION_PATCH 0)
|
||||||
|
|
||||||
|
option(ENABLE_HELP "Enable built-in documentation" ON)
|
||||||
|
option(ENABLE_UTF8 "Enable UTF-8 support" ON)
|
||||||
|
option(ENABLE_STATIC "Link FLTK statically" OFF)
|
||||||
|
|
||||||
|
add_library(teapotlib context.c csv.c eval.c func.c htmlio.c latex.c main.c misc.c parser.c sc.c scanner.c sheet.c utf8.c wk1.c xdr.c)
|
||||||
|
|
||||||
|
find_library(LIB_PORTABLEXDR portablexdr)
|
||||||
|
if (NOT LIB_PORTABLEXDR)
|
||||||
|
set(LIB_PORTABLEXDR "")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
find_package(Curses)
|
||||||
|
if (CURSES_FOUND AND ENABLE_UTF8)
|
||||||
|
find_library(LIB_CURSESW ncursesw)
|
||||||
|
if (NOT LIB_CURSESW)
|
||||||
|
find_library(LIB_CURSESW ncursesw5)
|
||||||
|
endif ()
|
||||||
|
if (LIB_CURSESW)
|
||||||
|
set(teapot_DEB_DEPENDS ", libncursesw5 (>= 5.6+20071006-3)")
|
||||||
|
set(CURSES_CURSES_LIBRARY ${LIB_CURSESW})
|
||||||
|
else ()
|
||||||
|
set(ENABLE_UTF8 OFF)
|
||||||
|
set(teapot_DEB_DEPENDS ", libncurses5 (>= 5.6+20071006-3)")
|
||||||
|
endif ()
|
||||||
|
elseif (CURSES_FOUND)
|
||||||
|
set(teapot_DEB_DEPENDS ", libncurses5 (>= 5.6+20071006-3)")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (CURSES_FOUND)
|
||||||
|
include_directories("${CURSES_INCLUDE_DIR}")
|
||||||
|
add_executable(teapot display.c complete.c)
|
||||||
|
target_link_libraries(teapot teapotlib m ${CURSES_CURSES_LIBRARY} ${LIB_PORTABLEXDR})
|
||||||
|
install(TARGETS teapot DESTINATION bin)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
find_package(FLTK NO_MODULE)
|
||||||
|
if (FLTK_FOUND)
|
||||||
|
include("${FLTK_USE_FILE}")
|
||||||
|
|
||||||
|
fltk_wrap_ui(fteapot fteapot.fl)
|
||||||
|
add_executable(fteapot WIN32 ${fteapot_FLTK_UI_SRCS})
|
||||||
|
set(fteapot_DEB_DEPENDS ", libstdc++6 (>= 4.1.1), libfltk1.3")
|
||||||
|
if (ENABLE_HELP)
|
||||||
|
set(fteapot_DEB_DEPENDS "${fteapot_DEB_DEPENDS}, libfltk-images1.3")
|
||||||
|
if (ENABLE_STATIC)
|
||||||
|
target_link_libraries(fteapot teapotlib fltk fltk_images ${LIB_PORTABLEXDR})
|
||||||
|
else ()
|
||||||
|
target_link_libraries(fteapot teapotlib fltk_SHARED fltk_images_SHARED ${LIB_PORTABLEXDR})
|
||||||
|
endif ()
|
||||||
|
else ()
|
||||||
|
if (ENABLE_STATIC)
|
||||||
|
target_link_libraries(fteapot teapotlib fltk fltk_images ${LIB_PORTABLEXDR})
|
||||||
|
else ()
|
||||||
|
target_link_libraries(fteapot teapotlib fltk_SHARED ${LIB_PORTABLEXDR})
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
install(TARGETS fteapot DESTINATION bin)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (ENABLE_HELP)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT teapot.tex teapot.lyx
|
||||||
|
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/doc/teapot.lyx
|
||||||
|
VERBATIM
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/doc/teapot.lyx teapot.lyx
|
||||||
|
COMMAND lyx -e pdflatex -f main teapot.lyx
|
||||||
|
)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT teapot.pdf teapot.aux.old teapot.log teapot.toc
|
||||||
|
MAIN_DEPENDENCY teapot.tex
|
||||||
|
VERBATIM
|
||||||
|
COMMAND pdflatex teapot.tex; diff -q teapot.aux.old teapot.aux && cp teapot.aux teapot.aux.old
|
||||||
|
COMMAND pdflatex teapot.tex; diff -q teapot.aux.old teapot.aux && cp teapot.aux teapot.aux.old
|
||||||
|
)
|
||||||
|
add_custom_command(OUTPUT teapot.pdf teapot.out MAIN_DEPENDENCY teapot.tex teapot.aux.old VERBATIM COMMAND pdflatex teapot.tex; diff -q teapot.aux.old teapot.aux && cp teapot.aux teapot.aux.old)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT html/ html/index.html .latex2html-init
|
||||||
|
MAIN_DEPENDENCY teapot.tex
|
||||||
|
DEPENDS teapot.tex teapot.pdf ${CMAKE_CURRENT_SOURCE_DIR}/doc/.latex2html-init
|
||||||
|
VERBATIM
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/doc/.latex2html-init .latex2html-init
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory html
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/doc/contents.png html/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/doc/next.png html/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/doc/next_g.png html/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/doc/prev.png html/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/doc/prev_g.png html/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/doc/up.png html/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/doc/up_g.png html/
|
||||||
|
COMMAND latex2html teapot.tex
|
||||||
|
)
|
||||||
|
add_custom_target(pdf DEPENDS teapot.pdf)
|
||||||
|
add_custom_target(html DEPENDS html/index.html)
|
||||||
|
add_custom_target(doc ALL DEPENDS teapot.pdf html/index.html)
|
||||||
|
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION share/doc/teapot FILES_MATCHING PATTERN *.html PATTERN *.png)
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/teapot.pdf DESTINATION share/doc/teapot)
|
||||||
|
set(HELPFILE "${CMAKE_INSTALL_PREFIX}/share/doc/teapot/index.html")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
install(FILES COPYING README DESTINATION share/doc/teapot)
|
||||||
|
install(FILES teapot.1 DESTINATION share/man/man1)
|
||||||
|
|
||||||
|
add_custom_target(dist
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E remove_directory teapot-${Teapot_VERSION_MAJOR}.${Teapot_VERSION_MINOR}.${Teapot_VERSION_PATCH}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory teapot-${Teapot_VERSION_MAJOR}.${Teapot_VERSION_MINOR}.${Teapot_VERSION_PATCH}
|
||||||
|
COMMAND LANG=C bash -c "cp -r ${CMAKE_CURRENT_SOURCE_DIR}/doc ${CMAKE_CURRENT_SOURCE_DIR}/examples ${CMAKE_CURRENT_SOURCE_DIR}/[A-Z]*[A-Z] ${CMAKE_CURRENT_SOURCE_DIR}/*.*[a-z1] teapot-${Teapot_VERSION_MAJOR}.${Teapot_VERSION_MINOR}.${Teapot_VERSION_PATCH}"
|
||||||
|
COMMAND tar czf teapot-${Teapot_VERSION_MAJOR}.${Teapot_VERSION_MINOR}.${Teapot_VERSION_PATCH}.tar.gz teapot-${Teapot_VERSION_MAJOR}.${Teapot_VERSION_MINOR}.${Teapot_VERSION_PATCH}
|
||||||
|
COMMAND setarch ${CPACK_RPM_PACKAGE_ARCHITECTURE} cpack
|
||||||
|
COMMAND bash -c "[ ! -f fteapot ] || for i in Teapot-*-Linux.*; do mv \"\$i\" \"\${i%-Linux.*}-Linux-${CPACK_RPM_PACKAGE_ARCHITECTURE}.\${i##*-Linux.}\"; done"
|
||||||
|
COMMAND bash -c "[ ! -f fteapot.exe -o ${ENABLE_HELP} != OFF ] || { rm Teapot-*.zip; i586-mingw32msvc-strip fteapot.exe && upx -9 -o Teapot-${Teapot_VERSION_MAJOR}.${Teapot_VERSION_MINOR}.${Teapot_VERSION_PATCH}-win32-minimal.exe fteapot.exe; }"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${PROJECT_BINARY_DIR}/config.h")
|
||||||
|
include_directories("${PROJECT_BINARY_DIR}")
|
||||||
|
include_directories("${PROJECT_SOURCE_DIR}")
|
||||||
|
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ARCH-NOTFOUND CACHE ".deb Architecture" STRING)
|
||||||
|
set(CPACK_RPM_PACKAGE_ARCHITECTURE ARCH-NOTFOUND CACHE ".rpm Architecture" STRING)
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Table Editor And Planner, Or: Teapot!")
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION "A three-dimensional spreadsheet specialized in advanced calculations. Comes in GUI (FLTK) and console (curses) flavours.")
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
|
||||||
|
set(CPACK_PACKAGE_VENDOR "Jörg Walter, http://www.syntax-k.de/projekte/teapot")
|
||||||
|
|
||||||
|
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
|
||||||
|
set(CPACK_PACKAGE_VERSION_MAJOR "${Teapot_VERSION_MAJOR}")
|
||||||
|
set(CPACK_PACKAGE_VERSION_MINOR "${Teapot_VERSION_MINOR}")
|
||||||
|
set(CPACK_PACKAGE_VERSION_PATCH "${Teapot_VERSION_PATCH}")
|
||||||
|
set(CPACK_PACKAGE_CONTACT "Jörg Walter <info@syntax-k.de>")
|
||||||
|
set(CPACK_PACKAGE_EXECUTABLES "fteapot" "Teapot")
|
||||||
|
set(CPACK_STRIP_FILES TRUE)
|
||||||
|
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.11), libgcc1 (>= 1:4.1.1)${teapot_DEB_DEPENDS}${fteapot_DEB_DEPENDS}")
|
||||||
|
include(InstallRequiredSystemLibraries)
|
||||||
|
include(CPack)
|
||||||
|
|
||||||
|
if (NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
|
||||||
|
endif ()
|
674
COPYING
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. 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
|
||||||
|
them 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 prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. 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.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey 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;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If 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 convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU 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 that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
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.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
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
|
||||||
|
state 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) <year> <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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program 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, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU 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. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
31
INSTALL
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
The new build system uses CMake (http://www.cmake.org). It handles
|
||||||
|
all platform differences.
|
||||||
|
|
||||||
|
See the README for required third-party libraries.
|
||||||
|
|
||||||
|
The documentation can only be built if you have latex2html (version
|
||||||
|
2008), pdflatex and lyx installed. If you don't, turn off the
|
||||||
|
ENABLE_HELP option (using the ccmake command or any other CMake
|
||||||
|
frontend).
|
||||||
|
|
||||||
|
Note that the GUI version definitely needs FLTK-1.3, so you may need
|
||||||
|
to download and build an SVN snapshot. SVN r7704 was used for development.
|
||||||
|
You MUST use CMake to configure FLTK, not "./configure". You don't need
|
||||||
|
to install it, as FLTK is so small that statically linking it (the default)
|
||||||
|
is safe. If you don't install FLTK, set the path to your FLTK directory
|
||||||
|
using ccmake.
|
||||||
|
|
||||||
|
For the console version you will have to make sure your system
|
||||||
|
offers a SYSV compatible curses. You can check that you do by looking
|
||||||
|
at its include file curses.h; it should e.g. contain KEY_ macros. If you
|
||||||
|
have a system which contains BSD and SYSV curses libraries, make sure (by
|
||||||
|
checking the cmake variables) that the SYSV curses.h is used. This
|
||||||
|
particularly applies if you use the SYSV curses clone ncurses. If you do
|
||||||
|
so, further make sure that you use version 4 or higher. Otherwise teapot
|
||||||
|
may not work correctly and you get corrupted screen output. Since version
|
||||||
|
4 makes it easy to be built as shared (ELF) library, this can reduce the
|
||||||
|
size of the teapot binary considerably.
|
||||||
|
|
||||||
|
If you want the curses frontend to be fully UTF-8 aware, you need
|
||||||
|
libncursesw (Debian package name: libncursesw5-dev).
|
||||||
|
|
62
NEWS
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
This is release 2.3.0 of teapot (Table Editor And Planner, Or: Teapot),
|
||||||
|
a spread sheet program for UNIX.
|
||||||
|
|
||||||
|
The changes compared to 2.2.1 are:
|
||||||
|
|
||||||
|
o visual garbage fixed (curses version)
|
||||||
|
o made unquoted strings default, added "-q" flag to turn quotes back on
|
||||||
|
o made attributes menu more user friendly: no more question when changing a single cell, one menu option optimized away
|
||||||
|
o added "-H" command line flag to hide row/column headers; in FLTK, this means you can only change sheets via Ctrl-Shift-PgUp/PgDn
|
||||||
|
o expanded command line help
|
||||||
|
|
||||||
|
The changes compared to 2.2.0 are:
|
||||||
|
|
||||||
|
o Help system improved
|
||||||
|
o Compile fix for MacOS
|
||||||
|
o Link shared by default. Set option ENABLE_STATIC to statically link FLTK.
|
||||||
|
o Bugfixes for CSV export
|
||||||
|
o Bugfixes for console mode
|
||||||
|
o Added font styles bold and underline
|
||||||
|
|
||||||
|
The changes compared to 2.1.0 are:
|
||||||
|
|
||||||
|
o UTF-8 support for curses frontend
|
||||||
|
o various bug fixes
|
||||||
|
|
||||||
|
The changes compared to 2.0.2 are:
|
||||||
|
|
||||||
|
o switched to CMake as build system
|
||||||
|
o Win32 compatibility
|
||||||
|
o usage improvements in the GUI version
|
||||||
|
o various bug fixes
|
||||||
|
|
||||||
|
The changes compared to 2.0.1 are:
|
||||||
|
|
||||||
|
o Low-resource builds (leaving out the help system)
|
||||||
|
o various bug fixes
|
||||||
|
|
||||||
|
The changes compared to 2.0 are:
|
||||||
|
|
||||||
|
o Fix a possible crash and some minor bugs
|
||||||
|
o improve FLTK navigation and cell editing (moving around and
|
||||||
|
selecting cells now works while editing a formula)
|
||||||
|
o automatically start a string value when typing a letter
|
||||||
|
o fix build system
|
||||||
|
|
||||||
|
The changes compared to 1.09 are:
|
||||||
|
|
||||||
|
o Several bug fixes and changes how files are handled
|
||||||
|
o FLTK user interface
|
||||||
|
o Built-in Help and About screen (currently only in FLTK)
|
||||||
|
o License changed to GPL (see mbox file in doc folder for permission)
|
||||||
|
|
||||||
|
The changes compared to 1.07 are:
|
||||||
|
|
||||||
|
o Use KEY_HOME additional to KEY_BEG to move to the beginning of
|
||||||
|
the line in the line editor
|
||||||
|
|
||||||
|
A GNU zipped tar file is available from:
|
||||||
|
|
||||||
|
http://www.syntax-k.de/projekte/teapot/
|
||||||
|
|
||||||
|
Michael
|
52
README
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
This is release 2.3.0 of teapot (Table Editor And Planner, Or: Teapot),
|
||||||
|
a spread sheet program for UNIX.
|
||||||
|
|
||||||
|
Copyright (C) 1995-2006 Michael Haardt
|
||||||
|
Copyright (C) 2009-2012 Joerg Walter
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The current release has the following features:
|
||||||
|
|
||||||
|
o curses based user interface with easy to understand menus
|
||||||
|
o FLTK 1.3 based GUI following common user interface conventions
|
||||||
|
o Cross-platform compatibility
|
||||||
|
o UTF-8 support
|
||||||
|
o portable sheet file format uses XDR or ASCII format
|
||||||
|
o tbl, LaTeX, HTML, CSV or formatted text files can be generated and
|
||||||
|
simple SC and WK1 sheets can be imported
|
||||||
|
o typed expression evaluator with the types int, float, string, error,
|
||||||
|
pointer to cell and empty
|
||||||
|
o iterative expressions
|
||||||
|
o powerful cell addressing
|
||||||
|
o three-dimensional sheets
|
||||||
|
o new expression evaluator functions can be added very easy
|
||||||
|
o a user guide, available as PDF and HTML
|
||||||
|
o It is still a small and simple program!
|
||||||
|
|
||||||
|
teapot should work on any system which supports the following:
|
||||||
|
|
||||||
|
o ANSI C
|
||||||
|
o An XDR library (included in the GNU C library, otherwise
|
||||||
|
use http://people.redhat.com/~rjones/portablexdr/ )
|
||||||
|
o For the text interface: SYSV curses or ncurses library
|
||||||
|
o For UTF-8 in the text interface: libncursesw and a UTF-8 locale
|
||||||
|
o For the FLTK interface: C++
|
||||||
|
o For the FLTK interface: FLTK 1.3
|
||||||
|
|
||||||
|
A GNU zipped tar file is available from:
|
||||||
|
|
||||||
|
http://www.syntax-k.de/projekte/teapot/
|
||||||
|
|
||||||
|
For more information, read the included manual in HTML or PDF format.
|
||||||
|
|
55
complete.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#define _XOPEN_SOURCE 500
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "complete.h"
|
||||||
|
|
||||||
|
void completefile(char *file, char *pos, size_t size)
|
||||||
|
{
|
||||||
|
struct dirent *direntp;
|
||||||
|
char *dir, *slash, *complete;
|
||||||
|
char next;
|
||||||
|
int required, atmost;
|
||||||
|
DIR *dirp;
|
||||||
|
|
||||||
|
next = *pos;
|
||||||
|
*pos = 0;
|
||||||
|
|
||||||
|
if (!(complete=strrchr(file,'/'))) {
|
||||||
|
dir = strdup(".");
|
||||||
|
complete = file;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (complete == file) {
|
||||||
|
dir = strdup("/");
|
||||||
|
} else {
|
||||||
|
dir = strdup(file);
|
||||||
|
dir[complete-file] = 0;
|
||||||
|
}
|
||||||
|
complete++;
|
||||||
|
}
|
||||||
|
required = strlen(complete);
|
||||||
|
|
||||||
|
if (!(dirp = opendir(dir))) {
|
||||||
|
free(dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((direntp = readdir(dirp))) {
|
||||||
|
if ((direntp->d_name[0] != '.' || complete[0] == '.') && !strncmp(complete, direntp->d_name, required)) {
|
||||||
|
if (!next && strlen(direntp->d_name) > required) {
|
||||||
|
strncpy(pos, direntp->d_name+required, size-(pos-file));
|
||||||
|
file[size-1] = 0;
|
||||||
|
break;
|
||||||
|
} else if (direntp->d_name[required] == next && !strcmp(pos+1, direntp->d_name+required+1)) {
|
||||||
|
next = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dirp);
|
||||||
|
free(dir);
|
||||||
|
}
|
6
complete.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef COMPLETE_H
|
||||||
|
#define COMPLETE_H
|
||||||
|
|
||||||
|
void completefile(char *, char *, size_t size);
|
||||||
|
|
||||||
|
#endif
|
13
config.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* configuration values */
|
||||||
|
|
||||||
|
|
||||||
|
#define VERSION "2.2.1"
|
||||||
|
|
||||||
|
#define HELPFILE "/usr/local/share/doc/teapot/html/index.html"
|
||||||
|
|
||||||
|
#define ENABLE_HELP
|
||||||
|
#define ENABLE_UTF8
|
||||||
|
#define CURSES_HAVE_CURSES_H
|
||||||
|
/* #undef CURSES_HAVE_NCURSES_H */
|
||||||
|
/* #undef CURSES_HAVE_NCURSES_NCURSES_H */
|
||||||
|
/* #undef CURSES_HAVE_NCURSES_CURSES_H */
|
13
config.h.in
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* configuration values */
|
||||||
|
|
||||||
|
|
||||||
|
#define VERSION "@Teapot_VERSION_MAJOR@.@Teapot_VERSION_MINOR@.@Teapot_VERSION_PATCH@"
|
||||||
|
|
||||||
|
#define HELPFILE "@HELPFILE@"
|
||||||
|
|
||||||
|
#cmakedefine ENABLE_HELP
|
||||||
|
#cmakedefine ENABLE_UTF8
|
||||||
|
#cmakedefine CURSES_HAVE_CURSES_H
|
||||||
|
#cmakedefine CURSES_HAVE_NCURSES_H
|
||||||
|
#cmakedefine CURSES_HAVE_NCURSES_NCURSES_H
|
||||||
|
#cmakedefine CURSES_HAVE_NCURSES_CURSES_H
|
138
context.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||||
|
#ifndef NO_POSIX_SOURCE
|
||||||
|
#undef _POSIX_SOURCE
|
||||||
|
#define _POSIX_SOURCE 1
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DMALLOC
|
||||||
|
#include "dmalloc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "misc.h"
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* savecontext -- save as ConTeXt table */ /*{{{*/
|
||||||
|
const char *savecontext(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count)
|
||||||
|
{
|
||||||
|
/* variables */ /*{{{*/
|
||||||
|
FILE *fp=(FILE*)0; /* cause runtime error */
|
||||||
|
int x,y,z;
|
||||||
|
char buf[1024];
|
||||||
|
char num[20];
|
||||||
|
char fullname[PATH_MAX];
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* asserts */ /*{{{*/
|
||||||
|
assert(sheet!=(Sheet*)0);
|
||||||
|
assert(name!=(const char*)0);
|
||||||
|
/*}}}*/
|
||||||
|
*count=0;
|
||||||
|
for (z=z1; z<=z2; ++z) for (y=y1; y<=y2; ++y) if (shadowed(sheet,x1,y,z)) return _("Shadowed cells in first column");
|
||||||
|
if (!body && (fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
|
||||||
|
for (z=z1; z<=z2; ++z)
|
||||||
|
{
|
||||||
|
if (body)
|
||||||
|
/* open new file */ /*{{{*/
|
||||||
|
{
|
||||||
|
sprintf(num,".%d",z);
|
||||||
|
|
||||||
|
fullname[sizeof(fullname)-strlen(num)-1]='\0';
|
||||||
|
(void)strncpy(fullname,name,sizeof(fullname)-strlen(num)-1);
|
||||||
|
fullname[sizeof(fullname)-1]='\0';
|
||||||
|
(void)strncat(fullname,num,sizeof(fullname)-strlen(num)-1);
|
||||||
|
fullname[sizeof(fullname)-1]='\0';
|
||||||
|
if ((fp=fopen(fullname,"w"))==(FILE*)0) return strerror(errno);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else
|
||||||
|
/* print header */ /*{{{*/
|
||||||
|
if (z==z1)
|
||||||
|
{
|
||||||
|
if (fputs_close("\\starttext\n",fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fputs_close("\\page\n",fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* print bogus format */ /*{{{*/
|
||||||
|
fprintf(fp,"\\starttable[");
|
||||||
|
for (x=x1; x<=x2; ++x) if (fputs_close("|l",fp)==EOF) return strerror(errno);
|
||||||
|
fprintf(fp,"|]\n");
|
||||||
|
/*}}}*/
|
||||||
|
for (y=y1; y<=y2; ++y)
|
||||||
|
/* print contents */ /*{{{*/
|
||||||
|
{
|
||||||
|
for (x=x1; x<=x2; )
|
||||||
|
{
|
||||||
|
int multicols;
|
||||||
|
char *bufp;
|
||||||
|
|
||||||
|
if (x>x1 && fputs_close("\\NC",fp)==EOF) return strerror(errno);
|
||||||
|
for (multicols=x+1; multicols<sheet->dimx && shadowed(sheet,multicols,y,z); ++multicols);
|
||||||
|
multicols=multicols-x;
|
||||||
|
if (multicols>1) fprintf(fp,"\\use{%d}",multicols);
|
||||||
|
switch (getadjust(sheet,x,y,z))
|
||||||
|
{
|
||||||
|
case LEFT: if (fputs_close("\\JustLeft ",fp)==EOF) return strerror(errno); break;
|
||||||
|
case RIGHT: if (fputs_close("\\JustRight ",fp)==EOF) return strerror(errno); break;
|
||||||
|
case CENTER: if (fputs_close("\\JustCenter ",fp)==EOF) return strerror(errno); break;
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
printvalue(buf,sizeof(buf),0,0,getscientific(sheet,x,y,z),getprecision(sheet,x,y,z),sheet,x,y,z);
|
||||||
|
/* if (fputs_close("}{",fp)==EOF) return strerror(errno);*/
|
||||||
|
if (transparent(sheet,x,y,z))
|
||||||
|
{
|
||||||
|
if (fputs_close(buf,fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
else for (bufp=buf; *bufp; ++bufp) switch (*bufp)
|
||||||
|
{
|
||||||
|
case '%':
|
||||||
|
case '$':
|
||||||
|
case '&':
|
||||||
|
case '#':
|
||||||
|
case '_':
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
|
case '~':
|
||||||
|
case '^': if (fputc_close('\\',fp)==EOF || fputc_close(*bufp,fp)==EOF) return strerror(errno); break;
|
||||||
|
case '\\': if (fputs_close("\\backslash ",fp)==EOF) return strerror(errno); break;
|
||||||
|
default: if (fputc_close(*bufp,fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
/* if (fputc_close('}',fp)==EOF) return strerror(errno);*/
|
||||||
|
x+=multicols;
|
||||||
|
++*count;
|
||||||
|
}
|
||||||
|
if (fputs_close(y<y2 ? "\\MR\n" : "\n\\stoptable\n",fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
if (body)
|
||||||
|
{
|
||||||
|
if (fclose(fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fputs_close("\n",fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!body)
|
||||||
|
{
|
||||||
|
if (fputs_close("\\stoptext\n",fp)==EOF) return strerror(errno);
|
||||||
|
if (fclose(fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
return (const char*)0;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
8
context.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef CONTEXT_H
|
||||||
|
#define CONTEXT_H
|
||||||
|
|
||||||
|
#include "sheet.h"
|
||||||
|
|
||||||
|
const char *savecontext(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
|
||||||
|
|
||||||
|
#endif
|
160
csv.c
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
#ifndef NO_POSIX_SOURCE
|
||||||
|
#undef _POSIX_SOURCE
|
||||||
|
#define _POSIX_SOURCE 1
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef OLD_REALLOC
|
||||||
|
#define realloc(s,l) myrealloc(s,l)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DMALLOC
|
||||||
|
#include "dmalloc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "csv.h"
|
||||||
|
|
||||||
|
static int semicol=0;
|
||||||
|
|
||||||
|
/* csv_setopt -- set language */ /*{{{C}}}*//*{{{*/
|
||||||
|
void csv_setopt(int sem)
|
||||||
|
{
|
||||||
|
semicol=sem;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
#if 0
|
||||||
|
/* csv_date -- convert string "year<sep>month<sep>day<sep>" to date */ /*{{{*/
|
||||||
|
static struct CSV_Date csv_date(const char *s, const char **end)
|
||||||
|
{
|
||||||
|
struct CSV_Date date;
|
||||||
|
|
||||||
|
assert(s!=(const char*)0);
|
||||||
|
assert(end!=(const char**)0);
|
||||||
|
*end=s;
|
||||||
|
if (*s=='"')
|
||||||
|
{
|
||||||
|
++s;
|
||||||
|
if (isdigit(*s))
|
||||||
|
{
|
||||||
|
for (date.year=0; isdigit(*s); date.year=10*date.year+(*s-'0'),++s);
|
||||||
|
if (*s)
|
||||||
|
{
|
||||||
|
++s;
|
||||||
|
if (isdigit(*s))
|
||||||
|
{
|
||||||
|
for (date.month=0; isdigit(*s); date.month=10*date.month+(*s-'0'),++s);
|
||||||
|
if (*s)
|
||||||
|
{
|
||||||
|
++s;
|
||||||
|
if (isdigit(*s))
|
||||||
|
{
|
||||||
|
for (date.day=0; isdigit(*s); date.day=10*date.day+(*s-'0'),++s);
|
||||||
|
if (*s=='"')
|
||||||
|
{
|
||||||
|
++s;
|
||||||
|
*end=s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
#endif
|
||||||
|
/* csv_separator -- convert string \t to nothing */ /*{{{*/
|
||||||
|
void csv_separator(const char *s, const char **end)
|
||||||
|
{
|
||||||
|
assert(s!=(const char*)0);
|
||||||
|
assert(end!=(const char**)0);
|
||||||
|
*end=s+(*s=='\t' || (semicol && *s==';') || (!semicol && *s==','));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* csv_long -- convert string [0[x]]12345 to long */ /*{{{*/
|
||||||
|
long csv_long(const char *s, const char **end)
|
||||||
|
{
|
||||||
|
long value;
|
||||||
|
const char *t;
|
||||||
|
|
||||||
|
assert(s!=(const char*)0);
|
||||||
|
assert(end!=(const char**)0);
|
||||||
|
if (*s=='\t') { *end=s; return 0L; };
|
||||||
|
value=strtol(s,(char**)end,0);
|
||||||
|
if (s!=*end)
|
||||||
|
{
|
||||||
|
t=*end; csv_separator(t,end);
|
||||||
|
if (t!=*end || *t=='\0' || *t=='\n') return value;
|
||||||
|
}
|
||||||
|
*end=s; return 0L;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* csv_double -- convert string 123.4e5 to double */ /*{{{*/
|
||||||
|
double csv_double(const char *s, const char **end)
|
||||||
|
{
|
||||||
|
double value;
|
||||||
|
const char *t;
|
||||||
|
|
||||||
|
assert(s!=(const char*)0);
|
||||||
|
assert(end!=(const char**)0);
|
||||||
|
if (*s=='\t') { *end=s; return 0.0; };
|
||||||
|
value=strtod(s,(char**)end);
|
||||||
|
if (s!=*end)
|
||||||
|
{
|
||||||
|
t=*end; csv_separator(t,end);
|
||||||
|
if (t!=*end || *t=='\0' || *t=='\n') return value;
|
||||||
|
}
|
||||||
|
*end=s; return 0.0;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* csv_string -- convert almost any string to string */ /*{{{*/
|
||||||
|
char *csv_string(const char *s, const char **end)
|
||||||
|
{
|
||||||
|
static char *string;
|
||||||
|
static int strings,stringsz;
|
||||||
|
|
||||||
|
assert(s!=(const char*)0);
|
||||||
|
assert(end!=(const char**)0);
|
||||||
|
strings=0;
|
||||||
|
stringsz=0;
|
||||||
|
string=(char*)0;
|
||||||
|
if (!isprint((int)*s) || (!semicol && *s==',') || (semicol && *s==';')) return (char*)0;
|
||||||
|
if (*s=='"')
|
||||||
|
{
|
||||||
|
++s;
|
||||||
|
while (*s!='\0' && *s!='\n' && *s!='"')
|
||||||
|
{
|
||||||
|
if ((strings+2)>=stringsz)
|
||||||
|
{
|
||||||
|
string=realloc(string,stringsz+=32);
|
||||||
|
}
|
||||||
|
string[strings]=*s;
|
||||||
|
++strings;
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
if (*s=='"') ++s;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (*s!='\0' && *s!='\n' && *s!='\t' && ((!semicol && *s!=',') || (semicol && *s!=';')))
|
||||||
|
{
|
||||||
|
if ((strings+2)>=stringsz)
|
||||||
|
{
|
||||||
|
string=realloc(string,stringsz+=32);
|
||||||
|
}
|
||||||
|
string[strings]=*s;
|
||||||
|
++strings;
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string[strings]='\0';
|
||||||
|
*end=s;
|
||||||
|
csv_separator(s,end);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
17
csv.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef CSV_H
|
||||||
|
#define CSV_H
|
||||||
|
|
||||||
|
struct CSV_Date
|
||||||
|
{
|
||||||
|
int day;
|
||||||
|
int month;
|
||||||
|
int year;
|
||||||
|
};
|
||||||
|
|
||||||
|
void csv_setopt(int sem);
|
||||||
|
void csv_separator(const char *s, const char **end);
|
||||||
|
char *csv_string(const char *s, const char **end);
|
||||||
|
double csv_double(const char *s, const char **end);
|
||||||
|
long csv_long(const char *s, const char **end);
|
||||||
|
|
||||||
|
#endif
|
38
default.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef DEFAULT_H
|
||||||
|
#define DEFAULT_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* default width of a column */
|
||||||
|
#define DEF_COLUMNWIDTH 12
|
||||||
|
|
||||||
|
/* default precision of a printed value */
|
||||||
|
#define DEF_PRECISION 2
|
||||||
|
|
||||||
|
/* default is no scientific notation for numbers */
|
||||||
|
#define DEF_SCIENTIFIC 0
|
||||||
|
|
||||||
|
/* character attribute for cell and row numbers */
|
||||||
|
#define DEF_NUMBER A_BOLD
|
||||||
|
|
||||||
|
/* character attribute for cell cursor */
|
||||||
|
#define DEF_CELLCURSOR A_REVERSE
|
||||||
|
|
||||||
|
/* character attribute for selected menu choice */
|
||||||
|
#define DEF_MENU A_REVERSE
|
||||||
|
|
||||||
|
/* maximum number of sort keys */
|
||||||
|
#define MAX_SORTKEYS 8
|
||||||
|
|
||||||
|
/* maximum number of eval() nesting */
|
||||||
|
#define MAX_EVALNEST 32
|
||||||
|
|
||||||
|
/* define if testing with EletricFence */
|
||||||
|
#ifdef THE_ELECTRIC_FENCE
|
||||||
|
#undef malloc
|
||||||
|
#undef free
|
||||||
|
#undef realloc
|
||||||
|
#undef calloc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
38
display.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef DISPLAY_H
|
||||||
|
#define DISPLAY_H
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "sheet.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Key c;
|
||||||
|
char *str;
|
||||||
|
} MenuChoice;
|
||||||
|
|
||||||
|
void display_main(Sheet *cursheet);
|
||||||
|
void display_init(Sheet *cursheet, int always_redraw);
|
||||||
|
void display_end(void);
|
||||||
|
void redraw_cell(Sheet *sheet, int x, int y, int z);
|
||||||
|
void redraw_sheet(Sheet *sheet);
|
||||||
|
const char *line_file(const char *file, const char *pattern, const char *title, int create);
|
||||||
|
int line_edit(Sheet *sheet, char *buf, size_t size, const char *prompt, size_t *x, size_t *offx);
|
||||||
|
int line_ok(const char *prompt, int curx);
|
||||||
|
void line_msg(const char *prompt, const char *msg);
|
||||||
|
int keypressed(void);
|
||||||
|
void show_text(const char *text);
|
||||||
|
|
||||||
|
Key show_menu(Sheet *cursheet);
|
||||||
|
int line_menu(const char *prompt, const MenuChoice *choice, int curx);
|
||||||
|
void find_helpfile(char *buf, int size, const char *argv0);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
198
doc/.latex2html-init
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
#LaTeX2HTML Version 96.1 : dot.latex2html-init
|
||||||
|
#
|
||||||
|
### Command Line Argument Defaults #######################################
|
||||||
|
|
||||||
|
$MAX_SPLIT_DEPTH = 5; # Stop making separate files at this depth
|
||||||
|
|
||||||
|
$MAX_LINK_DEPTH = 4; # Stop showing child nodes at this depth
|
||||||
|
|
||||||
|
$NOLATEX = 0; # 1 = do not pass unknown environments to Latex
|
||||||
|
|
||||||
|
$EXTERNAL_IMAGES = 0; # 1 = leave the images outside the document
|
||||||
|
|
||||||
|
$ASCII_MODE = 0; # 1 = do not use any icons or internal images
|
||||||
|
|
||||||
|
$LOCAL_ICONS = 1;
|
||||||
|
|
||||||
|
# 1 = use links to external postscript images rather than inlined bitmap
|
||||||
|
# images.
|
||||||
|
$PS_IMAGES = 0;
|
||||||
|
|
||||||
|
$TITLE = "fteapot manual"; # The default is "No Title"
|
||||||
|
|
||||||
|
$DESTDIR = 'html'; # Put the result in this directory
|
||||||
|
|
||||||
|
# When this is set, the generated HTML files will be placed in the
|
||||||
|
# current directory. If set to 0 the default behaviour is to create (or reuse)
|
||||||
|
# another file directory.
|
||||||
|
$NO_SUBDIR = 0;
|
||||||
|
|
||||||
|
|
||||||
|
# Supply your own string if you don't like the default <Name> <Date>
|
||||||
|
$ADDRESS = "";
|
||||||
|
|
||||||
|
$NO_NAVIGATION = 0; # 1 = do not put a navigation panel at the top of each page
|
||||||
|
|
||||||
|
# Put navigation links at the top of each page. If the page exceeds
|
||||||
|
# $WORDS_IN_PAGE number of words then put one at the bottom of the page.
|
||||||
|
$AUTO_NAVIGATION = 1;
|
||||||
|
|
||||||
|
# Put a link to the index page in the navigation panel
|
||||||
|
$INDEX_IN_NAVIGATION = 0;
|
||||||
|
|
||||||
|
# Put a link to the table of contents in the navigation panel
|
||||||
|
$CONTENTS_IN_NAVIGATION = 1;
|
||||||
|
|
||||||
|
# Put a link to the next logical page in the navigation panel
|
||||||
|
$NEXT_PAGE_IN_NAVIGATION = 1;
|
||||||
|
|
||||||
|
# Put a link to the previous logical page in the navigation panel
|
||||||
|
$PREVIOUS_PAGE_IN_NAVIGATION = 1;
|
||||||
|
|
||||||
|
$INFO = 1; # 0 = do not make a "About this document..." section
|
||||||
|
|
||||||
|
# Reuse images generated during previous runs
|
||||||
|
$REUSE = 2;
|
||||||
|
|
||||||
|
# When this is 1, the section numbers are shown. The section numbers should
|
||||||
|
# then match those that would have bee produced by LaTeX.
|
||||||
|
# The correct section numbers are obtained from the $FILE.aux file generated
|
||||||
|
# by LaTeX.
|
||||||
|
# Hiding the seciton numbers encourages use of particular sections
|
||||||
|
# as standalone documents. In this case the cross reference to a section
|
||||||
|
# is shown using the default symbol rather than the section number.
|
||||||
|
$SHOW_SECTION_NUMBERS = 0;
|
||||||
|
|
||||||
|
### Other global variables ###############################################
|
||||||
|
$CHILDLINE = "<BR> <HR>\n";
|
||||||
|
|
||||||
|
# This is the line width measured in pixels and it is used to right justify
|
||||||
|
# equations and equation arrays;
|
||||||
|
$LINE_WIDTH = 500;
|
||||||
|
|
||||||
|
# Used in conjunction with AUTO_NAVIGATION
|
||||||
|
$WORDS_IN_PAGE = 300;
|
||||||
|
|
||||||
|
# Affects ONLY the way accents are processed
|
||||||
|
$default_language = 'english';
|
||||||
|
|
||||||
|
# The value of this variable determines how many words to use in each
|
||||||
|
# title that is added to the navigation panel (see below)
|
||||||
|
#
|
||||||
|
$WORDS_IN_NAVIGATION_PANEL_TITLES = 5;
|
||||||
|
|
||||||
|
# This number will determine the size of the equations, special characters,
|
||||||
|
# and anything which will be converted into an inlined image
|
||||||
|
# *except* "image generating environments" such as "figure", "table"
|
||||||
|
# or "minipage".
|
||||||
|
# Effective values are those greater than 0.
|
||||||
|
# Sensible values are between 0.1 - 4.
|
||||||
|
$MATH_SCALE_FACTOR = 2;
|
||||||
|
|
||||||
|
# This number will determine the size of
|
||||||
|
# image generating environments such as "figure", "table" or "minipage".
|
||||||
|
# Effective values are those greater than 0.
|
||||||
|
# Sensible values are between 0.1 - 4.
|
||||||
|
$FIGURE_SCALE_FACTOR = 2;
|
||||||
|
|
||||||
|
|
||||||
|
# If this is set then intermediate files are left for later inspection.
|
||||||
|
# This includes $$_images.tex and $$_images.log created during image
|
||||||
|
# conversion.
|
||||||
|
# Caution: Intermediate files can be *enormous*.
|
||||||
|
$DEBUG = 0;
|
||||||
|
|
||||||
|
# If both of the following two variables are set then the "Up" button
|
||||||
|
# of the navigation panel in the first node/page of a converted document
|
||||||
|
# will point to $EXTERNAL_UP_LINK. $EXTERNAL_UP_TITLE should be set
|
||||||
|
# to some text which describes this external link.
|
||||||
|
$EXTERNAL_UP_LINK = "";
|
||||||
|
$EXTERNAL_UP_TITLE = "";
|
||||||
|
|
||||||
|
# If this is set then the resulting HTML will look marginally better if viewed
|
||||||
|
# with Netscape.
|
||||||
|
$NETSCAPE_HTML = 0;
|
||||||
|
|
||||||
|
# Valid paper sizes are "letter", "legal", "a4","a3","a2" and "a0"
|
||||||
|
# Paper sizes has no effect other than in the time it takes to create inlined
|
||||||
|
# images and in whether large images can be created at all ie
|
||||||
|
# - larger paper sizes *MAY* help with large image problems
|
||||||
|
# - smaller paper sizes are quicker to handle
|
||||||
|
$PAPERSIZE = "a5";
|
||||||
|
|
||||||
|
# Replace "english" with another language in order to tell LaTeX2HTML that you
|
||||||
|
# want some generated section titles (eg "Table of Contents" or "References")
|
||||||
|
# to appear in a different language. Currently only "english" and "french"
|
||||||
|
# is supported but it is very easy to add your own. See the example in the
|
||||||
|
# file "latex2html.config"
|
||||||
|
$TITLES_LANGUAGE = "english";
|
||||||
|
|
||||||
|
### Navigation Panel ##########################################################
|
||||||
|
#
|
||||||
|
# The navigation panel is constructed out of buttons and section titles.
|
||||||
|
# These can be configured in any combination with arbitrary text and
|
||||||
|
# HTML tags interspersed between them.
|
||||||
|
# The buttons available are:
|
||||||
|
# $PREVIOUS - points to the previous section
|
||||||
|
# $UP - points up to the "parent" section
|
||||||
|
# $NEXT - points to the next section
|
||||||
|
# $NEXT_GROUP - points to the next "group" section
|
||||||
|
# $PREVIOUS_GROUP - points to the previous "group" section
|
||||||
|
# $CONTENTS - points to the contents page if there is one
|
||||||
|
# $INDEX - points to the index page if there is one
|
||||||
|
#
|
||||||
|
# If the corresponding section exists the button will contain an
|
||||||
|
# active link to that section. If the corresponding section does
|
||||||
|
# not exist the button will be inactive.
|
||||||
|
#
|
||||||
|
# Also for each of the $PREVIOUS $UP $NEXT $NEXT_GROUP and $PREVIOUS_GROUP
|
||||||
|
# buttons there are equivalent $PREVIOUS_TITLE, $UP_TITLE, etc variables
|
||||||
|
# which contain the titles of their corresponding sections.
|
||||||
|
# Each title is empty if there is no corresponding section.
|
||||||
|
#
|
||||||
|
# The subroutine below constructs the navigation panels in each page.
|
||||||
|
# Feel free to mix and match buttons, titles, your own text, your logos,
|
||||||
|
# and arbitrary HTML (the "." is the Perl concatenation operator).
|
||||||
|
sub top_navigation_panel {
|
||||||
|
|
||||||
|
# Now add a few buttons with a space between them
|
||||||
|
"<FONT SIZE=6> $PREVIOUS $UP $NEXT - $CONTENTS $INDEX $CUSTOM_BUTTONS</FONT>" .
|
||||||
|
|
||||||
|
#"<BR>\n" . # Line break
|
||||||
|
|
||||||
|
# ... and the ``previous'' title
|
||||||
|
#($PREVIOUS_TITLE ? "<B><<</B> $PREVIOUS_TITLE\n" : undef) .
|
||||||
|
|
||||||
|
# Similarly with the ``up'' title ...
|
||||||
|
#($UP_TITLE ? "<B>^</B> $UP_TITLE <B>^</B>\n" : undef) .
|
||||||
|
|
||||||
|
# If ``next'' section exists, add its title to the navigation panel
|
||||||
|
#($NEXT_TITLE ? "$NEXT_TITLE <B>>></B>\n" : undef)
|
||||||
|
|
||||||
|
# Line Break, horizontal rule (3-d dividing line) and new paragraph
|
||||||
|
#"<BR>\n"
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
sub bot_navigation_panel {
|
||||||
|
|
||||||
|
# Start with a horizontal rule (3-d dividing line)
|
||||||
|
#"<HR>".
|
||||||
|
|
||||||
|
# Now add a few buttons with a space between them
|
||||||
|
"<FONT SIZE=6> $PREVIOUS $UP $NEXT - $CONTENTS $INDEX $CUSTOM_BUTTONS</FONT>" .
|
||||||
|
|
||||||
|
"<BR>\n" . # Line break
|
||||||
|
|
||||||
|
# ... and the ``previous'' title
|
||||||
|
($PREVIOUS_TITLE ? "<B><<</B> $PREVIOUS_TITLE\n" : undef) .
|
||||||
|
|
||||||
|
# Similarly with the ``up'' title ...
|
||||||
|
($UP_TITLE ? "<B>^</B> $UP_TITLE <B>^</B>\n" : undef) .
|
||||||
|
|
||||||
|
# If ``next'' section exists, add its title to the navigation panel
|
||||||
|
($NEXT_TITLE ? "$NEXT_TITLE <B>>></B>\n" : undef)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
1; # This must be the last line
|
43
doc/Ein neues Leben für Teapot.mbox
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
From michael@moria.de Mon Jan 26 11:41:49 2009
|
||||||
|
Return-path: <michael@moria.de>
|
||||||
|
Envelope-to: info@syntax-k.de
|
||||||
|
Delivery-date: Mon, 26 Jan 2009 11:42:30 +0100
|
||||||
|
Received: from [194.97.106.210] (helo=fangorn.moria.de)
|
||||||
|
by mercenary.garni.ch with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32)
|
||||||
|
(Exim 4.67)
|
||||||
|
(envelope-from <michael@moria.de>)
|
||||||
|
id 1LROv8-0007ub-Oi
|
||||||
|
for info@syntax-k.de; Mon, 26 Jan 2009 11:42:30 +0100
|
||||||
|
Received: from michael by fangorn.moria.de with local (ID michael) (Exim 4.69 #20)
|
||||||
|
id 1LROub-0002Gz-Ge
|
||||||
|
for info@syntax-k.de; Mon, 26 Jan 2009 11:41:49 +0100
|
||||||
|
Date: Mon, 26 Jan 2009 11:41:49 +0100
|
||||||
|
To: info@syntax-k.de
|
||||||
|
Subject: Re: Ein neues Leben =?iso-8859-1?Q?f=FCr?= Teapot
|
||||||
|
References: <200901260214.44366.info@syntax-k.de>
|
||||||
|
In-Reply-To: <200901260214.44366.info@syntax-k.de>
|
||||||
|
User-Agent: Heirloom mailx 12.1 6/15/06
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain;
|
||||||
|
charset=iso-8859-1
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
Message-Id: <E1LROub-0002Gz-Ge@fangorn.moria.de>
|
||||||
|
From: Michael Haardt <michael@moria.de>
|
||||||
|
X-Spam-Level: --
|
||||||
|
X-Spam-Status: NO, score=-2.5, required=7.0
|
||||||
|
X-Antivirus-Scanner: Clean mail. You should still use a local antivirus program.
|
||||||
|
X-Length: 1754
|
||||||
|
X-UID: 1
|
||||||
|
|
||||||
|
> Ich war auf der Suche nach einer einfachen Tabellenkalkulation, die
|
||||||
|
> universell (also auch embedded, per SSH usw.) eingesetzt werden kann.
|
||||||
|
> Entdeckt habe ich Teapot, das dank Curses-UI wahrlich universell ist. Um
|
||||||
|
> es aber auf grafischen Systemen bequemer benutzen zu können, habe ich
|
||||||
|
> einfach mal ein GTK+-Frontend dafür geschrieben.
|
||||||
|
|
||||||
|
Klingt ganz nett, aber ich mache nichts mehr an Teapot und GTK ist mir
|
||||||
|
ein zu veraenderliches Ding, um mich auf fremde Patches zu verlassen.
|
||||||
|
Magst Du teapot als Projekt uebernehmen? Ich wuerde es unter GPL gerne
|
||||||
|
an jemand abgeben, der am Code arbeitet.
|
||||||
|
|
||||||
|
Michael
|
BIN
doc/contents.png
Normal file
After Width: | Height: | Size: 223 B |
BIN
doc/next.png
Normal file
After Width: | Height: | Size: 200 B |
BIN
doc/next_g.png
Normal file
After Width: | Height: | Size: 188 B |
BIN
doc/prev.png
Normal file
After Width: | Height: | Size: 223 B |
BIN
doc/prev_g.png
Normal file
After Width: | Height: | Size: 212 B |
6417
doc/teapot.lyx
Normal file
BIN
doc/up.png
Normal file
After Width: | Height: | Size: 172 B |
BIN
doc/up_g.png
Normal file
After Width: | Height: | Size: 169 B |
25
eval.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef THE_EVAL_H
|
||||||
|
#define THE_EVAL_H
|
||||||
|
|
||||||
|
#include "scanner.h"
|
||||||
|
|
||||||
|
Token tcopy(Token n);
|
||||||
|
void tfree(Token *n);
|
||||||
|
void tvecfree(Token **tvec);
|
||||||
|
Token tpow(Token l, Token r);
|
||||||
|
Token tdiv(Token l, Token r);
|
||||||
|
Token tmod(Token l, Token r);
|
||||||
|
Token tmul(Token l, Token r);
|
||||||
|
Token tadd(Token l, Token r);
|
||||||
|
Token tsub(Token l, Token r);
|
||||||
|
Token tneg(Token x);
|
||||||
|
Token tfuncall(Token *ident, int argc, Token argv[]);
|
||||||
|
Token tlt(Token l, Token r);
|
||||||
|
Token tle(Token l, Token r);
|
||||||
|
Token tge(Token l, Token r);
|
||||||
|
Token tgt(Token l, Token r);
|
||||||
|
Token teq(Token l, Token r);
|
||||||
|
Token tabouteq(Token l, Token r);
|
||||||
|
Token tne(Token l, Token r);
|
||||||
|
|
||||||
|
#endif
|
3
examples/asqrt.README
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
This sheet calculates the square root of x automatically, as soon as
|
||||||
|
you enter a number in cell X. The calculation will be iterated until
|
||||||
|
the square of the square root is as close as 0.1.
|
BIN
examples/asqrt.tp
Normal file
BIN
examples/blink.tp
Normal file
3
examples/counter.README
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
This sheet shows how to use clock() to model a counter which
|
||||||
|
automatically counts up to 1000 once the sheet gets clocked with
|
||||||
|
control-s.
|
BIN
examples/counter.tp
Normal file
16
examples/graphtest.sh
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
( echo This is the same data, once as a pie graph and once as a box graph.
|
||||||
|
echo .PS
|
||||||
|
../graph -w 2 <<eof
|
||||||
|
"a" 1 1
|
||||||
|
"b" 2.5
|
||||||
|
"c" 4
|
||||||
|
eof
|
||||||
|
../graph -n -b -w 2 <<eof
|
||||||
|
"a" 1
|
||||||
|
"b" 2.5
|
||||||
|
"c" 4
|
||||||
|
eof
|
||||||
|
echo with .w at last [].e
|
||||||
|
echo .PE ) | groff -Tps -p -mm >graphtest.ps
|
4
examples/life.README
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
This is a sheet which contains the well known game of life. Load it and
|
||||||
|
clock the sheet with control-s a few times, and you will see the glider
|
||||||
|
moving. Layer 0 contains the grid and layer 1 contains some help
|
||||||
|
formulas.
|
BIN
examples/life.tp
Normal file
6
examples/load_save_time.README
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
This sheet demonstrates the use of the time functions strftime and
|
||||||
|
strptime.
|
||||||
|
The associated shell script shows how to use teapot in batch mode,
|
||||||
|
with the definitions and output formulas in level 0, and variable data
|
||||||
|
loaded to level 1.
|
||||||
|
|
12
examples/load_save_time.sh
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
echo 11.9.2001,2.2.2002 >load_save_time.txt
|
||||||
|
teapot -b load_save_time.tp<<EOF
|
||||||
|
goto &(0,0,1)
|
||||||
|
load-csv load_save_time.txt
|
||||||
|
from &(0,1,0)
|
||||||
|
to &(0,1,0)
|
||||||
|
save-csv load_save_result.txt
|
||||||
|
EOF
|
||||||
|
rm -f load_save_time.txt
|
||||||
|
cat load_save_result.txt
|
||||||
|
rm -f load_save_result.txt
|
BIN
examples/load_save_time.tp
Normal file
3
examples/sqrt.README
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
This sheet calculates the square root of x if you clock it a few times
|
||||||
|
with control-s. It is a nice introductional example of how to use
|
||||||
|
clocked expressions.
|
BIN
examples/sqrt.tp
Normal file
851
fteapot.fl
Normal file
@ -0,0 +1,851 @@
|
|||||||
|
# data file for the Fltk User Interface Designer (fluid)
|
||||||
|
version 1.0300
|
||||||
|
header_name {.h}
|
||||||
|
code_name {.cxx}
|
||||||
|
decl {\#include <stdint.h>} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include <limits.h>} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include <fcntl.h>} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#define shadow _shadow} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#define transparent _transparent} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#define MenuChoice _MenuChoice} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#define Cell _Cell} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include <FL/fl_message.H>} {private local
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include <FL/fl_draw.H>} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include <FL/Fl_Native_File_Chooser.H>} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include <FL/Fl_File_Icon.H>} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include <FL/filename.H>} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include <FL/Fl_Table.H>} {public global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include <FL/Fl_Select_Browser.H>} {public global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include <FL/Fl_Sys_Menu_Bar.H>} {public global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#undef shadow} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#undef transparent} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#undef MenuChoice} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#undef Cell} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include "misc.h"} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#include "display.h"} {public global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#define SHEET(s,x,y,z) (*(s->sheet+(x)*s->dimz*s->dimy+(y)*s->dimz+(z)))} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {\#define SHADOWED(sheet,x,y,z) (x<sheet->dimx && y<sheet->dimy && z<sheet->dimz && SHEET(sheet,x,y,z)!=(Cell*)0 && SHEET(sheet,x,y,z)->shadowed)} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
class TeapotTable {open : {public Fl_Table}
|
||||||
|
} {
|
||||||
|
decl {Sheet *cursheet;} {protected local
|
||||||
|
}
|
||||||
|
decl {bool cut, updating;} {protected local
|
||||||
|
}
|
||||||
|
decl {static const TableContext ACTION = (TableContext)(1<<8);} {public local
|
||||||
|
}
|
||||||
|
decl {static const TableContext REFRESH = (TableContext)(1<<9);} {public local
|
||||||
|
}
|
||||||
|
Function {TeapotTable(int x, int y, int w, int h, const char *l=0) : Fl_Table(x, y, w, h, l), cut(false), updating(false)} {open
|
||||||
|
} {
|
||||||
|
code {end();
|
||||||
|
col_resize_min(10);
|
||||||
|
col_resize(true);
|
||||||
|
col_header(header);
|
||||||
|
row_resize(false);
|
||||||
|
row_header(header);
|
||||||
|
set_visible_focus();
|
||||||
|
table_box(FL_THIN_UP_FRAME);} {}
|
||||||
|
}
|
||||||
|
Function {~TeapotTable()} {} {
|
||||||
|
code {} {}
|
||||||
|
}
|
||||||
|
Function {sheet(Sheet *s)} {open return_type void
|
||||||
|
} {
|
||||||
|
code {cursheet = s;
|
||||||
|
s->display = (void *)this;
|
||||||
|
clear();
|
||||||
|
update_table();
|
||||||
|
do_callback(CONTEXT_NONE, 0, 0);} {}
|
||||||
|
}
|
||||||
|
Function {sheet()} {return_type {Sheet *}
|
||||||
|
} {
|
||||||
|
code {return cursheet;} {}
|
||||||
|
}
|
||||||
|
Function {draw_cell(TableContext context, int R, int C, int X, int Y, int W, int H)} {open return_type void
|
||||||
|
} {
|
||||||
|
code {char s[1024];
|
||||||
|
//printf("DRAW: %i @%i,%i - (%i,%i) %ix%i\\n", context, C,R, X,Y, W,H);
|
||||||
|
switch (context) {
|
||||||
|
case CONTEXT_ENDPAGE:
|
||||||
|
W = X-x()-2;
|
||||||
|
H = Y-y()-2;
|
||||||
|
X = x()+2;
|
||||||
|
Y = y()+2;
|
||||||
|
fl_font(FL_HELVETICA | FL_BOLD, 14);
|
||||||
|
fl_push_clip(X, Y, W, H);
|
||||||
|
fl_draw_box(FL_DIAMOND_UP_BOX, X, Y, W, H, col_header_color());
|
||||||
|
fl_color(FL_INACTIVE_COLOR);
|
||||||
|
sprintf(s, "%d", cursheet->curz);
|
||||||
|
fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
|
||||||
|
fl_pop_clip();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONTEXT_STARTPAGE:
|
||||||
|
adjust_outside();
|
||||||
|
if (Fl::event_button1()) update_sheet();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONTEXT_COL_HEADER:
|
||||||
|
fl_font(FL_HELVETICA | FL_BOLD, 14);
|
||||||
|
fl_push_clip(X, Y, W, H);
|
||||||
|
fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, col_header_color());
|
||||||
|
fl_color(FL_FOREGROUND_COLOR);
|
||||||
|
sprintf(s, "%d", C);
|
||||||
|
fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
|
||||||
|
fl_pop_clip();
|
||||||
|
return;
|
||||||
|
|
||||||
|
case CONTEXT_ROW_HEADER:
|
||||||
|
fl_font(FL_HELVETICA | FL_BOLD, 14);
|
||||||
|
fl_push_clip(X, Y, W, H);
|
||||||
|
fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, row_header_color());
|
||||||
|
fl_color(FL_FOREGROUND_COLOR);
|
||||||
|
sprintf(s, "%d", R);
|
||||||
|
fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER);
|
||||||
|
fl_pop_clip();
|
||||||
|
return;
|
||||||
|
|
||||||
|
case CONTEXT_CELL: {
|
||||||
|
while (SHADOWED(cursheet, C, R, cursheet->curz)) X -= W = col_width(--C);
|
||||||
|
int x = C+1;
|
||||||
|
while (SHADOWED(cursheet,x,R,cursheet->curz)) W += col_width(x), x++;
|
||||||
|
|
||||||
|
fl_push_clip(X, Y, W, H);
|
||||||
|
bool selected = false;
|
||||||
|
if (cursheet->mark1x >= 0) {
|
||||||
|
int x1 = cursheet->mark1x, x2 = cursheet->mark2x, y1 = cursheet->mark1y, y2 = cursheet->mark2y, z1 = cursheet->mark1z, z2 = cursheet->mark2z;
|
||||||
|
posorder(&x1, &x2);
|
||||||
|
posorder(&y1, &y2);
|
||||||
|
posorder(&z1, &z2);
|
||||||
|
selected = cursheet->mark1x >= 0 && C >= x1 && C <= x2 && R >= y1 && R <= y2 && cursheet->curz >= z1 && cursheet->curz <= z2;
|
||||||
|
}
|
||||||
|
fl_draw_box(C == cursheet->curx && R == cursheet->cury?FL_BORDER_BOX:FL_THIN_DOWN_BOX, X, Y, W, H, selected?FL_SELECTION_COLOR:FL_BACKGROUND2_COLOR);
|
||||||
|
if (Fl::focus() == this && C == cursheet->curx && R == cursheet->cury) draw_focus(FL_BORDER_BOX, X, Y, W, H);
|
||||||
|
fl_pop_clip();
|
||||||
|
|
||||||
|
fl_push_clip(X+3, Y+3, W-6, H-6);
|
||||||
|
fl_color(FL_FOREGROUND_COLOR);
|
||||||
|
fl_font(FL_HELVETICA | (isbold(cursheet, C, R, cursheet->curz)? FL_BOLD:0), 14);
|
||||||
|
|
||||||
|
printvalue(s, sizeof(s), 0, 0, getscientific(cursheet, C, R, cursheet->curz), getprecision(cursheet, C, R, cursheet->curz), cursheet, C, R, cursheet->curz);
|
||||||
|
int ww = 0, hh = 0;
|
||||||
|
fl_measure(s, ww, hh, 0);
|
||||||
|
if (ww > W-6) for (int i = 0; s[i]; i++) s[i] = '\#';
|
||||||
|
|
||||||
|
int adj = getadjust(cursheet, C, R, cursheet->curz);
|
||||||
|
fl_draw(s, X+3, Y+3, W-6, H-6, adj == RIGHT?FL_ALIGN_RIGHT:adj == LEFT?FL_ALIGN_LEFT:FL_ALIGN_CENTER);
|
||||||
|
if (underlined(cursheet, C, R, cursheet->curz)) fl_xyline(X, Y+H-7, X+W);
|
||||||
|
fl_pop_clip();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}} {selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Function {update_table()} {open return_type void
|
||||||
|
} {
|
||||||
|
code {if (updating) return;
|
||||||
|
|
||||||
|
updating = true;
|
||||||
|
//printf("update_table: %ix%i@%i,%i; %i[%i], %i[%i]\\n", cursheet->dimx, cursheet->dimy, cursheet->curx, cursheet->cury, cursheet->offx, cursheet->maxx, cursheet->offy, cursheet->maxy);
|
||||||
|
|
||||||
|
if (cursheet->dimx > cols()) cols(cursheet->dimx);
|
||||||
|
if (cursheet->dimy > rows()) rows(cursheet->dimy);
|
||||||
|
adjust_outside();
|
||||||
|
|
||||||
|
for (int x = 0; x < cursheet->dimx; x++) {
|
||||||
|
int w = columnwidth(cursheet, x, cursheet->curz)*10;
|
||||||
|
if (col_width(x) != w) col_width(x, w);
|
||||||
|
}
|
||||||
|
col_position(cursheet->offx);
|
||||||
|
row_position(cursheet->offy);
|
||||||
|
set_selection(cursheet->cury, cursheet->curx, cursheet->cury, cursheet->curx);
|
||||||
|
move_cursor(0,0);
|
||||||
|
updating = false;} {}
|
||||||
|
}
|
||||||
|
Function {update_sheet()} {return_type void
|
||||||
|
} {
|
||||||
|
code {int x1, x2, y1, y2;
|
||||||
|
|
||||||
|
if (updating) return;
|
||||||
|
updating = true;
|
||||||
|
|
||||||
|
get_selection(y1, x1, y2, x2);
|
||||||
|
if (x1 != x2 || y1 != y2) {
|
||||||
|
cursheet->mark1x = x1;
|
||||||
|
cursheet->mark1y = y1;
|
||||||
|
cursheet->mark2x = x2;
|
||||||
|
cursheet->mark2y = y2;
|
||||||
|
cursheet->mark1z = cursheet->mark2z = cursheet->curz;
|
||||||
|
cursheet->marking = 0;
|
||||||
|
}
|
||||||
|
moveto(cursheet, current_col, current_row, -1);
|
||||||
|
visible_cells(cursheet->offy, cursheet->maxy, cursheet->offx, cursheet->maxx);
|
||||||
|
cursheet->maxx -= cursheet->offx;
|
||||||
|
cursheet->maxy -= cursheet->offy;
|
||||||
|
|
||||||
|
if (is_interactive_resize()) {
|
||||||
|
for (int C = 0; C < cursheet->dimx; C++) {
|
||||||
|
int w = (col_width(C) + 5)/10;
|
||||||
|
if (w != columnwidth(cursheet, C, cursheet->curz)) setwidth(cursheet, C, cursheet->curz, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
updating = false;
|
||||||
|
//printf("update_sheet: %ix%i@%i,%i; %i[%i], %i[%i] (%i,%i)-(%i,%i)\\n", cols(), rows(), cursheet->curx, cursheet->cury, cursheet->offx, cursheet->maxx, cursheet->offy, cursheet->maxy, x1, y1, x2, y2);} {}
|
||||||
|
}
|
||||||
|
Function {handle(int event)} {open return_type int
|
||||||
|
} {
|
||||||
|
code {if (event == FL_KEYDOWN) {
|
||||||
|
int ctrl = Fl::event_ctrl();
|
||||||
|
int alt = Fl::event_alt();
|
||||||
|
int shift = Fl::event_shift();
|
||||||
|
Key k = (Key)Fl::event_key();
|
||||||
|
|
||||||
|
switch ((unsigned int)k) {
|
||||||
|
case FL_Escape: k = K_INVALID; break;
|
||||||
|
case FL_BackSpace: k = K_BACKSPACE; break;
|
||||||
|
case FL_F+1: k = ctrl?K_ABOUT:K_HELP; break;
|
||||||
|
case FL_F+8: k = ctrl?K_RECALC:K_CLOCK; break;
|
||||||
|
case FL_F+9: k = ctrl?K_RECALC:K_CLOCK; break;
|
||||||
|
case FL_F+10: k = (Key)'/'; break;
|
||||||
|
case FL_Enter:
|
||||||
|
case FL_KP_Enter: k = alt?K_MENTER:K_ENTER; break;
|
||||||
|
case 'c': if (ctrl) { do_mark(cursheet, 2); cut = false; k = K_NONE; } break;
|
||||||
|
case 'v': k = ctrl?(cut?BLOCK_MOVE:BLOCK_COPY):(Key)'v'; break;
|
||||||
|
case 'x': if (ctrl) { do_mark(cursheet, 2); cut = true, k = K_NONE; } break;
|
||||||
|
case FL_Insert: if (ctrl) { do_mark(cursheet, 2); cut = false; } k = !shift?K_NONE:cut?BLOCK_MOVE:BLOCK_COPY; break;
|
||||||
|
case FL_Delete: if (shift) { do_mark(cursheet, 2); cut = true; } k = shift?K_NONE:BLOCK_CLEAR; break;
|
||||||
|
case FL_Home: k = ctrl?K_FIRSTL:shift?K_FSHEET:K_HOME; break;
|
||||||
|
case FL_End: k = ctrl?K_LASTL:shift?K_LSHEET:K_END; break;
|
||||||
|
case FL_Up: if (shift && !cursheet->marking) do_mark(cursheet, 1); k = ctrl?K_PPAGE:K_UP; break;
|
||||||
|
case FL_Down: if (shift && !cursheet->marking) do_mark(cursheet, 1); k = ctrl?K_NPAGE:K_DOWN; break;
|
||||||
|
case FL_Right: if (shift && !cursheet->marking) do_mark(cursheet, 1); k = ctrl?K_FPAGE:K_RIGHT; break;
|
||||||
|
case FL_Left: if (shift && !cursheet->marking) do_mark(cursheet, 1); k = ctrl?K_BPAGE:K_LEFT; break;
|
||||||
|
case FL_Page_Down: k = shift?K_NSHEET:ctrl?K_LASTL :K_NPAGE; break;
|
||||||
|
case FL_Page_Up: k = shift?K_PSHEET:ctrl?K_FIRSTL:K_PPAGE; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k > 0 && (ctrl || alt)) return 0;
|
||||||
|
|
||||||
|
// Quick and dirty upper-case fix, fails for international chars on keyboards...
|
||||||
|
if (shift && !alt && !ctrl && k >= 'a' && k <= 'z') k = (Key)(k - 'a' + 'A');
|
||||||
|
|
||||||
|
do_sheetcmd(cursheet, k, cursheet->moveonly);
|
||||||
|
do_callback(ACTION, 0, 0);
|
||||||
|
redraw();
|
||||||
|
} else if (event == FL_FOCUS) {
|
||||||
|
do_callback(REFRESH, 0, 0);
|
||||||
|
return 1;
|
||||||
|
} else if (event == FL_PUSH) {
|
||||||
|
int ex = Fl::event_x() - x(), ey = Fl::event_y() - y();
|
||||||
|
if (ex >= row_header_width() || ey >= col_header_height()) {
|
||||||
|
int rc = Fl_Table::handle(event);
|
||||||
|
do_callback(ACTION, 0, 0);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if (ex < row_header_width()/2) relmoveto(cursheet, 0, 0, -1);
|
||||||
|
else relmoveto(cursheet, 0, 0, 1);
|
||||||
|
return 1;
|
||||||
|
} else if (event != FL_KEYUP) {
|
||||||
|
return Fl_Table::handle(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;} {}
|
||||||
|
}
|
||||||
|
Function {adjust_outside()} {open protected return_type void
|
||||||
|
} {
|
||||||
|
code {int x1, x2, y1, y2;
|
||||||
|
|
||||||
|
if (!cols() || !rows()) {
|
||||||
|
cols(1);
|
||||||
|
rows(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
visible_cells(y1, y2, x1, x2);
|
||||||
|
//printf("adj: (%i,%i)-(%i,%i) %ix%i\\n", x1, y1, x2, y2, cols(), rows());
|
||||||
|
if (x2+2 < cols() && cols() > cursheet->dimx) cols(x2+2 < cursheet->dimx?cursheet->dimx:x2+2);
|
||||||
|
else if (x2+1 == cols()) {
|
||||||
|
int xpos = col_scroll_position(cols());
|
||||||
|
int w = col_width(cols()-1);
|
||||||
|
x2 += (tow + hscrollbar->value() - xpos) / w + 2;
|
||||||
|
//printf(" : t: %i, w: %i, p: %i, r: %i\\n", tow, w, xpos, x2+1);
|
||||||
|
cols(x2+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y2+2 < rows() && rows() > cursheet->dimy) rows(y2+2 < cursheet->dimy?cursheet->dimy:y2+2);
|
||||||
|
else if (y2+1 == rows()) {
|
||||||
|
int ypos = row_scroll_position(rows());
|
||||||
|
int h = row_height(rows()-1);
|
||||||
|
y2 += (toh + vscrollbar->value() - ypos) / h + 2;
|
||||||
|
rows(y2+1);
|
||||||
|
}} {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainWindow {open
|
||||||
|
} {
|
||||||
|
decl {static MainWindow *current;} {protected local
|
||||||
|
}
|
||||||
|
decl {int edit_rc;} {private local
|
||||||
|
}
|
||||||
|
Function {MainWindow(Sheet *sheet)} {open
|
||||||
|
} {
|
||||||
|
Fl_Window window {
|
||||||
|
label teapot
|
||||||
|
callback {if (Fl::event_key(FL_Escape)) table->take_focus();
|
||||||
|
else if (do_sheetcmd(table->sheet(), K_QUIT, 0) && doanyway(table->sheet(), _("Sheet modified, leave anyway?"))) {
|
||||||
|
line_label->deactivate();
|
||||||
|
window->hide();
|
||||||
|
}} open
|
||||||
|
protected xywh {866 342 800 600} type Double when 0 hide resizable
|
||||||
|
} {
|
||||||
|
Fl_Menu_Bar menu {
|
||||||
|
callback {Sheet *sheet = table->sheet();
|
||||||
|
Key action = (Key)(intptr_t)o->mvalue()->user_data();
|
||||||
|
|
||||||
|
if (do_sheetcmd(sheet, action, sheet->moveonly) && doanyway(sheet, _("Sheet modified, leave anyway?"))) {
|
||||||
|
window->hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
table->update_table();
|
||||||
|
table->redraw();} open
|
||||||
|
xywh {0 0 800 25}
|
||||||
|
class Fl_Sys_Menu_Bar
|
||||||
|
} {
|
||||||
|
Submenu {} {
|
||||||
|
label {&File}
|
||||||
|
xywh {25 25 67 24}
|
||||||
|
} {
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Open...}
|
||||||
|
user_data K_LOADMENU
|
||||||
|
xywh {5 5 30 20} shortcut 0x4006f
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Save}
|
||||||
|
user_data K_SAVE
|
||||||
|
xywh {0 0 30 20} shortcut 0x40073
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {Save &As...}
|
||||||
|
user_data K_NAME
|
||||||
|
xywh {0 0 30 20} shortcut 0x50053 divider
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Quit}
|
||||||
|
user_data K_QUIT
|
||||||
|
xywh {0 0 30 20} shortcut 0x40071
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Submenu {} {
|
||||||
|
label {&Block}
|
||||||
|
xywh {25 25 67 24}
|
||||||
|
} {
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Insert}
|
||||||
|
user_data BLOCK_INSERT
|
||||||
|
xywh {0 0 30 20} shortcut 0x90069
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Delete}
|
||||||
|
user_data BLOCK_DELETE
|
||||||
|
xywh {0 0 30 20} shortcut 0x90064 divider
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Move}
|
||||||
|
user_data BLOCK_MOVE
|
||||||
|
xywh {0 0 30 20} shortcut 0x9006d
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Copy}
|
||||||
|
user_data BLOCK_COPY
|
||||||
|
xywh {0 0 36 21} shortcut 0x90063 divider
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Fill}
|
||||||
|
user_data BLOCK_FILL
|
||||||
|
xywh {0 0 36 21} shortcut 0x90066
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {C&lear}
|
||||||
|
user_data BLOCK_CLEAR
|
||||||
|
xywh {0 0 36 21} shortcut 0x9006c divider
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Sort}
|
||||||
|
user_data BLOCK_SORT
|
||||||
|
xywh {0 0 36 21} shortcut 0x90073
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {Mi&rror}
|
||||||
|
user_data BLOCK_MIRROR
|
||||||
|
xywh {0 0 36 21} shortcut 0x90072
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Submenu {} {
|
||||||
|
label {&View}
|
||||||
|
xywh {0 0 70 21}
|
||||||
|
} {
|
||||||
|
MenuItem {} {
|
||||||
|
label {Column &Width...}
|
||||||
|
user_data K_COLWIDTH
|
||||||
|
xywh {0 0 36 21} shortcut 0x80077
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Goto}
|
||||||
|
user_data K_GOTO
|
||||||
|
xywh {0 0 36 21} shortcut 0x40067
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Submenu {} {
|
||||||
|
label {F&ormat} open
|
||||||
|
xywh {5 5 70 21}
|
||||||
|
} {
|
||||||
|
MenuItem {} {
|
||||||
|
label {L&abel...}
|
||||||
|
user_data ADJUST_LABEL
|
||||||
|
xywh {0 0 36 21} shortcut 0x80061 divider
|
||||||
|
}
|
||||||
|
MenuItem bold {
|
||||||
|
label {&Bold}
|
||||||
|
user_data ADJUST_BOLD
|
||||||
|
protected xywh {0 0 34 21} shortcut 0x80062
|
||||||
|
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||||
|
}
|
||||||
|
MenuItem underline {
|
||||||
|
label {&Underline}
|
||||||
|
user_data ADJUST_UNDERLINE
|
||||||
|
protected xywh {0 0 34 21} shortcut 0x80075 divider
|
||||||
|
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||||
|
}
|
||||||
|
MenuItem left {
|
||||||
|
label {&Left}
|
||||||
|
user_data ADJUST_LEFT
|
||||||
|
protected xywh {0 0 36 21} shortcut 0x8006c
|
||||||
|
code0 {o->flags |= FL_MENU_RADIO;}
|
||||||
|
}
|
||||||
|
MenuItem right {
|
||||||
|
label {&Right}
|
||||||
|
user_data ADJUST_RIGHT
|
||||||
|
protected xywh {0 0 36 21} shortcut 0x80072
|
||||||
|
code0 {o->flags |= FL_MENU_RADIO;}
|
||||||
|
}
|
||||||
|
MenuItem center {
|
||||||
|
label {&Center}
|
||||||
|
user_data ADJUST_CENTER
|
||||||
|
protected xywh {0 0 36 21} shortcut 0x80063 divider
|
||||||
|
code0 {o->flags |= FL_MENU_RADIO;}
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Precision...}
|
||||||
|
user_data ADJUST_PRECISION
|
||||||
|
xywh {0 0 36 21} shortcut 0x80070 divider
|
||||||
|
}
|
||||||
|
MenuItem sci {
|
||||||
|
label {&Scientific}
|
||||||
|
user_data ADJUST_SCIENTIFIC
|
||||||
|
protected xywh {0 0 36 21} shortcut 0x80073
|
||||||
|
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||||
|
}
|
||||||
|
MenuItem shadow {
|
||||||
|
label {Shadow&ed}
|
||||||
|
user_data ADJUST_SHADOW
|
||||||
|
protected xywh {0 0 36 21} shortcut 0x80065
|
||||||
|
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||||
|
}
|
||||||
|
MenuItem transparent {
|
||||||
|
label {&Transparent}
|
||||||
|
user_data ADJUST_TRANSPARENT
|
||||||
|
protected xywh {0 0 36 21} shortcut 0x80074 divider
|
||||||
|
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||||
|
}
|
||||||
|
MenuItem lock {
|
||||||
|
label {Lo&ck}
|
||||||
|
user_data ADJUST_LOCK
|
||||||
|
protected xywh {0 0 36 21} shortcut 0x80063
|
||||||
|
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||||
|
}
|
||||||
|
MenuItem ignore {
|
||||||
|
label {&Ignore}
|
||||||
|
user_data ADJUST_IGNORE
|
||||||
|
protected xywh {0 0 36 21} shortcut 0x80069
|
||||||
|
code0 {o->flags |= FL_MENU_TOGGLE;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Submenu {} {
|
||||||
|
label {&Help} open
|
||||||
|
xywh {25 25 67 24}
|
||||||
|
} {
|
||||||
|
MenuItem {} {
|
||||||
|
label {&Manual}
|
||||||
|
user_data K_HELP
|
||||||
|
xywh {0 0 30 20} shortcut 0xffbe
|
||||||
|
}
|
||||||
|
MenuItem {} {
|
||||||
|
label {&About}
|
||||||
|
user_data K_ABOUT
|
||||||
|
xywh {0 0 30 20}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fl_Group line_label {
|
||||||
|
label { Input:} open
|
||||||
|
protected xywh {0 25 800 25} box ROUND_UP_BOX align 20 deactivate
|
||||||
|
} {
|
||||||
|
Fl_Input line_input {
|
||||||
|
callback {bool enterkey = Fl::event_key(FL_Enter) || Fl::event_key(FL_KP_Enter);
|
||||||
|
if (Fl::focus() && (Fl::focus() != table || enterkey || Fl::event_key(FL_Escape))) {
|
||||||
|
if (enterkey) edit_rc = 0;
|
||||||
|
line_label->deactivate();
|
||||||
|
}}
|
||||||
|
protected xywh {75 27 723 21} box ROUND_DOWN_BOX labeltype NO_LABEL align 20 when 6 deactivate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fl_Box table {
|
||||||
|
callback {Sheet *sheet = table->sheet();
|
||||||
|
table->update_sheet();
|
||||||
|
|
||||||
|
const char *label = getlabel(sheet,sheet->curx,sheet->cury,sheet->curz);
|
||||||
|
char moveonly=sheet->moveonly ? *_("V") : *_("E");
|
||||||
|
|
||||||
|
char buf[1024];
|
||||||
|
if (*label == 0) snprintf(buf, sizeof(buf), "%c @@(%d,%d,%d)=", moveonly, sheet->curx, sheet->cury, sheet->curz);
|
||||||
|
else snprintf(buf, sizeof(buf), "%c @@(%s)=", moveonly, label);
|
||||||
|
|
||||||
|
if (moveonly && table->callback_context() == TeapotTable::ACTION) {
|
||||||
|
char valbuf[1024] = "";
|
||||||
|
if (Fl::event_key() == 'p' || Fl::event_button1()) sprintf(valbuf, "(%i,%i,%i)", sheet->curx, sheet->cury, sheet->curz);
|
||||||
|
else if (Fl::event_key() == 'v') printvalue(valbuf,sizeof(valbuf),0,1,getscientific(sheet,sheet->curx,sheet->cury,sheet->curz),-1,sheet,sheet->curx,sheet->cury,sheet->curz);
|
||||||
|
else if (Fl::event_key(FL_Tab)) line_input->take_focus();
|
||||||
|
if (valbuf[0]) {
|
||||||
|
line_input->insert(valbuf);
|
||||||
|
line_input->take_focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *err;
|
||||||
|
char val[1024];
|
||||||
|
if ((err = geterror(sheet, sheet->curx, sheet->cury, sheet->curz))) {
|
||||||
|
strncpy(val,err,sizeof(val));
|
||||||
|
free(err);
|
||||||
|
val[sizeof(val)-1] = 0;
|
||||||
|
} else {
|
||||||
|
print(val,sizeof(val),0,1,getscientific(sheet,sheet->curx,sheet->cury,sheet->curz),-1,getcont(sheet,sheet->curx,sheet->cury,sheet->curz,0));
|
||||||
|
if (getcont(sheet,sheet->curx,sheet->cury,sheet->curz,1)) {
|
||||||
|
snprintf(val+strlen(val),sizeof(val)-strlen(val)," -> ");
|
||||||
|
print(val+strlen(val),sizeof(val)-strlen(val),0,1,getscientific(sheet,sheet->curx,sheet->cury,sheet->curz),-1,getcont(sheet,sheet->curx,sheet->cury,sheet->curz,1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line_edit(sheet, val, 0, buf, 0, 0);
|
||||||
|
int x = sheet->curx, y = sheet->cury, z = sheet->curz;
|
||||||
|
int adj = getadjust(sheet, x, y, z);
|
||||||
|
if (adj == LEFT) left->setonly();
|
||||||
|
else if (adj == RIGHT) right->setonly();
|
||||||
|
else if (adj == CENTER) center->setonly();
|
||||||
|
if (shadowed(sheet, x+1, y, z)) shadow->set();
|
||||||
|
else shadow->clear();
|
||||||
|
if (::transparent(sheet, x, y, z)) transparent->set();
|
||||||
|
else transparent->clear();
|
||||||
|
if (locked(sheet, x, y, z)) lock->set();
|
||||||
|
else lock->clear();
|
||||||
|
if (ignored(sheet, x, y, z)) ignore->set();
|
||||||
|
else ignore->clear();
|
||||||
|
if (isbold(sheet, x, y, z)) bold->set();
|
||||||
|
else bold->clear();
|
||||||
|
if (underlined(sheet, x, y, z)) underline->set();
|
||||||
|
else underline->clear();
|
||||||
|
if (getscientific(sheet, x, y, z)) sci->set();
|
||||||
|
else sci->clear();}
|
||||||
|
protected xywh {0 50 800 525} box DOWN_FRAME labeltype NO_LABEL resizable
|
||||||
|
code0 {table->sheet(sheet);}
|
||||||
|
class TeapotTable
|
||||||
|
}
|
||||||
|
Fl_Box status {
|
||||||
|
label {teapot ready.}
|
||||||
|
protected xywh {0 575 800 25} box GTK_ROUND_DOWN_BOX align 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
code {current = this;} {}
|
||||||
|
}
|
||||||
|
Function {line_edit(Sheet *sheet, char *buf, size_t size, const char *prompt, size_t *x, size_t *offx)} {open return_type int
|
||||||
|
} {
|
||||||
|
code {if (line_label->active()) {
|
||||||
|
if (x) line_msg(NULL, "Action not possible at this time.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_label->copy_label(prompt);
|
||||||
|
|
||||||
|
int ww = 0, hh = 0;
|
||||||
|
line_label->measure_label(ww, hh);
|
||||||
|
line_input->resize(line_label->x()+ww+5, line_input->y(), line_label->w()-ww-7, line_input->h());
|
||||||
|
line_input->value(buf);
|
||||||
|
|
||||||
|
if (!x) return 0;
|
||||||
|
|
||||||
|
line_input->maximum_size(size);
|
||||||
|
line_input->position(*x, *x);
|
||||||
|
line_label->activate();
|
||||||
|
line_input->activate();
|
||||||
|
table->sheet()->moveonly = 1;
|
||||||
|
line_input->take_focus();
|
||||||
|
|
||||||
|
edit_rc = -1;
|
||||||
|
while (line_label->active()) Fl::wait();
|
||||||
|
|
||||||
|
memcpy(buf, line_input->value(), size);
|
||||||
|
line_input->deactivate();
|
||||||
|
table->sheet()->moveonly = 0;
|
||||||
|
table->take_focus();
|
||||||
|
return edit_rc;} {}
|
||||||
|
}
|
||||||
|
Function {line_msg(const char *prompt, const char *msg)} {return_type void
|
||||||
|
} {
|
||||||
|
code {char label[1024];
|
||||||
|
snprintf(label, sizeof(label), "%s%s%s", prompt?prompt:"", prompt?" ":"", msg);
|
||||||
|
status->copy_label(label);} {}
|
||||||
|
}
|
||||||
|
decl {friend void line_msg(const char*, const char*);} {private local
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {line_file(const char *file, const char *pattern, const char *title, int create)} {open C return_type {const char *}
|
||||||
|
} {
|
||||||
|
code {static char buf[PATH_MAX];
|
||||||
|
Fl_Native_File_Chooser chooser;
|
||||||
|
|
||||||
|
chooser.title(title);
|
||||||
|
chooser.type(create?Fl_Native_File_Chooser::BROWSE_SAVE_FILE:Fl_Native_File_Chooser::BROWSE_FILE);
|
||||||
|
chooser.filter(pattern);
|
||||||
|
chooser.options((create?Fl_Native_File_Chooser::NEW_FOLDER:0)|Fl_Native_File_Chooser::SAVEAS_CONFIRM);
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
fl_filename_absolute(buf, sizeof(buf), file);
|
||||||
|
char *p = (char *)fl_filename_name(buf);
|
||||||
|
*p = 0;
|
||||||
|
chooser.directory(buf);
|
||||||
|
}
|
||||||
|
if (chooser.show()) return NULL;
|
||||||
|
|
||||||
|
strncpy(buf, chooser.filename(), sizeof(buf));
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
return buf;} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {line_edit(Sheet *sheet, char *buf, size_t size, const char *prompt, size_t *x, size_t *offx)} {C return_type int
|
||||||
|
} {
|
||||||
|
code {if (sheet) return ((MainWindow*)((TeapotTable*)sheet->display)->parent()->user_data())->line_edit(sheet, buf, size, prompt, x, offx);
|
||||||
|
|
||||||
|
const char *val = fl_input("%s", buf, prompt);
|
||||||
|
if (val) {
|
||||||
|
strncpy(buf, val, size);
|
||||||
|
buf[size-1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !val;} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {line_ok(const char *prompt, int curx)} {C return_type int
|
||||||
|
} {
|
||||||
|
code {int rc = !!fl_choice("%s", "&No", NULL, "&Yes", prompt);
|
||||||
|
if (Fl::event_key(FL_Escape)) return -1;
|
||||||
|
return rc;} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {line_msg(const char *prompt, const char *msg)} {C return_type void
|
||||||
|
} {
|
||||||
|
code {MainWindow::current->line_msg(prompt, msg);} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {keypressed()} {open C return_type int
|
||||||
|
} {
|
||||||
|
code {while (Fl::wait(.01)) if (Fl::event_key(FL_Escape)) return 1;
|
||||||
|
return 0;} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {line_menu(const char *prompt, const MenuChoice *choice, int curx)} {C return_type int
|
||||||
|
} {
|
||||||
|
Fl_Window line_menu_menu {
|
||||||
|
label {Please Choose} open
|
||||||
|
xywh {706 58 250 245} type Double hide resizable modal
|
||||||
|
} {
|
||||||
|
Fl_Group {} {
|
||||||
|
label {Please Choose:} open
|
||||||
|
xywh {0 0 250 200} box ENGRAVED_BOX align 21
|
||||||
|
} {
|
||||||
|
Fl_Browser line_menu_browser {
|
||||||
|
callback {line_menu_menu->hide();}
|
||||||
|
xywh {5 25 240 170}
|
||||||
|
class Fl_Select_Browser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fl_Button {} {
|
||||||
|
label Cancel
|
||||||
|
callback {line_menu_menu->hide();}
|
||||||
|
xywh {5 205 240 35}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
code {line_menu_browser->clear();
|
||||||
|
while (choice->str) {
|
||||||
|
line_menu_browser->add(choice->str+1);
|
||||||
|
choice++;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_menu_menu->show();
|
||||||
|
while (line_menu_menu->shown()) Fl::wait();
|
||||||
|
|
||||||
|
return line_menu_browser->value()-1;} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {redraw_sheet(Sheet *sheet)} {C return_type void
|
||||||
|
} {
|
||||||
|
code {TeapotTable *t = (TeapotTable*)sheet->display;
|
||||||
|
t->update_table();
|
||||||
|
t->redraw();} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {redraw_cell(Sheet *sheet, int x, int y, int z)} {C return_type void
|
||||||
|
} {
|
||||||
|
code {redraw_sheet(sheet);} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {display_init(Sheet *sheet, int always_redraw)} {open C return_type void
|
||||||
|
} {
|
||||||
|
code {Fl::get_system_colors();
|
||||||
|
\#ifdef ENABLE_HELP
|
||||||
|
Fl_File_Icon::load_system_icons();
|
||||||
|
\#endif
|
||||||
|
Fl::scheme("gtk+");
|
||||||
|
int ch = sheet->changed;
|
||||||
|
resize(sheet, 1, 1, 1);
|
||||||
|
sheet->changed = ch;
|
||||||
|
new MainWindow(sheet);} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {display_end()} {C return_type void
|
||||||
|
} {
|
||||||
|
code {} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {display_main(Sheet *cursheet)} {C return_type void
|
||||||
|
} {
|
||||||
|
code {((TeapotTable *)cursheet->display)->parent()->show();
|
||||||
|
Fl::run();} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {show_menu(Sheet *sheet)} {C return_type Key
|
||||||
|
} {
|
||||||
|
code {return K_NONE;} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
decl {MainWindow *MainWindow::current;} {private global
|
||||||
|
}
|
||||||
|
|
||||||
|
declblock {\#ifdef ENABLE_HELP} {after {\#endif}
|
||||||
|
} {
|
||||||
|
decl {\#include <FL/Fl_Help_Dialog.H>} {private global
|
||||||
|
}
|
||||||
|
Function {show_text(const char *text)} {open C return_type void
|
||||||
|
} {
|
||||||
|
code {Fl_Help_Dialog *d = new Fl_Help_Dialog();
|
||||||
|
if (strchr(text, '<')) {
|
||||||
|
d->value(text);
|
||||||
|
} else {
|
||||||
|
d->load(text);
|
||||||
|
}
|
||||||
|
d->resize(d->x(), d->y(), d->w()*3/2, d->h()*3/2);
|
||||||
|
d->show();} {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declblock {\#ifndef ENABLE_HELP} {after {\#endif}
|
||||||
|
} {
|
||||||
|
Function {show_text(const char *text)} {open C return_type void
|
||||||
|
} {
|
||||||
|
code {char *txt = striphtml(text);
|
||||||
|
fl_message("%s", txt);
|
||||||
|
free(txt);} {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function {find_helpfile(char *buf, int size, const char *argv0)} {open C return_type void
|
||||||
|
} {
|
||||||
|
code {fl_filename_absolute(buf, size, argv0);
|
||||||
|
char *p = (char *)fl_filename_name(buf);
|
||||||
|
strncpy(p, "../share/doc/teapot/html/index.html", buf+size-p);
|
||||||
|
buf[size-1] = 0;
|
||||||
|
|
||||||
|
// Check if help exists in default installed location, fallback value is valid for build directory
|
||||||
|
int test = open(buf, O_RDONLY);
|
||||||
|
if (test < 0) strncpy(p, "html/index.html", buf+size-p);
|
||||||
|
else close(test);
|
||||||
|
buf[size-1] = 0;
|
||||||
|
|
||||||
|
// Try the configure-time determined value
|
||||||
|
test = open(buf, O_RDONLY);
|
||||||
|
if (test < 0) strncpy(buf, HELPFILE, size);
|
||||||
|
else close(test);
|
||||||
|
buf[size-1] = 0;
|
||||||
|
|
||||||
|
// Fall back to a sane value for unixoid systems
|
||||||
|
test = open(buf, O_RDONLY);
|
||||||
|
if (test < 0) strncpy(buf, "/usr/share/doc/teapot/html/index.html", size);
|
||||||
|
else close(test);
|
||||||
|
buf[size-1] = 0;
|
||||||
|
|
||||||
|
} {}
|
||||||
|
}
|
14
func.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef FUNC_H
|
||||||
|
#define FUNC_H
|
||||||
|
|
||||||
|
#include "scanner.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char name[20];
|
||||||
|
Token (*func)(int, const Token[]);
|
||||||
|
} Tfunc;
|
||||||
|
|
||||||
|
extern Tfunc tfunc[];
|
||||||
|
|
||||||
|
#endif
|
247
graph.c
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||||
|
#undef _POSIX_SOURCE
|
||||||
|
#define _POSIX_SOURCE 1
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 2
|
||||||
|
#define _GNU_SOURCE 1
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
double strtod(const char *nptr, char **endptr); /* SunOS 4 hack */
|
||||||
|
#ifdef OLD_REALLOC
|
||||||
|
#define realloc(s,l) myrealloc(s,l)
|
||||||
|
#endif
|
||||||
|
extern char *optarg;
|
||||||
|
extern int optind,opterr,optopt;
|
||||||
|
int getopt(int argc, char * const *argv, const char *optstring);
|
||||||
|
|
||||||
|
#ifdef DMALLOC
|
||||||
|
#include "dmalloc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "csv.h"
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) /*{{{*/
|
||||||
|
{
|
||||||
|
/* variables */ /*{{{*/
|
||||||
|
struct Pair
|
||||||
|
{
|
||||||
|
const char *label;
|
||||||
|
double value;
|
||||||
|
int special;
|
||||||
|
} *pair;
|
||||||
|
int pairs;
|
||||||
|
double height,width;
|
||||||
|
int box;
|
||||||
|
int nl;
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* parse options */ /*{{{*/
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
height=width=2.0;
|
||||||
|
box=0;
|
||||||
|
nl=1;
|
||||||
|
while ((c=getopt(argc,argv,"bnw:h:?"))!=EOF) switch (c)
|
||||||
|
{
|
||||||
|
/* w width */ /*{{{*/
|
||||||
|
case 'w':
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
|
||||||
|
width=strtod(optarg,&end);
|
||||||
|
if (*end!='\0')
|
||||||
|
{
|
||||||
|
fprintf(stderr,"graph: invalid width\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* h height */ /*{{{*/
|
||||||
|
case 'h':
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
|
||||||
|
height=strtod(optarg,&end);
|
||||||
|
if (*end!='\0')
|
||||||
|
{
|
||||||
|
fprintf(stderr,"graph: invalid height\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* n */
|
||||||
|
case 'n':
|
||||||
|
{
|
||||||
|
nl=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* b */
|
||||||
|
case 'b':
|
||||||
|
{
|
||||||
|
box=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Usage: graph [-b][-h height][-w width]\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* get data */ /*{{{*/
|
||||||
|
{
|
||||||
|
char ln[256];
|
||||||
|
int line,pairsz;
|
||||||
|
|
||||||
|
pairs=pairsz=0;
|
||||||
|
pair=(struct Pair*)0;
|
||||||
|
for (line=1; fgets(ln,sizeof(ln),stdin); ++line)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
const char *end;
|
||||||
|
|
||||||
|
if (pairs==pairsz)
|
||||||
|
{
|
||||||
|
if ((pair=realloc(pair,sizeof(struct Pair)*(pairsz+=128)))==(struct Pair*)0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"graph:%d:out of memory\n",line);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s=ln;
|
||||||
|
pair[pairs].label=csv_string(s,&end);
|
||||||
|
if (s==end) fprintf(stderr,"graph:%d:invalid string, ignoring record\n",line);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s=end;
|
||||||
|
pair[pairs].value=csv_double(s,&end);
|
||||||
|
if (s==end) fprintf(stderr,"graph:%d:invalid value, ignoring record\n",line);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s=end;
|
||||||
|
pair[pairs].special=csv_double(s,&end);
|
||||||
|
if (s==end && *s!='\n') fprintf(stderr,"graph:%d:invalid mark value, ignoringrecord\n",line);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s=end;
|
||||||
|
if (*s!='\n') fprintf(stderr,"graph:%d:trailing garbage\n",line);
|
||||||
|
}
|
||||||
|
++pairs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
if (box) /* make box graph */ /*{{{*/
|
||||||
|
{
|
||||||
|
double height,boxwid,min,max,scale;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
height=2;
|
||||||
|
boxwid=width/pairs;
|
||||||
|
for (min=max=0.0,i=0; i<pairs; ++i)
|
||||||
|
{
|
||||||
|
if (pair[i].value<min) min=pair[i].value;
|
||||||
|
else if (pair[i].value>max) max=pair[i].value;
|
||||||
|
}
|
||||||
|
scale=height/(max-min);
|
||||||
|
printf("[\nFRAME: box invis wid %f ht %f\n",width,height);
|
||||||
|
for (i=0; i<pairs; ++i)
|
||||||
|
{
|
||||||
|
double v;
|
||||||
|
|
||||||
|
v=fabs(pair[i].value);
|
||||||
|
printf
|
||||||
|
(
|
||||||
|
"box wid %f ht %f with .%s at FRAME.sw + (%f,%f) \"%s\"\n",
|
||||||
|
boxwid,
|
||||||
|
v*scale,
|
||||||
|
pair[i].value>0 ? "sw" : "nw",
|
||||||
|
i*boxwid,
|
||||||
|
-min*scale,
|
||||||
|
pair[i].label
|
||||||
|
);
|
||||||
|
}
|
||||||
|
printf("]"); if (nl) printf("\n");
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else /* make pie graph */ /*{{{*/
|
||||||
|
{
|
||||||
|
int anyspecial,i;
|
||||||
|
double sum,scale,extra,arc;
|
||||||
|
|
||||||
|
for (sum=0.0,i=0,anyspecial=0; i<pairs; ++i)
|
||||||
|
{
|
||||||
|
sum+=pair[i].value;
|
||||||
|
if (pair[i].special) anyspecial=1;
|
||||||
|
}
|
||||||
|
scale=2.0*M_PI/sum;
|
||||||
|
printf("[\n");
|
||||||
|
printf("box invis wid %f ht %f\n",width,width);
|
||||||
|
if (anyspecial) width-=width/10.0;
|
||||||
|
for (sum=0,i=0; i<pairs; sum+=pair[i].value,++i)
|
||||||
|
{
|
||||||
|
extra=(pair[i].special!=0)*width/20.0;
|
||||||
|
for (arc=0; (arc+M_PI_4)<(pair[i].value*scale); arc+=M_PI_4)
|
||||||
|
{
|
||||||
|
printf
|
||||||
|
(
|
||||||
|
"arc from last box.c + (%f,%f) to last box.c + (%f,%f) rad %f\n",
|
||||||
|
cos((sum+arc)*scale)*width/2.0 + cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
sin((sum+arc)*scale)*width/2.0 + sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
cos((sum+arc+M_PI_4)*scale)*width/2.0 + cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
sin((sum+arc+M_PI_4)*scale)*width/2.0 + sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
width/2.0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
printf
|
||||||
|
(
|
||||||
|
"arc from last box.c + (%f,%f) to last box.c + (%f,%f) rad %f\n",
|
||||||
|
cos((sum+arc)*scale)*width/2.0 + cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
sin((sum+arc)*scale)*width/2.0 + sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
cos((sum+pair[i].value)*scale)*width/2.0 + cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
sin((sum+pair[i].value)*scale)*width/2.0 + sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
width/2.0
|
||||||
|
);
|
||||||
|
|
||||||
|
printf
|
||||||
|
(
|
||||||
|
"line from last box.c + (%f,%f) to last box.c + (%f,%f)\n",
|
||||||
|
cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
cos(sum*scale)*width/2.0+cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
sin(sum*scale)*width/2.0+sin((sum+pair[i].value/2.0)*scale)*extra
|
||||||
|
);
|
||||||
|
|
||||||
|
printf
|
||||||
|
(
|
||||||
|
"line from last box.c + (%f,%f) to last box.c + (%f,%f)\n",
|
||||||
|
cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
sin((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
cos((sum+pair[i].value)*scale)*width/2.0+cos((sum+pair[i].value/2.0)*scale)*extra,
|
||||||
|
sin((sum+pair[i].value)*scale)*width/2.0+sin((sum+pair[i].value/2.0)*scale)*extra
|
||||||
|
);
|
||||||
|
|
||||||
|
printf
|
||||||
|
(
|
||||||
|
"\"%s\" at last box.c + (%f,%f)\n",
|
||||||
|
pair[i].label,
|
||||||
|
cos((sum+pair[i].value/2.0)*scale)*width*0.35,
|
||||||
|
sin((sum+pair[i].value/2.0)*scale)*width*0.35
|
||||||
|
);
|
||||||
|
}
|
||||||
|
printf("]"); if (nl) printf("\n");
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
115
htmlio.c
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||||
|
#ifndef NO_POSIX_SOURCE
|
||||||
|
#undef _POSIX_SOURCE
|
||||||
|
#define _POSIX_SOURCE 1
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DMALLOC
|
||||||
|
#include "dmalloc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "htmlio.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "misc.h"
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* savehtml -- save as HTML table */ /*{{{*/
|
||||||
|
const char *savehtml(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count)
|
||||||
|
{
|
||||||
|
/* variables */ /*{{{*/
|
||||||
|
FILE *fp=(FILE*)0; /* cause runtime error */
|
||||||
|
int x,y,z;
|
||||||
|
char buf[1024];
|
||||||
|
char num[20];
|
||||||
|
char fullname[PATH_MAX];
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* asserts */ /*{{{*/
|
||||||
|
assert(sheet!=(Sheet*)0);
|
||||||
|
assert(name!=(const char*)0);
|
||||||
|
/*}}}*/
|
||||||
|
*count=0;
|
||||||
|
for (z=z1; z<=z2; ++z) for (y=y1; y<=y2; ++y) if (shadowed(sheet,x1,y,z)) return _("Shadowed cells in first column");
|
||||||
|
if (!body && (fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
|
||||||
|
for (z=z1; z<=z2; ++z)
|
||||||
|
{
|
||||||
|
if (body) /* open new file */ /*{{{*/
|
||||||
|
{
|
||||||
|
sprintf(num,".%d",z);
|
||||||
|
|
||||||
|
fullname[sizeof(fullname)-strlen(num)-1]='\0';
|
||||||
|
(void)strncpy(fullname,name,sizeof(fullname)-strlen(num)-1);
|
||||||
|
fullname[sizeof(fullname)-1]='\0';
|
||||||
|
(void)strncat(fullname,num,sizeof(fullname)-strlen(num)-1);
|
||||||
|
fullname[sizeof(fullname)-1]='\0';
|
||||||
|
if ((fp=fopen(fullname,"w"))==(FILE*)0) return strerror(errno);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else /* print header */ /*{{{*/
|
||||||
|
if (fputs_close("<html>\n<head>\n<title>\n</title>\n</head>\n<body>\n",fp)==EOF) return strerror(errno);
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
if (fputs_close("<table>\n",fp)==EOF) return strerror(errno);
|
||||||
|
for (y=y1; y<=y2; ++y) /* print contents */ /*{{{*/
|
||||||
|
{
|
||||||
|
if (fputs_close("<tr>",fp)==EOF) return strerror(errno);
|
||||||
|
for (x=x1; x<=x2; )
|
||||||
|
{
|
||||||
|
int multicols;
|
||||||
|
char *bufp;
|
||||||
|
|
||||||
|
for (multicols=x+1; multicols<sheet->dimx && shadowed(sheet,multicols,y,z); ++multicols);
|
||||||
|
multicols=multicols-x;
|
||||||
|
if (multicols>1) fprintf(fp,"<td colspan=%d",multicols);
|
||||||
|
else fprintf(fp,"<td");
|
||||||
|
switch (getadjust(sheet,x,y,z))
|
||||||
|
{
|
||||||
|
case LEFT: if (fputs_close(" align=left>",fp)==EOF) return strerror(errno); break;
|
||||||
|
case RIGHT: if (fputs_close(" align=right>",fp)==EOF) return strerror(errno); break;
|
||||||
|
case CENTER: if (fputs_close(" align=center>",fp)==EOF) return strerror(errno); break;
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
printvalue(buf,sizeof(buf),0,0,getscientific(sheet,x,y,z),getprecision(sheet,x,y,z),sheet,x,y,z);
|
||||||
|
if (transparent(sheet,x,y,z))
|
||||||
|
{
|
||||||
|
if (fputs_close(buf,fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
else for (bufp=buf; *bufp; ++bufp) switch (*bufp)
|
||||||
|
{
|
||||||
|
case '<': if (fputs_close("<",fp)==EOF) return strerror(errno); break;
|
||||||
|
case '>': if (fputs_close(">",fp)==EOF) return strerror(errno); break;
|
||||||
|
case '&': if (fputs_close("&",fp)==EOF) return strerror(errno); break;
|
||||||
|
case '"': if (fputs_close(""",fp)==EOF) return strerror(errno); break;
|
||||||
|
default: if (fputc_close(*bufp,fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
if (fputs_close("</td>",fp)==EOF) return strerror(errno);
|
||||||
|
x+=multicols;
|
||||||
|
++*count;
|
||||||
|
}
|
||||||
|
if (fputs_close("</tr>\n",fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
if (fputs_close("</table>\n",fp)==EOF) return strerror(errno);
|
||||||
|
if (body)
|
||||||
|
{
|
||||||
|
if (fclose(fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!body)
|
||||||
|
{
|
||||||
|
if (fputs_close("</body>\n</html>\n",fp)==EOF) return strerror(errno);
|
||||||
|
if (fclose(fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
return (const char*)0;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
8
htmlio.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef HTML_H
|
||||||
|
#define HTML_H
|
||||||
|
|
||||||
|
#include "sheet.h"
|
||||||
|
|
||||||
|
const char *savehtml(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
|
||||||
|
|
||||||
|
#endif
|
138
latex.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||||
|
#ifndef NO_POSIX_SOURCE
|
||||||
|
#undef _POSIX_SOURCE
|
||||||
|
#define _POSIX_SOURCE 1
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DMALLOC
|
||||||
|
#include "dmalloc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "latex.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "misc.h"
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* savelatex -- save as LaTeX table */ /*{{{*/
|
||||||
|
const char *savelatex(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count)
|
||||||
|
{
|
||||||
|
/* variables */ /*{{{*/
|
||||||
|
FILE *fp=(FILE*)0; /* cause runtime error */
|
||||||
|
int x,y,z;
|
||||||
|
char buf[1024];
|
||||||
|
char num[20];
|
||||||
|
char fullname[PATH_MAX];
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* asserts */ /*{{{*/
|
||||||
|
assert(sheet!=(Sheet*)0);
|
||||||
|
assert(name!=(const char*)0);
|
||||||
|
/*}}}*/
|
||||||
|
*count=0;
|
||||||
|
for (z=z1; z<=z2; ++z) for (y=y1; y<=y2; ++y) if (shadowed(sheet,x1,y,z)) return _("Shadowed cells in first column");
|
||||||
|
if (!body && (fp=fopen(name,"w"))==(FILE*)0) return strerror(errno);
|
||||||
|
for (z=z1; z<=z2; ++z)
|
||||||
|
{
|
||||||
|
if (body)
|
||||||
|
/* open new file */ /*{{{*/
|
||||||
|
{
|
||||||
|
sprintf(num,".%d",z);
|
||||||
|
|
||||||
|
fullname[sizeof(fullname)-strlen(num)-1]='\0';
|
||||||
|
(void)strncpy(fullname,name,sizeof(fullname)-strlen(num)-1);
|
||||||
|
fullname[sizeof(fullname)-1]='\0';
|
||||||
|
(void)strncat(fullname,num,sizeof(fullname)-strlen(num)-1);
|
||||||
|
fullname[sizeof(fullname)-1]='\0';
|
||||||
|
if ((fp=fopen(fullname,"w"))==(FILE*)0) return strerror(errno);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else
|
||||||
|
/* print header */ /*{{{*/
|
||||||
|
if (z==z1)
|
||||||
|
{
|
||||||
|
if (fputs_close("\\documentclass{article}\n\\usepackage{longtable}\n\\begin{document}\n\\setlongtables\n\\vfill\n",fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fputs_close("\\clearpage\n\\vfill\n",fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* print bogus format */ /*{{{*/
|
||||||
|
fprintf(fp,"\\begin{longtable}{");
|
||||||
|
for (x=x1; x<=x2; ++x) if (fputc_close('l',fp)==EOF) return strerror(errno);
|
||||||
|
fprintf(fp,"}\n");
|
||||||
|
/*}}}*/
|
||||||
|
for (y=y1; y<=y2; ++y)
|
||||||
|
/* print contents */ /*{{{*/
|
||||||
|
{
|
||||||
|
for (x=x1; x<=x2; )
|
||||||
|
{
|
||||||
|
int multicols;
|
||||||
|
char *bufp;
|
||||||
|
|
||||||
|
if (x>x1 && fputc_close('&',fp)==EOF) return strerror(errno);
|
||||||
|
for (multicols=x+1; multicols<sheet->dimx && shadowed(sheet,multicols,y,z); ++multicols);
|
||||||
|
multicols=multicols-x;
|
||||||
|
fprintf(fp,"\\multicolumn{%d}{",multicols);
|
||||||
|
switch (getadjust(sheet,x,y,z))
|
||||||
|
{
|
||||||
|
case LEFT: if (fputc_close('l',fp)==EOF) return strerror(errno); break;
|
||||||
|
case RIGHT: if (fputc_close('r',fp)==EOF) return strerror(errno); break;
|
||||||
|
case CENTER: if (fputc_close('c',fp)==EOF) return strerror(errno); break;
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
printvalue(buf,sizeof(buf),0,0,getscientific(sheet,x,y,z),getprecision(sheet,x,y,z),sheet,x,y,z);
|
||||||
|
if (fputs_close("}{",fp)==EOF) return strerror(errno);
|
||||||
|
if (transparent(sheet,x,y,z))
|
||||||
|
{
|
||||||
|
if (fputs_close(buf,fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
else for (bufp=buf; *bufp; ++bufp) switch (*bufp)
|
||||||
|
{
|
||||||
|
case '%':
|
||||||
|
case '$':
|
||||||
|
case '&':
|
||||||
|
case '#':
|
||||||
|
case '_':
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
|
case '~':
|
||||||
|
case '^': if (fputc_close('\\',fp)==EOF || fputc_close(*bufp,fp)==EOF) return strerror(errno); break;
|
||||||
|
case '\\': if (fputs_close("\\backslash ",fp)==EOF) return strerror(errno); break;
|
||||||
|
default: if (fputc_close(*bufp,fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
if (fputc_close('}',fp)==EOF) return strerror(errno);
|
||||||
|
x+=multicols;
|
||||||
|
++*count;
|
||||||
|
}
|
||||||
|
if (fputs_close(y<y2 ? "\\\\\n" : "\n\\end{longtable}\n",fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
if (body)
|
||||||
|
{
|
||||||
|
if (fclose(fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fputs_close("\\vfill\n",fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!body)
|
||||||
|
{
|
||||||
|
if (fputs_close("\\end{document}\n",fp)==EOF) return strerror(errno);
|
||||||
|
if (fclose(fp)==EOF) return strerror(errno);
|
||||||
|
}
|
||||||
|
return (const char*)0;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
8
latex.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef LATEX_H
|
||||||
|
#define LATEX_H
|
||||||
|
|
||||||
|
#include "sheet.h"
|
||||||
|
|
||||||
|
const char *savelatex(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
|
||||||
|
|
||||||
|
#endif
|
94
main.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#ifndef MAIN_H
|
||||||
|
#define MAIN_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#define _(x) (x)
|
||||||
|
|
||||||
|
#include "sheet.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int batch;
|
||||||
|
extern int def_precision;
|
||||||
|
extern int quote;
|
||||||
|
extern int header;
|
||||||
|
extern unsigned int batchln;
|
||||||
|
|
||||||
|
/* A variable of type Key is either a special symbol from this enum, representing
|
||||||
|
actions the user has triggered (by whatever means available), or a Unicode
|
||||||
|
character that was entered
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
K_NONE = 0,
|
||||||
|
K_INVALID = -1,
|
||||||
|
K_BACKSPACE = -2,
|
||||||
|
K_BPAGE = -3,
|
||||||
|
K_CLOCK = -4,
|
||||||
|
K_COPY = -5,
|
||||||
|
K_DC = -6,
|
||||||
|
K_DOWN = -7,
|
||||||
|
K_END = -8,
|
||||||
|
K_ENTER = -9,
|
||||||
|
K_FIRSTL = -10,
|
||||||
|
K_FPAGE = -11,
|
||||||
|
K_FSHEET = -12,
|
||||||
|
K_HOME = -13,
|
||||||
|
K_LASTL = -14,
|
||||||
|
K_LEFT = -15,
|
||||||
|
K_LOAD = -16,
|
||||||
|
K_LOADMENU = -17,
|
||||||
|
K_LSHEET = -18,
|
||||||
|
K_MARK = -19,
|
||||||
|
K_MENTER = -20,
|
||||||
|
K_NPAGE = -21,
|
||||||
|
K_NSHEET = -22,
|
||||||
|
K_PPAGE = -23,
|
||||||
|
K_PSHEET = -24,
|
||||||
|
K_QUIT = -25,
|
||||||
|
K_RECALC = -26,
|
||||||
|
K_RIGHT = -27,
|
||||||
|
K_SAVE = -28,
|
||||||
|
K_SAVEMENU = -29,
|
||||||
|
K_SAVEQUIT = -30,
|
||||||
|
K_UP = -31,
|
||||||
|
K_GOTO = -32,
|
||||||
|
K_NAME = -33,
|
||||||
|
ADJUST_LEFT = -34,
|
||||||
|
ADJUST_RIGHT = -35,
|
||||||
|
ADJUST_CENTER = -36,
|
||||||
|
ADJUST_SCIENTIFIC = -37,
|
||||||
|
ADJUST_BOLD = -38,
|
||||||
|
ADJUST_PRECISION = -39,
|
||||||
|
ADJUST_SHADOW = -40,
|
||||||
|
ADJUST_TRANSPARENT = -41,
|
||||||
|
ADJUST_LABEL = -42,
|
||||||
|
ADJUST_LOCK = -43,
|
||||||
|
ADJUST_IGNORE = -44,
|
||||||
|
K_COLWIDTH = -45,
|
||||||
|
BLOCK_CLEAR = -46,
|
||||||
|
BLOCK_INSERT = -47,
|
||||||
|
BLOCK_DELETE = -48,
|
||||||
|
BLOCK_MOVE = -49,
|
||||||
|
BLOCK_COPY = -50,
|
||||||
|
BLOCK_FILL = -51,
|
||||||
|
BLOCK_SORT = -52,
|
||||||
|
BLOCK_MIRROR = -53,
|
||||||
|
K_ABOUT = -54,
|
||||||
|
K_HELP = -55,
|
||||||
|
ADJUST_UNDERLINE = -56
|
||||||
|
} Key;
|
||||||
|
|
||||||
|
extern int do_sheetcmd(Sheet *cursheet, Key c, int moveonly);
|
||||||
|
extern int doanyway(Sheet *sheet, const char *msg);
|
||||||
|
extern void moveto(Sheet *sheet, int x, int y, int z);
|
||||||
|
extern void relmoveto(Sheet *sheet, int x, int y, int z);
|
||||||
|
extern void do_mark(Sheet *cursheet, int force);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
249
misc.c
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||||
|
#ifndef NO_POSIX_SOURCE
|
||||||
|
#undef _POSIX_SOURCE
|
||||||
|
#define _POSIX_SOURCE 1
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DMALLOC
|
||||||
|
#include "dmalloc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef NEED_BCOPY
|
||||||
|
#define memmove(dst,src,len) bcopy(src,dst,len)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "default.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "utf8.h"
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* posnumber -- match positive integer */ /*{{{*/
|
||||||
|
long int posnumber(const char *s, const char **endptr)
|
||||||
|
{
|
||||||
|
unsigned int base=10;
|
||||||
|
unsigned char c;
|
||||||
|
register const char *nptr = s;
|
||||||
|
long int result = 0L;
|
||||||
|
int saw_a_digit = 0;
|
||||||
|
|
||||||
|
if (*nptr == '0')
|
||||||
|
{
|
||||||
|
if ((c = *++nptr) == 'x' || c == 'X')
|
||||||
|
{
|
||||||
|
++nptr;
|
||||||
|
base = 16;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
saw_a_digit = 1;
|
||||||
|
base = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--nptr;
|
||||||
|
while ((c=*++nptr)!='\0')
|
||||||
|
{
|
||||||
|
if (isdigit(c)) c -= '0';
|
||||||
|
else if (isupper(c)) c -= ('A'-10);
|
||||||
|
else if (islower(c)) c -= ('a'-10);
|
||||||
|
else break;
|
||||||
|
if (c>=base) break;
|
||||||
|
saw_a_digit = 1;
|
||||||
|
result = result*base+c;
|
||||||
|
}
|
||||||
|
|
||||||
|
*endptr=(saw_a_digit ? nptr : s);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* posorder -- sort two integers */ /*{{{*/
|
||||||
|
void posorder(int *x, int *y)
|
||||||
|
{
|
||||||
|
/* variables */ /*{{{*/
|
||||||
|
int t;
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
assert(x!=(int*)0);
|
||||||
|
assert(*x>=0);
|
||||||
|
assert(y!=(int*)0);
|
||||||
|
assert(*y>=0);
|
||||||
|
if (*x>*y)
|
||||||
|
{
|
||||||
|
t=*x;
|
||||||
|
*x=*y;
|
||||||
|
*y=t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* mystrmalloc -- return malloced copy of string */ /*{{{*/
|
||||||
|
char *mystrmalloc(const char *str)
|
||||||
|
{
|
||||||
|
return (strcpy(malloc(strlen(str)+1),str));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* finite -- return error message about number or null */ /*{{{*/
|
||||||
|
static volatile int caughtfpe;
|
||||||
|
|
||||||
|
static void catchfpe(int n)
|
||||||
|
{
|
||||||
|
caughtfpe=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *dblfinite(double x)
|
||||||
|
{
|
||||||
|
/*struct sigaction act;
|
||||||
|
|
||||||
|
caughtfpe=0;
|
||||||
|
act.sa_handler=catchfpe;
|
||||||
|
act.sa_flags=0;
|
||||||
|
(void)sigemptyset(&act.sa_mask);
|
||||||
|
(void)sigaction(SIGFPE,&act,(struct sigaction*)0);*/
|
||||||
|
signal(SIGFPE, catchfpe);
|
||||||
|
if (x==0.0)
|
||||||
|
{
|
||||||
|
if (caughtfpe) return _("Not a (finite) floating point number"); /* who knows */
|
||||||
|
else return (const char*)0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (caughtfpe) return _("Not a (finite) floating point number");
|
||||||
|
/* If one comparison was allowed, more won't hurt either. */
|
||||||
|
if (x<0.0)
|
||||||
|
{
|
||||||
|
if (x<-DBL_MAX) return _("Not a (finite) floating point number"); /* -infinite */
|
||||||
|
else return (const char*)0;
|
||||||
|
}
|
||||||
|
else if (x>0.0)
|
||||||
|
{
|
||||||
|
if (x>DBL_MAX) return _("Not a (finite) floating point number"); /* +infinite */
|
||||||
|
else return (const char*)0;
|
||||||
|
}
|
||||||
|
else return _("Not a (finite) floating point number"); /* NaN */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* fputc_close -- error checking fputc which closes stream on error */ /*{{{*/
|
||||||
|
int fputc_close(char c, FILE *fp)
|
||||||
|
{
|
||||||
|
int e;
|
||||||
|
|
||||||
|
if ((e=fputc(c,fp))==EOF)
|
||||||
|
{
|
||||||
|
int oerrno;
|
||||||
|
|
||||||
|
oerrno=errno;
|
||||||
|
(void)fclose(fp);
|
||||||
|
errno=oerrno;
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fputs_close -- error checking fputs which closes stream on error */ /*{{{*/
|
||||||
|
int fputs_close(const char *s, FILE *fp)
|
||||||
|
{
|
||||||
|
int e;
|
||||||
|
|
||||||
|
if ((e=fputs(s,fp))==EOF)
|
||||||
|
{
|
||||||
|
int oerrno;
|
||||||
|
|
||||||
|
oerrno=errno;
|
||||||
|
(void)fclose(fp);
|
||||||
|
errno=oerrno;
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* adjust -- readjust a left adjusted string in a buffer */ /*{{{*/
|
||||||
|
void adjust(Adjust a, char *s, size_t n)
|
||||||
|
{
|
||||||
|
assert(s!=(char*)0);
|
||||||
|
assert(mbslen(s)<=n);
|
||||||
|
switch (a)
|
||||||
|
{
|
||||||
|
/* LEFT */ /*{{{*/
|
||||||
|
case LEFT: break;
|
||||||
|
/*}}}*/
|
||||||
|
/* RIGHT */ /*{{{*/
|
||||||
|
case RIGHT:
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len=mbslen(s);
|
||||||
|
if (len < n)
|
||||||
|
{
|
||||||
|
memmove(s+n-len, s, strlen(s)+1);
|
||||||
|
memset(s, ' ', n-len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* CENTER */ /*{{{*/
|
||||||
|
case CENTER:
|
||||||
|
{
|
||||||
|
size_t len,pad;
|
||||||
|
|
||||||
|
len=mbslen(s);
|
||||||
|
pad=(n-len)/2;
|
||||||
|
assert((pad+len)<=n);
|
||||||
|
memmove(s+pad, s, strlen(s)+1);
|
||||||
|
memset(s, ' ', pad);
|
||||||
|
//*(s+strlen(s)+n-pad-len)='\0';
|
||||||
|
//(void)memset(s+strlen(s),' ',n-pad-len-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* default */ /*{{{*/
|
||||||
|
default: assert(0);
|
||||||
|
/*}}}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* strerror -- strerror(3) */ /*{{{*/
|
||||||
|
#ifdef NEED_STRERROR
|
||||||
|
extern int sys_nerr;
|
||||||
|
extern const char *sys_errlist[];
|
||||||
|
|
||||||
|
const char *strerror(int errno)
|
||||||
|
{
|
||||||
|
return (errno>=0 && errno<sys_nerr ? sys_errlist[errno] : "unknown error");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*}}}*/
|
||||||
|
/* myrealloc -- ANSI conforming realloc() */ /*{{{*/
|
||||||
|
#ifdef OLD_REALLOC
|
||||||
|
#undef realloc
|
||||||
|
void *myrealloc(void *p, size_t n)
|
||||||
|
{
|
||||||
|
return (p==(void*)0 ? malloc(n) : realloc(p,n));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
char *striphtml(const char *in)
|
||||||
|
{
|
||||||
|
char *end, *stripped = malloc(strlen(in)), *out = stripped;
|
||||||
|
in--;
|
||||||
|
|
||||||
|
while (in && (end = strchr(++in, '<'))) {
|
||||||
|
memcpy(out, in, end-in);
|
||||||
|
out += end-in;
|
||||||
|
in = strchr(end+1, '>');
|
||||||
|
}
|
||||||
|
if (in) strcpy(out, in);
|
||||||
|
else *out = 0;
|
||||||
|
return stripped;
|
||||||
|
}
|
25
misc.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef MISC_H
|
||||||
|
#define MISC_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "sheet.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void posorder(int *x, int *y);
|
||||||
|
long int posnumber(const char *s, const char **endptr);
|
||||||
|
char *mystrmalloc(const char *str);
|
||||||
|
const char *dblfinite(double x);
|
||||||
|
int fputc_close(char c, FILE *fp);
|
||||||
|
int fputs_close(const char *s, FILE *fp);
|
||||||
|
void adjust(Adjust a, char *s, size_t n);
|
||||||
|
char *striphtml(const char *in);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
316
parser.c
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||||
|
#ifndef NO_POSIX_SOURCE
|
||||||
|
#undef _POSIX_SOURCE
|
||||||
|
#define _POSIX_SOURCE 1
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DMALLOC
|
||||||
|
#include "dmalloc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "eval.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "scanner.h"
|
||||||
|
#include "sheet.h"
|
||||||
|
/*}}}*/
|
||||||
|
/* #defines */ /*{{{*/
|
||||||
|
#define MAXARGC 16
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* prototypes */ /*{{{*/
|
||||||
|
static Token term(Token *n[], int *i);
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* primary -- parse and evaluate a primary term */ /*{{{*/
|
||||||
|
static Token primary(Token *n[], int *i)
|
||||||
|
{
|
||||||
|
/* variables */ /*{{{*/
|
||||||
|
int argc,j;
|
||||||
|
Token *ident,argv[MAXARGC],result;
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
if (n[*i]==(Token*)0)
|
||||||
|
/* error */ /*{{{*/
|
||||||
|
{
|
||||||
|
result.type=EEK;
|
||||||
|
result.u.err=strcpy(malloc(strlen(_("missing operator"))+1),_("missing operator"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else switch (n[*i]->type)
|
||||||
|
{
|
||||||
|
/* STRING, FLOAT, INT */ /*{{{*/
|
||||||
|
case STRING:
|
||||||
|
case FLOAT:
|
||||||
|
case INT:
|
||||||
|
{
|
||||||
|
return tcopy(*n[(*i)++]);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* OPERATOR */ /*{{{*/
|
||||||
|
case OPERATOR:
|
||||||
|
{
|
||||||
|
if (n[*i]->u.op==OP)
|
||||||
|
/* return paren term */ /*{{{*/
|
||||||
|
{
|
||||||
|
++(*i);
|
||||||
|
result=term(n,i);
|
||||||
|
if (result.type==EEK) return result;
|
||||||
|
if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==CP)
|
||||||
|
{
|
||||||
|
++(*i);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
tfree(&result);
|
||||||
|
result.type=EEK;
|
||||||
|
result.u.err=strcpy(malloc(strlen(_(") expected"))+1),_(") expected"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else if (n[*i]->u.op==MINUS)
|
||||||
|
/* return negated term */ /*{{{*/
|
||||||
|
{
|
||||||
|
++(*i);
|
||||||
|
return(tneg(primary(n,i)));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else
|
||||||
|
/* return error, value expected */ /*{{{*/
|
||||||
|
{
|
||||||
|
result.type=EEK;
|
||||||
|
result.u.err=mystrmalloc(_("value expected"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* LIDENT */ /*{{{*/
|
||||||
|
case LIDENT:
|
||||||
|
{
|
||||||
|
ident=n[*i];
|
||||||
|
++(*i);
|
||||||
|
return findlabel(upd_sheet,ident->u.lident);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* FIDENT */ /*{{{*/
|
||||||
|
case FIDENT:
|
||||||
|
{
|
||||||
|
ident=n[*i];
|
||||||
|
++(*i);
|
||||||
|
if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==OP)
|
||||||
|
/* parse arguments and closing paren of function call, return its value */ /*{{{*/
|
||||||
|
{
|
||||||
|
++(*i);
|
||||||
|
argc=0;
|
||||||
|
if (!(n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==CP))
|
||||||
|
/* parse at least one argument */ /*{{{*/
|
||||||
|
{
|
||||||
|
if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==COMMA)
|
||||||
|
/* empty argument */ /*{{{*/
|
||||||
|
{
|
||||||
|
argv[argc].type=EMPTY;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else argv[argc]=term(n,i);
|
||||||
|
if (argv[argc].type==EEK) return argv[argc];
|
||||||
|
++argc;
|
||||||
|
while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==COMMA)
|
||||||
|
/* parse the following argument */ /*{{{*/
|
||||||
|
{
|
||||||
|
++(*i);
|
||||||
|
if (argc<=MAXARGC)
|
||||||
|
{
|
||||||
|
if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && (n[*i]->u.op==COMMA || n[*i]->u.op==CP))
|
||||||
|
{
|
||||||
|
argv[argc].type=EMPTY;
|
||||||
|
}
|
||||||
|
else argv[argc]=term(n,i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.type=EEK;
|
||||||
|
result.u.err=strcpy(malloc(strlen(_("too many arguments"))+1),_("too many arguments"));
|
||||||
|
for (j=0; j<=argc; ++j) tfree(&argv[j]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
++argc;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
if (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==CP)
|
||||||
|
/* eval function */ /*{{{*/
|
||||||
|
{
|
||||||
|
++(*i);
|
||||||
|
result=tfuncall(ident,argc,argv);
|
||||||
|
for (j=0; j<argc; ++j) tfree(&argv[j]);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else
|
||||||
|
/* ) expected */ /*{{{*/
|
||||||
|
{
|
||||||
|
for (j=0; j<argc; ++j) tfree(&argv[j]);
|
||||||
|
result.type=EEK;
|
||||||
|
result.u.err=strcpy(malloc(strlen(_(") expected"))+1),_(") expected"));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.type=EEK;
|
||||||
|
result.u.err=mystrmalloc(_("( expected"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
default: ; /* fall through */
|
||||||
|
}
|
||||||
|
result.type=EEK;
|
||||||
|
result.u.err=mystrmalloc(_("value expected"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* powterm -- parse and evaluate a x^y term */ /*{{{*/
|
||||||
|
static Token powterm(Token *n[], int *i)
|
||||||
|
{
|
||||||
|
Token l;
|
||||||
|
|
||||||
|
l=primary(n,i);
|
||||||
|
if (l.type==EEK) return l;
|
||||||
|
while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op==POW)
|
||||||
|
{
|
||||||
|
Token result,r;
|
||||||
|
|
||||||
|
++(*i);
|
||||||
|
r=primary(n,i);
|
||||||
|
result=tpow(l,r);
|
||||||
|
tfree(&l);
|
||||||
|
tfree(&r);
|
||||||
|
if (result.type==EEK) return result;
|
||||||
|
l=result;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* piterm -- parse and evaluate a product/division/modulo term */ /*{{{*/
|
||||||
|
static Token piterm(Token *n[], int *i)
|
||||||
|
{
|
||||||
|
Token l;
|
||||||
|
|
||||||
|
l=powterm(n,i);
|
||||||
|
if (l.type==EEK) return l;
|
||||||
|
while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && (n[*i]->u.op==DIV || n[*i]->u.op==MUL || n[*i]->u.op==MOD))
|
||||||
|
{
|
||||||
|
Operator op;
|
||||||
|
Token result,r;
|
||||||
|
|
||||||
|
op=n[*i]->u.op;
|
||||||
|
++(*i);
|
||||||
|
r=powterm(n,i);
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case MUL: result=tmul(l,r); break;
|
||||||
|
case DIV: result=tdiv(l,r); break;
|
||||||
|
case MOD: result=tmod(l,r); break;
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
tfree(&l);
|
||||||
|
tfree(&r);
|
||||||
|
if (result.type==EEK) return result;
|
||||||
|
l=result;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* factor -- parse and evaluate a factor of sums/differences */ /*{{{*/
|
||||||
|
static Token factor(Token *n[], int *i)
|
||||||
|
{
|
||||||
|
Token l;
|
||||||
|
|
||||||
|
l=piterm(n,i);
|
||||||
|
if (l.type==EEK) return l;
|
||||||
|
while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && (n[*i]->u.op==PLUS || n[*i]->u.op==MINUS))
|
||||||
|
{
|
||||||
|
Operator op;
|
||||||
|
Token result,r;
|
||||||
|
|
||||||
|
op=n[*i]->u.op;
|
||||||
|
++(*i);
|
||||||
|
r=piterm(n,i);
|
||||||
|
result=(op==PLUS ? tadd(l,r) : tsub(l,r));
|
||||||
|
tfree(&l);
|
||||||
|
tfree(&r);
|
||||||
|
if (result.type==EEK) return result;
|
||||||
|
l=result;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* term -- parse and evaluate a relational term */ /*{{{*/
|
||||||
|
static Token term(Token *n[], int *i)
|
||||||
|
{
|
||||||
|
Token l;
|
||||||
|
|
||||||
|
l=factor(n,i);
|
||||||
|
if (l.type==EEK) return l;
|
||||||
|
while (n[*i]!=(Token*)0 && n[*i]->type==OPERATOR && n[*i]->u.op>=LT && n[*i]->u.op<=NE)
|
||||||
|
{
|
||||||
|
Operator op;
|
||||||
|
Token result,r;
|
||||||
|
|
||||||
|
op=n[*i]->u.op;
|
||||||
|
++(*i);
|
||||||
|
r=factor(n,i);
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case LT: result=tlt(l,r); break;
|
||||||
|
case LE: result=tle(l,r); break;
|
||||||
|
case GE: result=tge(l,r); break;
|
||||||
|
case GT: result=tgt(l,r); break;
|
||||||
|
case ISEQUAL: result=teq(l,r); break;
|
||||||
|
case ABOUTEQ: result=tabouteq(l,r); break;
|
||||||
|
case NE: result=tne(l,r); break;
|
||||||
|
default: assert(0);
|
||||||
|
}
|
||||||
|
tfree(&l);
|
||||||
|
tfree(&r);
|
||||||
|
if (result.type==EEK) return result;
|
||||||
|
l=result;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* eval -- parse and evaluate token sequence */ /*{{{*/
|
||||||
|
Token eval(Token **n)
|
||||||
|
{
|
||||||
|
Token result;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(upd_sheet!=(Sheet*)0);
|
||||||
|
i=0;
|
||||||
|
result=term(n,&i);
|
||||||
|
if (result.type==EEK) return result;
|
||||||
|
if (n[i]!=(Token*)0)
|
||||||
|
{
|
||||||
|
tfree(&result);
|
||||||
|
result.type=EEK;
|
||||||
|
result.u.err=strcpy(malloc(strlen(_("parse error after term"))+1),_("parse error after term"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
8
parser.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef PARSER_H
|
||||||
|
#define PARSER_H
|
||||||
|
|
||||||
|
#include "scanner.h"
|
||||||
|
|
||||||
|
Token eval(Token *n[]);
|
||||||
|
|
||||||
|
#endif
|
320
sc.c
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||||
|
#ifndef NO_POSIX_SOURCE
|
||||||
|
#undef _POSIX_SOURCE
|
||||||
|
#define _POSIX_SOURCE 1
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DMALLOC
|
||||||
|
#include "dmalloc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "eval.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "sheet.h"
|
||||||
|
#include "sc.h"
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
static const char *s2t_s;
|
||||||
|
static char *s2t_t;
|
||||||
|
|
||||||
|
static int s2t_term(Sheet *sheet);
|
||||||
|
|
||||||
|
/* s2t_loc */ /*{{{*/
|
||||||
|
static int s2t_loc(Sheet *sheet, const char **s, char **t)
|
||||||
|
{
|
||||||
|
int x,y;
|
||||||
|
char label[10],*l;
|
||||||
|
|
||||||
|
l=label;
|
||||||
|
if (**s>='A' && **s<='Z')
|
||||||
|
{
|
||||||
|
*l++=**s;
|
||||||
|
*(*t)++=**s;
|
||||||
|
x=*(*s)++-'A';
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
if (**s>='A' && **s<='Z')
|
||||||
|
{
|
||||||
|
*l++=**s;
|
||||||
|
*(*t)++=**s;
|
||||||
|
x=x*26+(*(*s)++-'A');
|
||||||
|
}
|
||||||
|
if (**s>='0' && **s<='9')
|
||||||
|
{
|
||||||
|
*l++=**s;
|
||||||
|
y=**s-'0';
|
||||||
|
*(*t)++=*(*s)++;
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
while (**s>='0' && **s<='9')
|
||||||
|
{
|
||||||
|
*l++=**s;
|
||||||
|
y=y*10+(**s-'0');
|
||||||
|
*(*t)++=*(*s)++;
|
||||||
|
}
|
||||||
|
*l='\0';
|
||||||
|
if (*getlabel(sheet,x,y,0)=='\0') setlabel(sheet,x,y,0,label,0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* s2t_range */ /*{{{*/
|
||||||
|
static int s2t_range(Sheet *sheet)
|
||||||
|
{
|
||||||
|
if (s2t_loc(sheet,&s2t_s,&s2t_t)==0) return 0;
|
||||||
|
if (*s2t_s==':')
|
||||||
|
{
|
||||||
|
s2t_s++; *s2t_t++=',';
|
||||||
|
if (s2t_loc(sheet,&s2t_s,&s2t_t)==0) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* s2t_primary */ /*{{{*/
|
||||||
|
static int s2t_primary(Sheet *sheet)
|
||||||
|
{
|
||||||
|
if (*s2t_s=='@')
|
||||||
|
/* @function */ /*{{{*/
|
||||||
|
{
|
||||||
|
++s2t_s;
|
||||||
|
if (strncmp(s2t_s,"sum(",4)==0)
|
||||||
|
/* @sum(range) -> sum(range) */ /*{{{*/
|
||||||
|
{
|
||||||
|
s2t_s+=4;
|
||||||
|
*s2t_t++='s'; *s2t_t++='u'; *s2t_t++='m'; *s2t_t++='(';
|
||||||
|
if (s2t_range(sheet)==0) return 0;
|
||||||
|
*s2t_t++=')';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else if (strncmp(s2t_s,"rnd(",4)==0)
|
||||||
|
/* @rnd(e) -> int(e,-1,1) */ /*{{{*/
|
||||||
|
{
|
||||||
|
s2t_s+=4;
|
||||||
|
*s2t_t++='i'; *s2t_t++='n'; *s2t_t++='t'; *s2t_t++='(';
|
||||||
|
if (s2t_term(sheet)==0) return 0;
|
||||||
|
*s2t_t++=','; *s2t_t++='-'; *s2t_t++='1'; *s2t_t++=','; *s2t_t++='1'; *s2t_t++=')';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else if (strncmp(s2t_s,"floor(",6)==0)
|
||||||
|
/* @floor(e) -> int(e,-2,-2) */ /*{{{*/
|
||||||
|
{
|
||||||
|
s2t_s+=6;
|
||||||
|
*s2t_t++='i'; *s2t_t++='n'; *s2t_t++='t'; *s2t_t++='(';
|
||||||
|
if (s2t_term(sheet)==0) return 0;
|
||||||
|
*s2t_t++=','; *s2t_t++='-'; *s2t_t++='2'; *s2t_t++=','; *s2t_t++='-'; *s2t_t++='2'; *s2t_t++=')';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else if (strncmp(s2t_s,"ceil(",5)==0)
|
||||||
|
/* @ceil(e) -> int(e,2,2) */ /*{{{*/
|
||||||
|
{
|
||||||
|
s2t_s+=5;
|
||||||
|
*s2t_t++='i'; *s2t_t++='n'; *s2t_t++='t'; *s2t_t++='(';
|
||||||
|
if (s2t_term(sheet)==0) return 0;
|
||||||
|
*s2t_t++=','; *s2t_t++='2'; *s2t_t++=','; *s2t_t++='2'; *s2t_t++=')';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else if ((*s2t_s>='0' && *s2t_s<='9') || *s2t_s=='.')
|
||||||
|
/* number */ /*{{{*/
|
||||||
|
{
|
||||||
|
if (*s2t_s=='.') *s2t_t++='0'; else *s2t_t++=*s2t_s++;
|
||||||
|
while (*s2t_s>='0' && *s2t_s<='9') *s2t_t++=*s2t_s++;
|
||||||
|
if (*s2t_s=='.')
|
||||||
|
{
|
||||||
|
*s2t_t++=*s2t_s++;
|
||||||
|
while (*s2t_s>='0' && *s2t_s<='9') *s2t_t++=*s2t_s++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*s2t_t++='.'; *s2t_t++='0';
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else if (*s2t_s>='A' && *s2t_s<='Z')
|
||||||
|
/* cell value */ /*{{{*/
|
||||||
|
{
|
||||||
|
*s2t_t++='@'; *s2t_t++='(';
|
||||||
|
if (s2t_loc(sheet,&s2t_s,&s2t_t)==0) return 0;
|
||||||
|
*s2t_t++=')';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else if (*s2t_s) return 0;
|
||||||
|
else return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* s2t_powterm */ /*{{{*/
|
||||||
|
static int s2t_powterm(Sheet *sheet)
|
||||||
|
{
|
||||||
|
if (s2t_primary(sheet)==0) return 0;
|
||||||
|
while (*s2t_s=='^')
|
||||||
|
{
|
||||||
|
*s2t_t++=*s2t_s++;
|
||||||
|
if (s2t_primary(sheet)==0) return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* s2t_piterm */ /*{{{*/
|
||||||
|
static int s2t_piterm(Sheet *sheet)
|
||||||
|
{
|
||||||
|
if (s2t_powterm(sheet)==0) return 0;
|
||||||
|
while (*s2t_s=='*' || *s2t_s=='/')
|
||||||
|
{
|
||||||
|
*s2t_t++=*s2t_s++;
|
||||||
|
if (s2t_powterm(sheet)==0) return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* s2t_term */ /*{{{*/
|
||||||
|
static int s2t_term(Sheet *sheet)
|
||||||
|
{
|
||||||
|
if (s2t_piterm(sheet)==0) return 0;
|
||||||
|
while (*s2t_s=='+' || *s2t_s=='-')
|
||||||
|
{
|
||||||
|
*s2t_t++=*s2t_s++;
|
||||||
|
if (s2t_piterm(sheet)==0) return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* loadsc */ /*{{{*/
|
||||||
|
const char *loadsc(Sheet *sheet, const char *name)
|
||||||
|
{
|
||||||
|
/* variables */ /*{{{*/
|
||||||
|
static char errbuf[80];
|
||||||
|
FILE *fp;
|
||||||
|
char buf[256];
|
||||||
|
int line;
|
||||||
|
size_t width;
|
||||||
|
const char *err;
|
||||||
|
int x,y;
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
if ((fp=fopen(name,"r"))==(FILE*)0) return strerror(errno);
|
||||||
|
freesheet(sheet,0);
|
||||||
|
err=(const char*)0;
|
||||||
|
line=1;
|
||||||
|
while (fgets(buf,sizeof(buf),fp)!=(char*)0)
|
||||||
|
{
|
||||||
|
/* remove nl */ /*{{{*/
|
||||||
|
width=strlen(buf);
|
||||||
|
if (width>0 && buf[width-1]=='\n') buf[width-1]='\0';
|
||||||
|
/*}}}*/
|
||||||
|
if (buf[0] && buf[0]!='#')
|
||||||
|
{
|
||||||
|
if (strncmp(buf,"format ",7)==0) /* format col width precision whoknows */ /*{{{*/
|
||||||
|
{
|
||||||
|
char colstr[3];
|
||||||
|
int col,colwidth,precision,whoknows;
|
||||||
|
|
||||||
|
sscanf(buf+7,"%s %d %d %d",colstr,&colwidth,&precision,&whoknows);
|
||||||
|
col=(colstr[0]-'A'); if (colstr[1]) col=col*26+(colstr[1]-'A');
|
||||||
|
initcell(sheet,col,0,0);
|
||||||
|
SHEET(sheet,col,0,0)->adjust=RIGHT;
|
||||||
|
SHEET(sheet,col,0,0)->precision=precision;
|
||||||
|
setwidth(sheet,col,0,colwidth);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else if (strncmp(buf,"leftstring ",11)==0 || strncmp(buf,"rightstring ",12)==0) /* rightstring/leftstring cell = "string" */ /*{{{*/
|
||||||
|
{
|
||||||
|
int x,y;
|
||||||
|
const char *s;
|
||||||
|
Token **contents;
|
||||||
|
|
||||||
|
if (strncmp(buf,"leftstring ",11)==0) s=buf+11; else s=buf+12;
|
||||||
|
x=*s++-'A'; if (*s>='A' && *s<='Z') x=x*26+(*s++-'A');
|
||||||
|
y=*s++-'0'; while (*s>='0' && *s<='9') y=10*y+(*s++-'0');
|
||||||
|
s+=3;
|
||||||
|
contents=scan(&s);
|
||||||
|
if (contents==(Token**)0)
|
||||||
|
{
|
||||||
|
tvecfree(contents);
|
||||||
|
sprintf(errbuf,_("Expression syntax error in line %d"),line);
|
||||||
|
err=errbuf;
|
||||||
|
goto eek;
|
||||||
|
}
|
||||||
|
initcell(sheet,x,y,0);
|
||||||
|
SHEET(sheet,x,y,0)->adjust=strncmp(buf,"leftstring ",11) ? RIGHT : LEFT;
|
||||||
|
SHEET(sheet,x,y,0)->contents=contents;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
else if (strncmp(buf,"let ",4)==0) /* let cell = expression */ /*{{{*/
|
||||||
|
{
|
||||||
|
/* variables */ /*{{{*/
|
||||||
|
const char *s;
|
||||||
|
Token **contents;
|
||||||
|
char newbuf[512];
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
s=buf+4;
|
||||||
|
x=*s++-'A'; if (*s>='A' && *s<='Z') x=x*26+(*s++-'A');
|
||||||
|
y=*s++-'0'; while (*s>='0' && *s<='9') y=10*y+(*s++-'0');
|
||||||
|
if (getcont(sheet,x,y,0,0)==(Token**)0)
|
||||||
|
{
|
||||||
|
s+=3;
|
||||||
|
s2t_s=s; s2t_t=newbuf;
|
||||||
|
if (s2t_term(sheet)==0)
|
||||||
|
{
|
||||||
|
*s2t_t='\0';
|
||||||
|
if (err==(const char*)0)
|
||||||
|
{
|
||||||
|
sprintf(errbuf,_("Unimplemented SC feature in line %d"),line);
|
||||||
|
err=errbuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s2t_t='\0';
|
||||||
|
s=newbuf;
|
||||||
|
contents=scan(&s);
|
||||||
|
if (contents==(Token**)0)
|
||||||
|
{
|
||||||
|
tvecfree(contents);
|
||||||
|
sprintf(errbuf,_("Expression syntax error in line %d"),line);
|
||||||
|
err=errbuf;
|
||||||
|
goto eek;
|
||||||
|
}
|
||||||
|
initcell(sheet,x,y,0);
|
||||||
|
SHEET(sheet,x,y,0)->adjust=RIGHT;
|
||||||
|
SHEET(sheet,x,y,0)->contents=contents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
}
|
||||||
|
++line;
|
||||||
|
}
|
||||||
|
/* set precisions for each column */ /*{{{*/
|
||||||
|
for (x=0; x<sheet->dimx; ++x)
|
||||||
|
{
|
||||||
|
int prec;
|
||||||
|
|
||||||
|
prec=getprecision(sheet,x,0,0)==def_precision ? 2 : getprecision(sheet,x,0,0);
|
||||||
|
for (y=1; y<sheet->dimy; ++y) if (SHEET(sheet,x,y,0)) SHEET(sheet,x,y,0)->precision=prec;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
eek:
|
||||||
|
if (fclose(fp)==EOF && err==(const char*)0) err=strerror(errno);
|
||||||
|
sheet->changed=0;
|
||||||
|
cachelabels(sheet);
|
||||||
|
forceupdate(sheet);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
8
sc.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef SC_H
|
||||||
|
#define SC_H
|
||||||
|
|
||||||
|
#include "sheet.h"
|
||||||
|
|
||||||
|
const char *loadsc(Sheet *sheet, const char *name);
|
||||||
|
|
||||||
|
#endif
|
362
scanner.c
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
/* #includes */ /*{{{C}}}*//*{{{*/
|
||||||
|
#ifndef NO_POSIX_SOURCE
|
||||||
|
#undef _POSIX_SOURCE
|
||||||
|
#define _POSIX_SOURCE 1
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DMALLOC
|
||||||
|
#include "dmalloc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
extern double strtod(const char *nptr, char **endptr); /* SunOS 4 hack */
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "default.h"
|
||||||
|
#include "func.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "scanner.h"
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* identcode -- return number of identifier */ /*{{{*/
|
||||||
|
int identcode(const char *s, size_t len)
|
||||||
|
{
|
||||||
|
Tfunc *p;
|
||||||
|
int fident;
|
||||||
|
|
||||||
|
for (p=tfunc,fident=0; p->name[0]!='\0' && (len!=strlen(p->name) || strncmp(s,p->name,len)); ++p,++fident);
|
||||||
|
if (p->name[0]=='\0') return -1;
|
||||||
|
else return fident;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* charstring -- match quoted string and return token */ /*{{{*/
|
||||||
|
static Token *charstring(const char **s)
|
||||||
|
{
|
||||||
|
const char *r;
|
||||||
|
|
||||||
|
r=*s;
|
||||||
|
if (**s=='"')
|
||||||
|
{
|
||||||
|
++(*s);
|
||||||
|
while (**s!='\0' && **s!='"') if (**s=='\\' && *((*s)+1)!='\0') (*s)+=2; else ++(*s);
|
||||||
|
if (**s=='\0') { *s=r; return 0; }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Token *n;
|
||||||
|
char *t;
|
||||||
|
|
||||||
|
++(*s);
|
||||||
|
n=malloc(sizeof(Token));
|
||||||
|
n->type=STRING;
|
||||||
|
t=n->u.string=malloc((size_t)(*s-r));
|
||||||
|
/* Clean string of quotes. This may waste a few bytes, so? */
|
||||||
|
++r;
|
||||||
|
while (r<(*s-1)) if (*r=='\\') { *t++=*(r+1); r+=2; } else *t++=*r++;
|
||||||
|
*t='\0';
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else return (Token*)0;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* integer -- match an unsigned integer and return token */ /*{{{*/
|
||||||
|
static Token *integer(const char **s)
|
||||||
|
{
|
||||||
|
const char *r;
|
||||||
|
long i;
|
||||||
|
|
||||||
|
r=*s;
|
||||||
|
i=posnumber(r,s);
|
||||||
|
if (*s!=r && **s!='.' && **s!='e')
|
||||||
|
{
|
||||||
|
Token *n;
|
||||||
|
|
||||||
|
n=malloc(sizeof(Token));
|
||||||
|
n->type=INT;
|
||||||
|
n->u.integer=i;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
else { *s=r; return (Token*)0; }
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* flt -- match a floating point number */ /*{{{*/
|
||||||
|
static Token *flt(const char **s)
|
||||||
|
{
|
||||||
|
/* variables */ /*{{{*/
|
||||||
|
const char *t;
|
||||||
|
char *end;
|
||||||
|
Token *n;
|
||||||
|
double x;
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
t=*s;
|
||||||
|
x=strtod(t,&end);
|
||||||
|
*s = end;
|
||||||
|
if (t!=*s && dblfinite(x)==(const char*)0)
|
||||||
|
{
|
||||||
|
n=malloc(sizeof(Token));
|
||||||
|
n->type=FLOAT;
|
||||||
|
n->u.flt=x;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*s=t;
|
||||||
|
return (Token*)0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* op -- match an op and return token */ /*{{{*/
|
||||||
|
static Token *op(const char **s)
|
||||||
|
{
|
||||||
|
Token *n;
|
||||||
|
Operator op;
|
||||||
|
|
||||||
|
switch (**s)
|
||||||
|
{
|
||||||
|
case '+': op=PLUS; break;
|
||||||
|
case '-': op=MINUS; break;
|
||||||
|
case '*': op=MUL; break;
|
||||||
|
case '/': op=DIV; break;
|
||||||
|
case '%': op=MOD; break;
|
||||||
|
case '(': op=OP; break;
|
||||||
|
case ')': op=CP; break;
|
||||||
|
case ',': op=COMMA; break;
|
||||||
|
case '^': op=POW; break;
|
||||||
|
case '<': if (*(*s+1)=='=') { ++(*s); op=LE; } else op=LT; break;
|
||||||
|
case '>': if (*(*s+1)=='=') { ++(*s); op=GE; } else op=GT; break;
|
||||||
|
case '=': if (*(*s+1)=='=') { ++(*s); op=ISEQUAL; } else return (Token*)0; break;
|
||||||
|
case '~': if (*(*s+1)=='=') { ++(*s); op=ABOUTEQ; } else return (Token*)0; break;
|
||||||
|
case '!': if (*(*s+1)=='=') { ++(*s); op=NE; } else return (Token*)0; break;
|
||||||
|
default: return (Token*)0;
|
||||||
|
}
|
||||||
|
n=malloc(sizeof(Token));
|
||||||
|
n->type=OPERATOR;
|
||||||
|
n->u.op=op;
|
||||||
|
++(*s);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* ident -- match an identifier and return token */ /*{{{*/
|
||||||
|
static Token *ident(const char **s)
|
||||||
|
{
|
||||||
|
const char *begin;
|
||||||
|
Token *result;
|
||||||
|
|
||||||
|
if (isalpha((int)**s) || **s=='_' || **s=='@' || **s=='&' || **s=='.' || **s=='$')
|
||||||
|
{
|
||||||
|
int fident;
|
||||||
|
|
||||||
|
begin=*s; ++(*s);
|
||||||
|
while (isalpha((int)**s) || **s=='_' || **s=='@' || **s=='&' || **s=='.' || **s=='$' || isdigit((int)**s)) ++(*s);
|
||||||
|
result=malloc(sizeof(Token));
|
||||||
|
if ((fident=identcode(begin,(size_t)(*s-begin)))==-1)
|
||||||
|
{
|
||||||
|
result->type=LIDENT;
|
||||||
|
result->u.lident=malloc((size_t)(*s-begin+1));
|
||||||
|
(void)strncpy(result->u.lident,begin,(size_t)(*s-begin));
|
||||||
|
result->u.lident[*s-begin]='\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result->type=FIDENT;
|
||||||
|
result->u.fident=fident;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return (Token*)0;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* scan -- scan string into tokens */ /*{{{*/
|
||||||
|
Token **scan(const char **s)
|
||||||
|
{
|
||||||
|
/* variables */ /*{{{*/
|
||||||
|
Token **na,*n;
|
||||||
|
const char *r;
|
||||||
|
int i,j;
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* compute number of tokens */ /*{{{*/
|
||||||
|
r=*s;
|
||||||
|
while (*r==' ') ++r;
|
||||||
|
for (i=0; *r!='\0'; ++i)
|
||||||
|
{
|
||||||
|
const char *or;
|
||||||
|
|
||||||
|
or=r;
|
||||||
|
while (*r==' ') ++r;
|
||||||
|
n=charstring(&r);
|
||||||
|
if (n==(Token*)0) n=op(&r);
|
||||||
|
if (n==(Token*)0) n=integer(&r);
|
||||||
|
if (n==(Token*)0) n=flt(&r);
|
||||||
|
if (n==(Token*)0) n=ident(&r);
|
||||||
|
if (or==r) { *s=r; return (Token**)0; }
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* allocate token space */ /*{{{*/
|
||||||
|
na=malloc(sizeof(Token*)*(i+1));
|
||||||
|
/*}}}*/
|
||||||
|
/* store tokens */ /*{{{*/
|
||||||
|
r=*s;
|
||||||
|
while (*r==' ') ++r;
|
||||||
|
for (j=0; j<i; ++j)
|
||||||
|
{
|
||||||
|
while (*r==' ') ++r;
|
||||||
|
n=charstring(&r);
|
||||||
|
if (n==(Token*)0) n=op(&r);
|
||||||
|
if (n==(Token*)0) n=integer(&r);
|
||||||
|
if (n==(Token*)0) n=flt(&r);
|
||||||
|
if (n==(Token*)0) n=ident(&r);
|
||||||
|
na[j]=n;
|
||||||
|
}
|
||||||
|
na[j]=(Token*)0;
|
||||||
|
/*}}}*/
|
||||||
|
return na;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* print -- print token sequence */ /*{{{*/
|
||||||
|
void print(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Token **n)
|
||||||
|
{
|
||||||
|
size_t cur;
|
||||||
|
|
||||||
|
cur=0;
|
||||||
|
if (n!=(Token**)0) for (; cur<size-1 && (*n)!=(Token*)0; ++n) switch ((*n)->type)
|
||||||
|
{
|
||||||
|
/* EMPTY */ /*{{{*/
|
||||||
|
case EMPTY: assert(cur==0); *(s+cur)='\0'; ++cur; break;
|
||||||
|
/*}}}*/
|
||||||
|
/* STRING */ /*{{{*/
|
||||||
|
case STRING:
|
||||||
|
{
|
||||||
|
char *str=(*n)->u.string;
|
||||||
|
|
||||||
|
if (quote)
|
||||||
|
{
|
||||||
|
*(s+cur)='"';
|
||||||
|
++cur;
|
||||||
|
}
|
||||||
|
while (cur<size && *str!='\0')
|
||||||
|
{
|
||||||
|
if (quote) if (*str=='"' || *str=='\\') *(s+cur++)='\\';
|
||||||
|
if (cur<size) *(s+cur++)=*str;
|
||||||
|
++str;
|
||||||
|
}
|
||||||
|
if (quote)
|
||||||
|
{
|
||||||
|
if (cur<size) *(s+cur)='"';
|
||||||
|
++cur;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* INT */ /*{{{*/
|
||||||
|
case INT:
|
||||||
|
{
|
||||||
|
char buf[20];
|
||||||
|
size_t buflen;
|
||||||
|
|
||||||
|
buflen=sprintf(buf,"%ld",(*n)->u.integer);
|
||||||
|
assert(buflen<sizeof(buf));
|
||||||
|
(void)strncpy(s+cur,buf,size-cur-1);
|
||||||
|
cur+=buflen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* FLOAT */ /*{{{*/
|
||||||
|
case FLOAT:
|
||||||
|
{
|
||||||
|
/* variables */ /*{{{*/
|
||||||
|
char buf[1024],*p;
|
||||||
|
size_t len;
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
len=sprintf(buf,scientific ? "%.*e" : "%.*f",precision==-1 ? DBL_DIG-2 : precision, (*n)->u.flt);
|
||||||
|
assert(len<sizeof(buf));
|
||||||
|
if (!scientific && precision==-1)
|
||||||
|
{
|
||||||
|
p=&buf[len-1];
|
||||||
|
while (p>buf && *p=='0' && *(p-1)!='.') { *p='\0'; --p; --len; }
|
||||||
|
}
|
||||||
|
p=buf+len;
|
||||||
|
while (*--p==' ') { *p='\0'; --len; }
|
||||||
|
(void)strncpy(s+cur,buf,size-cur-1);
|
||||||
|
cur+=len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* OPERATOR */ /*{{{*/
|
||||||
|
case OPERATOR:
|
||||||
|
{
|
||||||
|
static const char *ops[]={ "+", "-", "*", "/", "(", ")", ",", "<", "<=", ">=", ">", "==", "~=", "!=", "^", "%" };
|
||||||
|
|
||||||
|
if ((size-cur)>1) *(s+cur++)=*ops[(*n)->u.op];
|
||||||
|
if (*(ops[(*n)->u.op]+1) && (size-cur)>1) *(s+cur++)=*(ops[(*n)->u.op]+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* LIDENT */ /*{{{*/
|
||||||
|
case LIDENT:
|
||||||
|
{
|
||||||
|
size_t identlen;
|
||||||
|
|
||||||
|
identlen=strlen((*n)->u.lident);
|
||||||
|
if ((cur+identlen+1)<=size) strcpy(s+cur,(*n)->u.lident);
|
||||||
|
else (void)strncpy(s+cur,(*n)->u.lident,size-cur-1);
|
||||||
|
cur+=identlen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* FIDENT */ /*{{{*/
|
||||||
|
case FIDENT:
|
||||||
|
{
|
||||||
|
size_t identlen;
|
||||||
|
|
||||||
|
identlen=strlen(tfunc[(*n)->u.fident].name);
|
||||||
|
if ((cur+identlen+1)<=size) strcpy(s+cur,tfunc[(*n)->u.fident].name);
|
||||||
|
else (void)strncpy(s+cur,tfunc[(*n)->u.fident].name,size-cur-1);
|
||||||
|
cur+=identlen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* LOCATION */ /*{{{*/
|
||||||
|
case LOCATION:
|
||||||
|
{
|
||||||
|
char buf[60];
|
||||||
|
|
||||||
|
sprintf(buf,"&(%d,%d,%d)",(*n)->u.location[0],(*n)->u.location[1],(*n)->u.location[2]);
|
||||||
|
(void)strncpy(s+cur,buf,size-cur-1);
|
||||||
|
cur+=strlen(buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* EEK */ /*{{{*/
|
||||||
|
case EEK:
|
||||||
|
{
|
||||||
|
(void)strncpy(s+cur,_("ERROR"),size-cur-1);
|
||||||
|
cur+=5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* default */ /*{{{*/
|
||||||
|
default: assert(0);
|
||||||
|
/*}}}*/
|
||||||
|
}
|
||||||
|
if (cur<size) s[cur] = 0;
|
||||||
|
else s[size-1] = 0;
|
||||||
|
if (chars && mbslen(s) > chars) {
|
||||||
|
for (cur=0; cur < chars; ++cur) s[cur] = '#';
|
||||||
|
s[cur] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*}}}*/
|
43
scanner.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef SCANNER_H
|
||||||
|
#define SCANNER_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EMPTY
|
||||||
|
#ifndef __cplusplus
|
||||||
|
, STRING, FLOAT, INT, OPERATOR, LIDENT, FIDENT, LOCATION, EEK
|
||||||
|
#endif
|
||||||
|
} Type;
|
||||||
|
|
||||||
|
typedef enum { PLUS, MINUS, MUL, DIV, OP, CP, COMMA, LT, LE, GE, GT, ISEQUAL, ABOUTEQ, NE, POW, MOD } Operator;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Type type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
char *string;
|
||||||
|
double flt;
|
||||||
|
long integer;
|
||||||
|
Operator op;
|
||||||
|
char *lident;
|
||||||
|
int fident;
|
||||||
|
int location[3];
|
||||||
|
char *err;
|
||||||
|
} u;
|
||||||
|
} Token;
|
||||||
|
|
||||||
|
int identcode(const char *s, size_t len);
|
||||||
|
Token **scan(const char **s);
|
||||||
|
void print(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Token **n);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
140
sheet.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#ifndef SHEET_H
|
||||||
|
#define SHEET_H
|
||||||
|
|
||||||
|
#include "scanner.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SHEET(s,x,y,z) (*(s->sheet+(x)*s->dimz*s->dimy+(y)*s->dimz+(z)))
|
||||||
|
|
||||||
|
typedef enum { LEFT=0, RIGHT=1, CENTER=2, AUTOADJUST=3 } Adjust;
|
||||||
|
|
||||||
|
typedef enum { IN_X, IN_Y, IN_Z } Direction;
|
||||||
|
|
||||||
|
/* must be a prime */
|
||||||
|
#define LABEL_CACHE 29
|
||||||
|
|
||||||
|
#define ASCENDING 001
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
int sortkey; /* OR-ed value of the above constants */
|
||||||
|
} Sortkey;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Token **contents;
|
||||||
|
Token **ccontents;
|
||||||
|
char *label;
|
||||||
|
Token value;
|
||||||
|
Token resvalue;
|
||||||
|
Adjust adjust;
|
||||||
|
int precision;
|
||||||
|
unsigned int updated:1;
|
||||||
|
unsigned int shadowed:1;
|
||||||
|
unsigned int scientific:1;
|
||||||
|
unsigned int locked:1;
|
||||||
|
unsigned int transparent:1;
|
||||||
|
unsigned int ignored:1;
|
||||||
|
unsigned int clock_t0:1;
|
||||||
|
unsigned int clock_t1:1;
|
||||||
|
unsigned int clock_t2:1;
|
||||||
|
unsigned int bold:1;
|
||||||
|
unsigned int underline:1;
|
||||||
|
} Cell;
|
||||||
|
|
||||||
|
struct Label
|
||||||
|
{
|
||||||
|
const char *label;
|
||||||
|
int x,y,z;
|
||||||
|
struct Label *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct Label *labelcache[LABEL_CACHE];
|
||||||
|
int curx, cury, curz;
|
||||||
|
int mark1x, mark1y, mark1z;
|
||||||
|
int mark2x, mark2y, mark2z;
|
||||||
|
int marking;
|
||||||
|
int offx, offy;
|
||||||
|
Cell **sheet;
|
||||||
|
int *column;
|
||||||
|
int dimx, dimy, dimz;
|
||||||
|
int orix, oriy, maxx, maxy;
|
||||||
|
int width;
|
||||||
|
char *name;
|
||||||
|
unsigned int changed:1;
|
||||||
|
unsigned int moveonly:1;
|
||||||
|
unsigned int clk:1;
|
||||||
|
void *display;
|
||||||
|
} Sheet;
|
||||||
|
|
||||||
|
extern Sheet *upd_sheet;
|
||||||
|
extern int upd_x;
|
||||||
|
extern int upd_y;
|
||||||
|
extern int upd_z;
|
||||||
|
extern int max_eval;
|
||||||
|
|
||||||
|
void resize(Sheet *sheet, int x, int y, int z);
|
||||||
|
void initcell(Sheet *sheet, int x, int y, int z);
|
||||||
|
void cachelabels(Sheet *sheet);
|
||||||
|
void freesheet(Sheet *sheet, int all);
|
||||||
|
void forceupdate(Sheet *sheet);
|
||||||
|
void freecell(Sheet *sheet, int x, int y, int z);
|
||||||
|
int columnwidth(Sheet *sheet, int x, int z);
|
||||||
|
void setwidth(Sheet *sheet, int x, int z, int width);
|
||||||
|
int cellwidth(Sheet *sheet, int x, int y, int z);
|
||||||
|
void putcont(Sheet *sheet, int x, int y, int z, Token **t, int c);
|
||||||
|
Token **getcont(Sheet *sheet, int x, int y, int z, int c);
|
||||||
|
Token getvalue(Sheet *sheet, int x, int y, int z);
|
||||||
|
void update(Sheet *sheet);
|
||||||
|
char *geterror(Sheet *sheet, int x, int y, int z);
|
||||||
|
void printvalue(char *s, size_t size, size_t chars, int quote, int scientific, int precision, Sheet *sheet, int x, int y, int z);
|
||||||
|
Adjust getadjust(Sheet *sheet, int x, int y, int z);
|
||||||
|
void setadjust(Sheet *sheet, int x, int y, int z, Adjust adjust);
|
||||||
|
void shadow(Sheet *sheet, int x, int y, int z, int yep);
|
||||||
|
int shadowed(Sheet *sheet, int x, int y, int z);
|
||||||
|
void bold(Sheet *sheet, int x, int y, int z, int yep);
|
||||||
|
int isbold(Sheet *sheet, int x, int y, int z);
|
||||||
|
void underline(Sheet *sheet, int x, int y, int z, int yep);
|
||||||
|
int underlined(Sheet *sheet, int x, int y, int z);
|
||||||
|
void lockcell(Sheet *sheet, int x, int y, int z, int yep);
|
||||||
|
int locked(Sheet *sheet, int x, int y, int z);
|
||||||
|
int transparent(Sheet *sheet, int x, int y, int z);
|
||||||
|
void maketrans(Sheet *sheet, int x, int y, int z, int yep);
|
||||||
|
void igncell(Sheet *sheet, int x, int y, int z, int yep);
|
||||||
|
int ignored(Sheet *sheet, int x, int y, int z);
|
||||||
|
void clk(Sheet *sheet, int x, int y, int z);
|
||||||
|
void setscientific(Sheet *sheet, int x, int y, int z, int yep);
|
||||||
|
int getscientific(Sheet *sheet, int x, int y, int z);
|
||||||
|
void setprecision(Sheet *sheet, int x, int y, int z, int precision);
|
||||||
|
int getprecision(Sheet *sheet, int x, int y, int z);
|
||||||
|
const char *getlabel(Sheet *sheet, int x, int y, int z);
|
||||||
|
void setlabel(Sheet *sheet, int x, int y, int z, const char *buf, int update);
|
||||||
|
Token findlabel(Sheet *sheet, const char *label);
|
||||||
|
void relabel(Sheet *sheet, const char *oldlabel, const char *newlabel, int x, int y, int z);
|
||||||
|
const char *savexdr(Sheet *sheet, const char *name, unsigned int *count);
|
||||||
|
const char *savetbl(Sheet *sheet, const char *name, int body, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
|
||||||
|
const char *savetext(Sheet *sheet, const char *name, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
|
||||||
|
const char *savecsv(Sheet *sheet, const char *name, char sep, int x1, int y1, int z1, int x2, int y2, int z2, unsigned int *count);
|
||||||
|
const char *saveport(Sheet *sheet, const char *name, unsigned int *count);
|
||||||
|
const char *loadxdr(Sheet *sheet, const char *name);
|
||||||
|
const char *loadport(Sheet *sheet, const char *name);
|
||||||
|
const char *loadcsv(Sheet *sheet, const char *name);
|
||||||
|
void insertcube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction ins);
|
||||||
|
void deletecube(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction ins);
|
||||||
|
void moveblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3, int copy);
|
||||||
|
const char *sortblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction dir, Sortkey *sk, size_t sklen);
|
||||||
|
void mirrorblock(Sheet *sheet, int x1, int y1, int z1, int x2, int y2, int z2, Direction dir);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
84
teapot.1
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
.\" teapot.1: teapot manual
|
||||||
|
.\" Copyright(c) 2010 by wave++ "Yuri D'Elia" <wavexx@users.sf.net>
|
||||||
|
.\" Distributed under GNU GPL WITHOUT ANY WARRANTY.
|
||||||
|
.\"
|
||||||
|
.Dd Dicember 8, 2010
|
||||||
|
.Dt TEAPOT 1
|
||||||
|
.\"
|
||||||
|
.\"
|
||||||
|
.Sh NAME
|
||||||
|
.Nm teapot
|
||||||
|
.Nd Table Editor And Planner, Or: Teapot!
|
||||||
|
.\"
|
||||||
|
.\"
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl abHqr
|
||||||
|
.Op Fl p Ar digits
|
||||||
|
.Op Ar file
|
||||||
|
.\"
|
||||||
|
.\"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
(Table Editor And Planner, Or Teapot!) is a compact spreadsheet program, featuring three
|
||||||
|
dimensions with linear addressing, relative references, formula references,
|
||||||
|
type safety of computations, iterative expressions and platform independent
|
||||||
|
file format.
|
||||||
|
.Pp
|
||||||
|
This document only describes command-line arguments. Please refer to the
|
||||||
|
complete manual that can be found under
|
||||||
|
.Pa /usr/share/doc/teapot
|
||||||
|
in both html and pdf format.
|
||||||
|
The manual can also be viewed from within the graphical version, fteapot,
|
||||||
|
using the Help menu.
|
||||||
|
.\"
|
||||||
|
.\"
|
||||||
|
.Sh OPTIONS
|
||||||
|
.Bl -tag -compact -width " \-p digits "
|
||||||
|
.It Fl a
|
||||||
|
Use ASCII instead of XDR as default file format when loading or saving.
|
||||||
|
.It Fl b
|
||||||
|
Read batch commands from standard input.
|
||||||
|
.It Fl H
|
||||||
|
Hide row and column headers.
|
||||||
|
.It Fl q
|
||||||
|
Display strings quoted.
|
||||||
|
.It Fl r
|
||||||
|
Redraw the terminal window more often.
|
||||||
|
.It Fl p Ar digits
|
||||||
|
Set default precision of displayed numbers.
|
||||||
|
.El
|
||||||
|
.\"
|
||||||
|
.\"
|
||||||
|
.Sh ENVIRONMENT
|
||||||
|
.Ev DISPLAY See Xr X 7 .
|
||||||
|
.\"
|
||||||
|
.\"
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Pa /usr/share/doc/teapot/
|
||||||
|
.\"
|
||||||
|
.\"
|
||||||
|
.Sh LICENSE
|
||||||
|
Copyright (C) 1995-2006
|
||||||
|
.An "Michael Haardt"
|
||||||
|
.Pp
|
||||||
|
Copyright (C) 2009-2012
|
||||||
|
.Mt info@syntax-k.de
|
||||||
|
J\(:org Walter
|
||||||
|
.Me
|
||||||
|
.Pp
|
||||||
|
Manual page written by
|
||||||
|
.Mt wavexx@users.sf.net
|
||||||
|
Yuri D'Elia
|
||||||
|
.Me
|
||||||
|
.Pp
|
||||||
|
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 3 of the License, or (at your option) any later version.
|
||||||
|
.Pp
|
||||||
|
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.
|
||||||
|
.Pp
|
||||||
|
You should have received a copy of the GNU General Public License along with this program.
|
||||||
|
If not, see
|
||||||
|
.Ur http://www.gnu.org/licenses/
|
||||||
|
http://www.gnu.org/licenses/
|
||||||
|
.Ue .
|
70
utf8.c
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
UTF-8 wrapper for teapot
|
||||||
|
Copyright (C) 2010 Joerg Walter
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utf8.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef ENABLE_UTF8
|
||||||
|
|
||||||
|
size_t mbslen(const char *s)
|
||||||
|
{
|
||||||
|
const unsigned char *str = (unsigned char *)s;
|
||||||
|
size_t chars = 0;
|
||||||
|
|
||||||
|
while (*str) {
|
||||||
|
chars++;
|
||||||
|
if (is_mbchar(*str++)) while (is_mbcont(*str)) str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *mbspos(const char *s, int ch)
|
||||||
|
{
|
||||||
|
const unsigned char *str = (unsigned char *)s;
|
||||||
|
int chars = 0;
|
||||||
|
|
||||||
|
if (ch < 0) {
|
||||||
|
while (chars > ch) {
|
||||||
|
chars--;
|
||||||
|
while (is_mbcont(*--str));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (chars < ch && *str) {
|
||||||
|
chars++;
|
||||||
|
if (is_mbchar(*str++)) while (is_mbcont(*str)) str++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (char *)(void *)str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
size_t mbslen(const char *str)
|
||||||
|
{
|
||||||
|
return strlen(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *mbspos(const char *str, int ch)
|
||||||
|
{
|
||||||
|
return (char *)(void *)(str+ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
64
utf8.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
UTF-8 wrapper for teapot
|
||||||
|
Copyright (C) 2010 Joerg Walter
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UTF8_H
|
||||||
|
#define UTF8_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t mbslen(const char *str);
|
||||||
|
char *mbspos(const char *str, int ch);
|
||||||
|
|
||||||
|
#ifdef ENABLE_UTF8
|
||||||
|
|
||||||
|
#define UTF8SZ 4
|
||||||
|
static inline int is_mbcont(unsigned char c)
|
||||||
|
{
|
||||||
|
return (c >= 0x80 && c < 0xc0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int is_mbchar(unsigned char c)
|
||||||
|
{
|
||||||
|
return (c >= 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define UTF8SZ 1
|
||||||
|
static inline int is_mbcont(unsigned char c)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int is_mbchar(unsigned char c)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
8
wk1.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef WK1_H
|
||||||
|
#define WK1_H
|
||||||
|
|
||||||
|
#include "sheet.h"
|
||||||
|
|
||||||
|
const char *loadwk1(Sheet *sheet, const char *name);
|
||||||
|
|
||||||
|
#endif
|
209
xdr.c
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
/* Notes */ /*{{{C}}}*//*{{{*/
|
||||||
|
/*
|
||||||
|
|
||||||
|
xdr_enum() is unusable, because enum_t may have a different size than
|
||||||
|
an enum. The construction
|
||||||
|
|
||||||
|
int_value=*enum_value;
|
||||||
|
result=xdr_int(xdrs,&int_value);
|
||||||
|
*enum_value=int_value;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
solves the problem and works for both encoding and decoding.
|
||||||
|
Unfortunately, I could not yet find such a solution for a variable sized
|
||||||
|
array terminated by a special element.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*}}}*/
|
||||||
|
/* #includes */ /*{{{*/
|
||||||
|
#ifdef DMALLOC
|
||||||
|
#include "dmalloc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "sheet.h"
|
||||||
|
#include "xdr.h"
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* xdr_token */ /*{{{*/
|
||||||
|
static bool_t xdr_token(XDR *xdrs, Token *t)
|
||||||
|
{
|
||||||
|
int x,result;
|
||||||
|
|
||||||
|
if (xdrs->x_op==XDR_DECODE) (void)memset(t,0,sizeof(Token));
|
||||||
|
x=t->type;
|
||||||
|
if (t->type==OPERATOR) x|=t->u.op<<8;
|
||||||
|
result=xdr_int(xdrs,&x);
|
||||||
|
if ((x&0xff)==OPERATOR) t->u.op=(x>>8)&0xff;
|
||||||
|
t->type=x&0xff;
|
||||||
|
if (result==0) return result;
|
||||||
|
switch (t->type)
|
||||||
|
{
|
||||||
|
/* EMPTY */ /*{{{*/
|
||||||
|
case EMPTY:
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* STRING */ /*{{{*/
|
||||||
|
case STRING:
|
||||||
|
{
|
||||||
|
return xdr_wrapstring(xdrs,&(t->u.string));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* FLOAT */ /*{{{*/
|
||||||
|
case FLOAT:
|
||||||
|
{
|
||||||
|
return xdr_double(xdrs,&(t->u.flt));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* INT */ /*{{{*/
|
||||||
|
case INT:
|
||||||
|
{
|
||||||
|
return xdr_long(xdrs,&(t->u.integer));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* OPERATOR */ /*{{{*/
|
||||||
|
case OPERATOR:
|
||||||
|
{
|
||||||
|
return 1; /* since op is encoded in type */
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* LIDENT */ /*{{{*/
|
||||||
|
case LIDENT:
|
||||||
|
{
|
||||||
|
return xdr_wrapstring(xdrs,&(t->u.lident));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* FIDENT */ /*{{{*/
|
||||||
|
case FIDENT:
|
||||||
|
{
|
||||||
|
return xdr_int(xdrs,&(t->u.fident));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* LOCATION */ /*{{{*/
|
||||||
|
case LOCATION:
|
||||||
|
{
|
||||||
|
return (xdr_int(xdrs,&(t->u.location[0])) && xdr_int(xdrs,&(t->u.location[1])) && xdr_int(xdrs,&(t->u.location[2])));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* EEK */ /*{{{*/
|
||||||
|
case EEK:
|
||||||
|
{
|
||||||
|
return xdr_wrapstring(xdrs,&(t->u.err));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* default -- should not happen */ /*{{{*/
|
||||||
|
default: assert(0);
|
||||||
|
/*}}}*/
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* xdr_tokenptr */ /*{{{*/
|
||||||
|
static bool_t xdr_tokenptr(XDR *xdrs, Token **t)
|
||||||
|
{
|
||||||
|
return xdr_pointer(xdrs,(char**)t,sizeof(Token),(xdrproc_t)xdr_token);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* xdr_tokenptrvec */ /*{{{*/
|
||||||
|
static bool_t xdr_tokenptrvec(XDR *xdrs, Token ***t)
|
||||||
|
{
|
||||||
|
unsigned int len;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
assert(t!=(Token***)0);
|
||||||
|
if (xdrs->x_op!=XDR_DECODE)
|
||||||
|
{
|
||||||
|
Token **run;
|
||||||
|
|
||||||
|
if (*t==(Token**)0) len=0;
|
||||||
|
else for (len=1,run=*t; *run!=(Token*)0; ++len,++run);
|
||||||
|
}
|
||||||
|
result=xdr_array(xdrs,(char**)t,&len,65536,sizeof(Token*),(xdrproc_t)xdr_tokenptr);
|
||||||
|
if (len==0) *t=(Token**)0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* xdr_mystring */ /*{{{*/
|
||||||
|
static bool_t xdr_mystring(XDR *xdrs, char **str)
|
||||||
|
{
|
||||||
|
static struct xdr_discrim arms[3]=
|
||||||
|
{
|
||||||
|
{ 0, (xdrproc_t)xdr_void },
|
||||||
|
{ 1, (xdrproc_t)xdr_wrapstring },
|
||||||
|
{ -1, (xdrproc_t)0 }
|
||||||
|
};
|
||||||
|
enum_t x;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
x=(*str!=(char*)0);
|
||||||
|
res=xdr_union(xdrs, &x, (char*)str, arms, (xdrproc_t)0);
|
||||||
|
if (!x) *str=(char*)0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
|
||||||
|
/* Notes */ /*{{{*/
|
||||||
|
/*
|
||||||
|
|
||||||
|
The saved sheet consists of three xdr_int()s which specify x, y and z
|
||||||
|
position of the cell saved with xdr_cell(). Perhaps xdr_cell could be
|
||||||
|
given those as parameters, which would be more correct concerning the
|
||||||
|
purpose of the xdr_functions. Then again, reading the position may
|
||||||
|
fail (eof), whereas after the position has been read, xdr_cell() must
|
||||||
|
not fail when loading a sheet.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*}}}*/
|
||||||
|
/* xdr_cell */ /*{{{*/
|
||||||
|
bool_t xdr_cell(XDR *xdrs, Cell *cell)
|
||||||
|
{
|
||||||
|
int result,x;
|
||||||
|
|
||||||
|
assert(cell!=(Cell*)0);
|
||||||
|
if (!(xdr_tokenptrvec(xdrs, &(cell->contents)) && xdr_tokenptrvec(xdrs, &(cell->ccontents)) /* && xdr_token(xdrs, &(cell->value)) */ )) return 0;
|
||||||
|
if (xdr_mystring(xdrs, &(cell->label))==0) return 0;
|
||||||
|
x=cell->adjust;
|
||||||
|
result=xdr_int(xdrs, &x);
|
||||||
|
cell->adjust=x;
|
||||||
|
if (result==0) return 0;
|
||||||
|
if (xdr_int(xdrs, &(cell->precision))==0) return 0;
|
||||||
|
x=(cell->updated&1)|((cell->shadowed&1)<<1)|((cell->scientific&1)<<2)|((cell->locked&1)<<3)|((cell->transparent&1)<<4)|((cell->ignored&1)<<5)|((cell->bold&1)<<6)|((cell->underline&1)<<7);
|
||||||
|
result=xdr_int(xdrs, &x);
|
||||||
|
cell->updated=((x&(1))!=0);
|
||||||
|
cell->shadowed=((x&(1<<1))!=0);
|
||||||
|
cell->scientific=((x&(1<<2))!=0);
|
||||||
|
cell->locked=((x&(1<<3))!=0);
|
||||||
|
cell->transparent=((x&(1<<4))!=0);
|
||||||
|
cell->ignored=((x&(1<<5))!=0);
|
||||||
|
cell->bold=((x&(1<<6))!=0);
|
||||||
|
cell->underline=((x&(1<<7))!=0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* xdr_column */ /*{{{*/
|
||||||
|
bool_t xdr_column(XDR *xdrs, int *x, int *z, int *width)
|
||||||
|
{
|
||||||
|
return (xdr_int(xdrs, x) && xdr_int(xdrs, z) && xdr_int(xdrs, width));
|
||||||
|
}
|
||||||
|
/*}}}*/
|
||||||
|
/* xdr_magic */ /*{{{*/
|
||||||
|
#define MAGIC0 (('#'<<24)|('!'<<16)|('t'<<8)|'e')
|
||||||
|
#define MAGIC1 (('a'<<24)|('p'<<16)|('o'<<8)|'t')
|
||||||
|
#define MAGIC2 (('\n'<<24)|('x'<<16)|('d'<<8)|'r')
|
||||||
|
|
||||||
|
bool_t xdr_magic(XDR *xdrs)
|
||||||
|
{
|
||||||
|
long m0,m1,m2;
|
||||||
|
|
||||||
|
m0=MAGIC0;
|
||||||
|
m1=MAGIC1;
|
||||||
|
m2=MAGIC2;
|
||||||
|
return (xdr_long(xdrs,&m0) && m0==MAGIC0 && xdr_long(xdrs,&m1) && m1==MAGIC1 && xdr_long(xdrs,&m2) && m2==MAGIC2);
|
||||||
|
}
|
||||||
|
/*}}}*/
|
20
xdr.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef XDR_H
|
||||||
|
#define XDR_H
|
||||||
|
|
||||||
|
/* Thanks to curses. */
|
||||||
|
#if 0
|
||||||
|
#undef TRUE
|
||||||
|
#undef FALSE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <rpc/types.h>
|
||||||
|
#include <rpc/xdr.h>
|
||||||
|
|
||||||
|
#include "sheet.h"
|
||||||
|
|
||||||
|
bool_t xdr_cell(XDR *xdrs, Cell *cell);
|
||||||
|
bool_t xdr_column(XDR *xdrs, int *x, int *z, int *width);
|
||||||
|
bool_t xdr_magic(XDR *xdrs);
|
||||||
|
|
||||||
|
#endif
|