pspp-master/000077500000000000000000000000001177044323000133325ustar00rootroot00000000000000pspp-master/.gitignore000066400000000000000000000007561177044323000153320ustar00rootroot00000000000000ChangeLog /Makefile /Makefile.in /gl/Makefile /gl/Makefile.in aclocal.m4 autom4te.cache compile config.guess config.h config.h.in config.libpath config.log config.rpath config.status config.sub configure depcomp gl install-reloc install-sh intl link-warning.h ltmain.sh m4 mdate-sh missing mkinstalldirs patches potfiles.tmp pref.h reloc-ldflags stamp-h1 gitlog-to-changelog *~ *.o *.lo *.a *.dirstamp *.deps *.la *.libs /arg-nonnull.h /c++defs.h /package.m4 /unused-parameter.h /warn-on-use.h pspp-master/ABOUT-NLS000066400000000000000000002641231177044323000145710ustar00rootroot000000000000001 Notes on the Free Translation Project *************************************** Free software is going international! The Free Translation Project is a way to get maintainers of free software, translators, and users all together, so that free software will gradually become able to speak many languages. A few packages already provide translations for their messages. If you found this `ABOUT-NLS' file inside a distribution, you may assume that the distributed package does use GNU `gettext' internally, itself available at your nearest GNU archive site. But you do _not_ need to install GNU `gettext' prior to configuring, installing or using this package with messages translated. Installers will find here some useful hints. These notes also explain how users should proceed for getting the programs to use the available translations. They tell how people wanting to contribute and work on translations can contact the appropriate team. When reporting bugs in the `intl/' directory or bugs which may be related to internationalization, you should tell about the version of `gettext' which is used. The information can be found in the `intl/VERSION' file, in internationalized packages. 1.1 Quick configuration advice ============================== If you want to exploit the full power of internationalization, you should configure it using ./configure --with-included-gettext to force usage of internationalizing routines provided within this package, despite the existence of internationalizing capabilities in the operating system where this package is being installed. So far, only the `gettext' implementation in the GNU C library version 2 provides as many features (such as locale alias, message inheritance, automatic charset conversion or plural form handling) as the implementation here. It is also not possible to offer this additional functionality on top of a `catgets' implementation. Future versions of GNU `gettext' will very likely convey even more functionality. So it might be a good idea to change to GNU `gettext' as soon as possible. So you need _not_ provide this option if you are using GNU libc 2 or you have installed a recent copy of the GNU gettext package with the included `libintl'. 1.2 INSTALL Matters =================== Some packages are "localizable" when properly installed; the programs they contain can be made to speak your own native language. Most such packages use GNU `gettext'. Other packages have their own ways to internationalization, predating GNU `gettext'. By default, this package will be installed to allow translation of messages. It will automatically detect whether the system already provides the GNU `gettext' functions. If not, the included GNU `gettext' library will be used. This library is wholly contained within this package, usually in the `intl/' subdirectory, so prior installation of the GNU `gettext' package is _not_ required. Installers may use special options at configuration time for changing the default behaviour. The commands: ./configure --with-included-gettext ./configure --disable-nls will, respectively, bypass any pre-existing `gettext' to use the internationalizing routines provided within this package, or else, _totally_ disable translation of messages. When you already have GNU `gettext' installed on your system and run configure without an option for your new package, `configure' will probably detect the previously built and installed `libintl.a' file and will decide to use this. This might not be desirable. You should use the more recent version of the GNU `gettext' library. I.e. if the file `intl/VERSION' shows that the library which comes with this package is more recent, you should use ./configure --with-included-gettext to prevent auto-detection. The configuration process will not test for the `catgets' function and therefore it will not be used. The reason is that even an emulation of `gettext' on top of `catgets' could not provide all the extensions of the GNU `gettext' library. Internationalized packages usually have many `po/LL.po' files, where LL gives an ISO 639 two-letter code identifying the language. Unless translations have been forbidden at `configure' time by using the `--disable-nls' switch, all available translations are installed together with the package. However, the environment variable `LINGUAS' may be set, prior to configuration, to limit the installed set. `LINGUAS' should then contain a space separated list of two-letter codes, stating which languages are allowed. 1.3 Using This Package ====================== As a user, if your language has been installed for this package, you only have to set the `LANG' environment variable to the appropriate `LL_CC' combination. If you happen to have the `LC_ALL' or some other `LC_xxx' environment variables set, you should unset them before setting `LANG', otherwise the setting of `LANG' will not have the desired effect. Here `LL' is an ISO 639 two-letter language code, and `CC' is an ISO 3166 two-letter country code. For example, let's suppose that you speak German and live in Germany. At the shell prompt, merely execute `setenv LANG de_DE' (in `csh'), `export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). This can be done from your `.login' or `.profile' file, once and for all. You might think that the country code specification is redundant. But in fact, some languages have dialects in different countries. For example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The country code serves to distinguish the dialects. The locale naming convention of `LL_CC', with `LL' denoting the language and `CC' denoting the country, is the one use on systems based on GNU libc. On other systems, some variations of this scheme are used, such as `LL' or `LL_CC.ENCODING'. You can get the list of locales supported by your system for your language by running the command `locale -a | grep '^LL''. Not all programs have translations for all languages. By default, an English message is shown in place of a nonexistent translation. If you understand other languages, you can set up a priority list of languages. This is done through a different environment variable, called `LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' for the purpose of message handling, but you still need to have `LANG' set to the primary language; this is required by other parts of the system libraries. For example, some Swedish users who would rather read translations in German than English for when Swedish is not available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. Special advice for Norwegian users: The language code for Norwegian bokma*l changed from `no' to `nb' recently (in 2003). During the transition period, while some message catalogs for this language are installed under `nb' and some older ones under `no', it's recommended for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and older translations are used. In the `LANGUAGE' environment variable, but not in the `LANG' environment variable, `LL_CC' combinations can be abbreviated as `LL' to denote the language's main dialect. For example, `de' is equivalent to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' (Portuguese as spoken in Portugal) in this context. 1.4 Translating Teams ===================== For the Free Translation Project to be a success, we need interested people who like their own language and write it well, and who are also able to synergize with other translators speaking the same language. Each translation team has its own mailing list. The up-to-date list of teams can be found at the Free Translation Project's homepage, `http://translationproject.org/', in the "Teams" area. If you'd like to volunteer to _work_ at translating messages, you should become a member of the translating team for your own language. The subscribing address is _not_ the same as the list itself, it has `-request' appended. For example, speakers of Swedish can send a message to `sv-request@li.org', having this message body: subscribe Keep in mind that team members are expected to participate _actively_ in translations, or at solving translational difficulties, rather than merely lurking around. If your team does not exist yet and you want to start one, or if you are unsure about what to do or how to get started, please write to `coordinator@translationproject.org' to reach the coordinator for all translator teams. The English team is special. It works at improving and uniformizing the terminology in use. Proven linguistic skills are praised more than programming skills, here. 1.5 Available Packages ====================== Languages are not equally supported in all packages. The following matrix shows the current state of internationalization, as of March 2010. The matrix shows, in regard of each package, for which languages PO files have been submitted to translation coordination, with a translation percentage of at least 50%. Ready PO files af am ar ast az be be@latin bg bn_IN bs ca crh +------------------------------------------------+ a2ps | [] [] | aegis | | ant-phone | | anubis | | aspell | [] [] | bash | | bfd | | bibshelf | [] | binutils | | bison | | bison-runtime | [] | bluez-pin | [] [] | bombono-dvd | | buzztard | | cflow | | clisp | | coreutils | [] [] | cpio | | cppi | | cpplib | [] | cryptsetup | | dfarc | | dialog | [] [] | dico | | diffutils | [] | dink | | doodle | | e2fsprogs | [] | enscript | [] | exif | | fetchmail | [] | findutils | [] | flex | [] | freedink | | gas | | gawk | [] [] | gcal | [] | gcc | | gettext-examples | [] [] [] [] | gettext-runtime | [] [] [] | gettext-tools | [] [] | gip | [] | gliv | [] | glunarclock | [] [] | gnubiff | | gnucash | [] | gnuedu | | gnulib | | gnunet | | gnunet-gtk | | gnutls | | gold | | gpe-aerial | | gpe-beam | | gpe-bluetooth | | gpe-calendar | | gpe-clock | [] | gpe-conf | | gpe-contacts | | gpe-edit | | gpe-filemanager | | gpe-go | | gpe-login | | gpe-ownerinfo | [] | gpe-package | | gpe-sketchbook | | gpe-su | [] | gpe-taskmanager | [] | gpe-timesheet | [] | gpe-today | [] | gpe-todo | | gphoto2 | | gprof | [] | gpsdrive | | gramadoir | | grep | | grub | [] [] | gsasl | | gss | | gst-plugins-bad | [] | gst-plugins-base | [] | gst-plugins-good | [] | gst-plugins-ugly | [] | gstreamer | [] [] [] | gtick | | gtkam | [] | gtkorphan | [] | gtkspell | [] [] [] | gutenprint | | hello | [] | hylafax | | idutils | | indent | [] [] | iso_15924 | | iso_3166 | [] [] [] [] [] [] [] | iso_3166_2 | | iso_4217 | | iso_639 | [] [] [] [] | iso_639_3 | [] | jwhois | | kbd | | keytouch | [] | keytouch-editor | | keytouch-keyboa... | [] | klavaro | [] | latrine | | ld | [] | leafpad | [] [] | libc | [] [] | libexif | () | libextractor | | libgnutls | | libgpewidget | | libgpg-error | | libgphoto2 | | libgphoto2_port | | libgsasl | | libiconv | [] | libidn | | lifelines | | liferea | [] [] | lilypond | | linkdr | [] | lordsawar | | lprng | | lynx | [] | m4 | | mailfromd | | mailutils | | make | | man-db | | man-db-manpages | | minicom | | mkisofs | | nano | [] [] | opcodes | | parted | | pies | | popt | | psmisc | | pspp | [] | pwdutils | | radius | [] | recode | [] [] | rosegarden | | rpm | | rush | | screem | | scrollkeeper | [] [] [] | sed | [] [] | sharutils | [] [] | shishi | | skencil | | solfege | | solfege-manual | | soundtracker | | sp | | sysstat | | tar | [] | texinfo | | tin | | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] | vice | | vmm | | vorbis-tools | | wastesedge | | wdiff | | wget | [] | wyslij-po | | xchat | [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] | +------------------------------------------------+ af am ar ast az be be@latin bg bn_IN bs ca crh 6 0 2 19 1 10 3 28 2 1 38 5 cs da de el en en_GB en_ZA eo es et eu fa fi +-------------------------------------------------+ a2ps | [] [] [] [] [] [] [] [] | aegis | [] [] [] | ant-phone | [] () | anubis | [] [] [] | aspell | [] [] [] [] [] | bash | [] [] [] [] | bfd | [] [] | bibshelf | [] [] [] [] | binutils | [] [] | bison | [] [] [] | bison-runtime | [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] | bombono-dvd | [] | buzztard | [] [] [] | cflow | [] [] [] | clisp | [] [] [] [] | coreutils | [] [] [] [] | cpio | [] | cppi | | cpplib | [] [] [] | cryptsetup | [] | dfarc | [] [] [] [] | dialog | [] [] [] [] [] | dico | | diffutils | [] [] [] [] [] [] [] | dink | [] [] [] | doodle | [] | e2fsprogs | [] [] [] | enscript | [] [] [] | exif | () [] [] [] | fetchmail | [] [] () [] [] [] | findutils | [] [] [] [] | flex | [] [] [] | freedink | [] [] [] [] | gas | [] | gawk | [] [] [] | gcal | [] | gcc | [] [] | gettext-examples | [] [] [] [] [] | gettext-runtime | [] [] [] [] [] | gettext-tools | [] [] [] | gip | [] [] [] [] [] | gliv | [] [] [] [] | glunarclock | [] [] [] | gnubiff | () | gnucash | [] () () () () () | gnuedu | [] [] | gnulib | [] [] [] | gnunet | | gnunet-gtk | [] | gnutls | [] [] | gold | [] [] | gpe-aerial | [] [] [] [] [] | gpe-beam | [] [] [] [] [] | gpe-bluetooth | [] [] | gpe-calendar | [] [] | gpe-clock | [] [] [] [] [] | gpe-conf | [] [] [] [] | gpe-contacts | [] [] [] [] | gpe-edit | [] [] [] | gpe-filemanager | [] [] [] [] | gpe-go | [] [] [] [] [] | gpe-login | [] [] [] | gpe-ownerinfo | [] [] [] [] [] | gpe-package | [] [] [] [] | gpe-sketchbook | [] [] [] [] [] | gpe-su | [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] | gpe-timesheet | [] [] [] [] [] | gpe-today | [] [] [] [] [] | gpe-todo | [] [] [] [] | gphoto2 | [] [] () [] [] [] [] | gprof | [] [] [] [] | gpsdrive | [] [] [] | gramadoir | [] [] [] | grep | [] [] | grub | [] [] | gsasl | [] [] | gss | [] | gst-plugins-bad | [] [] [] [] [] [] | gst-plugins-base | [] [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] [] [] | gstreamer | [] [] [] [] [] [] | gtick | [] () [] [] | gtkam | [] [] () [] [] | gtkorphan | [] [] [] [] | gtkspell | [] [] [] [] [] [] [] [] | gutenprint | [] [] [] | hello | [] [] [] [] [] | hylafax | [] [] | idutils | [] [] [] | indent | [] [] [] [] [] [] [] [] | iso_15924 | [] () [] [] [] | iso_3166 | [] [] [] () [] [] [] () [] | iso_3166_2 | () | iso_4217 | [] [] [] () [] [] [] | iso_639 | [] [] [] () [] [] [] | iso_639_3 | | jwhois | [] [] | kbd | [] [] [] [] [] | keytouch | [] [] [] | keytouch-editor | [] [] [] | keytouch-keyboa... | [] [] | klavaro | [] [] [] [] | latrine | [] () [] | ld | [] [] [] | leafpad | [] [] [] [] [] [] [] | libc | [] [] [] [] [] | libexif | [] [] () | libextractor | | libgnutls | [] | libgpewidget | [] [] [] | libgpg-error | [] [] | libgphoto2 | [] () | libgphoto2_port | [] () [] | libgsasl | [] | libiconv | [] [] [] [] [] [] | libidn | [] [] [] [] | lifelines | [] () | liferea | [] [] [] [] [] | lilypond | [] [] [] [] | linkdr | [] [] [] [] | lordsawar | [] | lprng | | lynx | [] [] [] [] | m4 | [] [] [] [] [] | mailfromd | | mailutils | [] | make | [] [] [] [] | man-db | | man-db-manpages | | minicom | [] [] [] [] [] | mkisofs | [] | nano | [] [] [] [] | opcodes | [] [] [] | parted | [] [] | pies | | popt | [] [] [] [] [] [] | psmisc | [] [] [] [] | pspp | [] | pwdutils | [] | radius | [] | recode | [] [] [] [] [] [] [] | rosegarden | () () () () | rpm | [] [] [] | rush | | screem | | scrollkeeper | [] [] [] [] [] [] | sed | [] [] [] [] [] [] [] | sharutils | [] [] [] [] [] | shishi | | skencil | [] () [] | solfege | [] [] [] [] | solfege-manual | [] [] | soundtracker | [] [] [] | sp | [] | sysstat | [] [] [] [] | tar | [] [] [] [] [] | texinfo | [] [] [] | tin | [] [] | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] [] [] [] [] | vice | () () | vmm | [] | vorbis-tools | [] [] | wastesedge | [] | wdiff | [] [] | wget | [] [] [] [] | wyslij-po | [] | xchat | [] [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] [] [] | +-------------------------------------------------+ cs da de el en en_GB en_ZA eo es et eu fa fi 64 103 113 18 1 8 0 28 89 18 19 0 100 fr ga gl gu he hi hr hu hy id is it ja ka kn +------------------------------------------------+ a2ps | [] [] [] | aegis | [] [] | ant-phone | [] [] | anubis | [] [] [] | aspell | [] [] [] [] | bash | [] | bfd | [] | bibshelf | [] [] [] [] | binutils | [] [] | bison | [] [] [] | bison-runtime | [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] | bombono-dvd | | buzztard | [] | cflow | [] [] | clisp | [] | coreutils | [] [] [] [] [] | cpio | [] [] [] | cppi | [] | cpplib | [] [] | cryptsetup | [] [] [] | dfarc | [] [] | dialog | [] [] [] [] [] [] [] | dico | | diffutils | [] [] [] [] [] [] [] [] | dink | [] | doodle | [] [] | e2fsprogs | [] [] | enscript | [] [] [] [] | exif | [] [] [] [] [] | fetchmail | [] [] [] [] | findutils | [] [] [] [] [] | flex | [] [] | freedink | [] [] | gas | [] [] | gawk | [] [] [] [] () [] | gcal | [] | gcc | [] | gettext-examples | [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] | gettext-tools | [] [] [] [] | gip | [] [] [] [] [] | gliv | () | glunarclock | [] [] [] | gnubiff | () [] () | gnucash | () () () () [] | gnuedu | [] [] | gnulib | [] [] [] [] [] | gnunet | | gnunet-gtk | [] | gnutls | [] [] | gold | [] | gpe-aerial | [] [] | gpe-beam | [] [] [] | gpe-bluetooth | [] [] [] | gpe-calendar | [] | gpe-clock | [] [] [] [] | gpe-conf | [] [] [] | gpe-contacts | [] [] [] | gpe-edit | [] [] | gpe-filemanager | [] [] [] | gpe-go | [] [] [] [] | gpe-login | [] [] | gpe-ownerinfo | [] [] [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] [] | gpe-su | [] [] [] [] [] | gpe-taskmanager | [] [] [] | gpe-timesheet | [] [] [] [] | gpe-today | [] [] [] [] [] | gpe-todo | [] [] | gphoto2 | [] [] [] [] [] | gprof | [] [] [] | gpsdrive | [] [] [] | gramadoir | [] [] [] | grep | | grub | [] | gsasl | [] [] [] [] | gss | [] [] [] [] | gst-plugins-bad | [] [] [] [] | gst-plugins-base | [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] | gstreamer | [] [] [] [] | gtick | [] [] [] [] | gtkam | [] [] [] [] [] | gtkorphan | [] [] [] | gtkspell | [] [] [] [] [] [] [] [] | gutenprint | [] [] [] | hello | [] [] | hylafax | [] | idutils | [] [] [] [] [] | indent | [] [] [] [] [] [] [] | iso_15924 | () [] [] | iso_3166 | () [] [] [] [] [] [] [] [] [] [] | iso_3166_2 | () [] [] | iso_4217 | () [] [] [] [] | iso_639 | () [] [] [] [] [] [] [] | iso_639_3 | () [] [] | jwhois | [] [] [] [] | kbd | [] [] | keytouch | [] [] [] [] [] | keytouch-editor | [] [] [] [] | keytouch-keyboa... | [] [] [] [] | klavaro | [] [] | latrine | [] [] | ld | [] [] [] | leafpad | [] [] [] [] [] [] () | libc | [] [] [] [] | libexif | | libextractor | | libgnutls | [] [] | libgpewidget | [] [] [] | libgpg-error | [] [] | libgphoto2 | [] [] | libgphoto2_port | [] [] [] | libgsasl | [] [] [] [] | libiconv | [] [] [] [] [] | libidn | [] [] [] | lifelines | () | liferea | [] [] [] [] | lilypond | [] | linkdr | [] [] [] [] | lordsawar | | lprng | [] | lynx | [] [] [] [] [] | m4 | [] [] [] [] [] | mailfromd | | mailutils | [] [] | make | [] [] [] [] [] [] [] [] | man-db | [] [] | man-db-manpages | [] | minicom | [] [] [] [] | mkisofs | [] [] [] | nano | [] [] [] [] [] | opcodes | [] [] [] | parted | [] [] [] [] | pies | | popt | [] [] [] [] [] [] [] [] | psmisc | [] [] [] | pspp | | pwdutils | [] [] | radius | [] [] | recode | [] [] [] [] [] [] [] | rosegarden | () () () () | rpm | [] [] | rush | | screem | [] [] | scrollkeeper | [] [] [] | sed | [] [] [] [] [] [] [] | sharutils | [] [] [] [] [] [] | shishi | [] | skencil | [] | solfege | [] [] [] | solfege-manual | [] [] | soundtracker | [] [] | sp | [] () | sysstat | [] [] [] [] | tar | [] [] [] [] [] [] | texinfo | [] [] [] | tin | [] | unicode-han-tra... | | unicode-transla... | [] [] | util-linux-ng | [] [] [] [] [] | vice | () () () | vmm | [] | vorbis-tools | [] | wastesedge | () () | wdiff | | wget | [] [] [] [] [] [] [] | wyslij-po | [] [] | xchat | [] [] [] [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] | +------------------------------------------------+ fr ga gl gu he hi hr hu hy id is it ja ka kn 116 53 20 4 8 2 5 50 2 120 5 81 64 0 4 ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne +-----------------------------------------------+ a2ps | [] | aegis | | ant-phone | | anubis | [] [] | aspell | [] | bash | | bfd | | bibshelf | [] [] | binutils | | bison | [] | bison-runtime | [] [] [] [] [] | bluez-pin | [] [] [] [] [] | bombono-dvd | | buzztard | | cflow | | clisp | | coreutils | [] | cpio | | cppi | | cpplib | | cryptsetup | | dfarc | [] | dialog | [] [] [] [] [] | dico | | diffutils | [] [] | dink | | doodle | | e2fsprogs | | enscript | | exif | [] | fetchmail | | findutils | | flex | | freedink | [] | gas | | gawk | | gcal | | gcc | | gettext-examples | [] [] [] [] | gettext-runtime | [] | gettext-tools | [] | gip | [] [] | gliv | | glunarclock | [] | gnubiff | | gnucash | () () () () | gnuedu | | gnulib | | gnunet | | gnunet-gtk | | gnutls | [] | gold | | gpe-aerial | [] | gpe-beam | [] | gpe-bluetooth | [] [] | gpe-calendar | [] | gpe-clock | [] [] [] [] [] | gpe-conf | [] [] | gpe-contacts | [] [] | gpe-edit | [] | gpe-filemanager | [] [] | gpe-go | [] [] [] | gpe-login | [] | gpe-ownerinfo | [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] | gpe-su | [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] [] | gpe-timesheet | [] [] | gpe-today | [] [] [] [] | gpe-todo | [] [] | gphoto2 | | gprof | [] | gpsdrive | | gramadoir | | grep | | grub | | gsasl | | gss | | gst-plugins-bad | [] [] | gst-plugins-base | [] [] | gst-plugins-good | [] [] | gst-plugins-ugly | [] [] [] [] [] | gstreamer | | gtick | | gtkam | [] | gtkorphan | [] [] | gtkspell | [] [] [] [] [] [] [] | gutenprint | | hello | [] [] [] | hylafax | | idutils | | indent | | iso_15924 | [] [] | iso_3166 | [] [] () [] [] [] [] [] | iso_3166_2 | | iso_4217 | [] [] | iso_639 | [] | iso_639_3 | [] | jwhois | [] | kbd | | keytouch | [] | keytouch-editor | [] | keytouch-keyboa... | [] | klavaro | [] | latrine | [] | ld | | leafpad | [] [] [] | libc | [] | libexif | | libextractor | | libgnutls | [] | libgpewidget | [] [] | libgpg-error | | libgphoto2 | | libgphoto2_port | | libgsasl | | libiconv | | libidn | | lifelines | | liferea | | lilypond | | linkdr | | lordsawar | | lprng | | lynx | | m4 | | mailfromd | | mailutils | | make | [] | man-db | | man-db-manpages | | minicom | [] | mkisofs | | nano | [] [] | opcodes | | parted | | pies | | popt | [] [] [] | psmisc | | pspp | | pwdutils | | radius | | recode | | rosegarden | | rpm | | rush | | screem | | scrollkeeper | [] [] | sed | | sharutils | | shishi | | skencil | | solfege | [] | solfege-manual | | soundtracker | | sp | | sysstat | [] | tar | [] | texinfo | [] | tin | | unicode-han-tra... | | unicode-transla... | | util-linux-ng | | vice | | vmm | | vorbis-tools | | wastesedge | | wdiff | | wget | [] | wyslij-po | | xchat | [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] | +-----------------------------------------------+ ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne 20 5 10 1 12 48 4 1 2 4 24 10 19 3 1 nl nn pa pl ps pt pt_BR ro ru rw sk sl sq sr sv +---------------------------------------------------+ a2ps | [] [] [] [] [] [] [] [] [] | aegis | [] [] [] | ant-phone | [] [] | anubis | [] [] [] [] | aspell | [] [] [] [] [] | bash | [] [] [] | bfd | [] | bibshelf | [] [] [] | binutils | [] [] | bison | [] [] [] [] | bison-runtime | [] [] [] [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] [] [] | bombono-dvd | [] () | buzztard | [] [] | cflow | [] | clisp | [] [] | coreutils | [] [] [] [] [] [] [] | cpio | [] [] [] [] | cppi | | cpplib | [] [] | cryptsetup | [] [] | dfarc | [] | dialog | [] [] [] [] [] | dico | [] | diffutils | [] [] [] [] [] [] [] | dink | () | doodle | [] [] [] | e2fsprogs | [] [] [] | enscript | [] [] [] [] [] [] | exif | [] [] [] () [] [] | fetchmail | [] [] [] [] | findutils | [] [] [] [] [] [] | flex | [] [] [] [] [] [] | freedink | [] [] | gas | | gawk | [] [] [] [] [] | gcal | [] | gcc | [] [] | gettext-examples | [] [] [] [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] [] [] [] [] | gettext-tools | [] [] [] [] [] [] [] | gip | [] [] [] [] [] [] | gliv | [] [] [] [] [] [] [] | glunarclock | [] [] [] [] [] [] | gnubiff | [] () [] | gnucash | [] () () () | gnuedu | [] | gnulib | [] [] [] [] [] | gnunet | | gnunet-gtk | [] | gnutls | [] [] [] | gold | | gpe-aerial | [] [] [] [] [] [] [] [] | gpe-beam | [] [] [] [] [] [] [] [] | gpe-bluetooth | [] [] [] | gpe-calendar | [] [] [] [] [] | gpe-clock | [] [] [] [] [] [] [] [] [] | gpe-conf | [] [] [] [] [] [] [] [] | gpe-contacts | [] [] [] [] [] [] | gpe-edit | [] [] [] [] | gpe-filemanager | [] [] [] [] | gpe-go | [] [] [] [] [] [] [] [] [] | gpe-login | [] [] [] | gpe-ownerinfo | [] [] [] [] [] [] [] [] [] | gpe-package | [] [] [] | gpe-sketchbook | [] [] [] [] [] [] [] [] | gpe-su | [] [] [] [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] [] [] [] [] | gpe-timesheet | [] [] [] [] [] [] [] [] [] | gpe-today | [] [] [] [] [] [] [] [] [] | gpe-todo | [] [] [] [] [] [] | gphoto2 | [] [] [] [] [] [] [] [] [] | gprof | [] [] [] [] | gpsdrive | [] [] [] | gramadoir | [] [] [] | grep | [] [] | grub | [] [] | gsasl | [] [] [] [] [] | gss | [] [] [] [] | gst-plugins-bad | [] [] [] [] [] [] | gst-plugins-base | [] [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] [] [] | gstreamer | [] [] [] [] [] [] | gtick | [] [] [] | gtkam | [] [] [] [] [] [] [] | gtkorphan | [] [] | gtkspell | [] [] [] [] [] [] [] [] [] [] [] | gutenprint | [] [] [] | hello | [] [] [] [] [] | hylafax | [] | idutils | [] [] [] [] [] [] | indent | [] [] [] [] [] [] [] [] | iso_15924 | [] [] [] [] | iso_3166 | [] [] [] [] () [] [] [] [] [] [] [] [] [] | iso_3166_2 | [] [] | iso_4217 | [] [] [] [] [] [] [] [] [] | iso_639 | [] [] [] [] [] [] [] [] | iso_639_3 | [] | jwhois | [] [] [] [] [] | kbd | [] [] [] [] | keytouch | [] [] [] | keytouch-editor | [] [] [] | keytouch-keyboa... | [] [] [] | klavaro | [] [] | latrine | [] [] | ld | [] | leafpad | [] [] [] [] [] [] [] [] [] [] | libc | [] [] [] [] [] | libexif | [] [] () [] | libextractor | | libgnutls | [] [] [] | libgpewidget | [] [] [] [] | libgpg-error | [] [] [] | libgphoto2 | [] [] | libgphoto2_port | [] [] [] [] [] | libgsasl | [] [] [] [] [] [] | libiconv | [] [] [] [] [] [] | libidn | [] [] () | lifelines | [] [] [] | liferea | [] [] [] [] [] () () [] [] | lilypond | [] | linkdr | [] [] [] [] | lordsawar | | lprng | [] | lynx | [] [] [] [] | m4 | [] [] [] [] [] [] | mailfromd | [] | mailutils | [] | make | [] [] [] [] [] | man-db | [] [] [] [] | man-db-manpages | [] [] [] | minicom | [] [] [] [] [] | mkisofs | [] [] | nano | [] [] [] [] | opcodes | [] [] [] | parted | [] [] [] [] [] | pies | [] | popt | [] [] [] [] [] | psmisc | [] [] [] [] | pspp | [] [] | pwdutils | [] [] | radius | [] [] [] | recode | [] [] [] [] [] [] [] [] [] | rosegarden | () () () | rpm | [] [] [] [] | rush | [] | screem | | scrollkeeper | [] [] [] [] [] [] [] [] [] | sed | [] [] [] [] [] [] [] [] [] [] | sharutils | [] [] [] [] [] | shishi | [] | skencil | [] [] [] | solfege | [] [] [] [] [] | solfege-manual | [] [] [] | soundtracker | [] [] | sp | | sysstat | [] [] [] [] | tar | [] [] [] [] [] | texinfo | [] [] [] [] [] | tin | [] | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] [] [] [] [] [] | vice | [] () | vmm | [] | vorbis-tools | [] [] | wastesedge | [] | wdiff | [] [] [] | wget | [] [] [] [] [] [] [] [] | wyslij-po | [] [] | xchat | [] [] [] [] [] [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] [] [] | +---------------------------------------------------+ nl nn pa pl ps pt pt_BR ro ru rw sk sl sq sr sv 132 10 7 96 1 29 60 47 89 3 54 46 8 37 118 sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW +-----------------------------------------------+ a2ps | [] [] [] [] | 27 aegis | [] | 9 ant-phone | [] [] [] | 8 anubis | [] [] [] | 15 aspell | [] [] [] | 20 bash | [] | 9 bfd | [] | 5 bibshelf | [] [] | 16 binutils | [] [] | 8 bison | [] | 12 bison-runtime | [] [] [] [] [] | 29 bluez-pin | [] [] [] [] [] [] [] | 37 bombono-dvd | [] | 3 buzztard | | 6 cflow | [] [] [] | 9 clisp | | 10 coreutils | [] [] [] | 22 cpio | [] [] [] [] [] | 13 cppi | [] | 2 cpplib | [] [] [] [] [] | 13 cryptsetup | [] | 7 dfarc | [] | 9 dialog | [] [] [] [] [] [] | 30 dico | [] | 2 diffutils | [] [] [] [] [] | 30 dink | | 4 doodle | [] | 7 e2fsprogs | [] [] | 11 enscript | [] [] [] | 17 exif | [] [] | 16 fetchmail | [] [] [] | 17 findutils | [] [] [] [] | 20 flex | [] [] [] | 15 freedink | [] | 10 gas | [] | 4 gawk | [] [] [] | 18 gcal | [] | 5 gcc | [] [] | 7 gettext-examples | [] [] [] [] [] [] | 34 gettext-runtime | [] [] [] [] [] [] | 30 gettext-tools | [] [] [] [] [] | 22 gip | [] [] [] | 22 gliv | [] [] | 14 glunarclock | [] [] [] [] | 19 gnubiff | [] | 4 gnucash | () [] () () | 9 gnuedu | [] [] | 7 gnulib | [] [] [] | 16 gnunet | [] | 1 gnunet-gtk | [] [] | 5 gnutls | [] [] | 10 gold | | 3 gpe-aerial | [] [] | 18 gpe-beam | [] [] | 19 gpe-bluetooth | [] [] | 12 gpe-calendar | [] [] [] | 12 gpe-clock | [] [] [] [] | 28 gpe-conf | [] [] [] | 20 gpe-contacts | [] [] | 17 gpe-edit | [] [] | 12 gpe-filemanager | [] [] [] | 16 gpe-go | [] [] [] [] | 25 gpe-login | [] [] | 11 gpe-ownerinfo | [] [] [] [] | 25 gpe-package | [] [] | 13 gpe-sketchbook | [] [] | 20 gpe-su | [] [] [] [] | 30 gpe-taskmanager | [] [] [] [] | 28 gpe-timesheet | [] [] [] [] | 25 gpe-today | [] [] [] [] [] | 29 gpe-todo | [] [] [] | 17 gphoto2 | [] [] [] [] | 24 gprof | [] [] | 15 gpsdrive | [] [] | 11 gramadoir | [] [] | 11 grep | [] [] | 6 grub | [] [] | 9 gsasl | [] [] [] | 14 gss | [] [] | 11 gst-plugins-bad | [] [] [] | 22 gst-plugins-base | [] [] [] [] | 24 gst-plugins-good | [] [] [] [] | 25 gst-plugins-ugly | [] [] [] [] | 29 gstreamer | [] [] [] | 22 gtick | [] [] [] | 13 gtkam | [] [] | 20 gtkorphan | [] [] | 14 gtkspell | [] [] [] [] [] [] [] [] | 45 gutenprint | | 9 hello | [] [] [] [] [] | 21 hylafax | [] | 5 idutils | [] [] [] | 17 indent | [] [] [] [] [] | 30 iso_15924 | () [] () [] [] | 16 iso_3166 | [] () [] [] () [] [] [] () | 51 iso_3166_2 | () [] () [] | 7 iso_4217 | () [] [] () [] [] | 26 iso_639 | [] [] () [] () [] [] [] [] | 34 iso_639_3 | [] () | 7 jwhois | [] [] [] [] | 16 kbd | [] [] [] [] | 15 keytouch | [] [] | 15 keytouch-editor | [] [] | 13 keytouch-keyboa... | [] [] | 13 klavaro | [] | 11 latrine | [] [] [] | 10 ld | [] [] [] | 11 leafpad | [] [] [] [] [] | 33 libc | [] [] [] [] | 21 libexif | [] () | 6 libextractor | [] | 1 libgnutls | [] [] | 9 libgpewidget | [] [] | 14 libgpg-error | [] [] | 9 libgphoto2 | [] [] | 7 libgphoto2_port | [] [] [] | 13 libgsasl | [] [] | 13 libiconv | [] [] [] | 21 libidn | [] [] | 11 lifelines | | 4 liferea | [] [] | 21 lilypond | [] | 7 linkdr | [] [] [] [] | 17 lordsawar | | 1 lprng | [] | 3 lynx | [] [] [] | 17 m4 | [] [] [] | 19 mailfromd | [] [] | 3 mailutils | [] | 5 make | [] [] [] | 21 man-db | [] [] | 8 man-db-manpages | | 4 minicom | [] | 16 mkisofs | [] | 7 nano | [] [] [] | 20 opcodes | [] [] | 11 parted | [] [] [] [] | 15 pies | [] | 2 popt | [] [] [] [] [] | 27 psmisc | [] | 12 pspp | | 4 pwdutils | [] | 6 radius | [] [] | 9 recode | [] [] [] | 28 rosegarden | | 0 rpm | [] [] | 11 rush | [] [] | 3 screem | [] | 3 scrollkeeper | [] [] [] [] | 27 sed | [] [] [] [] | 30 sharutils | [] [] [] [] | 22 shishi | [] | 3 skencil | [] | 7 solfege | [] [] [] | 16 solfege-manual | [] | 8 soundtracker | [] [] | 9 sp | [] | 3 sysstat | [] [] | 15 tar | [] [] [] [] [] | 23 texinfo | [] [] [] | 15 tin | | 4 unicode-han-tra... | | 0 unicode-transla... | | 2 util-linux-ng | [] [] [] | 20 vice | () | 1 vmm | [] | 4 vorbis-tools | [] | 6 wastesedge | | 2 wdiff | [] | 6 wget | [] [] [] [] | 25 wyslij-po | [] | 6 xchat | [] [] [] [] [] | 36 xdg-user-dirs | [] [] [] [] [] [] [] [] | 57 xkeyboard-config | [] [] [] | 25 +-----------------------------------------------+ 82 teams sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW 174 domains 1 3 2 0 10 66 48 149 17 96 7 41 2551 Some counters in the preceding matrix are higher than the number of visible blocks let us expect. This is because a few extra PO files are used for implementing regional variants of languages, or language dialects. For a PO file in the matrix above to be effective, the package to which it applies should also have been internationalized and distributed as such by its maintainer. There might be an observable lag between the mere existence a PO file and its wide availability in a distribution. If March 2010 seems to be old, you may fetch a more recent copy of this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date matrix with full percentage details can be found at `http://translationproject.org/extra/matrix.html'. 1.6 Using `gettext' in new packages =================================== If you are writing a freely available program and want to internationalize it you are welcome to use GNU `gettext' in your package. Of course you have to respect the GNU Library General Public License which covers the use of the GNU `gettext' library. This means in particular that even non-free programs can use `libintl' as a shared library, whereas only free software can use `libintl' as a static library or use modified versions of `libintl'. Once the sources are changed appropriately and the setup can handle the use of `gettext' the only thing missing are the translations. The Free Translation Project is also available for packages which are not developed inside the GNU project. Therefore the information given above applies also for every other Free Software Project. Contact `coordinator@translationproject.org' to make the `.pot' files available to the translation teams. pspp-master/AUTHORS000066400000000000000000000022251177044323000144030ustar00rootroot00000000000000We wish to thank current active contributors to PSPP: * Ben Pfaff wrote the initial program and manual, which comprises the majority of the current code. Ben continues to contribute and most of the core libraries which ensure that PSPP runs with optimal speed are his work. * John Darrington wrote the graphical user interface, and the T-TEST, ONEWAY, EXAMINE, RANK and NPAR TESTS commands, implemented support for long variable names, PostgreSQL and Gnumeric and made numerous revisions to other modules. * Jason Stover contributed statistical and numerical functionality, including lib/gslextras and the linear regression features. Jason is also an important contributor to GSL, which is used by PSPP. * Mehmet Hakan Satman wrote the QUICK CLUSTER command. We also thank past contributors: * John Williams wrote an initial draft of the T-TEST procedure. * Michael Kiefte contributed bug fixes and other enhancements. * Patrick Kobly contributed bug fixes and other enhancements. * Rob van Son wrote the original version of the routine for calculation of the significance of the Wilcoxon matched pairs signed rank statistic used by the NPAR TEST command. pspp-master/COPYING000066400000000000000000001043741177044323000143760ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. 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. Copyright (C) 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 . 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: Copyright (C) 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 . 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 . pspp-master/INSTALL000066400000000000000000000333361177044323000143730ustar00rootroot00000000000000Installation Instructions for GNU pspp ************************************** These instructions are based on the generic GNU installation instructions, but they have been tailored for PSPP. Overview ======== PSPP uses the standard GNU configuration system. Therefore, if all is well, the following simple procedure should work, even on non-GNU systems: tar -xzf pspp-*.tar.gz cd pspp-* ./configure make sudo make install Obviously, you should replace 'pspp-*' in the above, with the name of the tarball you are installing. If any part of this process fails, then it's likely that one or more of the necessary prerequisites is missing from your system. Read on to find out how to correct this. Before You Install ================== Before you install PSPP, you will need to install certain prerequisite packages. You may also want to install other packages that enable additional functionality in PSPP. If you do not know whether you have these installed already, you may proceed to "Basic Installation", below. The PSPP configuration process will notify you about required and optional packages that are not present on your system. The following packages are required to install PSPP: * An ANSI C compiler and tool chain. On Unix-like systems, we recommend GCC, but any modern compilation environment should work. On Microsoft Windows, Cygwin (http://www.cygwin.com/) and MinGW (http://www.mingw.org/) are known to work. * The GNU Scientific Library (http://www.gnu.org/software/gsl/), version 1.8 or later, including libgslcblas included with GSL. * Perl (http://www.perl.org/), version 5.005_03 or later. Perl is required during build but not after installation. * iconv, which should be installed as part of a Unix-like system. If you don't have a version already, you can install GNU libiconv (http://www.gnu.org/software/libiconv/). * libintl, from GNU gettext (http://ww.gnu.org/software/gettext). GNU libc includes an integrated libintl, so there is no need to separately install libintl on a GNU/Linux system. The following packages are required to enable PSPP's graphing features. If you cannot arrange to install them, you must run `configure' with --without-cairo. * Cairo (http://cairographics.org/), version 1.5 or later. * Pango (http://www.pango.org/), version 1.22 or later. The following packages are required to enable PSPPIRE, the graphical user interface for PSPP. If you cannot install them or do not wish to use the GUI, you must run `configure' with --without-gui. * pkg-config (http://pkg-config.freedesktop.org/wiki/). Versions 0.18 and 0.19 have a bug that will prevent library detection, but other versions should be fine. * GTK+ (http://www.gtk.org/), version 2.12.0 or later. * GtkSourceView (http://projects.gnome.org/gtksourceview/) version 2.2 or later. Installing the following packages will allow your PSPP binary to read Gnumeric files. * zlib (http://www.zlib.net/). * libxml2 (http://xmlsoft.org/). Installing the following packages will allow your PSPP binary to write OpenDocument text (ODT) files: * libxml2 (http://xmlsoft.org/). The following packages are optional. * libncurses (http://www.gnu.org/software/ncurses/). Without it, PSPP will assume it is running in an 80x25 terminal. * libreadline and libhistory (http://tiswww.case.edu/php/chet/readline/rltop.html). Without them, interactive command editing and history features in the text-based user interface will be disabled. * Texinfo (http://www.gnu.org/software/texinfo/), version 4.7 or later. Installing Texinfo will allow you to build PSPP documentation in PostScript or PDF format. * libpq, from Postgresql (http://postgresql.org). This enables PSPP to read Postgresql databases. The tests for the Postgresql interface, but not the Postgresql interface itself, requires the Postgresql server to be installed. * The Text::Diff module for Perl (http://cpan.org). This enables PSPP to test the Perl module more thoroughly. It is not needed to build or use the Perl module. Basic Installation ================== These are installation instructions specific to PSPP (including PSPPIRE, the graphic user interface). These instructions contain the information most commonly needed by people wishing to build the program from source. More detailed information can be found in the generic autoconf manual which is available at http://www.gnu.org/software/autoconf/manual/html_node/Running-configure-Scripts.html The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. If you need to do unusual things to compile the package, please report the problem to bug-gnu-pspp@gnu.org. We will try to figure out how `configure' could work better in your situation for the next release. The simplest way to compile PSPP is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. You may invoke `configure' with --help to see what options are available. The most common of these are listed under "Optional Features", below. It is best to build and install PSPP in directories whose names do not contain unusual characters such as spaces or single-quotes, due to limitations of the tools involved in the build process. If you installed some of the libraries that PSPP uses in a non-standard location (on many systems, anywhere other than /usr), you may need to provide some special flags to `configure' to tell it where to find them. For example, on GNU/Linux, if you installed some libraries in /usr/local, then you need to invoke it with at least the following options: ./configure LDFLAGS='-L/usr/local/lib -Wl,-rpath,/usr/local/lib' CPPFLAGS='-I/usr/local/include' Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. If `configure' completes successfully, it prints the message "PSPP configured successfully." at the end of its run. Otherwise, it may stop with a list of packages that you must install before PSPP. If it does, you need to install those packages, then re-run this step. Some prerequisites may be omitted by passing a --without- flag to `configure' (see "Optional Features", below). If you use one of these flags, then the feature that it disables will not be available in your PSPP installation. `configure' may also print a list of packages that you should consider installing. If you install them, then re-run `configure', additional features will be available in your PSPP installation. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run the self-tests that come with the package. If any of the self-tests fail, please mail bug-gnu-pspp@gnu.org with the details, to give the PSPP developers an opportunity to fix the problem in the next release. 4. Type `make install' to install the programs and any data files and documentation. Ordinarily you will need root permissions to do this. The "su" and "sudo" commands are common ways to obtain root permissions. If you cannot get root permissions, see "Installation Names", below. Please note: The `make install' target does NOT install the perl module (see below). To install the perl module, you must change to the `perl-module' directory and manually run `make install' there. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. Compilers and Options ===================== Some systems may require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix To cross-compile PSPP, you will likely need to set the PKG_CONFIG_LIBDIR environment variable to point to an appropriate pkg-config for the cross-compilation environment. See "Defining Variables", below, for more details. Installation Names ================== By default, `make install' installs PSPP's commands under `/usr/local/bin', data files under `/usr/local/share', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX'. You may wish to install PSPP on a machine where you do not have root permissions. To do so, specify a prefix relative within your home directory, e.g. `--prefix=$HOME' or `--prefix=$HOME/inst'. All PSPP files will be installed under the prefix directory, which `make install' will create if necessary. You may run PSPP directly from the `bin' directory under the prefix directory as, e.g., `~/inst/bin/pspp' under most shells, or for added convenience you can add the installation directory to your PATH by editing a shell startup file such as `.bashrc'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. You can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= `--without-cairo' Don't compile in support for charts (using Cairo and Pango). This is useful if your system lacks these libraries. `--without-gui' Don't build the PSPPIRE gui. Use this option if you only want to build the command line version of PSPP. Cairo and Pango required to build the GUI, so --without-cairo implies --without-gui. `--with-gui-tools' Build the gui developer tools. There is no reason to use this option unless you're involved with the development of PSPP `--without-lib{xx}' Optional libraries should normally be detected and the relevant functionality will be built they exist. However, on some poorly configured systems a library may exist, but be totally broken. In these cases you can use --without-lib{xx} to force configure to disregard it. `--without-perl-module' Disable building the Perl module, in case it does not build properly or you do not need it. `--enable-anachronistic-dependencies' If you use this option, some of the checks for dependent libraries will be relaxed, permitting configure to succeed when older versions of libraries are detected. Use of this option is not recommended. If you use it, some features may be missing and the build may fail with obscure error messages. `--enable-relocatable' This option is useful for building a package which can be installed into an arbitrary directory and freely copied to any other directory. If you use this option, you will probably want to install the pspp with a command similar to "make install DESTDIR=". Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Here is another example: /bin/bash ./configure CONFIG_SHELL=/bin/bash Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent configuration-related scripts to be executed by `/bin/bash'. Generic `configure' Options =========================== `configure' also recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. ---------------------------------------------------------------------- Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2007 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. pspp-master/Makefile.am000066400000000000000000000037761177044323000154030ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in -*- makefile -*- AUTOMAKE_OPTIONS = std-options check-news 1.10.1 subdir-objects SUBDIRS = gl po DISTCLEANFILES = ./po/stamp-po xconfigure BUILT_SOURCES = AM_CPPFLAGS = \ -I$(top_srcdir)/gl \ -I$(top_builddir)/gl \ -DINSTALLDIR=\"$(bindir)\" AM_CFLAGS= if cc_is_gcc AM_CFLAGS+=-Wall -W -Wwrite-strings -Wstrict-prototypes \ -Wpointer-arith -Wno-sign-compare -Wmissing-prototypes endif .q.c: @$(MKDIR_P) `dirname $@` ./src/language/lexer/q2c$(EXEEXT_FOR_BUILD) $< $@ $(all_q_sources:.q=.c): src/language/lexer/q2c$(EXEEXT_FOR_BUILD) all_q_sources = pkgsysconfdir = $(sysconfdir)/$(PACKAGE) EXTRA_DIST = OChangeLog ONEWS pspp-mode.el CLEANFILES = CLEAN_LOCAL = ALL_LOCAL = CHECK_LOCAL = ACLOCAL_AMFLAGS = -I m4 -I gl/m4 noinst_LIBRARIES= noinst_LTLIBRARIES= noinst_PROGRAMS= check_PROGRAMS= bin_PROGRAMS= dist_man_MANS = DIST_HOOKS = INSTALL_DATA_HOOKS = UNINSTALL_DATA_HOOKS = PHONY = SUFFIXES = .q LDADD = gl/libgl.la generate-changelog: if test -d $(top_srcdir)/.git; then \ $(top_srcdir)/build-aux/gitlog-to-changelog --since=2008-07-27 \ > $(distdir)/cl-t; \ rm -f $(distdir)/ChangeLog; \ mv $(distdir)/cl-t $(distdir)/ChangeLog; \ fi DIST_HOOKS += generate-changelog include $(top_srcdir)/po/automake.mk include $(top_srcdir)/lib/automake.mk include $(top_srcdir)/doc/automake.mk include $(top_srcdir)/examples/automake.mk include $(top_srcdir)/src/automake.mk include $(top_srcdir)/utilities/automake.mk include $(top_srcdir)/tests/automake.mk if WITH_GUI_TOOLS include $(top_srcdir)/glade/automake.mk endif if WITH_PERL_MODULE include $(top_srcdir)/perl-module/automake.mk endif PHONY += $(DIST_HOOKS) $(INSTALL_DATA_HOOKS) $(UNINSTALL_DATA_HOOKS) .PHONY: $(PHONY) dist-hook: $(DIST_HOOKS) install-data-hook: $(INSTALL_DATA_HOOKS) uninstall-hook: $(UNINSTALL_DATA_HOOKS) clean-local: $(CLEAN_LOCAL) all-local: $(ALL_LOCAL) check-local: $(CHECK_LOCAL) # A convenience target to build all the binaries programs: $(PROGRAMS) pspp-master/NEWS000066400000000000000000000742511177044323000140420ustar00rootroot00000000000000PSPP NEWS -- history of user-visible changes. Copyright (C) 1996-2000, 2008-2012 Free Software Foundation, Inc. See the end for copying conditions. Please send PSPP bug reports to bug-gnu-pspp@gnu.org. Changes from 0.6.2 to 0.7.9: * New commands: - ADD FILES - CORRELATIONS - DATAFILE ATTRIBUTES - DATASET ACTIVATE - DATASET CLOSE - DATASET COPY - DATASET DECLARE - DATASET DISPLAY - DATASET NAME - MATCH FILES - MEANS - MRSETS - PRESERVE and RESTORE - QUICK CLUSTER - RELIABILITY - ROC - SAVE TRANSLATE to CSV and tab-delimited files - UPDATE - VARIABLE ATTRIBUTES * Changes to existing commands: - AUTORECODE has a new GROUP subcommand. - CROSSTABS has been re-implemented to fix numerous bugs. - EXAMINE: /MISSING=LISTWISE is now the default. - DO REPEAT command has been reimplemented. Now, when DO REPEAT contains an INCLUDE or INSERT command, substitutions are not applied to the included file. - HOST has been updated to use more modern syntax. - Most commands that work with data files now support a new ENCODING subcommand. - MISSING VALUES can now assign missing values to long string variables. - ONEWAY: the POSTHOC subcommand is now implemented. - The following new subcommands to NPAR TESTS have been implemented: COCHRAN, FRIEDMAN, JONCKHEERE-TERPSTRA, KENDALL, KRUSKAL-WALLIS, MANN-WHITNEY, MCNEMAR, SIGN, WILCOXON, and RUNS - SET and SHOW no longer have ENDCMD, NULLINE, PROMPT, CPROMPT, and DPROMPT subcommands. The defaults are now fixed values. - VALUE LABELS can now assign value labels to long string variables. * Other language changes: - The new DATASET commands replace the "scratch file" PSPP extension, which is no longer supported. - Strings may now include arbitrary Unicode code points specified in hexadecimal, using the syntax U'hhhh'. For example, Unicode code point U+1D11E, the musical G clef character, may be expressed as U'1D11E'. See the "Tokens" section in the PSPP manual for more information. - In previous versions of PSPP, in a string expressed in hexadecimal with X'hh' syntax, the hexadecimal digits expressed bytes in the locale encoding. In this version of PSPP, X'hh' syntax always expresses bytes in UTF-8 encoding. See the "Tokens" section in the PSPP manual for more information. * PSPPIRE graphical user interface improvements: - Added support for non-ASCII characters in strings, labels and variable names. - A "Split Window" function is available, which makes it easier to see different parts of a large data file. - Data files can now be opened by specifing their name as the first argument. This means that on a properly configured desktop, double clicking on an icon will open the file. * Output changes: - The new "cairo" output driver supports output in PostScript, PDF, and SVG formats. Its functionality is a superset of that of the "postscript" driver, which has been removed. You must have Cairo and Pango installed to build the "cairo" driver. - Charts are now produced with Cairo and Pango, instead of libplot. Without them, the new graphing features will not work. If you do not have Cairo and Pango installed, you must run `configure' with --without-cairo. - The plain text output driver now properly supports multibyte UTF-8 characters, including double-width characters and combining accents. - Output to OpenDocument format is now supported. - The HTML output is much improved. * The "pspp" program has a new option --batch (or -b) that selects "batch" syntax mode. In previous versions of PSPP this syntax mode was the default. Now a new "auto" syntax mode is the default. In "auto" mode, PSPP interprets most syntax files correctly regardless of their intended syntax mode. See the "Syntax Variants" section in the PSPP manual for more information. * The "pspp" program has a new option --syntax-encoding that specifies the encoding for syntax files listed on the command line, as well as the default encoding for syntax files included with INCLUDE or INSERT. The default is to accept the system locale encoding, UTF-8, UTF-16, or UTF-32, automatically detecting which one the system file uses. See the documentation for the INSERT command in the PSPP manual for more information. * A new Perl module allows Perl programs to read and write PSPP system files. * A tutorial chapter has been added to the user manual. Changes from 0.6.1 to 0.6.2: * New translations: - Dutch, thanks to Harry Thijssen. - Brazilian Portuguese, thanks to Michel Boaventura. Thanks for translations are also due to the coordinators at translationproject.org. * Statistical bug fixes: - REGRESSION: Report correct standard error of the estimate (bug #25677). - T-TEST: Report correct significance of paired sample T-test in the common case (bug #26936) and corner cases. Thanks to Mike Griffiths and Matej Cepl for reporting these bugs. * Build fixes and changes: - Fix build with GTK+ 2.17.4 and later. - Make running "make" after running "configure" with different settings reliably rebuild version.c. - Cygwin and MinGW build fixes. - Fixes for building with recent gnulib. - The Makefile now honors two new variables, PSPP_LDFLAGS and PSPPIRE_LDFLAGS, that affect linking of the PSPP and PSPPIRE binaries, respectively. This makes building easier for some packagers. - Fixes for "configure --enable-relocatable" (bug #25508). * Data file bug fixes and changes: - Fix reading text data files that contain a mix of white space and commas. Now "a ,b" is treated as two fields containing "a" and "b"; previously it was treated as three, with an empty field in the middle. - Fix writing corrupted .sav files on Windows. - Fix writing variable labels longer than 252 bytes to save files. Thanks to Robert Westlund for reporting this bug. - Fix writing corrupted .por files (bug #26034). - Fix reading .por files whose initial lines are not padded out with spaces as expected. - PSPP will no longer issue warnings about some .sav file records or values that it does not understand. These warnings were harmless, but needlessly alarmed some users. - Fix crash reading empty string fields from PostgreSQL databases. * Bug fixes that affect PSPP and PSPPIRE: - Users may now control precision of output statistics. Instead of hard coding the width and decimals of output numbers, respect the default format in most instances. Counts are now normally displayed with the format of the weight variable, if any. - Fix crash when an INSERT command specifies the name of a file that does not exist (bug #24569). - Fix crash when CROSSTABS specifies a long-string variable (bugs #24557 and #26131). - Fix crash drawing pie charts with many segments. - Fix crash when NUMERIC specifies an invalid format. * PSPPIRE bug fixes and changes: - On Windows, write the output file to the user's home directory instead of the current directory, to better match user expectations. - Some data editor fixes. * Documentation: - Fix typo in BINOMIAL section of user manual (bug #25892). Changes from 0.6.0 to 0.6.1: * Statistical bug fixes: - Report correct standardized regression coefficients in linear regression output (bug #23567). * Bug fixes that affect PSPP and PSPPIRE: - Avoid crash with pie charts (bug #24014). - Don't append % to count totals (bug #24003). - Don't crash on bad input (bug #24031). - Don't crash if "end data." is not left aligned (bug #24115). - Change default workspace value to 64 MB, to avoid unnecessary disk accesses on modern machines. * PSPPIRE bug fixes: - Add ".sav" or ".por" suffix to filename when saving with Save_As (bug #23137). - Make it possible to reopen the output window on Windows (bug #24033). - A POSIX regular expression library is now included and used automatically if the host does not have one or has one that is inadequate. * Build fixes and changes: - Work around bug in GSL that prevented build with recent GCC versions without manually adding -fgnu89-inline to CFLAGS. - Also warn about missing prerequisites as we encounter them (bug #24445). - Distribute necessary files to allow users working from the distributed tarball to configure with --enable-gui-tools. - Append $(EXEEXT_FOR_BUILD) to output file name when building q2c, fixing build problems on Windows. - GSL 1.8 or later is now required. - Build errors with --enable-relocatable were fixed. * The German translations were removed, since native German speakers found them too poor to be useful. Changes from 0.4.0 to 0.6.0: * The PSPP license is now version 3 or later of the GNU General Public License. Previously, it was version 2 or later. * PSPP now has a graphical interface, called PSPPIRE. This interface allows you to enter data and variable definitions interactively. Commands may be executed in syntax form, or by using the interactive dialog boxes available from the dropdown menus. * A few sample syntax files are now included in the `examples' directory. * Numerous major and minor bugs have been fixed. Build changes: * The INSTALL file now reflects the details of how to install PSPP. It is a tailored version of the generic installation instructions, instead of a verbatim copy. * iconv, which is ordinarily installed as part of a Unix-like system, is now required. If you don't have it already, you can install GNU libiconv (http://www.gnu.org/software/libiconv/). * libxml2 and zlib are new optional dependencies. They are required to use PSPP's support for reading Gnumeric files. Statistical procedure changes: * REGRESSION is a new procedure for fitting linear models to data via least-squares estimation. * NPAR TESTS is a new procedure for non-parametric tests. In this release, it supports binomial and chi-square tests. * RANK is a new procedure to rank variables. It supports numerous forms of ranking. * FREQUENCIES can now output histograms and pie charts. These features were present in earlier releases, but not documented. User interface changes: * In many situations where PSPP once terminated with a fatal error, PSPP now recovers and continues execution. * PSPP is now able to start up and run even if it cannot find its configuration files. * Journaling of interactive commands to a disk file is now implemented. By default, journaling is enabled, to a file named `pspp.jnl' in the current directory. SET JOURNAL may be used to control journaling. * The use of `+' between syntax file names on the command line to prevent the dictionary from being cleared between their executions is no longer supported. All syntax files are now executed as if `+' had been specified. * The -d/--define and -u/--undef command line options are no longer supported. Instead, use /usr/bin/env or shell primitives to define or clear environment variables before invoking PSPP. * If a syntax file named named `rc' is found in a configuration directory (such as $HOME/.pspp), it is executed before any syntax file specified on the command line. The -r or --no-statrc command line option may be used to disable this behavior. Output changes: * Output configuration options have changed. Please refer to the manual for a full description of the available options. In consequence, you will need to reinstall your "devices" file. "make install" will do this for you. * Most error messages are now written to PSPP output files by default. SET ERROR can be used to disable this behavior. * When invoked interactively, PSPP now by default produces output on the terminal, piping it through the "more" program. Previously, by default output was written only to file pspp.list. On most terminals, the page length used for output automatically adapts to the terminal size, even if the terminal is resized. * ASCII driver: - This driver now supports charts in output. Charts are written as separate files that the main output file refers to. By default, charts are written in PNG format to files named pspp-1.png, pspp-2.png, and so on. - Configurations are provided that use VT100 (and xterm) line-drawing characters in tables. The option "-o list-vt100" requests use of this device for output to pspp.list. * PostScript driver: - The default paper size is now determined using the PAPERSIZE environment variable, or the LC_PAPER locale category on systems that support it. If these are not set, the default is now A4, instead of US letter. To make US letter the default, set PAPERSIZE to "letter" in your environment. - Font metrics are now read from AFM files, instead of Groff-format metrics files. PostScript fonts can now be embedded in output. In consequence, you will need to install an AFM file for each font used in PostScript output. "make install" will install AFM files for the standard PostScript fonts, including the ones that the PostScript driver uses by default. - Standard paper sizes no longer need to be specified through a configuration file. The "papersize" configuration file is no longer needed, or supported. - The PostScript prologue is no longer obtained from the "ps-prologue" configuration file. This configuration file is no longer needed, or supported. * HTML driver: - The HTML prologue is no longer obtained from the "html-prologue" configuration file. This configuration file is no longer needed, or supported. Command language changes: * The following commands are new: - GET DATA, which currently supports reading Gnumeric files and text data files. It will be extended later to read other types of foreign data. - CD, to change the current directory. - INSERT, to execute a syntax file. - DELETE VARIABLES, to remove variables from the active file dictionary. - ADD DOCUMENT, to add text to active file documents. - CLOSE FILE HANDLE (a PSPP extension; see below). - XEXPORT, a PSPP extension that is a transformation equivalent to EXPORT. * The following functions for transformation expressions are new: - DATEDIFF, for computing the difference of two dates. - DATESUM, for advancing a date by a specified duration. - VALUELABEL, to obtain the value label for a value. * PSPP now supports very long string variables (over 255 bytes long). * MATCH FILES now supports the FIRST and LAST subcommands. * Previous versions of PSPP prohibited using commands to both read and write a single file at the same time. Now, PSPP allows this, and the new version of the file atomically replaces the old version. * The following commands are no longer available. They will be re-implemented in a later release: - CLEAR TRANSFORMATIONS - MATRIX DATA - REPEATING DATA * The PROCESS IF command, which was deprecated, has been removed. You may replace any usage of it by SELECT IF following TEMPORARY, which has the same effect. * The output format for variables created by VECTOR may now be specified as part of the VECTOR syntax. "Scratch files", a new PSPP extension: A scratch file, like a system file, consists of a dictionary and any number of cases. Small scratch files are stored in memory; one that grows too large is written to disk. By default, any file handle whose name begins with # is assumed to refer to a scratch file. Scratch files can be used just about anywhere a system or portable file can be used. Also, portable files are now allowed in most places that system files were allowed in previous PSPP version. A new CLOSE FILE HANDLE command allows the storage associated with scratch files to be freed. It also allows file handles to be reassigned to new files. For more information on scratch files, refer to the "File Handles" section in the PSPP manual. For specifics of what commands now allow what kinds of files to be specified, refer to the documentation on those particular commands. Data access changes: * Binary formats and IBM/360 formats, including ASCII/EBCDIC translation, are now supported. Use FILE HANDLE to specify the format of these files. * Little-endian, big-endian, and VAX-endian formats are now supported for integer binary formats when reading and writing data files. The new RIB and WIB subcommands on the SET command control endianness of integer data. The default is the host's native endianness. * IEEE 754, VAX, and IBM hexadecimal formats are now supported for floating point binary formats when reading and writing data files. The new RRB and WRB subcommands on the SET command control the floating point format. The default is the host's native floating point format. * DATA LIST now supports the SKIP subcommand, to skip records at the beginning of a file. For compatibility, DATA LIST now treats N format as F format for FREE and LIST format input. * The SAVE and XSAVE commands now support the UNSELECTED, PERMISSIONS, NAMES, and MAP subcommands. * The EXPORT command has been re-implemented to obtain better results. Support for the UNSELECTED, DIGITS, and TYPE subcommands has been added. * For compatibility, PRINT now inserts a space at the beginning of every output line, even lines that would otherwise be blank, when OUTFILE is specified. (The behavior of WRITE is unchanged.) * For compatibility, PRINT EJECT now inserts the digit `1' at the beginning of each line that should begin a new page. * For compatibility, WRITE now outputs the system-missing value as a field filled with spaces. Binary formats are an exception. (The behavior of PRINT is unchanged.) Documentation: * Input and output format descriptions have been rewritten. They now precisely describe what is accepted on input and written on output. * The descriptions of the PSPP system and portable file formats have been extensively revised and improved. For developers, the build system now requires Autoconf 2.60 and Automake 1.10. Changes from 0.3.0 to 0.4.0: Changes in build dependencies: * The GNU Scientific Library (libgsl), version 1.6 or later, is now required. * libplot from GNU plotutils is optional. Without it, the new graphing features will not work. If you do not have it installed, you must run `configure' with --without-libplot. * libgmp2 is no longer a dependency. Newly implemented commands and statistical features: * EXAMINE, including its graphing features. * FREQUENCIES now supports percentiles. * ONEWAY. * PERMISSIONS. * SHOW. * SORT CASES now sorts stably, that is, two cases with equal sort criteria will be in the same relative order before and after the sort. * T-TEST (re-written). * DATE and USE. These commands are parsed but otherwise ignored, to enhance compatibility with certain command files that invoke them unnecessarily. * VARIABLE WIDTH, VARIABLE ALIGNMENT, and VARIABLE LEVEL. These currently have no effect on PSPP output, but their values are written to and read from system files and thus may affect third-party software. * SET EPOCH implemented. * DATA LIST FREE and DATA LIST LIST now support arbitrary field delimiters. * FILE HANDLE now supports custom tab widths. Long variable names (and other identifiers) are now supported. Up to the first 64 bytes of each identifier is significant. PSPP now reads and writes system files compatible with SPSS version 12. New --algorithm and --syntax command line options allow SPSS-compatible or enhanced modes to be selected. Support for transformation expressions has been rewritten and significantly improved. Refer to the manual for details. Calculation of moments (mean, standard deviation, kurtosis, skewness) has been rewritten and should now be more accurate. In --algorithm=enhanced mode moments may be more accurate than SPSS in some cases. Numerous bugs have been fixed, too many to mention here. Many new tests have been added, leading to the discovery and fixing of many of these bugs. The ASCII output driver can now squeeze multiple blank lines into single blank lines. Much of the code has been rewritten and refactored. It is now much cleaner. The FILE TYPE and REPEATING DATA commands have been disabled for this release because their implementations were deemed too buggy to be useful. They will be fixed and replaced in a future release. New pspp-mode for Emacs (in pspp-mode.el). Added rudimentary command-line completion for interactive input. lib/julcal and lib/dcdflib are no longer used, so they have been removed. For developers, the build system now requires Autoconf 2.58 and Automake 1.7. The included gettext has been updated to version 0.12.1. Some reports state that Texinfo 4.8, the latest version, may be necessary to successfully format the documentation on some systems. Version 0.3.0 changes since 0.2.3: Bugs fixed: * Using alphanumeric variables in functions under AGGREGATE segfaulted. Fixed. * Under certain circumstances, the final case would be omitted from the results of an AGGREGATE operation. Fixed. * Undefined behavior was invoked by referencing a freed pointer under certain circumstances. Fixed. * A wrong record size was displayed when paging the active file to disk. Fixed. * Not having enough temporary space for sorting caused a core dump. Fixed. * Syntax errors in function descriptions on AGGREGATE caused core dumps. Fixed. * A null pointer was dereferenced, causing a core dump, when PERCENTILES was specified on FREQUENCIES. This fixes the problem, but PSPP still doesn't calculate percentiles. * SORT always sorted in ascending order. Fixed. * Some minor memory leaks in the expression parser were removed. * Many assertions fixed for strict ANSI C compliance. New features: * SET ECHO ON now implemented, but turned off by default. * PRINT specifier supported on END REPEAT. Other: * System libgmp2 library is used if installed instead of unconditionally using the included libgmp2 subset. * Extensive code cleanup, which continues. * Added CORRELATIONS command parser, but not implemented. Version 0.2.3 changes since 0.2.2: Bugs fixed: * SPLIT FILE with a string variable caused a core dump. Fixed. * Nested INCLUDEs didn't work. Fixed. * The MATCH FILES procedure set the values of variables not present to 0. It should have been SYSMIS. This is now fixed. * The REMARK command was too aggressive about skipping lines. It didn't like being the last command in a file. * Comment parsing wasn't consistent with the rest of the code in its idea of where one command ends and another starts. This meant that sometimes commands would be mysteriously ignored. Thanks to Dr. Dirk Melcher for reporting this bug. * The TABLE subcommand on MATCH FILES worked only erratically at best. This fixes it. Thanks to Dr. Dirk Melcher for reporting this bug. * VARIABLE LABELS rejected a slash before the first variable specification, contradicting the documentation. Thanks to Walter M. Gray for reporting this bug. * Because of an incorrect optimization in memory allocation, CROSSTABS sometimes segfaulted when asked to output multiple tables. Thanks to Walter M. Gray for reporting this bug. * CROSSTABS didn't display value labels for column and row variables. Thanks to Walter M. Gray for reporting this bug. * WRITE didn't write line ends. Fixed. Thanks to Dr. Dirk Melcher for reporting this bug. * The TABLE subcommand on MATCH FILES worked only erratically at best. This fixes it. Thanks to Dr. Dirk Melcher for reporting this bug. * VARIABLE LABELS rejected a slash before the first variable specification, contradicting the documentation. Thanks to Walter M. Gray for reporting this bug. * Because of an incorrect optimization in memory allocation, CROSSTABS sometimes segfaulted when asked to output multiple tables. Thanks to Walter M. Gray for reporting this bug. * CROSSTABS didn't display value labels for column and row variables. Thanks to Walter M. Gray for reporting this bug. * WRITE didn't write line ends. Fixed. Thanks to Dr. Dirk Melcher for reporting this bug. * MATCH FILES corrupted memory and dumped core on some syntax errors. Fixed. * MATCH FILES should set numeric values not available to the system-missing value, not to 0. Thanks to Dr. Dirk Melcher for reporting this bug. * KEEP didn't work properly on the SAVE procedure. Fixed. Thanks to Ralf Geschke for reporting this bug. * Memory leak fix. * Some systems didn't like the way open_file was coded. Thanks to Hankin for pointing this out. * The SAVE procedure didn't save long string variables properly. Fixed by this patch. Thanks to Hankin for this patch. * Minor documentation fixes for MATCH FILES. Version 0.2.2 changes since 0.2.1: Bugs fixed: * Fix behavior of PRINT SPACE for negative arguments. * Fix reading some unusual system files. * Fix LIST problems with very long variables. Thanks to Hankin for this bug report. * Fix problems with some string format specifiers. * Fix use of $CASENUM in expressions. Thanks to Dirk Melcher for reporting this bug. * Additional DATA LIST FREE and DATA LIST LIST fixes. Thanks to Hankin again on this one. * Sometimes you may encounter a PSPP script that has to be interpreted in interactive mode. Now you can use the -i flag to do this. * Warnings for egcs 1.1.1 cleaned up. (However you'll get lots of `unused variable' warnings under gcc 2.7.2.3, fixing this will take more effort.) * Tests fixed. * The files in gmp need the internationalization directory in their include path. Thanks to OKUJI Yoshinori for pointing this out. Version 0.2.1 changes since 0.2.0: Bugs fixed: * Remember to include examples/ directory in distribution :-) * Fixed gmp compile problems for some non-i386 architectures. Thanks to Hans Olav Eggestad and others for reporting this. * DATA LIST FREE and DATA LIST LIST parsing of input files is now matches the documented behavior exactly, and error messages are more helpful. Thanks to Mark H. Wood . Version 0.2.0 changes since 0.1.0: Procedures now implemented: * CROSSTABS. Please see documentation for caveats. Transformations and utilities now implemented: * AGGREGATE * APPLY DICTIONARY * CLEAR TRANSFORMATIONS * DISPLAY (all subcommands). * ERASE * FLIP * EXPORT * HOST * IMPORT * MATCH FILES * MATRIX DATA * NEW FILE * REPEATING DATA Support for input and output through pipes: "|command" and "command|" filenames; support for special filenames "-", "stdin", "stdout", "stderr". New command-line features: * New option --testing-mode: Invoke heuristics to assist testing. * New option --safer, -s: Don't allow certain unsafe operations. * New option --command=CMD, -c CMD: Perform literal command CMD. * rc file ~/.pspp/rc is executed before any other files. * Now multiple syntax files can be specified. Operator LAG is now implemented. Added missing FILE subcommand to REREAD. Table output manager completely rewritten. Device configuration file syntax changed. You will need to reinstall your `devices' file. New output driver for HTML. PostScript driver and prologue simplified. Many bugs fixed. General source-code cleanup. Added Texinfo documentation for: * PSPP system file format * PSPP portable file format * How to write input for q2c parser generator * HTML driver PSPP language is now fully documented. Please report any inaccuracies or omissions in the documentation. Changes for version 0.1.0: First public release. For changes from unreleased development versions, please see ONEWS. ---------------------------------------------------------------------- Copyright information: Permission is granted to anyone to make or distribute verbatim copies of this document as received, in any medium, provided that the copyright notice and this permission notice are preserved, thus giving the recipient permission to redistribute in turn. Permission is granted to distribute modified versions of this document, or of portions of it, under the above conditions, provided also that they carry prominent notices stating who last changed them. Local variables: version-control: never mode: indented-text end: pspp-master/OChangeLog000066400000000000000000001756061177044323000152420ustar00rootroot000000000000002008-06-13 Ben Pfaff * configure.ac: Fix typo in AC_PREREQ command name. Thanks to Stepan Kasal for reporting the problem. 2008-06-04 Ben Pfaff * configure.ac: Update version number to 0.6.0 in preparation for release. 2008-05-15 Ben Pfaff * Smake (GNULIB_MODULES): Don't depend on memmem module, because PSPP does not use memmem any longer. Use unilbrk/ulc-width-linebreaks module instead of the linebreak module, because the latter was split up into multiple modules and that's the one we actually need. 2008-05-09 John Darrington * INSTALL: For obscure reasons gettext 0.17 requires that the string 'GNU pspp' occurs in some file in the root directory. Otherwise make distcheck fails with a very non-intuitive error message. So for want of somewhere better I added it in INSTALL. But since this string now appears in this ChangeLog file, it could be taken out of INSTALL ... 2008-04-19 John Darrington * configure.ac : Improve checking of ncurses availability. 2008-04-15 Ben Pfaff * configure.ac: Properly report required version of libglade. Thanks to unknown-1 for reporting this bug. 2008-04-15 John Darrington * configure.ac : Replace AC_CHECK_LIB with AC_SEARCH_LIBS as recommended by latest autoconf manual. 2008-02-19 John Darrington * configure.ac INSTALL: We now depend on GTK+ 2.12 2007-12-11 John Darrington * t-test-independent-samples-dialog.c: Quoted the group values, when the group variable is a string variable. 2007-12-04 Ben Pfaff * Smake (GNULIB_MODULES): Add ftello module. 2007-11-05 Ben Pfaff * configure.ac: No need for check for off_t or for the size of float or long double any longer, as we don't use the results anymore. Also, no need to put #include into config.h any longer, as this was only needed for --with-included-gettext, which we have not supported for some time. 2007-11-03 Ben Pfaff Allow output files to overwrite input files (bug #21280). * Smake (GNULIB_MODULES): Add fatal-signal, tempname modules. 2007-11-02 Ben Pfaff * Smake (GNULIB_MODULES): Add isfinite, round modules. 2007-10-12 Ben Pfaff Use trunc module from gnulib instead of our home-grown solution. Patch #6224. * Smake: Add trunc to module list. * configure.ac: Don't need to check for trunc function any longer. 2007-10-12 Ben Pfaff Use fseeko module from gnulib instead of our home-grown solution. Patch #6228. * acinclude.m4: Delete PSPP_OFF_T macro. * configure.ac: Don't call AC_FUNC_FSEEKO or PSPP_OFF_T. 2007-10-12 Ben Pfaff * Smake: Add fprintf-posix, printf-posix, printf-safe, snprintf-posix, sprintf-posix, vasprintf-posxi, vfprintf-posix, vprintf-posix, vsnprintf-posix, and vsprintf-posix modules, which allow us to use C99 format specifiers (e.g. 'z') in *printf. Also, changed many formerly casted arguments in *printf calls to use one of these format specifiers and drop the cast. 2007-10-11 Ben Pfaff * Smake: Drop alloca, alloca-opt modules as we don't use them anymore. 2007-10-10 Ben Pfaff * acinclude.m4: Improve formatting. * configure.ac: Ditto. Don't check for headers whose presence is never tested. Don't use AC_C_CONST (we can assume that "const" is implemented these days). Don't pass default sizes to AC_CHECK_SIZEOF, since modern Autoconf doesn't need them. Don't define FPREP_IEEE754, since it was not tested for. Don't use AC_FUNC_VPRINTF, since we never tested for it. 2007-10-06 John Darrington * configure.ac INSTALL: Change libglade version requirement. Thanks to Paul Brown for reporting this issue. 2007-09-30 Ben Pfaff * configure.ac: Print a message indicating success at the end of the run. * INSTALL: Improve instructions. 2007-09-22 Ben Pfaff Bug #21128. Reviewed by John Darrington. * acinclude.m4 (PSPP_LC_PAPER): New macro. * configure.ac: Use PSPP_LC_PAPER. 2007-08-05 Ben Pfaff Bug #16189. Reviewed by Jason Stover. * acinclude.m4: If -lplot doesn't work by itself, also test with typical X11 libraries. 2007-07-27 Ben Pfaff Bug #19069. * INSTALL: Improve installation instructions. * README: Move prerequisites to INSTALL. Reviewed by Jason Stover. * configure.ac: Make PKG_CHECK_MODULES tests more user-friendly, by having them give their errors at the end of the configuration process instead of stopping it in the middle. Patch #6116. Reviewed by Jason Stover. 2007-06-14 Ben Pfaff * Smake: Use xmalloca instead of xallocsa due to module renaming. Update all uses. 2007-06-06 Ben Pfaff * Smake: Add xallocsa to modules. 2007-04-22 Ben Pfaff Implement model checker for testing purposes. Patch #5873. * Smake (GNULIB_MODULES): Add crypto/md4, fwriteerror, gettimeofday. 2007-04-03 Ben Pfaff * configure.ac: Increment version to 0.4.3 due to snapshot posted to alpha.gnu.org. Suggested by John Darrington. 2007-04-03 Ben Pfaff Use Gnulib's fpieee module instead of specifying -mieee by hand. * Smake: Use fpieee module from Gnulib. * configure.ac: Don't enable -mieee. 2007-03-19 Ben Pfaff Work toward modernizing the build system by updating our Automake and Autoconf dependencies and requiring libintl to be available externally (if desired) instead of including a copy in the distribution. * Makefile.am (AUTOMAKE_OPTIONS): Require Automake 1.10 (or later), which works better with systems that have a non-empty $(EXEEXT). (SUBDIRS): Drop intl. (DISTCLEANFILES): Drop intl/plural.c. * Throughout Makefile.am and the automake.mk files: Change mkinstalldirs to $(MKDIR_P), to support the corresponding Automake change. * Smake (GNULIB_MODULES): Use gettext-h instead of gettext module. (all): Don't create intl directory. (gettextize): Don't use --intl flag. * configure.ac: Require Autoconf 2.60 or later. Use external gettext. Drop intl/Makefile from config files. 2007-02-25 Ben Pfaff Thanks to Jason Stover for verifying that this patch helps under NetBSD. * acinclude.m4: Rename PSPP_ENABLE_WARNING to PSPP_ENABLE_OPTION, because it's useful for more than warnings. * configure.ac: Add PSPP_ENABLE_OPTION(-mieee) to improve IEEE floating-point conformance on Alpha and SH architectures. Also, check for fpsetmask function (available on BSDs). Mon Feb 19 10:52:21 2007 Ben Pfaff * Smake (GNULIB_MODULES): Add dirname module, remove canonicalize module. Corresponds to changes in src/data/file-name.c. Sat Feb 17 09:22:32 2007 Ben Pfaff * Smake (GNULIB_MODULES): Add tmpfile module, which fixes the use of the tmpfile function under Windows. Fri Feb 16 10:50:38 2007 Ben Pfaff Better support cross-compiling by using CC_FOR_BUILD and EXEEXT_FOR_BUILD for q2c. * Makefile.am: Add CC_FOR_BUILD, EXEEXT_FOR_BUILD variables. Use in .q.c rule. * acinclude.m4: Add PSPP_CC_FOR_BUILD macro. * configure.ac: Call PSPP_CC_FOR_BUILD. Mon Feb 12 16:39:18 2007 Ben Pfaff * README: Note that iconv is required. * configure.ac: Enforce iconv requirement. Thu Feb 8 14:56:18 2007 Ben Pfaff Reduce platform dependence. * Makefile.am: Don't add -Dunix or -D__MSDOS__ to compiler command line. Add $(top_builddir)/intl to include path to fix building with the included libintl. * Smake (GNULIB_MODULES): Add `canonicalize', `sys_stat', `mkstemp' modules. Remove `stat-macros' module, which is no longer what we want, because what we want is provided by sys_stat now, and remove its inclusions. Remove `strstr' module, which is no longer in gnulib. Remove `readlink', `xreadlink', because we no longer use either function. * configure.ac: Move gl_EARLY before AC_PROG_CC, where the gnulib manual says it should be. Check for presence of execl, fork, and popen. Drop check for unix versus msdos as host OS. Sat Nov 4 15:59:31 2006 Ben Pfaff * configure.ac: Check for the "round" function added in C99. Tue Oct 31 19:55:52 2006 Ben Pfaff * Smake (GNULIB_MODULES): Add `mempcpy' module. Tue Oct 31 19:29:05 2006 Ben Pfaff * configure.ac: Drop tests for strchr, strrchr because now we assume a C89 compliant library. (Gnulib makes this assumption so we might as well too.) Sun Oct 29 14:08:53 2006 Ben Pfaff * Smake (GNULIB_MODULES): Remove `restrict' from modules, because recent gnulib doesn't have such a module. Mon Jul 17 18:23:38 2006 Ben Pfaff * Smake: Add --doc-base=gl/doc to gnulib-tool invocation, which is required by recent gnulib. Sun Jul 16 19:51:45 2006 Ben Pfaff * Smake: Add xsize to GNULIB_MODULES. Wed Jul 12 13:41:18 2006 Ben Pfaff * Makefile.am: Add check_PROGRAMS and define to empty. Sat Jul 1 15:32:31 2006 Ben Pfaff * Makefile.am: Add noinst_PROGRAMS and define to empty. Tue May 9 20:46:06 2006 Ben Pfaff * Smake: Add stdarg to GNULIB_MODULES. Sun May 7 09:27:40 WST 2006 John Darrington * po/en_GB.po : Removed. Now that messages talking about coloUrs have been removed, it does nothing. Tue May 2 10:43:30 WST 2006 John Darrington * Bumped the minor version number from 0.4.1 to 0.4.2 to reflect changes to system file format. Mon Apr 24 14:12:25 2006 Ben Pfaff * Smake: Add exit to GNULIB_MODULES. Sun Apr 23 20:34:50 2006 Ben Pfaff * Smake: Add linebreak to GNULIB_MODULES. Sat Apr 15 21:45:40 2006 Ben Pfaff Get rid of src/libpspp/debug-print.h and all its uses. (There were few real users, but many inclusions of its header file.) Sat Apr 15 19:51:22 2006 Ben Pfaff Get rid of our own int32 type in favor of the standard int32_t type. * configure.ac: Don't need to check the sizes of integer types anymore. Sat Apr 15 19:13:59 2006 Ben Pfaff * configure.ac, acinclude.m4: Complain about missing prerequisites in a group at the end of configuration, not piecemeal. This should make building PSPP less frustrating. Thanks to John Darrington for the suggestion. Sat Apr 15 18:17:15 2006 Ben Pfaff * configure.ac: Move code into acinclude.m4 to make the configure script more readable. * acinclude.m4: New functions from configure.ac. Mon Apr 3 11:01:00 2006 Ben Pfaff * Smake: (GNULIB_MODULES) Add strsep. Thu Mar 30 15:50:05 2006 Ben Pfaff * Smake: Enable -Wdeclaration-after-statement warning if available. * acinclude.m4: Add macro for checking whether a warning is supported. Mon Mar 20 16:32:11 2006 Ben Pfaff * Smake: Require "unistd" gnulib module. Removed tests for HAVE_UNISTD_H from source code. Sat Mar 4 13:20:56 2006 Ben Pfaff * configure.ac: Get rid of pref.h.orig. * pref.h.orig: Removed. Moved SHORT_NAME_LEN, LONG_NAME_LEN to src/data/variable.h. Removed GLOBAL_DEBUGGING entirely, changing all references to DEBUGGING. Moved P_tmpdir to src/data/make-file.c. Moved NO_CHARTS to src/output/charts/automake.mk. Sat Mar 4 12:58:34 2006 Ben Pfaff * pref.h.orig: Move GCC attribute declarations to new file src/libpspp/compiler.h. Sat Mar 4 12:27:06 2006 Ben Pfaff * Smake: Require "intprops" gnulib module. * acinclude.m4: Remove BLP_INT_DIGITS. Now we use the intprops.h header file instead. * configure.ac: Don't call BLP_INT_DIGITS. Sat Mar 4 11:53:36 2006 Ben Pfaff * acinclude.m4: Remove BLP_RANDOM. Its results were unused. Remove BLP_IS_SPRINTF_GOOD. We now assume that the system's sprintf() returns the correct value. * configure.ac: Don't call those macros. John Darrington: * Deleted Make.build (inserted its contents into Makefile.am). * Moved the version number to 0.4.1 * Moved lib/linreg/linreg.[ch] and lib/linreg/coefficient.[ch] to src/math/linreg. * Moved the psppire gui into src/ui/gui and the gtk_sheet widget into lib/gtksheet. * Replaced recursive automake system with non-recursive one. * Moved files into subdirectories. See src/ChangeLog for details. Sat Feb 11 21:57:31 2006 Ben Pfaff * Smake: (GNULIB_MODULES) Add memcasecmp. * configure.ac: Remove existing checks for readline, replacing them by a call to PSPP_READLINE. * acinclude.m4: Add PSPP_READLINE macro based on gnulib test for readline. However, we only accept a readline installation if (1) the header files are in the normal readline/ directory and (2) the history library is also available. If both criteria are met, we declare HAVE_READLINE. This reduces the #ifdefs to actually use readline to something manageable. * pref.h.orig: Move DIR_SEPARATOR, PATH_DELIMITER definitions to src/filename.h. Wed Jan 25 21:48:20 2006 Ben Pfaff * Smake: (po/POTFILE.in) Exclude dotfiles. Sat Nov 27 20:29:19 2005 Jason Stover * Binary encoding for categorical variables. * Routines for design matrices. Thu Oct 20 18:19:58 2005 Ben Pfaff * configure.ac: Improve error messages. Thanks to Jaap-Andre de Hoop . Wed Oct 12 20:33:07 2005 Jason Stover * regression.q: Initial version of the REGRESSION procedure. Sun Sep 25 16:11:09 2005 Ben Pfaff * Makefile.am: Handles `examples' as a subdirectory instead of a dist-hook. The dist-hook copied examples/CVS into the distribution. Thanks to James R. Van Zandt for reporting the problem. Mon Sep 19 10:24:10 2005 Ben Pfaff * Smake: Add `check' target for convenience. Add --tests-base=tests to gnulib-tool invocation to compensate for bug. Sat Sep 17 15:57:32 2005 Jason Stover Added lib/linreg for procedures that use ordinary least squares. Sat Sep 17 11:01:44 2005 Ben Pfaff Adapt to newer versions of gnulib. * Smake: Put gnulib options directly on its command line, instead of embedding them in configure.ac. * configure.ac: Remove gnulib option commands. Fri Aug 3 07:22:28 2005 Ben Pfaff * PSPP 0.4.0 released. Sun Jul 31 10:49:47 2005 Ben Pfaff Adopt use of gnulib for portability. * Makefile.am: Add gl to SUBDIRS. Add gl/m4 to aclocal include path. Get rid of pkgdocdir data. Move noinst_DATA to EXTRA_DIST. * README.CVS: Add instructions for fetching gnulib. * Smake: Rewrite to run gnulib-tool. Avoid use of gettextize in normal case (it was unmaintainable). Just use autoreconf --install to do most of the work. Rewrite rule for POTFILES.in for non-GNU make compatibility. * configure.ac: Add gnulib commands. Specify gettext version 0.14.5 to placate autopoint. Check that off_t is an integer type, because Solaris can sometimes declare it as a struct. Drop explicit checks for gnulib-supported functionality. Fix typo in msdos check. * pref.h.orig: Define __attribute__ to avoid wart in gnulib. Don't #include and define gettext, _, N_, because gnulib wants to do the same thing. Sun Jul 24 20:31:13 2005 Ben Pfaff * configure.ac: Don't detect libgmp anymore, because we eliminated the dependency. * NEWS: Update. Mon Jul 4 17:59:54 2005 Ben Pfaff * Makefile.am: Add pspp-mode.el to EXTRA_DIST. Wed May 4 08:49:13 WST 2005 John Darrington * README.CVS Smake: Added a CONFIGUREFLAGS variable. * INSTALL: Mentioned build dependencies. Mon May 2 22:37:39 2005 Ben Pfaff * INSTALL: Mention dependencies. Thanks to Jaap-Andre de Hoop for the suggestion. * NEWS, README: Update. Sun May 1 15:00:09 WST 2005 John Darrington * pspp-mode.el: Now supports syntax highlighting, indentation and generally works a lot better. Thu Apr 28 10:24:47 WST 2005 John Darrington * Changed all copyright notices to contain the FSF's new address. Thu Apr 14 2005 John Darrington * AUTHORS: Added note about the long variable names extension. * pref.h.orig: Added definitions for variable names lengths. Thu Mar 3 22:06:19 WST 2005 John Darrington * configure.ac: Added AC_PROG_RANLIB --- needed by autoconf 1.9 Mon Feb 28 23:16:58 2005 Ben Pfaff * configure.ac: Check for perl. Check for bool. Substitute makefiles in src/expressions. Don't substitute makefile in deleted directory lib/julcal. * pref.h.orig: (macro MALLOC_LIKE) New macro. (macro flt64) Moved to src/sfmP.h. (macro FLT64_MAX) Moved to src/sfmP.h. Mon Feb 21 15:04:55 WST 2005 John Darrington * configure.ac: Added a --without-valgrind option to cope with building on machines with a broken valgrind installation Fri Jan 7 08:01:02 WST 2005 John Darrington * configure.ac pref.h.orig: Compilation with libplot is now optional by sacrificing the chart features. Sun Nov 28 19:24:02 2004 Ben Pfaff * Smake: Change -a to -pR in cp invocations for SUSv3 compliance. Mon May 31 17:21:25 2004 Ben Pfaff * configure.ac: Check for large file support. Get rid of posix_fadvise check--for some reason glibc 2.3.2 segfaults when I call it and I just couldn't figure out what was going on. Sun May 30 18:19:03 2004 Ben Pfaff * configure.ac: Check for valgrind/valgrind.h. Mon Mar 29 15:22:48 2004 Ben Pfaff * TODO: Updated. * configure.ac: Check for posix_fadvise. Tue Mar 23 14:21:12 WAST 2004 John Darrington * Removed dcdflib and replaced with a dependency upon the GNU Scientific library instead. Sat Mar 20 13:55:36 2004 Ben Pfaff * TODO: Updated. Wed Feb 11 23:54:15 2004 Ben Pfaff * pref.h.orig: Don't meddle with __WIN32__, __MSDOS, __DJGPP__, __CYGWIN32__, __unix__, or unix anymore, and deal with some of the consequences. Declare ATTRIBUTE instead of meddling withe __attribute__. Declare UNUSED instead of unused. Add macros NO_RETURN, PRINTF_FORMAT, SCANF_FORMAT. Reformat gettext, N_, _ macros. Move alloca()-related stuff to src/alloc.h and simplify. Get rid of PAGED_STACK entirely. Remove mkdir macro definition. Get rid of obsolete "procedure-specific options". 2004-01-23 gettextize * Makefile.am (SUBDIRS): Remove intl. * configure.ac (AC_CONFIG_FILES): Remove intl/Makefile. Tue Dec 30 22:23:40 WST 2003 John Darrington * Fixed floating point rounding bug in percentiles calculation Sat Dec 27 16:16:49 2003 Ben Pfaff * configure.ac: Add -Wmissing-prototypes flag to gcc. * TODO: Updated. Wed Dec 17 12:19:40 WAST 2003 John Darrington * Added an --enable-debug flag to configure 2003-12-13 gettextize * Makefile.am (EXTRA_DIST): Add mkinstalldirs. * configure.ac (AC_CONFIG_FILES): Add intl/Makefile. Thu Dec 11 19:35:32 WST 2003 John Darrington * Removed autogenerated files from the CVS archive * removed the included getopt.c as it failed to build under some systems. Thu Dec 11 00:12:19 2003 Ben Pfaff * Update build system to Autoconf 2.58, Automake 1.7, gettext 0.12.1. 2003-12-08 gettextize * Makefile.am (SUBDIRS): Add m4. (ACLOCAL_AMFLAGS): New variable. (EXTRA_DIST): Add config.rpath. * configure.in (AC_CONFIG_FILES): Add po/Makefile.in, Sun Jan 2 21:24:32 2000 Ben Pfaff * Makefile.am: Require Automake 1.4 or later. It's been out for almost a year now, so why haven't you installed it? :-) * TODO: Updated. * configure.in: Updated version number. Check for libgmp. Check of fenv.h. Check for feholdexpect(). * pref.h.orig: Don't include debug-print.h by default. Don't disable __attribute ((unused))__ for gcc 2.7.2. Remove LOAD_2, STORE_2. Comment fixes. * Updated copyright notices in all files. Fri Mar 12 12:38:55 1999 Ben Pfaff * Forked 0.3.0. Tue Mar 9 12:46:31 1999 Ben Pfaff * Released 0.2.3. * TODO: Updated. Tue Jan 5 15:18:07 1999 Ben Pfaff * Released 0.2.2. * TODO: Update from Zvi Grauer . Thu Nov 19 12:34:55 1998 Ben Pfaff * Released 0.2.1. Sun Aug 9 11:11:32 1998 Ben Pfaff * LANGUAGE: Updated. Sat Aug 8 00:19:08 1998 Ben Pfaff * LANGUAGE: Updated. * examples/: New directory. * Made patchlevel 95. Tue Aug 4 23:47:31 1998 Ben Pfaff * Bump version to 0.1.22 (0.2.0 release candidate). * configure.in: Remove --enable-Werror, new option --enable-debugging. New gcc option -Wpointer-arith. * pref.h.orig: Don't enable debugging by default (now a configure option). Use __inline__ instead of inline with gcc (partial -ansi -pedantic support). (macro local_strdup) Removed. * Made patchlevel 94. Wed Jul 29 22:03:11 1998 Ben Pfaff * Bump version to 0.1.21 (0.2.0 release candidate). * debian/: Removed. * Makefile.am: Don't copy debian/ into distribution. * pref.h.orig: Only enable `unused' attribute if gcc 2.8.0 or later is used. Sun Jul 5 14:20:04 1998 Ben Pfaff * configure.in: Bump version to 0.1.20 (0.2.0 release candidate). * Made patchlevel 93. Sun Jul 5 00:13:58 1998 Ben Pfaff * README: Updated. * TODO: Updated. * configure.in: Remove -Wno-unused from default gcc flags. * pref.h.orig: Add new #define, `unused', which under gcc expands to an explanation to the compiler that a function argument is unused, and expands to the null string under other compilers. Mon Jun 1 14:33:02 1998 Ben Pfaff * LANGUAGE: Updated. * configure.in: Bump version to 0.1.19. * Made patchlevel 92. Sun May 31 00:55:13 1998 Ben Pfaff * TODO: Updated. * configure.in: Generate Makefiles for lib/gmp/{,mpn,mpf}/. * Made patchlevel 91. Fri May 29 21:43:09 1998 Ben Pfaff * TODO: Updated. * LANGUAGE: Updated. * unconfigure: Remove TeX cruft from doc/. * Made patchlevel 90. Mon May 25 12:41:54 1998 Ben Pfaff * BUGS: Updated. * LANGUAGE: Updated. * TODO: Updated. * configure.in: Bumped version number up to 0.1.18. * Made patchlevel 89. Sun May 24 22:39:55 1998 Ben Pfaff * TODO: Updated. * Made patchlevel 88. Sat May 23 23:21:43 1998 Ben Pfaff * TODO: Updated. * configure.in: Remove gamma from replaceable functions. * Made patchlevel 87. Fri May 22 00:02:33 1998 Ben Pfaff * configure.in: Add gamma to list of functions with replacements. * Made patchlevel 86. Wed May 20 00:00:12 1998 Ben Pfaff * TODO: Updated. * Made patchlevel 85. Sat May 16 19:38:49 1998 Ben Pfaff * TODO: Updated. * Made patchlevel 84. Tue May 12 16:13:48 1998 Ben Pfaff * TODO: Updated. * unconfigure: Don't delete Makefile.in under intl/. * Made patchlevel 83. Thu May 7 23:16:26 1998 Ben Pfaff * unconfigure: Add some more files to reap. * Made patchlevel 82. Tue May 5 13:17:59 1998 Ben Pfaff * acconfig.h: Add HAVE_GOOD_RANDOM definition. * acinclude.m4: New macro BLP_RANDOM. * configure.in: Use new BLP_RANDOM macro. * unconfigure: New file. * Made patchlevel 81. Fri Apr 24 12:42:14 1998 Ben Pfaff * Makefile.am: Remove bad comment. * AUTHORS: Removed Brad Appleton. * TODO: Updated. * configure.in: Remove `satisfy automake' bit. Don't generate avllib Makefile, since we don't use avllib anymore. * pref.h.orig: Define PSPP. * Made patchlevel 80. Wed Apr 15 12:59:39 1998 Ben Pfaff * AUTHORS, BUGS, LANGUAGE, README, THANKS: No longer generated from HTML. This caused a lot of deletions from the Makefile.am. * TODO: Updated. * Made patchlevel 79. Tue Apr 14 00:48:00 1998 Ben Pfaff * TODO: Updated. * configure.in: Check for unistd.h. Fix AC_LN_S (should have been AC_PROG_LN_S). * Made patchlevel 78. Must have missed 77 in there somewhere :-) Mon Mar 9 15:40:40 1998 Ben Pfaff * Made patchlevel 76. * configure.in: Bumped version up to 0.1.16. 1998-03-05 Ben Pfaff * configure.in: Bumped version up to 0.1.15. 1998-02-23 Ben Pfaff * acinclude.m4: Add BLP_INT_DIGITS and BLP_IS_SPRINTF_GOOD macros. * configure.in: Those macros came from here. Better modularity this way. Bump version up to 0.1.14. * pref.h.orig: (macros CONFIG_PATH, INCLUDE_PATH, GROFF_FONT_PATH) Removed. * Made patchlevel 75. 1998-02-23 Ben Pfaff * acconfig.h: Hard-code PACKAGE and GNU_PACKAGE as "PSPP" and "GNU PSPP" respectively. * configure.in: Call the package pspp instead of PSPP. Don't define PACKAGE and GNU_PACKAGE symbols. Add replacement function for strtok_r. * TODO: Updated. * Made patchlevel 74. 1998-02-16 Ben Pfaff * Makefile.am: Remove a few now-useless targets. * TODO: Updated. * configure.in: Bump version up to 0.1.13. * reconfigure: Don't assume . is in PATH. * Made patchlevel 73. Fri Feb 13 15:35:03 1998 Ben Pfaff * configure.in: Bump version up to 0.1.12. * TODO: Updated. * pref.h.orig: Make __unix equivalent to unix and __unix__; don't require any of these to be defined to 1, just defined. Invert sense of some tests from testing for unix to testing for not being msdog. * Made patchlevel 72. Thu Feb 5 00:22:58 1998 Ben Pfaff * Made patchlevel 71. * configure.in: Bump version up to 0.1.11. Tue Feb 3 16:12:34 1998 Ben Pfaff * TODO: Updated. * Made patchlevel 70. * configure.in: Bump version up to 0.1.10. Fri Jan 23 00:17:18 1998 Ben Pfaff * Made patchlevel 69. Thu Jan 22 00:35:52 1998 Ben Pfaff * Made patchlevel 68. Sun Jan 18 00:30:18 1998 Ben Pfaff * configure.in: Add ieeefp.h to list of headers to check for. * Made patchlevel 67. Tue Jan 13 23:44:16 1998 Ben Pfaff * configure.in: Add sys/wait.h to list of headers to check for. * Made patchlevel 66. Sun Jan 11 21:30:09 1998 Ben Pfaff * configure.in: Bump version up to 0.1.9. * pref.h.orig (STORE_2): Fix parentheses. From Alexandre Oliva . * Made patchlevel 65. Sat Jan 10 23:59:06 1998 Ben Pfaff * Made patchlevel 64. Sat Jan 10 02:10:15 1998 Ben Pfaff * TODO: Updated. * pref.h.orig: Comment fixes. (macro second_lowest_flt64) New. * Made patchlevel 63. Thu Jan 8 22:27:03 1998 Ben Pfaff * TODO: Updated. * Made patchlevel 62. Mon Jan 5 11:18:37 1998 Ben Pfaff * Made patchlevel 61. Sun Jan 4 18:10:29 1998 Ben Pfaff * TODO: Updated. * pref.h.orig: (local_strdup) [HAVE_ALLOCA && PAGED_STACK && __GNUC__] Rewritten for space and time efficiency and to evaluate its argument only once. * Made patchlevel 60. Sat Jan 3 16:51:20 1998 Ben Pfaff * TODO: Updated. * Made patchlevel 59. Fri Jan 2 01:38:37 1998 Ben Pfaff * TODO: Updated. * config.sub: Got tired of `i686-unknown-linux: Unknown system', so I made 686 equivalent to 586. * pref.h.orig: (macros ASCII_*, HTML_*, PS_*) Removed. * Made patchlevel 58. Thu Jan 1 11:50:47 1998 Ben Pfaff * TODO: Updated. * Made patchlevel 57. Fri Dec 26 15:43:17 1997 Ben Pfaff * TODO: Updated. * Made patchlevel 56. Wed Dec 24 22:34:55 1997 Ben Pfaff * reconfigure: regularized option syntax. * configure.in: Bumped version to 0.1.8. Changed name from pspp to PSPP. Added lib/dcdflib/Makefile to list of output files. * Made patchlevel 55. Sun Dec 21 15:58:52 1997 Ben Pfaff * TODO: Updated. * acconfig.h: Reformat. * configure.in: Bumped version to 0.1.7. * Made patchlevel 54. Fri Dec 5 23:38:12 1997 Ben Pfaff * Replaced prep.ai.mit.edu with ftp.gnu.org and .gnu.ai.mit.edu with .gnu.org, everywhere. Fri Dec 5 23:02:40 1997 Ben Pfaff * Replaced remaining instances of Fiasco with PSPP. * Made patchlevel 53. Fri Dec 5 22:51:18 1997 Ben Pfaff * Every instance of the name Fiasco, throughout every file, replaced in-place with PSPP, with the exceptions of a few files that had `fiasco' in their names; these were renamed. * Made patchlevel 52. Fri Dec 5 21:50:52 1997 Ben Pfaff * pref.h.orig: (macros NO_HTML, HTML_DEFAULT_OUTPUT_FILE) New macros. * TODO: Updated. * Made patchlevel 51. Tue Dec 2 14:35:12 1997 Ben Pfaff * TODO: Updated. * configure.in: Bumped version to 0.1.6. * Made patchlevel 50. Sat Nov 22 01:20:32 1997 Ben Pfaff * Made patchlevel 49. Fri Nov 21 00:11:41 1997 Ben Pfaff * Made patchlevel 48. Sun Nov 16 01:31:38 1997 Ben Pfaff * Made patchlevel 47. Fri Nov 14 00:17:48 1997 Ben Pfaff * Made patchlevel 46. * configure.in: Bumped version to 0.1.5. Tue Oct 28 16:07:17 1997 Ben Pfaff * configure.in: Bumped version to 0.1.4. * TODO: Updated. * Made patchlevel 45. Wed Oct 8 15:55:50 1997 Ben Pfaff * intl: Upgraded from sources to gettext-0.10.32. * configure.in: Bumped version to 0.1.3. * Made patchlevel 44. Tue Oct 7 20:21:53 1997 Ben Pfaff * Makefile.am: (dist-hook) Use $(top_srcdir). * pref.h.orig: (MAX_WORKSPACE) Enlarge to 4 MB (from 1 MB). * Made patchlevel 43. Sun Oct 5 15:52:37 1997 Ben Pfaff * configure.in: Bumped version to 0.1.2. (strerror) Replace instead of check. From Alexandre Oliva . * pref.h.orig: Include `debug-print' instead of `src/debug-print.h'. * Made patchlevel 42. Sat Oct 4 16:19:44 1997 Ben Pfaff * pref.h.orig: Comment fixes. (local_strdup) [HAVE_ALLOCA && PAGED_STACK && __GNUC__] Use local_alloc() instead of alloca(), as local_alloc() isn't simply an alias for alloca(). * configure.in: Bumped version to 0.1.1. * Made patchlevel 41. Sat Oct 4 02:13:00 1997 Ben Pfaff * Made patchlevel 40. Sun Sep 21 00:07:09 1997 Ben Pfaff * Made patchlevel 39. Thu Sep 18 21:42:27 1997 Ben Pfaff * pref.h.orig: (CONFIG_PATH) [unix] Add /usr/local/etc/fiasco, /usr/etc/fiasco to search path. * Made patchlevel 38. Wed Aug 20 14:20:06 1997 Ben Pfaff * Makefile.am: (noinst_DATA) Removed ANNOUNCE, HELP-WANTED. (EXTRA_DIST) Removed ANNOUNCE, FAQ, HELP-WANTED, mk-web-dist. (MAINTAINERCLEANFILES) Removed ANNOUNCE, FAQ, HELP-WANTED. * Made patchlevel 37. Wed Aug 20 12:48:25 1997 Ben Pfaff * Makefile.am: (doc/ANNOUNCE.html, ANNOUNCE, FAQ, doc/FAQ.html, HELP-WANTED) Removed. (docfiles) Removed ANNOUNCE, FAQ, HELP-WANTED. * mk-web-dist: Removed. * Made patchlevel 36. Mon Aug 18 18:06:12 1997 Ben Pfaff * TODO: Updated. * pref.h.orig: (macro DEFAULT_COMPAT) Removed. * Made patchlevel 35. Sun Aug 17 22:48:36 1997 Ben Pfaff * Made patchlevel 34. Sat Aug 16 10:48:29 1997 Ben Pfaff * In many files, in this directory and others, messages were rephrased to eliminate or reduce usage of certain deprecated terms at suggestion of rms. * Makefile.am: (EXTRA_DIST) Removed unix2dos.pl. (MAINTAINERCLEANFILES) Removed doc/ANNOUNCE.html, doc/README.html. (docfiles-recursive) Removed. * TODO: Updated. * mk-web-dist: Doesn't produce any distributions at all, just a webpage. Doesn't configure the distribution. Changed list of files installed. * pref.h.orig: s/VER_PCP40/VER_PC/; s/VER_WIN61/VER_WND/; s/VER_X40/VER_X/; All references changed. * Made patchlevel 33. Thu Aug 14 22:02:08 1997 Ben Pfaff * Makefile.am: Comment fixes. Uses $(VERSION) instead of contents of VERSION file. (EXTRA_DIST) Remove fiasco.ide, mk-bc5-dist. (docfiles-recursive) Works if doc/Makefile doesn't exist. (DIST_BC5_ROOT) Renamed DISTBC5_DISTROOT. (DISTBC5_BC5ROOT) New var. (dist-bc5) Passes $(DISTBC5_BC5ROOT). * TODO: Update. * acinclude.m4: Remove blp_VERSION_CHEAT kluge. * configure.in: Don't use blp_VERSION_CHEAT kluge. * mk-web-dist, reconfigure: Extract version number from configure.in. * pref.h.orig: (CONFIG_PATH, INCLUDE_PATH, GROFF_FONT_PATH) [__MSDOS__] Fixed bad use of backslashes. * reconfigure: Pass $VERSION to Makefile. * Made patchlevel 32. Thu Aug 14 11:49:35 1997 Ben Pfaff * Makefile.am: (EXTRA_DIST, docfiles) Add ONEWS. (docfiles) Depends on docfiles-recursive. (docfiles-recursive) New target, call make for `docfiles' target in doc directory. (dist-bc5) Adds `foo' second arg to mk-bc5-dist. (.PHONY) Add docfiles. * mk-bc5-dist: Checks that it is passed a second arg of `foo'. * reconfigure: Changed == operators to = as arguments to `test'. No longer uses bash -v switch. * mk-distribution: Renamed mk-web-dist, all references changed. Now takes several options, added help. No longer uses -uv options. * Made patchlevel 31. Tue Aug 5 13:56:39 1997 Ben Pfaff * Makefile.am: (MAINTAINERCLEANFILES) Add HELP-WANTED. (EXTRA_DIST) Add ONEWS. * Made patchlevel 30. Sun Aug 3 11:30:17 1997 Ben Pfaff * Makefile.am: (noinst_data, docfiles) Added HELP-WANTED. (EXTRA_DIST) Added configure, mk-bc5-dist, unix2dos.pl, HELP-WANTED. (HELP-WANTED) Generated from doc/HELP-WANTED.html. (dist-bc5) New target. * TODO: Updated. * mk-distribution: Fixed bugs, added HELP-WANTED. * reconfigure: When invoking Makefile.am, pass top_srcdir=. explicitly. * unix2dos.pl: New file. * Made patchlevel 29. Thu Jul 17 21:49:13 1997 Ben Pfaff * Made patchlevel 28. Thu Jul 17 01:43:25 1997 Ben Pfaff * Makefile.am: Remove inactive .html suffix rule. New rules to generate doc/ANNOUNCE.html and doc/README.html from corresponding .in files. (EXTRA_DIST) Add VERSION, fiasco.ide, mk-distribution. (MAINTAINERCLEANFILES) Add doc/ANNOUNCE.html, doc/README.html. * acinclude.m4: (blp_VERSION_CHEAT) New macro. * configure.in: Forces _GNU_SOURCES not only to be defined, but to a value of 1. Substitutes VERSION from the new file VERSION. Removed DEBIAN reference. Checks for sys/mman.h header. * pref.h.orig: (macro gettext) Don't put parentheses in the expansion. (macro N_) Same. * reconfigure: Sets -ev in shell. Doesn't try to pass --include-deps to configure (it's an automake flag!). Moved `make docfiles'. * sysdeps/borlandc4.0/README, sysdeps/borlandc4.0/_read.c, sysdeps/borlandc4.0/_write.c, sysdeps/borlandc4.0: Removed. * VERSION: New file. * fiasco.ide: New file. * mk-distribution: New file. * Made patchlevel 27. Fri Jul 11 23:00:53 1997 Ben Pfaff * TODO: Updates. * Made patchlevel 26. Fri Jul 11 14:08:21 1997 Ben Pfaff * pref.h.orig: __CYGWIN32__ is a form of __unix__. * reconfigure: Add -k for make maintainer-clean. * Made patchlevel 25. Thu Jul 10 22:13:07 1997 Ben Pfaff * configure.in: Add "-D_GNU_SOURCE" to CPPFLAGS to force GNU glibc extensions to be detected. * Made patchlevel 24. Sun Jul 6 19:13:07 1997 Ben Pfaff * pref.h.orig: Include "src/debug-print.h" instead of "debug-print.h". (macros local_alloc, local_free) More robust under Checker: put their allocations in namespace different from malloc()/free(). * Made patchlevel 23. Sat Jul 5 23:42:14 1997 Ben Pfaff * TODO: Updates. * Made patchlevel 22. Fri Jul 4 13:20:47 1997 Ben Pfaff * Makefile.am: (EXTRA_DIST) Removed orphaned-rules. (docfiles) Removed ChangeLog, COPYING. (html, maintainer-clean-hook, install-data-hook) Removed. * reconfigure: Added --help option. Calls configure again even if --no-include-deps. * Made patchlevel 21. Wed Jun 25 22:47:17 1997 Ben Pfaff * Makefile.am: Require Automake 1.2. (dist-hook) Don't copy config dir. (EXTRA_DIST, MAINTAINERCLEANFILES) Add FAQ. (docfiles) Made a variable as well as a target; added ChangeLog, COPYING, FAQ, INSTALL, TODO. (html, maintainer-clean-hook, install-data-hook, debian, debian-clean, debian-clean-full) New targets. * orphaned-rules: Removed. * configure.in: Bumped up to version 0.1.0. * reconfigure: New options --enable-nls, --no-include-deps. Comment fixes. * Made patchlevel 20. Sun Jun 22 22:10:27 1997 Ben Pfaff * Made patchlevel 19. Sun Jun 15 16:44:14 1997 Ben Pfaff * pref.h.orig: Comment fixes. Includes debug-print.h. (DEMAND_PAGE, ALWAYS_PAGE, NEVER_PAGE) Removed. * Made patchlevel 18. Sun Jun 8 01:25:40 1997 Ben Pfaff * Made patchlevel 17. Fri Jun 6 22:41:08 1997 Ben Pfaff * TODO: Updates. * pref.h.orig: Reformatted macros. [!ENABLE_NLS] Defines gettext() as a trivial substitution to allow gcc to give warnings on printf(). * Made patchlevel 16. Thu Jun 5 23:01:49 1997 Ben Pfaff * Made patchlevel 15. Tue Jun 3 23:24:08 1997 Ben Pfaff * Makefile.am: AUTOMAKE_OPTIONS changed from `foreign 1.1l' to `gnits 1.1p'. SUBDIRS reordered. New target `docfiles'. * TODO: Updates. * configure.in: Removed AM_MAINTAINER_MODE. Added --enable-Werror, which is implied by --with-checker. * reconfigure: Moved `aclocal' from beginning to just before cleaning `autoheader'. Removed --enable-maintainer-mode. Added --disable-nls. Added `make docfiles' to placate autoheader. Added `aclocal' before first real `autoheader'. Uses `make mostlyclean' instead of `make depend'. * Made patchlevel 14. Mon Jun 2 14:21:54 1997 Ben Pfaff * configure.in: Removed comment that screwed things up. * reconfigure: Added `aclocal' at beginning. * Made patchlevel 13. Sun Jun 1 23:25:39 1997 Ben Pfaff * Makefile.am: Add intl, po to SUBDIRS. Add aclocal.m4, config.h.in to MAINTAINERCLEANFILES. * acconfig.h: Add HAVE_LC_MESSAGES, ENABLE_NLS, HAVE_CATGETS, HAVE_GETTEXT, HAVE_STPCPY. * configure.in: Reordered to placate autoheader. Added AC_ISC_POSIX, AM_PROG_CC_STDC. Added internationalization: ALL_LINGUAS="", AM_GNU_GETTEXT, AC_LINK_FILES(...). Added po/Makefile.in, intl/Makefile to generated files list. Generates po/Makefile from po/Makefile.in. Comment fix. * pref.h.orig: Uncommented i18n support. * acinclude.m4: New file. * ABOUT-NLS: New file. * intl/: New directory, taken from gettext-0.10.27. * missing: New file, taken from automake-1.1p. * po/: New directory. * Made patchlevel 12. Sun Jun 1 17:28:27 1997 Ben Pfaff * Made patchlevel 11. Sun Jun 1 11:58:43 1997 Ben Pfaff * pref.h.orig: Removed DEFAULT_VER_PCP40, DEFAULT_VER_WIN61, DEFAULT_VER_X40. Added a macro DEFAULT_COMPAT that takes one of the VER_* enums as a value. (HISTORY_FILE) Changed the definition to "~/.fiasco_history". * Made patchlevel 10. Fri May 30 19:40:22 1997 Ben Pfaff * pref.h.orig: [__MSDOS__] Reordered INCLUDE_PATH. * Made patchlevel 9. Sun May 25 22:32:57 1997 Ben Pfaff * acconfig.h: For support of glibc 2, define _GNU_SOURCE. * Made patchlevel 8. Mon May 5 21:58:22 1997 Ben Pfaff * Made patchlevel 7. Fri May 2 22:27:36 1997 Ben Pfaff * Made patchlevel 6. Thu May 1 15:34:01 1997 Ben Pfaff * All files: Changed copyright from `Ben Pfaff' to `Free Software Foundation, Inc'. * Made patchlevel 5. Thu May 1 15:00:51 1997 Ben Pfaff * Made patchlevel 4. Sat Apr 26 11:34:05 1997 Ben Pfaff * ChangeLog: Split into one ChangeLog per directory. * Made patchlevel 3. Wed Apr 23 21:33:48 1997 Ben Pfaff * TODO: Update. * Made patchlevel 2. Fri Apr 18 16:48:41 1997 Ben Pfaff * Makefile.am: Removed `include', `util' from SUBDIRS; added `config'. Includes `config' directory in distributions. Added `private-install', `private-uninstall' targets. * configure.in: AC_INIT tests for src/q2c.c now. Removed redundant AC_PROG_MAKE_SET call. Removed include/Makefile, util/Makefile from generated files list; added config/Makefile. * include/approx.h, include/arena.h, include/common.h, include/dfm.h, include/do-ifP.h, include/error.h, include/expr.h, include/exprP.h, include/file-handle.h, include/filename.h, include/font.h, include/getline.h, include/getopt.h, include/hash.h, include/heap.h, include/log.h, include/misc.h, include/output.h, include/settings.h, include/sfm.h, include/sfmP.h, include/som.h, include/somP.h, include/stat.h, include/stats.h, include/str.h, include/tokens.h, include/var.h, include/version.h, include/vfmP.h: Moved into src/ directory. * include/Makefile.am, include/: Removed. * util/Makefile.am: Removed. * util/q2c.c: Moved to src/. * util/reconfigure: Moved to source root. * util/: Removed. * Made patchlevel 1. Fri Apr 18 15:42:22 1997 Ben Pfaff * Makefile.am: Maintainer-cleans generated documentation and Makefile.in. * include/Makefile.am, util/Makefile.am: Maintainer-cleans Makefile.in. * include/somP.h: (static struct var som) Removed passed_t member. * TODO: Updated. * configure.in: Fixed source directory for copying pref.h; always updates pref.h or at least touch'es it. * pref.h.orig: Made a rather pejorative comment a lot milder so it wouldn't be misinterpreted. * Made interim release x3. Thu Mar 27 01:11:29 1997 Ben Pfaff * All directories now contain new `Makefile.am's, in some cases produced from bits and pieces of the single monolithic old one. * PATCHLEVEL: Removed. * acconfig.h: Added GNU_PACKAGE, PACKAGE, PROTOTYPES, VERSION; removed inclusion of conf.h. * confh.in: Removed. * confh.tmp.in: Removed. * configure.in: Deepened. Updated for use with Automake 1.1l. Removed PATCHLEVEL hacks. Fixed lots of functions in AC_CHECK_FUNCS, AC_REPLACE_FUNCS, and similar. Only passes `-Werror' to gcc in maintainer mode. Doesn't output conf.h. Touches pref.h even if it wasn't changed. * aclocal.m4: New file. * config.h.in: Renamed from configh.in. * pref.h.orig: Renamed from prefh.orig. * Made interim release x2. Thu Mar 27 01:07:02 1997 Ben Pfaff Changed the distribution from flat to deep. New configuration: ANNOUNCE Makefile.in config.h.in mkinstalldirs AUTHORS NEWS config.sub orphaned-rules BUGS README configure pref.h COPYING THANKS configure.in pref.h.orig ChangeLog TODO debian src ChangeLog~ acconfig.h doc stamp-h.in INSTALL aclocal.m4 include sysdeps LANGUAGE config install-sh tests Makefile.am config.guess lib util config: devices environment papersize ps-fontmap ps-prologue debian: changelog control postinst rules conffiles copyright postrm doc: ANNOUNCE.html Makefile.in fiasco.info-2 stamp-vti AUTHORS.html README.html fiasco.info-3 texinfo.tex BUGS.html THANKS.html fiasco.info-4 version.texi LANGUAGE.html fiasco.info fiasco.texi Makefile.am fiasco.info-1 mdate-sh include: approx.h file-handle.h misc.h stats.h arena.h filename.h output.h str.h common.h font.h settings.h tokens.h dfm.h getline.h sfm.h var.h do-ifP.h getopt.h sfmP.h version.h error.h hash.h som.h vfmP.h expr.h heap.h somP.h exprP.h log.h stat.h lib: Makefile.am Makefile.in avllib julcal misc lib/avllib: AVLLIB.COPYING Makefile.in avl.h Makefile.am avl.c lib/julcal: Makefile.am Makefile.in julcal.c julcal.h lib/misc: Makefile.am getopt1.c memset.c strstr.c Makefile.in memchr.c qsort.c strtol.c alloca.c memcmp.c stpcpy.c strtoul.c getdelim.c memcpy.c strcasecmp.c getline.c memmem.c strncasecmp.c getopt.c memmove.c strpbrk.c src: Makefile.am error.c lexer.c sfm-write.c Makefile.in expr-evl.c list.c show.c arena.c expr-opt.c list.q som-frnt.c ascii.c expr-prs.c log.c som-high.c autorecode.c file-handle.c loop.c som-low.c cases.c file-handle.q main.c sort.c cmdline.c file-type.c mis-val.c split-file.c command.c filename.c misc.c stats.c common.c formats.c modify-vars.c str.c compute.c freq.c numeric.c sysfile-info.c count.c frequencies.c output.c temporary.c crosstabs.c frequencies.g postscript.c title.c crosstabs.q frequencies.q print.c val-labs.c data-in.c get.c recode.c var-labs.c data-list.c getline.c rename-vars.c vars-atr.c data-out.c glob.c repeat.c vars-prs.c descript.c groff-font.c sample.c vector.c descript.q hash.c sel-if.c version.c dfm.c heap.c set.c vfm.c display.c include.c set.q weight.c do-if.c inpt-pgm.c sfm-read.c sysdeps: BorlndC4.0 DJGPP2.0 Windows sysdeps/BorlndC4.0: Makefile _write.c conf.h _read.c compile.bat config.h sysdeps/DJGPP2.0: Makefile compile.bat conf.h config.h sysdeps/Windows: con32s.c tests: Makefile.am expression.stat reread.data Makefile.in fall92.data reread.stat autorecode.stat fall92.stat sample.stat begin-data.stat file-label.stat show-check-msg bignum.data file-type.stat sort.data bignum.stat filter.stat sort.stat bug.stat gengarbage.c split-file.stat compute.stat input-program.stat sysfile-info.stat count.stat list.data temporary.stat data-formats.stat list.stat time-date.stat data-list.data loop.stat vector.stat data-list.stat modify-vars.stat weighting.data descript.stat print.stat weighting.stat do-if.stat process-if.stat do-repeat.stat recode.stat util: Makefile.am Makefile.in q2c.c reconfigure Old configuration: ANNOUNCE.html count.c hash.h sample.c AUTHORS.html crosstabs.q heap.c sel-if.c AVLLIB.COPYING data-in.c heap.h set.q BUGS.html data-list.c include.c settings.h COPYING data-out.c inpt-pgm.c sfm-read.c ChangeLog debian install-sh sfm-write.c INSTALL descript.q julcal.c sfm.h LANGUAGE.html devices julcal.h sfmP.h Makefile.am dfm.c lexer.c show.c NEWS dfm.h list.q som-frnt.c PATCHLEVEL display.c log.c som-high.c README.html do-if.c log.h som-low.c THANKS.html do-ifP.h loop.c som.h TODO environment main.c somP.h _read.c error.c makeb40.bat sort.c _write.c error.h makedj2.bat split-file.c acconfig.h expr-evl.c makefile.b40 stamp-h.in alloca.c expr-opt.c makefile.dj2 stats.c approx.h expr-prs.c mdate-sh stats.h arena.c expr.h memcmp.c stpcpy.c arena.h exprP.h mis-val.c str.c ascii.c fiasco.texi misc.c str.h autorecode.c file-handle.h misc.h sysfile-info.c avl.c file-handle.q mkinstalldirs temporary.c avl.h file-type.c modify-vars.c test cases.c filename.c numeric.c texinfo.tex cmdline.c filename.h output.c title.c command.c font.h output.h tokens.h common.c formats.c papersize val-labs.c common.h freq.c postscript.c var-labs.c compute.c frequencies.g prefh.orig var.h con32s.c frequencies.q print.c vars-atr.c confh.b40 get.c ps-fontmap vars-prs.c confh.dj2 getline.c ps-prologue vector.c confh.in getline.h q2c.c version.c confh.tmp.in getopt.c qsort.c version.h config.guess getopt.h recode.c vfm.c config.sub getopt1.c reconfigure vfmP.h configh.b40 glob.c reject weight.c configh.dj2 groff-font.c rename-vars.c configure.in hash.c repeat.c debian: changelog control postinst rules conffiles copyright postrm test: autorecode.stat fall92.data recode.stat begin-data.stat fall92.stat reread.data bignum.data file-label.stat reread.stat bignum.stat file-type.stat sample.stat bug.stat filter.stat sort.stat compute.stat gengarbage.c split-file.stat count.stat gengarbage.pl sysfile-info.stat data-formats.stat input-program.stat temporary.stat data-list.data list.data time-date.stat data-list.stat list.stat vector.stat descript.stat loop.stat weighting.data do-if.stat modify-vars.stat weighting.stat do-repeat.stat print.stat expression.stat process-if.stat Mon Mar 24 21:47:31 1997 Ben Pfaff * Makefile.am: @ALLOCA@ is on list of source files instead of alloca.c. Added $(srcdir)/ to version.c reference. Changed to pkgdatadir (/usr/share) for pkgsysconfdir, from pkglibdir (/usr/lib). Removed some of extra distfiles. Added bogus `check' target. * Made transition release x1. Sun Mar 2 20:51:28 1997 Ben Pfaff No longer uses debmake: * Makefile.am: Installs documentation according to Debian policy manual. New targets `private-uninstall', `install-data-hook' to help implement this. `debian' target also revised. * configure.in: Sets up for Debian installation depending on DEBIAN environment variable. Also, improved & fixed (hopefully) the scheme for detecting patchlevel. * Made patchlevel 193. Wed Feb 19 21:30:31 1997 Ben Pfaff * TODO: Updated. * Made patchlevel 192. Sun Feb 16 20:57:20 1997 Ben Pfaff * Made patchlevel 191. Sat Feb 15 21:26:53 1997 Ben Pfaff * Makefile.am: Removed `descript.g' from sources. * Made patchlevel 190. Fri Feb 14 23:32:58 1997 Ben Pfaff * TODO: Updated. * configure.in: Fixed test for max number of digits in an `int' to use char[] rather than int[]. * Made patchlevel 189. Tue Feb 4 15:15:50 1997 Ben Pfaff * configure.in: Fixed some problems with `--with-checker' flag and with detection of available libraries; no longer any lines longer than 79 characters. * Made patchlevel 188. Wed Jan 22 21:54:00 1997 Ben Pfaff * Makefile.am: Add sysfile-info.c to sources. * TODO: Moved some notes to different files where they are more appropriate. * prefh.orig: (macros STORE_2 and LOAD_2) Always load/store as little-endian. * Made patchlevel 187. Sun Jan 19 14:22:11 1997 Ben Pfaff * Makefile.am: Added rename-vars.c to sources. Added to distclean files. * TODO: Updates. * Made patchlevel 186. Thu Jan 16 13:08:57 1997 Ben Pfaff * Most files have updated copyright notices for 1997. * Makefile.am: Added modify-vars.c to source files. Also changed `lynx' to $(HTML_FORMATTER), etc. Changed messages. * TODO: Updates. * Made patchlevel 185. Sat Jan 11 15:44:15 1997 Ben Pfaff * Makefile.am: By default, now installs config files in pkglibdir, generally /usr/local/lib/fiasco. * TODO: Updated. * prefh.orig: Added `/etc/fiasco' to config paths. Removed $ARCH/$VER dirs from include paths. * Made patchlevel 184. Fri Jan 10 20:22:08 1997 Ben Pfaff * debian/changelog, debian/control, debian/copyright, debian/dirs, debian/info, debian/menu, debian/rules: Added Debian GNU/Linux control files. * Makefile.am: Added sfmP.h to source files. Added several files to the list of distfiles. dist-hook now copies debian control files. New targets `debian', `debian-clean', `debian-clean-full'. * confh.in: Defines PATCHLEVEL. * configure.in: Adds the current patchlevel to the version number. Versions are now of the form `1.2.3pl456'. Determines the patchlevel based on directory name and contents of file PATCHLEVEL. * reconfigure: Passes automake `--strictness=foreign'. * Made patchlevel 183. Thu Jan 2 19:08:23 1997 Ben Pfaff * Made patchlevel 182. Wed Jan 1 22:08:10 1997 Ben Pfaff * TODO: Updated. * Made patchlevel 181. Wed Jan 1 17:00:59 1997 Ben Pfaff * Makefile.am: New target for test/sort.data. * Made patchlevel 180. Sun Dec 29 21:36:48 1996 Ben Pfaff * Made patchlevel 179. Tue Dec 24 20:42:32 1996 Ben Pfaff * Made patchlevel 178. Sun Dec 22 23:10:39 1996 Ben Pfaff * Makefile.am: Added heap.c, heap.h to source files. Added new html files to distfiles & maintainer-clean files. * configure.in: Tests for presence of getpid(), sys/types.h. * prefh.orig: #defines mkdir() for MS-DOS compatibility. * Made patchlevel 177. Sat Dec 21 21:51:04 1996 Ben Pfaff * Makefile.am: Added README.html, LANGUAGE.html to list of distfiles. Added README, LANGUAGE to list of maintainer-clean files. Added .html to suffixes. Added .html implicit rule that calls `lynx -dump -nolist'. * Made patchlevel 176. Tue Dec 17 18:57:59 1996 Ben Pfaff * Made patchlevel 175. Sun Dec 15 15:32:16 1996 Ben Pfaff * Makefile.am: Added vfmP.c, qsort, sort.c to list of source files. * prefh.orig: Subtle changes to MAX_WORKSPACE, ALWAYS_PAGE, NEVER_PAGE, DEMAND_PAGE macro meanings. * Made patchlevel 174. Sat Dec 14 10:35:30 1996 Ben Pfaff * Made patchlevel 173. Fri Dec 13 21:30:53 1996 Ben Pfaff * Makefile.am: Added autorecode.c to source files. * prefh.orig: Fixed path GROFF_FONT_PATH. * Made patchlevel 172. Fri Dec 6 23:53:47 1996 Ben Pfaff * TODO: Updated. * Made patchlevel 171. Wed Dec 4 21:34:17 1996 Ben Pfaff * Made patchlevel 170. Sun Dec 1 17:19:00 1996 Ben Pfaff * Made patchlevel 169. Thu Nov 28 23:14:07 1996 Ben Pfaff * Makefile.am: Added `set.q' to list of source files. * Made patchlevel 168. Thu Nov 28 19:46:10 1996 Ben Pfaff * Made patchlevel 167. Wed Nov 27 23:18:35 1996 Ben Pfaff * Makefile.am: Added `sfm-write.c' to list of source files. * confh.in: New #defines RELEASE_NO, SUB_RELEASE_NO, and SPEC_RELEASE_NO for each part of a version number of form 1.2.3. * configure.in: Computes RELEASE_NO, etc., by breaking apart VERSION. * prefh.orig: (defn of int32, flt64) Formatting fixes. (FLT64_MAX) New define. * Made patchlevel 166. Sun Nov 24 14:53:53 1996 Ben Pfaff * Wow, it's been almost two weeks since the last update, hard to believe. * All source files: Updated e-mail address. * prefh.orig: local_alloc() calls xmalloc() under Checker because Checker can keep track of heap blocks much more accurately. * Made patchlevel 165. Mon Nov 11 15:34:09 1996 Ben Pfaff * Made patchlevel 164. Thu Nov 7 20:52:28 1996 Ben Pfaff * Made patchlevel 163. Thu Nov 7 17:29:16 1996 Ben Pfaff * Made patchlevel 162. Thu Nov 7 15:48:52 1996 Ben Pfaff * Made patchlevel 161. Tue Nov 5 18:34:59 1996 Ben Pfaff * TODO: Updated. * Made patchlevel 160. Mon Nov 4 22:03:28 1996 Ben Pfaff * Makefile.am: Added get.c. * TODO: Updated. * Made patchlevel 159. Sun Nov 3 12:24:36 1996 Ben Pfaff * Makefile.am: Added sfm.h, sfm-read.c to source files. * Made patchlevel 158. Wed Oct 30 17:13:08 1996 Ben Pfaff * Makefile.am: Added dist-zip target to AUTOMAKE_OPTIONS. * acconfig.h: Added FPREP_* defines. * configure.in: Added checks for the sizes of floating-point types. Added a test for the internal floating-point representation of the host architecture. * prefh.orig: Renamed `ATTRIBUTION' macro as `__attribute__'. All references changed. Defines `flt64' 64-bit floating-point for use with system files. [FPREP==FPREP_IEEE754 && __GNUC__ && (ENDIAN==BIG || ENDIAN==LITTLE] Defines SECOND_LOWEST_VALUE macro. * Made patchlevel 157. Sat Oct 26 23:06:06 1996 Ben Pfaff * configure.in: Checks sizes of short, int, long, long long. * prefh.orig: Defines new type int32 for use with system files. * Made patchlevel 156. Sat Oct 26 20:46:31 1996 Ben Pfaff * Made patchlevel 155. Sat Oct 26 10:39:25 1996 Ben Pfaff * TODO: Updated. * Made patchlevel 154. Thu Oct 24 20:13:42 1996 Ben Pfaff * Makefile.am: Added back in these files: recode.c, sample.c, sel-if.c. Also added files somP.h, hash.c that should've been there anyway. * TODO: Updated. * configure.in: Checks for strncasecmp in place of strcasecmp. * Made patchlevel 153. Thu Oct 24 17:47:14 1996 Ben Pfaff * TODO: Updated. * Made patchlevel 152. Wed Oct 23 21:53:43 1996 Ben Pfaff * TODO: Organized. * Made patchlevel 151. Tue Oct 22 17:27:04 1996 Ben Pfaff * TODO: Culled old notes. * Made patchlevel 150. Mon Oct 21 20:39:59 1996 Ben Pfaff * Made patchlevel 149. Sun Oct 20 13:45:28 1996 Ben Pfaff * Makefile.am: Added back in `numeric.c', `print.c', `title.c'. Defined ETAGS_ARGS. * Made patchlevel 148. Sun Oct 20 09:04:15 1996 Ben Pfaff * Made patchlevel 147. Fri Oct 18 19:46:49 1996 Ben Pfaff * Made patchlevel 146. Sun Sep 29 19:37:03 1996 Ben Pfaff * Made patchlevel 145. Sat Sep 28 21:28:07 1996 Ben Pfaff * Makefile.am: Added to DISTCLEANFILES. * Made patchlevel 144. Fri Sep 27 20:08:39 1996 Ben Pfaff * Made patchlevel 143. Thu Sep 26 22:20:26 1996 Ben Pfaff * Makefile.am: Added list.c back into the list of source files. * Made patchlevel 142. Wed Sep 25 19:36:11 1996 Ben Pfaff * Makefile.am: Updated for new files. * Made patchlevel 141. Tue Sep 24 18:39:09 1996 Ben Pfaff * Made patchlevel 140. Sat Sep 21 23:16:31 1996 Ben Pfaff * Made patchlevel 139. Fri Sep 20 22:52:28 1996 Ben Pfaff * Made patchlevel 138. Thu Sep 12 18:40:33 1996 Ben Pfaff * Made patchlevel 137. Wed Sep 11 22:01:41 1996 Ben Pfaff * TODO: Added timestamp. * prefh.orig: Removed `/usr/local/share/fiasco' and `/usr/share/fiasco' from CONFIG_PATH as per the Linux FSSTND, which specifies that programs should never give an explicit `/usr(/local)/share' path. * Made patchlevel 136. Tue Sep 10 21:39:00 1996 Ben Pfaff * Makefile.am: Added `display.c' back in. * TODO: Addition. * Made patchlevel 135. Mon Sep 9 21:43:13 1996 Ben Pfaff * Makefile.am: Added `split-file.c' back into the project. * Made patchlevel 134. Sat Sep 7 22:35:12 1996 Ben Pfaff * TODO: Updated. * prefh.orig: (local_strdup) Moved to misc.h. * Made patchlevel 133. Thu Sep 5 22:05:56 1996 Ben Pfaff * Makefile.am: Changed `prologue.ps' references to `ps-prologue'. * Made patchlevel 132. Wed Sep 4 21:45:35 1996 Ben Pfaff * prefh.orig: New i18n defines. * This patchlevel doesn't even compile. * Made patchlevel 131. Sat Aug 31 23:52:38 1996 Ben Pfaff * TODO: Addition. * Made patchlevel 130. Thu Aug 29 21:36:41 1996 Ben Pfaff * Made patchlevel 129. Sat Aug 24 23:26:00 1996 Ben Pfaff * Makefile.am: New target "private-install" to install config files to $HOME/.fiasco. * configure.in: Now that I have made a less-bogus Checker distribution, removed `-b i486-linuxaout -V 2.6.3' from AC_ARG_WITH(checker, ...). * Made patchlevel 127 somewhere in there. * Made patchlevel 128. Sun Aug 11 21:31:22 1996 Ben Pfaff * Makefile.am: Changed DISTCLEANFILES. * Does not compile. * Made patchlevel 126. Sat Aug 10 23:28:17 1996 Ben Pfaff * reconfigure: Calls `autoheader' twice: once at the beginning, once after make maintainer-clean. * Made patchlevel 125. Thu Aug 8 22:31:11 1996 Ben Pfaff * reconfigure: `autoheader' now first operation performed. * Made patchlevel 124. Sat Aug 3 20:50:35 1996 Ben Pfaff * Makefile.am: Added postscript.c to list of source files. * configh.in: Removed since autoheader can regenerate it. * configure.in: Improved tests for (ncurses or termcap) and (history and/or readline) libraries and associated headers. Added check for strcasecmp(). Changed default gcc CFLAGS. * prefh.orig: Removed `.' from GROFF_FONT_PATH. (local_alloc, local_free) New functions. * reconfigure: Added call to autoheader. * Made patchlevel 123. Sat Jul 27 22:32:38 1996 Ben Pfaff * There were some problems with the patchfiles so I had to merge what was previously patchlevels 121 and 122; now everything from what was previously 122 is called 121. Oh well, just don't let it happen often. * This patchlevel does not compile. * configure: No longer included in patches to save lotsa space when configure.in changes. * configure.in: Changed the technique for detecting libraries. * prefh.orig: Style changes; handles changed configure.in. * Made patchlevel 122 (second edition). Tue Jul 23 21:48:36 1996 Ben Pfaff * Made patchlevel 121. Wed Jul 17 21:23:36 1996 Ben Pfaff * Made patchlevel 120. Tue Jul 16 22:10:04 1996 Ben Pfaff * Made patchlevel 119. Sun Jul 14 15:45:31 1996 Ben Pfaff * Made patchlevel 118. Fri Jul 12 22:03:36 1996 Ben Pfaff * Makefile.am: Added list.c to sources. * Made patchlevel 117. Sat Jul 6 22:22:25 1996 Ben Pfaff * configure.in: Removed reference to `malloc.h'. * Made patchlevel 116. Fri Jul 5 20:16:19 1996 Ben Pfaff * Made patchlevel 115. Thu Jul 4 20:20:24 1996 Ben Pfaff * prefh.orig: Changes to CONFIG_PATH, INCLUDE_PATH, GROFF_FONT_PATH. * Makefile.am: pkgdata_DATA file `output' changed to `devices'. Thu Jul 4 00:35:59 1996 Ben Pfaff * TODO: doc fix. * Made patchlevel 114. Tue Jul 2 22:13:23 1996 Ben Pfaff * reconfigure: (new file) Runs all the programs necessary to create a Makefile that includes dependencies. * Made patchlevel 113. Mon Jul 1 22:13:39 1996 Ben Pfaff * Made patchlevel 112. Mon Jul 1 13:00:00 1996 Ben Pfaff * Most files: Changed references from `stat' (the original, rather dull old name for this project) to `Fiasco' (the creative, rather funny new name for this project). * Made patchlevel 111. Sat Jun 29 17:40:47 1996 Ben Pfaff * prefh.orig: changed default file search paths * Made patchlevel 110. Fri Jun 28 11:59:48 1996 Ben Pfaff * Added automake support; removed GNUmakefile and GNUmakefile.in. ---------------------------------------------------------------------- Local Variables: mode: change-log version-control: never End: pspp-master/ONEWS000066400000000000000000000262661177044323000141640ustar00rootroot00000000000000PSPP NEWS -- history of user-visible changes. Time-stamp: <2005-11-05 18:34:17 blp> Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. See the end for copying conditions. Please send PSPP bug reports to bug-gnu-pspp@gnu.org. * Changes for patchlevel 37: ** Bugfixes. * Changes for patchlevel 36: ** Documentation fixes. * Changes for patchlevel 35: ** DO REPEAT works. ** Removed PC+ emulation; merged X and Wnd emulations. ** Many smaller bugfixes. * Changes for patchlevel 34: ** More DO REPEAT work. Does not compile. * Changes for patchlevel 33: ** Excised politically incorrect words. * Changes for patchlevel 32: ** Worked on fixing DO REPEAT problems. * Changes for patchlevel 31: ** Fixed packaging problems. * Changes for patchlevel 30: ** Looks for include files and data file relative to the syntax file directory, not the current working directory. * Changes for patchlevel 29: ** Add capability for PSPP syntax files to invoked as programs with `#!' notation. * Changes for patchlevels 20, 21, 22, 23, 24, 25, 26, 27, 28: ** Bugfixes. * Changes for version 0.1.0: ** Debian package support. * Changes for patchlevel 19: ** Bugfixes. ** Began PSPP FAQ list. * Changes for patchlevel 18: ** Scratch variables are fully implemented. They are deleted after every procedure. ** The virtual file manager has been completely rewritten. Although all known bugs have been fixed, the new object-oriented structure to vfm is so different that there are likely some that are as-yet-undiscovered. * Changes for patchlevel 14, 15, 16, 17: ** Bugfixes. * Changes for patchlevels 12, 13: ** Internationalization! * Changes for patchlevels 7, 8, 9, 10, 11: ** Bugfixes. * Changes for patchlevel 6: ** Removed the need for a `ps-fontmap' in the PostScript driver. This changes the options for the PostScript driver slightly. * Changes for new patchlevels 1, 2, 3, 4, 5: ** Bugfixes. * Changes for interim releases x1, x2, x3: ** Package changed from `flat' to `deep' format. * Changes for patchlevel 193: ** No user-visible changes. * Changes for patchlevel 192: ** Bugfixes. * Changes for patchlevel 191: ** Reimplemented FREQUENCIES method of calculation--it should now be * acceptable to numerical analysts. * Changes for patchlevel 190: ** Implemented PROCESS IF to be compatible with PC+. ** Reimplemented DESCRIPTIVES method of calculation--it should now be acceptable to numerical analysts. ** DESCRIPTIVES is now correct and complete--please report any bugs immediately. ** Implemented SYSFILE INFO, although it is limited in the way it displays value labels. ** SAVE now records the number of cases in the system file. * Changes for patchlevels 189, 188, 187: ** Bugfixes. * Changes for patchlevel 186: ** Bazillions of bugfixes, and more to come. This version ought to be much more usable than any previous. ** Added RENAME VARIABLES command and tested it. * Changes for patchlevel 185: ** Added MODIFY VARS command; poorly tested. ** Bugfixes. * Changes for patchlevel 184: ** Debianized and fixed a few packaging problems. ** First ALPHA release. ** Miscellaneous bugfixes. * Changes for patchlevel 182: * Added FILE LABEL, DOCUMENT, and DROP DOCUMENTS commands; not tested. * Changes for patchlevel 181: * Added FILTER command. * Changes for patchlevel 180: * SORT CASES bugfixes. * Changes for patchlevel 179: * SORT CASES implemented. * Changes for patchlevels 178, 177, 176, 175: * No user-visible changes; might not even compile. * Changes for patchlevel 174: ** AUTORECODE has been newly implemented. * Changes for patchlevel 173: ** Bugfixes. * Changes for patchlevel 172: ** SET has been reintroduced. It is somewhat incomplete. ** Bugfixes. * Changes for patchlevel 171: ** Several bugfixes. ** Minor language improvements. * Changes for patchlevel 170: ** Input/output formats DOT, PCT, EDATE, SDATE are now supported but not tested. * Changes for patchlevel 169: ** Several bugfixes. ** Implemented custom currency formats (CCA ... CCE); not tested. * Changes for patchlevel 168: ** No user-visible changes. * Changes for patchlevel 167: ** Compression is now available on SAVE and XSAVE. * Changes for patchlevel 166: ** SAVE and XSAVE are implemented. Compression is not yet available. * Changes for patchlevel 165: ** GET is now fully implemented for both compressed and uncompressed system files. * Changes for patchlevel 164: ** GET now works on system files (uncompressed only). * Changes for patchlevels 163, 162, 161, 160, 159, 158: ** No user-visible changes. ** Supports keywords LOWEST and HIGHEST on MISSING VALUES. * Changes for patchlevel 157: ** Fixed longtime bug with cross-compilation. * Changes for patchlevel 156: ** Fixed the (known) bugs introduced in patchlevel 155. ** Fixed a longtime bug in RECODE that might have affected other transformations as well. * Changes for patchlevel 155: ** A few bugs fixed, probably several introduced. * Changes for patchlevel 154: ** FILE HANDLE now supports most of the SPSS/Wnd compatible features. * Changes for patchlevel 153: ** PRINT now supports OUTFILE. ** WRITE is now distinct from PRINT. ** RECODE, SAMPLE, SELECT IF are re-enabled. * Changes for patchlevel 152: ** Bugfixes for times & dates. ** Misc. bugfixes. ** System variables supported on expressions. * Changes for patchlevel 151: ** Newly implemented input/output formats: Time/date output formats. Preliminary testing has been done on times & dates. * Changes for patchlevel 150: ** Newly implemented input/output formats Zoned decimal input/output format. Time/date input formats, but not output formats. All of these are untested. * Changes for patchlevel 149: ** Bugfixes. * Changes for patchlevel 148: ** Many bugfixes. ** Re-enabled the following transformations: LEAVE, NUMERIC, PRINT, PRINT EJECT, PRINT FORMATS, PRINT SPACE, STRING, TITLE, WRITE. * Changes for patchlevel 147: ** Crushed partial tables are much better. * Changes for patchlevel 146: ** Bugfixes. ** Crushed tables are working better! ** Still pretty broken. * Changes for patchlevel 145: ** Bugfixes. ** Broken stuff. * Changes for patchlevels 144, 143: ** Bugfixes. * Changes for patchlevel 142: ** LIST procedure is back, but not well-implemented. * Changes for patchlevel 141: ** No user-visible changes. * Changes for patchlevels 140, 139, 138: ** Worked on manual. ** Minor bugfixes. * Changes for patchlevel 136: ** Began revisions to manual. ** Changed default path for configuration files. * Changes for patchlevel 135: ** PostScript driver bugfixes. ** Many memory leaks eliminated. ** Miscellaneous Bugfixes. * Changes for patchlevel 134: ** SPLIT FILE works again. ** Documentation changes in README. ** New documentation in LANGUAGE, BUGS. * Changes for patchlevel 133: ** PostScript driver supports encodings. It also works now, as opposed to the brokenness of the last patchlevel. * Changes for patchlevel 132: ** PostScript driver supports font changes! Not well tested. * Changes for patchlevel 131: ** Does not compile. * Changes for patchlevel 130: ** Generated PostScript code is smaller in size. This is because, as long as the PostScript option `optimize-line-size' is at least 1, individual contiguous short lines are consolidated into longer monster lines. * Changes for patchlevel 129: ** PostScript output much improved. Mirror no longer necessary. * Changes for patchlevel 128: ** Try out the PostScript driver, if you've got a mirror handy. * Changes for patchlevel 126: ** Does not compile. * Changes for patchlevel 125: ** No user-visible changes. * Changes for patchlevel 124: ** PostScript driver. Don't use it yet. ** Bugfixes. * Changes for patchlevel 123: ** No user-visible changes. * Changes for patchlevel 122: ** FREQUENCIES procedure is more complete. It can now print out sorted frequency tables as well as all statistics except median. No percentiles. Full syntax. No integer mode. * Changes for patchlevel 121: ** Compiles again! ** FREQUENCIES procedure works but it is incomplete. * Changes for patchlevels 120, 119: ** Does not compile. * Changes for patchlevel 118: ** Does not compile. ** Bugfix regarding titles on LIST procedure. * Changes for patchlevel 117: ** LIST procedure implemented. ** Bugfix regarding unsupported REMARK utility. * Changes for patchlevel 116: ** Does not compile. * Changes for patchlevel 115: ** New output driver initialization interface. *** Changed option syntax. `-o driver' is the new syntax. The default driver is named `default'. *** The initialization file `output' has been renamed `devices'. *** Driver names actually specify categories. Each driver name specified can actually result in 0, 1, 2, or any greater number of actual drivers being used, depending solely on the contents of the `devices' output initialization file. *** The driver initialization file is read in a `termcap'-like manner. That is, it determines whether to use a driver based on the parameters passed to it, rather than mainly on the contents of the `devices' file plus some goofy hacks with command-line options. *** Macros defined in the `devices' file can be overridden. Do it by specifying a definition on the command line of form `KEY=VALUE'. See `devices' for details. ** Short form of option `--verbose' changed to `-V'. ** New option `-v' or `--verbose'. `-v' causes PSPP to display more info about what it's doing. Multiple `-v's display even more. ** Support for small 25-line screens. The ASCII driver minimum for page length is now 15 lines instead of 29. * Changes for patchlevel 114: ** Rich text now supported in the ascii driver. The style changes are done with overstriking or with defined sequences. ** New ascii output driver option `carriage-return-style'. This can be set to `cr' or to `bs', depending on whether returning to the left margin should be done with an ASCII CR or with multiple backspaces. * Changes for patchlevel 113: ** Table titles are more complete. Now they include a description of the table contents. * Changes for patchlevel 112: ** Tables now are preceded by a descriptive `title'. This line shows what procedure emitted it, etc. ** Some tables are now divided into multiple columns. These columns are displayed across the page in order to save vertical space. * Changes for patchlevel 111: ** Bugfixes. * Changes for patchlevel 110: ** `stat' has now been renamed `Fiasco', for `Fiasco Implements Accurate Statistical COmputations'! Let's all celebrate the clever acronym! ** Bugfixes. * Changes for patchlevel 109: ** Bugfixes. ---------------------------------------------------------------------- Copyright information: Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. Permission is granted to anyone to make or distribute verbatim copies of this document as received, in any medium, provided that the copyright notice and this permission notice are preserved, thus giving the recipient permission to redistribute in turn. Permission is granted to distribute modified versions of this document, or of portions of it, under the above conditions, provided also that they carry prominent notices stating who last changed them. Local variables: version-control: never mode: text mode: outline-minor end: pspp-master/README000066400000000000000000000101151177044323000142100ustar00rootroot00000000000000PSPP is a program for statistical analysis of sampled data. It is a free replacement for the proprietary program SPSS. PSPP supports T-tests, ANOVA and GLM analyses, factor analysis, non-parametric tests, and other statistical features. PSPP produces statistical reports in plain text, PDF, PostScript, CSV, HTML, SVG, and OpenDocument formats. PSPP has both text-based and graphical user interfaces. The PSPP user interface has been translated into a number of languages. Instructions for PSPP installation are in INSTALL, including a list of prerequisite packages and other PSPP-specific information. Full documentation on PSPP's language is also included. For information on differences from previous versions, please see file NEWS. Source code for the latest release of PSPP is available at ftp://ftp.gnu.org/pub/gnu/pspp/. Older versions may be obtained from ftp://alpha.gnu.org/gnu/pspp/. Development sources are available at http://savannah.gnu.org/projects/pspp The following miscellaneous notes apply to this release: * On a few operating systems, such as OpenBSD, some of the tests may fail with messages similar to: 'Warning: cannot create a convertor for "646" to "UTF-8"'. These test failures may safely be ignored. Questions and comments about using PSPP may be sent to pspp-users@gnu.org. Bug reports may be filed at http://savannah.gnu.org/bugs/?group=pspp or emailed to bug-gnu-pspp@gnu.org. We prefer the web-based system because it makes it more difficult for us to lose track of bugs, but we are happy to hear from users through any means. The long term goals for PSPP are ambitious. We wish to provide the following support to users: * All of the SPSS transformation language. PSPP already supports a large subset of it. * All the statistical procedures that someone is willing to implement, whether they exist in SPSS or not. * Compatibility with SPSS syntax, including compatibility with known bugs and warts, where it makes sense. We also provide an "enhanced" mode in certain cases where PSPP can output better results that may surprise SPSS users. * Friendly textual and graphical interfaces. This release includes the first version of PSPPIRE, the PSPP graphical user interface. * Good documentation. Currently the PSPP manual describes its language completely, but we would like to add information on how to select statistical procedures and interpret their results. * Efficient support for very large data sets. For procedures where it is practical, we wish to efficiently support data sets many times larger than physical memory. The framework for this feature is already in place. It has not been tuned or extensively tested, however initial experience has given impressive results. Over the long term, we also wish to provide support to developers who wish to extend PSPP with new statistical procedures, by supplying the following: * Easy-to-use support for parsing language syntax. Currently, parsing is done by writing "recursive descent" code by hand, with some support for automated parsing of the most common constructs. We wish to improve the situation by supplying a more complete and flexible parser generator. * Easy-to-use support for producing attractive output. Currently, output is done by writing code to explicitly fill in table cells with data. We should be able to supply a more convenient interface that also allows for providing machine-readable output. * Eventually, a plug-in interface for procedures. Over the short term, the interface between the PSPP core and statistical procedures is evolving quickly enough that a plug-in model does not make sense. Over the long term, it may make sense to introduce plug-ins. For any copyright year range specified as YYYY-ZZZZ in this package note that the range specifies every single year in that closed interval. pspp-master/README.Git000066400000000000000000000046731177044323000147460ustar00rootroot00000000000000Prerequisites for Building PSPP from Git ---------------------------------------- To build this project from the sources direct from the Git archive, you must install the prerequisites listed in README, plus the following: * Autoconf 2.60 (or later). * Automake 1.10 (or later). * Gettext 0.17 (or later). * GNU M4 1.4.9 (or later). * pkg-config 0.21 (or later). * gperf 3.0.1 (or later). * Gnulib (see below for details). * libtool 1.5.22 (or later). * Texinfo 4.7 or later, to build the documentation. After you install PSPP's prerequisites, you must obtain a copy of Gnulib, then bootstrap the tree, as described in the sections below. After that, you may follow the procedure described in INSTALL. Obtaining Gnulib ---------------- This version of PSPP should work with the Gnulib commit shown below. Gnulib does not maintain a stable API or ABI, so it is possible that PSPP will not work with older or newer versions of Gnulib. commit ebc6ce40ac3f349d69766e3b94db034a0245f3d7 Author: John Darrington Date: Wed Jun 20 23:30:48 2012 +0200 tmpfile, clean-temp: Fix invocation of GetVersionEx. To clone Gnulib into a directory named "gnulib" using Git, and then check out this particular commit, run these commands: git clone git://git.savannah.gnu.org/gnulib.git gnulib cd gnulib git checkout $COMMIT where $COMMIT should be replaced by the commit number listed above (usually it is sufficient to just type the first 6 or so digits). If you do not have Git installed, then you may alternately download http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=snapshot;h=$COMMIT;sf=tgz where $COMMIT is, again, at least the first few digits of the commit number listed above. This download will yield a tar.gz file that you may extract with "gunzip" and "tar" to yield identical results. Bootstrapping ------------- Once you have Gnulib installed, PSPP must be "bootstrapped" using the following command: make -f Smake If you checked Gnulib out in a directory named `gnulib' at the same level as PSPP, then this is sufficient. Otherwise, provide the location of GNULIB on the `make' command line: make -f Smake GNULIB=/gnulib/base/directory/name After executing Smake, follow the procedure described in INSTALL to build and install PSPP. On some systems this may be as simple as: ./configure make Once PSPP is built, you may run its self-tests with: make check or for a more thorough test: make distcheck pspp-master/Smake000066400000000000000000000064641177044323000143270ustar00rootroot00000000000000# -*- makefile -*- # Adjust these to reflect where you've installed gnulib. GNULIB = ../gnulib GNULIB_TOOL = $(GNULIB)/gnulib-tool GNULIB_MODULES = \ assert \ byteswap \ c-strcase \ c-strcasestr \ c-ctype \ c-strtod \ clean-temp \ close \ configmake \ count-one-bits \ crc \ crypto/md4 \ crypto/md5 \ dirname \ dtoastr \ environ \ fatal-signal \ fcntl \ fpieee \ fprintf-posix \ full-read \ full-write \ fseeko \ ftello \ fwriteerror \ getline \ gettext \ gettimeofday \ getopt-gnu \ gitlog-to-changelog \ include_next \ isfinite \ isinf \ isnan \ intprops \ inttostr \ localcharset \ mbchar \ mbiter \ memcasecmp \ memchr \ mempcpy \ memrchr \ minmax \ mkdtemp \ mkstemp \ printf-posix \ printf-safe \ progname \ rawmemchr \ read-file \ regex \ relocatable-prog \ rename \ round \ snprintf \ snprintf-posix \ sprintf-posix \ stdarg \ stdbool \ stdint \ stpcpy \ strerror \ strftime \ strtod \ strtok_r \ sys_stat \ tempname \ trunc \ unictype/ctype-print \ unictype/property-id-continue \ unictype/property-id-start \ unigbrk/uc-is-grapheme-break \ unilbrk/u8-possible-linebreaks \ unistd \ unistr/u8-check \ unistr/u8-cpy \ unistr/u8-mblen \ unistr/u8-mbtouc \ unistr/u8-mbtoucr \ unistr/u8-strlen \ unistr/u8-strmbtouc \ unistr/u8-strncat \ unistr/u8-uctomb \ uniwidth/u8-strwidth \ unitypes \ unlocked-io \ vasprintf-posix \ version-etc \ version-etc-fsf \ vfprintf-posix \ vprintf-posix \ vsnprintf \ vsnprintf-posix \ vsprintf-posix \ xalloc \ xalloc-die \ xmalloca \ xmemdup0 \ xsize \ xstrndup \ xvasprintf all: prep_ph $(MAKE) -f Smake Makefile.in configure .PHONY: prep_ph prep_ph: test -e ChangeLog || touch ChangeLog test -d m4 || mkdir m4 touch m4/Makefile.am $(GNULIB_TOOL) --add-import --no-changelog --m4-base=gl/m4 \ --source-base=gl --lib=libgl --tests-base=tests \ --doc-base=gl/doc --aux-dir=build-aux \ --libtool $(GNULIB_MODULES) libtoolize --force --automake aclocal.m4: aclocal -I m4 -I gl/m4 configure: configure.ac aclocal.m4 autoconf config.h.in: configure.ac autoheader Makefile.in: Makefile.am config.h.in aclocal.m4 automake --add-missing --copy --no-force --include-deps gettextize: test -d m4 || mkdir m4 touch m4/Makefile.am gettextize --force --no-changelog check: all rm -rf _check mkdir _check cd _check && ../configure $(CONFIGUREFLAGS) cd _check && make distcheck rm -rf _check _build: all test -d _build || mkdir _build cd _build && ../configure $(CONFIGUREFLAGS) _debug: all test -d _debug || mkdir _debug cd _debug && ../configure $(CONFIGUREFLAGS) --enable-debug PO_FILES = po/ChangeLog \ po/Rules-quot po/boldquot.sed \ po/cat-id-tbl.c po/en@boldquot.header po/en@quot.header \ po/insert-header.sin po/quot.sed po/remove-potcdate.sin po/stamp-po \ po/Makevars.template po/pspp.pot clean: rm -f config.sub config.guess config.rpath rm -fr autom4te.cache rm -f aclocal.m4 rm -f missing mkinstalldirs rm -f install-sh rm -f configure Makefile rm -f depcomp rm -rf intl gl rm -f m4/*.m4 rm -f $(PO_FILES) po/*.gmo rm -f mdate-sh texinfo.tex rm -f doc/stamp-vti rm -f config.h.in~ rm -f config.h.in find . -name Makefile.in -exec rm -f {} \; rm -f compile rm -f ltmain.sh rm -f reloc-ldflags install-reloc .PHONY: all gettextize clean pspp-master/THANKS000066400000000000000000000010261177044323000142440ustar00rootroot00000000000000Thanks to... * David MacKenzie for writing Autoconf, the automatic configuration tool. * David MacKenzie and Tom Tromey for writing Automake, the tool for generating `Makefile's. * Ulrich Drepper et al for writing gettext, the GNU internationalization package. * François Pinard for advice on proceeding with development. * Jim Van Zandt for Debian packaging and suggestions. * The coordinators and translators at translationproject.org. pspp-master/acinclude.m4000066400000000000000000000264551177044323000155370ustar00rootroot00000000000000dnl Copyright (C) 2005, 2006, 2007, 2009 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl Prerequisites. dnl Summarize all the missing prerequisites at the end of the run to dnl increase user-friendliness. AC_DEFUN([PSPP_REQUIRED_PREREQ], [AC_MSG_WARN([You must install $1 before building PSPP.]) pspp_required_prereqs="$pspp_required_prereqs $1"]) AC_DEFUN([PSPP_OPTIONAL_PREREQ], [pspp_optional_prereqs="$pspp_optional_prereqs $1"]) AC_DEFUN([PSPP_CHECK_PREREQS], [ if test "$pspp_optional_prereqs" != ""; then AC_MSG_WARN([The following optional prerequisites are not installed. You may wish to install them to obtain additional functionality:$pspp_optional_prereqs]) fi if test "$pspp_required_prereqs" != ""; then AC_MSG_ERROR([The following required prerequisites are not installed. You must install them before PSPP can be built:$pspp_required_prereqs]) fi ]) dnl Check that a new enough version of Perl is available. AC_DEFUN([PSPP_PERL], [ AC_PATH_PROG([PERL], perl, no) AC_SUBST([PERL])dnl if test "$PERL" != no && $PERL -e 'require 5.005_03;'; then :; else PSPP_REQUIRED_PREREQ([Perl 5.005_03 (or later)]) fi # The PSPP autobuilder appends a build number to the PSPP version number, # e.g. "0.7.2-build40". But Perl won't parse version numbers that contain # anything other than digits and periods, so "-build" causes an error. So we # define $(VERSION_FOR_PERL) that drops everything from the hyphen onward. VERSION_FOR_PERL=`echo "$VERSION" | sed 's/-.*//'` AC_SUBST([VERSION_FOR_PERL]) ]) dnl PSPP_CHECK_CC_OPTION([OPTION], [ACTION-IF-ACCEPTED], [ACTION-IF-REJECTED]) dnl Check whether the given C compiler OPTION is accepted. dnl If so, execute ACTION-IF-ACCEPTED, otherwise ACTION-IF-REJECTED. AC_DEFUN([PSPP_CHECK_CC_OPTION], [ m4_define([pspp_cv_name], [pspp_cv_[]m4_translit([$1], [-], [_])])dnl AC_CACHE_CHECK([whether $CC accepts $1], [pspp_cv_name], [pspp_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $1" AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,)], [pspp_cv_name[]=yes], [pspp_cv_name[]=no]) CFLAGS="$pspp_save_CFLAGS"]) if test $pspp_cv_name = yes; then m4_if([$2], [], [;], [$2]) else m4_if([$3], [], [:], [$3]) fi ]) dnl PSPP_ENABLE_OPTION([OPTION]) dnl Check whether the given C compiler OPTION is accepted. dnl If so, add it to CFLAGS. dnl Example: PSPP_ENABLE_OPTION([-Wdeclaration-after-statement]) AC_DEFUN([PSPP_ENABLE_OPTION], [PSPP_CHECK_CC_OPTION([$1], [CFLAGS="$CFLAGS $1"])]) dnl Check for readline and history libraries. dnl Modified for PSPP, based on readline.m4 serial 3 from dnl gnulib, which was written by Simon Josefsson, with help from Bruno dnl Haible and Oskar Liljeblad. AC_DEFUN([PSPP_READLINE], [ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Search for libreadline and define LIBREADLINE, LTLIBREADLINE and dnl INCREADLINE accordingly. AC_LIB_LINKFLAGS_BODY([readline]) AC_LIB_LINKFLAGS_BODY([history]) dnl Add $INCREADLINE to CPPFLAGS before performing the following checks, dnl because if the user has installed libreadline and not disabled its use dnl via --without-libreadline-prefix, he wants to use it. The AC_LINK_IFELSE dnl will then succeed. am_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCREADLINE $INCHISTORY]) AC_CACHE_CHECK(for readline, gl_cv_lib_readline, [ gl_cv_lib_readline=no am_save_LIBS="$LIBS" dnl On some systems, -lreadline doesn't link without an additional dnl -lncurses or -ltermcap. dnl Try -lncurses before -ltermcap, because libtermcap is unsecure dnl by design and obsolete since 1994. Try -lcurses last, because dnl libcurses is unusable on some old Unices. for extra_lib in "" ncurses termcap curses; do LIBS="$am_save_LIBS $LIBREADLINE $LIBHISTORY" if test -n "$extra_lib"; then LIBS="$LIBS -l$extra_lib" fi AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include #include #include ]], [[readline((char*)0); add_history((char*)0);]])],[gl_cv_lib_readline=yes],[]) if test "$gl_cv_lib_readline" = yes; then if test -n "$extra_lib"; then LIBREADLINE="$LIBREADLINE $LIBHISTORY -l$extra_lib" LTLIBREADLINE="$LTLIBREADLINE $LTLIBHISTORY -l$extra_lib" fi break fi done LIBS="$am_save_LIBS" ]) if test "$gl_cv_lib_readline" = yes; then AC_DEFINE(HAVE_READLINE, 1, [Define if you have the readline library.]) AC_MSG_CHECKING([how to link with libreadline]) AC_MSG_RESULT([$LIBREADLINE]) else dnl If $LIBREADLINE didn't lead to a usable library, we don't dnl need $INCREADLINE either. CPPFLAGS="$am_save_CPPFLAGS" LIBREADLINE= LTLIBREADLINE= LIBHISTORY= LTLIBHISTORY= PSPP_OPTIONAL_PREREQ([libreadline (which may itself require libncurses or libtermcap)]) fi AC_SUBST(LIBREADLINE) AC_SUBST(LTLIBREADLINE) ]) dnl Check for build tools. Adapted from bfd library. AC_DEFUN([PSPP_CC_FOR_BUILD], [# Put a plausible default for CC_FOR_BUILD in Makefile. if test -z "$CC_FOR_BUILD"; then if test "x$cross_compiling" = "xno"; then CC_FOR_BUILD='$(CC)' else CC_FOR_BUILD=cc fi fi AC_SUBST(CC_FOR_BUILD) # Also set EXEEXT_FOR_BUILD. if test "x$cross_compiling" = "xno"; then EXEEXT_FOR_BUILD='$(EXEEXT)' else AC_CACHE_CHECK([for build system executable suffix], pspp_cv_build_exeext, [rm -f conftest* echo 'int main () { return 0; }' > conftest.c pspp_cv_build_exeext= ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5 for file in conftest.*; do case $file in # ( *.c | *.o | *.obj | *.ilk | *.pdb) ;; # ( *) pspp_cv_build_exeext=`echo $file | sed -e s/conftest//` ;; esac done rm -f conftest* test x"${pspp_cv_build_exeext}" = x && pspp_cv_build_exeext=no]) EXEEXT_FOR_BUILD="" test x"${pspp_cv_build_exeext}" != xno && EXEEXT_FOR_BUILD=${pspp_cv_build_exeex t} fi AC_SUBST(EXEEXT_FOR_BUILD)]) dnl Check for LC_PAPER, _NL_PAPER_WIDTH, _NL_PAPER_HEIGHT. AC_DEFUN([PSPP_LC_PAPER], [AC_CACHE_CHECK(for LC_PAPER, pspp_cv_lc_paper, [ pspp_cv_lc_paper=no AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [#include #include ], [(void) LC_PAPER; (void) _NL_PAPER_WIDTH; (void) _NL_PAPER_HEIGHT])], [pspp_cv_lc_paper=yes]) ]) if test "$pspp_cv_lc_paper" = yes; then AC_DEFINE(HAVE_LC_PAPER, 1, [Define if you have LC_PAPER.]) fi ]) # PSPP_LINK2_IFELSE(SOURCE1, SOURCE2, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # ------------------------------------------------------------- # Based on AC_LINK_IFELSE, but tries to link both SOURCE1 and SOURCE2 # into a program. # # Test that resulting file is executable; see the problem reported by mwoehlke # in . # But skip the test when cross-compiling, to prevent problems like the one # reported by Chris Johns in # . # m4_define([PSPP_LINK2_IFELSE], [m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl mv conftest.$ac_ext conftest1.$ac_ext m4_ifvaln([$2], [AC_LANG_CONFTEST([$2])])dnl mv conftest.$ac_ext conftest2.$ac_ext rm -f conftest1.$ac_objext conftest2.$ac_objext conftest$ac_exeext pspp_link2='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest1.$ac_ext conftest2.$ac_ext $LIBS >&5' AS_IF([_AC_DO_STDERR($pspp_link2) && { test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || AS_TEST_X([conftest$ac_exeext]) }], [$3], [echo "$as_me: failed source file 1 of 2 was:" >&5 sed 's/^/| /' conftest1.$ac_ext >&5 echo "$as_me: failed source file 2 of 2 was:" >&5 sed 's/^/| /' conftest2.$ac_ext >&5 $4]) dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization) dnl information created by the PGI compiler (conftest_ipa8_conftest.oo), dnl as it would interfere with the next link command. rm -rf conftest.dSYM conftest1.dSYM conftest2.dSYM rm -f core conftest.err conftest1.err conftest2.err rm -f conftest1.$ac_objext conftest2.$ac_objext conftest*_ipa8_conftest*.oo rm -f conftest$ac_exeext rm -f m4_ifval([$1], [conftest1.$ac_ext]) m4_ifval([$2], [conftest1.$ac_ext])[]dnl ])# PSPP_LINK2_IFELSE # GSL uses "extern inline" without determining whether the compiler uses # GCC inline rules or C99 inline rules. If it uses the latter then GSL # will be broken without passing -fgnu89-inline to GCC. AC_DEFUN([PSPP_GSL_NEEDS_FGNU89_INLINE], [# GSL only uses "inline" at all if HAVE_INLINE is defined as a macro. # In turn, gnulib's gl_INLINE is one macro that does that. We need to # make sure that it has run by the time we run this test, otherwise we'll # get a false result. AC_REQUIRE([gl_INLINE]) PSPP_CHECK_CC_OPTION( [-fgnu89-inline], [AC_CACHE_CHECK([whether GSL needs -fgnu89-inline to link], pspp_cv_gsl_needs_fgnu89_inline, [ PSPP_LINK2_IFELSE( [AC_LANG_PROGRAM([#include ], [GSL_MAX_INT(1,2);])], [AC_LANG_SOURCE([#include void x (void) {}])], [pspp_cv_gsl_needs_fgnu89_inline=no], [pspp_cv_gsl_needs_fgnu89_inline=yes])]) if test "$pspp_cv_gsl_needs_fgnu89_inline" = "yes"; then CFLAGS="$CFLAGS -fgnu89-inline" fi]) ]) AC_DEFUN([PSPP_CHECK_CLICKSEQUENCE], [AC_REQUIRE([AM_INIT_AUTOMAKE]) # Defines MAKEINFO AC_CACHE_CHECK([whether makeinfo supports @clicksequence], [pspp_cv_have_clicksequence], [cat > conftest.texi <&AS_MESSAGE_LOG_FD" >&AS_MESSAGE_LOG_FD eval "$MAKEINFO conftest.texi >&AS_MESSAGE_LOG_FD 2>&1" retval=$? echo "configure:__oline__: \$? = $retval" >&AS_MESSAGE_LOG_FD if test $retval = 0; then pspp_cv_have_clicksequence=yes else pspp_cv_have_clicksequence=no fi rm -f conftest.texi conftest.info]) if test $pspp_cv_have_clicksequence = no; then AM_MAKEINFOFLAGS="$AM_MAKEINFOFLAGS -DMISSING_CLICKSEQUENCE" AC_SUBST([AM_MAKEINFOFLAGS]) fi]) # The following comes from Open vSwitch: # ---------------------------------------------------------------------- # Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. dnl PSPP_ENABLE_WERROR AC_DEFUN([PSPP_ENABLE_WERROR], [AC_ARG_ENABLE( [Werror], [AC_HELP_STRING([--enable-Werror], [Add -Werror to CFLAGS])], [], [enable_Werror=no]) AC_CONFIG_COMMANDS_PRE( [if test "X$enable_Werror" = Xyes; then CFLAGS="$CFLAGS -Werror" fi])]) pspp-master/build-aux/000077500000000000000000000000001177044323000152245ustar00rootroot00000000000000pspp-master/build-aux/.gitignore000066400000000000000000000002161177044323000172130ustar00rootroot00000000000000/arg-nonnull.h /c++defs.h /config.libpath /config.rpath /gitlog-to-changelog /install-reloc /reloc-ldflags /unused-parameter.h /warn-on-use.h pspp-master/build-aux/texinfo.tex000066400000000000000000010701111177044323000174230ustar00rootroot00000000000000% texinfo.tex -- TeX macros to handle Texinfo files. % % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % \def\texinfoversion{2008-11-17.21} % % Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, % 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, % 2007, 2008 Free Software Foundation, Inc. % % This texinfo.tex file 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 texinfo.tex file 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 . % % As a special exception, when this file is read by TeX when processing % a Texinfo source document, you may use the result without % restriction. (This has been our intent since Texinfo was invented.) % % Please try the latest version of texinfo.tex before submitting bug % reports; you can get the latest version from: % http://www.gnu.org/software/texinfo/ (the Texinfo home page), or % ftp://tug.org/tex/texinfo.tex % (and all CTAN mirrors, see http://www.ctan.org). % The texinfo.tex in any given distribution could well be out % of date, so if that's what you're using, please check. % % Send bug reports to bug-texinfo@gnu.org. Please include including a % complete document in each bug report with which we can reproduce the % problem. Patches are, of course, greatly appreciated. % % To process a Texinfo manual with TeX, it's most reliable to use the % texi2dvi shell script that comes with the distribution. For a simple % manual foo.texi, however, you can get away with this: % tex foo.texi % texindex foo.?? % tex foo.texi % tex foo.texi % dvips foo.dvi -o # or whatever; this makes foo.ps. % The extra TeX runs get the cross-reference information correct. % Sometimes one run after texindex suffices, and sometimes you need more % than two; texi2dvi does it as many times as necessary. % % It is possible to adapt texinfo.tex for other languages, to some % extent. You can get the existing language-specific files from the % full Texinfo distribution. % % The GNU Texinfo home page is http://www.gnu.org/software/texinfo. \message{Loading texinfo [version \texinfoversion]:} % If in a .fmt file, print the version number % and turn on active characters that we couldn't do earlier because % they might have appeared in the input file name. \everyjob{\message{[Texinfo version \texinfoversion]}% \catcode`+=\active \catcode`\_=\active} \chardef\other=12 % We never want plain's \outer definition of \+ in Texinfo. % For @tex, we can use \tabalign. \let\+ = \relax % Save some plain tex macros whose names we will redefine. \let\ptexb=\b \let\ptexbullet=\bullet \let\ptexc=\c \let\ptexcomma=\, \let\ptexdot=\. \let\ptexdots=\dots \let\ptexend=\end \let\ptexequiv=\equiv \let\ptexexclam=\! \let\ptexfootnote=\footnote \let\ptexgtr=> \let\ptexhat=^ \let\ptexi=\i \let\ptexindent=\indent \let\ptexinsert=\insert \let\ptexlbrace=\{ \let\ptexless=< \let\ptexnewwrite\newwrite \let\ptexnoindent=\noindent \let\ptexplus=+ \let\ptexrbrace=\} \let\ptexslash=\/ \let\ptexstar=\* \let\ptext=\t \let\ptextop=\top {\catcode`\'=\active \global\let\ptexquoteright'}% Math-mode def from plain.tex. % If this character appears in an error message or help string, it % starts a new line in the output. \newlinechar = `^^J % Use TeX 3.0's \inputlineno to get the line number, for better error % messages, but if we're using an old version of TeX, don't do anything. % \ifx\inputlineno\thisisundefined \let\linenumber = \empty % Pre-3.0. \else \def\linenumber{l.\the\inputlineno:\space} \fi % Set up fixed words for English if not already set. \ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi \ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi \ifx\putwordfile\undefined \gdef\putwordfile{file}\fi \ifx\putwordin\undefined \gdef\putwordin{in}\fi \ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi \ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi \ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi \ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi \ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi \ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi \ifx\putwordof\undefined \gdef\putwordof{of}\fi \ifx\putwordon\undefined \gdef\putwordon{on}\fi \ifx\putwordpage\undefined \gdef\putwordpage{page}\fi \ifx\putwordsection\undefined \gdef\putwordsection{section}\fi \ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi \ifx\putwordsee\undefined \gdef\putwordsee{see}\fi \ifx\putwordSee\undefined \gdef\putwordSee{See}\fi \ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi \ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi % \ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi \ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi \ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi \ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi \ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi \ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi \ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi \ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi \ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi \ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi \ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi \ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi % \ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi \ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi \ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi \ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi \ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi % Since the category of space is not known, we have to be careful. \chardef\spacecat = 10 \def\spaceisspace{\catcode`\ =\spacecat} % sometimes characters are active, so we need control sequences. \chardef\colonChar = `\: \chardef\commaChar = `\, \chardef\dashChar = `\- \chardef\dotChar = `\. \chardef\exclamChar= `\! \chardef\lquoteChar= `\` \chardef\questChar = `\? \chardef\rquoteChar= `\' \chardef\semiChar = `\; \chardef\underChar = `\_ % Ignore a token. % \def\gobble#1{} % The following is used inside several \edef's. \def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} % Hyphenation fixes. \hyphenation{ Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script ap-pen-dix bit-map bit-maps data-base data-bases eshell fall-ing half-way long-est man-u-script man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces spell-ing spell-ings stand-alone strong-est time-stamp time-stamps which-ever white-space wide-spread wrap-around } % Margin to add to right of even pages, to left of odd pages. \newdimen\bindingoffset \newdimen\normaloffset \newdimen\pagewidth \newdimen\pageheight % For a final copy, take out the rectangles % that mark overfull boxes (in case you have decided % that the text looks ok even though it passes the margin). % \def\finalout{\overfullrule=0pt} % @| inserts a changebar to the left of the current line. It should % surround any changed text. This approach does *not* work if the % change spans more than two lines of output. To handle that, we would % have adopt a much more difficult approach (putting marks into the main % vertical list for the beginning and end of each change). % \def\|{% % \vadjust can only be used in horizontal mode. \leavevmode % % Append this vertical mode material after the current line in the output. \vadjust{% % We want to insert a rule with the height and depth of the current % leading; that is exactly what \strutbox is supposed to record. \vskip-\baselineskip % % \vadjust-items are inserted at the left edge of the type. So % the \llap here moves out into the left-hand margin. \llap{% % % For a thicker or thinner bar, change the `1pt'. \vrule height\baselineskip width1pt % % This is the space between the bar and the text. \hskip 12pt }% }% } % Sometimes it is convenient to have everything in the transcript file % and nothing on the terminal. We don't just call \tracingall here, % since that produces some useless output on the terminal. We also make % some effort to order the tracing commands to reduce output in the log % file; cf. trace.sty in LaTeX. % \def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% \def\loggingall{% \tracingstats2 \tracingpages1 \tracinglostchars2 % 2 gives us more in etex \tracingparagraphs1 \tracingoutput1 \tracingmacros2 \tracingrestores1 \showboxbreadth\maxdimen \showboxdepth\maxdimen \ifx\eTeXversion\undefined\else % etex gives us more logging \tracingscantokens1 \tracingifs1 \tracinggroups1 \tracingnesting2 \tracingassigns1 \fi \tracingcommands3 % 3 gives us more in etex \errorcontextlines16 }% % add check for \lastpenalty to plain's definitions. If the last thing % we did was a \nobreak, we don't want to insert more space. % \def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount \removelastskip\penalty-50\smallskip\fi\fi} \def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount \removelastskip\penalty-100\medskip\fi\fi} \def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount \removelastskip\penalty-200\bigskip\fi\fi} % For @cropmarks command. % Do @cropmarks to get crop marks. % \newif\ifcropmarks \let\cropmarks = \cropmarkstrue % % Dimensions to add cropmarks at corners. % Added by P. A. MacKay, 12 Nov. 1986 % \newdimen\outerhsize \newdimen\outervsize % set by the paper size routines \newdimen\cornerlong \cornerlong=1pc \newdimen\cornerthick \cornerthick=.3pt \newdimen\topandbottommargin \topandbottommargin=.75in % Output a mark which sets \thischapter, \thissection and \thiscolor. % We dump everything together because we only have one kind of mark. % This works because we only use \botmark / \topmark, not \firstmark. % % A mark contains a subexpression of the \ifcase ... \fi construct. % \get*marks macros below extract the needed part using \ifcase. % % Another complication is to let the user choose whether \thischapter % (\thissection) refers to the chapter (section) in effect at the top % of a page, or that at the bottom of a page. The solution is % described on page 260 of The TeXbook. It involves outputting two % marks for the sectioning macros, one before the section break, and % one after. I won't pretend I can describe this better than DEK... \def\domark{% \toks0=\expandafter{\lastchapterdefs}% \toks2=\expandafter{\lastsectiondefs}% \toks4=\expandafter{\prevchapterdefs}% \toks6=\expandafter{\prevsectiondefs}% \toks8=\expandafter{\lastcolordefs}% \mark{% \the\toks0 \the\toks2 \noexpand\or \the\toks4 \the\toks6 \noexpand\else \the\toks8 }% } % \topmark doesn't work for the very first chapter (after the title % page or the contents), so we use \firstmark there -- this gets us % the mark with the chapter defs, unless the user sneaks in, e.g., % @setcolor (or @url, or @link, etc.) between @contents and the very % first @chapter. \def\gettopheadingmarks{% \ifcase0\topmark\fi \ifx\thischapter\empty \ifcase0\firstmark\fi \fi } \def\getbottomheadingmarks{\ifcase1\botmark\fi} \def\getcolormarks{\ifcase2\topmark\fi} % Avoid "undefined control sequence" errors. \def\lastchapterdefs{} \def\lastsectiondefs{} \def\prevchapterdefs{} \def\prevsectiondefs{} \def\lastcolordefs{} % Main output routine. \chardef\PAGE = 255 \output = {\onepageout{\pagecontents\PAGE}} \newbox\headlinebox \newbox\footlinebox % \onepageout takes a vbox as an argument. Note that \pagecontents % does insertions, but you have to call it yourself. \def\onepageout#1{% \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi % \ifodd\pageno \advance\hoffset by \bindingoffset \else \advance\hoffset by -\bindingoffset\fi % % Do this outside of the \shipout so @code etc. will be expanded in % the headline as they should be, not taken literally (outputting ''code). \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% % {% % Have to do this stuff outside the \shipout because we want it to % take effect in \write's, yet the group defined by the \vbox ends % before the \shipout runs. % \indexdummies % don't expand commands in the output. \normalturnoffactive % \ in index entries must not stay \, e.g., if % the page break happens to be in the middle of an example. % We don't want .vr (or whatever) entries like this: % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}} % "\acronym" won't work when it's read back in; % it needs to be % {\code {{\tt \backslashcurfont }acronym} \shipout\vbox{% % Do this early so pdf references go to the beginning of the page. \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi % \ifcropmarks \vbox to \outervsize\bgroup \hsize = \outerhsize \vskip-\topandbottommargin \vtop to0pt{% \line{\ewtop\hfil\ewtop}% \nointerlineskip \line{% \vbox{\moveleft\cornerthick\nstop}% \hfill \vbox{\moveright\cornerthick\nstop}% }% \vss}% \vskip\topandbottommargin \line\bgroup \hfil % center the page within the outer (page) hsize. \ifodd\pageno\hskip\bindingoffset\fi \vbox\bgroup \fi % \unvbox\headlinebox \pagebody{#1}% \ifdim\ht\footlinebox > 0pt % Only leave this space if the footline is nonempty. % (We lessened \vsize for it in \oddfootingyyy.) % The \baselineskip=24pt in plain's \makefootline has no effect. \vskip 24pt \unvbox\footlinebox \fi % \ifcropmarks \egroup % end of \vbox\bgroup \hfil\egroup % end of (centering) \line\bgroup \vskip\topandbottommargin plus1fill minus1fill \boxmaxdepth = \cornerthick \vbox to0pt{\vss \line{% \vbox{\moveleft\cornerthick\nsbot}% \hfill \vbox{\moveright\cornerthick\nsbot}% }% \nointerlineskip \line{\ewbot\hfil\ewbot}% }% \egroup % \vbox from first cropmarks clause \fi }% end of \shipout\vbox }% end of group with \indexdummies \advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi } \newinsert\margin \dimen\margin=\maxdimen \def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} {\catcode`\@ =11 \gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi % marginal hacks, juha@viisa.uucp (Juha Takala) \ifvoid\margin\else % marginal info is present \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi \dimen@=\dp#1\relax \unvbox#1\relax \ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi \ifr@ggedbottom \kern-\dimen@ \vfil \fi} } % Here are the rules for the cropmarks. Note that they are % offset so that the space between them is truly \outerhsize or \outervsize % (P. A. MacKay, 12 November, 1986) % \def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} \def\nstop{\vbox {\hrule height\cornerthick depth\cornerlong width\cornerthick}} \def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} \def\nsbot{\vbox {\hrule height\cornerlong depth\cornerthick width\cornerthick}} % Parse an argument, then pass it to #1. The argument is the rest of % the input line (except we remove a trailing comment). #1 should be a % macro which expects an ordinary undelimited TeX argument. % \def\parsearg{\parseargusing{}} \def\parseargusing#1#2{% \def\argtorun{#2}% \begingroup \obeylines \spaceisspace #1% \parseargline\empty% Insert the \empty token, see \finishparsearg below. } {\obeylines % \gdef\parseargline#1^^M{% \endgroup % End of the group started in \parsearg. \argremovecomment #1\comment\ArgTerm% }% } % First remove any @comment, then any @c comment. \def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} \def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} % Each occurrence of `\^^M' or `\^^M' is replaced by a single space. % % \argremovec might leave us with trailing space, e.g., % @end itemize @c foo % This space token undergoes the same procedure and is eventually removed % by \finishparsearg. % \def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} \def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} \def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% \def\temp{#3}% \ifx\temp\empty % Do not use \next, perhaps the caller of \parsearg uses it; reuse \temp: \let\temp\finishparsearg \else \let\temp\argcheckspaces \fi % Put the space token in: \temp#1 #3\ArgTerm } % If a _delimited_ argument is enclosed in braces, they get stripped; so % to get _exactly_ the rest of the line, we had to prevent such situation. % We prepended an \empty token at the very beginning and we expand it now, % just before passing the control to \argtorun. % (Similarly, we have to think about #3 of \argcheckspacesY above: it is % either the null string, or it ends with \^^M---thus there is no danger % that a pair of braces would be stripped. % % But first, we have to remove the trailing space token. % \def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}} % \parseargdef\foo{...} % is roughly equivalent to % \def\foo{\parsearg\Xfoo} % \def\Xfoo#1{...} % % Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my % favourite TeX trick. --kasal, 16nov03 \def\parseargdef#1{% \expandafter \doparseargdef \csname\string#1\endcsname #1% } \def\doparseargdef#1#2{% \def#2{\parsearg#1}% \def#1##1% } % Several utility definitions with active space: { \obeyspaces \gdef\obeyedspace{ } % Make each space character in the input produce a normal interword % space in the output. Don't allow a line break at this space, as this % is used only in environments like @example, where each line of input % should produce a line of output anyway. % \gdef\sepspaces{\obeyspaces\let =\tie} % If an index command is used in an @example environment, any spaces % therein should become regular spaces in the raw index file, not the % expansion of \tie (\leavevmode \penalty \@M \ ). \gdef\unsepspaces{\let =\space} } \def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} % Define the framework for environments in texinfo.tex. It's used like this: % % \envdef\foo{...} % \def\Efoo{...} % % It's the responsibility of \envdef to insert \begingroup before the % actual body; @end closes the group after calling \Efoo. \envdef also % defines \thisenv, so the current environment is known; @end checks % whether the environment name matches. The \checkenv macro can also be % used to check whether the current environment is the one expected. % % Non-false conditionals (@iftex, @ifset) don't fit into this, so they % are not treated as environments; they don't open a group. (The % implementation of @end takes care not to call \endgroup in this % special case.) % At run-time, environments start with this: \def\startenvironment#1{\begingroup\def\thisenv{#1}} % initialize \let\thisenv\empty % ... but they get defined via ``\envdef\foo{...}'': \long\def\envdef#1#2{\def#1{\startenvironment#1#2}} \def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} % Check whether we're in the right environment: \def\checkenv#1{% \def\temp{#1}% \ifx\thisenv\temp \else \badenverr \fi } % Environment mismatch, #1 expected: \def\badenverr{% \errhelp = \EMsimple \errmessage{This command can appear only \inenvironment\temp, not \inenvironment\thisenv}% } \def\inenvironment#1{% \ifx#1\empty out of any environment% \else in environment \expandafter\string#1% \fi } % @end foo executes the definition of \Efoo. % But first, it executes a specialized version of \checkenv % \parseargdef\end{% \if 1\csname iscond.#1\endcsname \else % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03 \expandafter\checkenv\csname#1\endcsname \csname E#1\endcsname \endgroup \fi } \newhelp\EMsimple{Press RETURN to continue.} %% Simple single-character @ commands % @@ prints an @ % Kludge this until the fonts are right (grr). \def\@{{\tt\char64}} % This is turned off because it was never documented % and you can use @w{...} around a quote to suppress ligatures. %% Define @` and @' to be the same as ` and ' %% but suppressing ligatures. %\def\`{{`}} %\def\'{{'}} % Used to generate quoted braces. \def\mylbrace {{\tt\char123}} \def\myrbrace {{\tt\char125}} \let\{=\mylbrace \let\}=\myrbrace \begingroup % Definitions to produce \{ and \} commands for indices, % and @{ and @} for the aux/toc files. \catcode`\{ = \other \catcode`\} = \other \catcode`\[ = 1 \catcode`\] = 2 \catcode`\! = 0 \catcode`\\ = \other !gdef!lbracecmd[\{]% !gdef!rbracecmd[\}]% !gdef!lbraceatcmd[@{]% !gdef!rbraceatcmd[@}]% !endgroup % @comma{} to avoid , parsing problems. \let\comma = , % Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent % Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. \let\, = \c \let\dotaccent = \. \def\ringaccent#1{{\accent23 #1}} \let\tieaccent = \t \let\ubaraccent = \b \let\udotaccent = \d % Other special characters: @questiondown @exclamdown @ordf @ordm % Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. \def\questiondown{?`} \def\exclamdown{!`} \def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} \def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} % Dotless i and dotless j, used for accents. \def\imacro{i} \def\jmacro{j} \def\dotless#1{% \def\temp{#1}% \ifx\temp\imacro \ifmmode\imath \else\ptexi \fi \else\ifx\temp\jmacro \ifmmode\jmath \else\j \fi \else \errmessage{@dotless can be used only with i or j}% \fi\fi } % The \TeX{} logo, as in plain, but resetting the spacing so that a % period following counts as ending a sentence. (Idea found in latex.) % \edef\TeX{\TeX \spacefactor=1000 } % @LaTeX{} logo. Not quite the same results as the definition in % latex.ltx, since we use a different font for the raised A; it's most % convenient for us to use an explicitly smaller font, rather than using % the \scriptstyle font (since we don't reset \scriptstyle and % \scriptscriptstyle). % \def\LaTeX{% L\kern-.36em {\setbox0=\hbox{T}% \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}% \kern-.15em \TeX } % Be sure we're in horizontal mode when doing a tie, since we make space % equivalent to this in @example-like environments. Otherwise, a space % at the beginning of a line will start with \penalty -- and % since \penalty is valid in vertical mode, we'd end up putting the % penalty on the vertical list instead of in the new paragraph. {\catcode`@ = 11 % Avoid using \@M directly, because that causes trouble % if the definition is written into an index file. \global\let\tiepenalty = \@M \gdef\tie{\leavevmode\penalty\tiepenalty\ } } % @: forces normal size whitespace following. \def\:{\spacefactor=1000 } % @* forces a line break. \def\*{\hfil\break\hbox{}\ignorespaces} % @/ allows a line break. \let\/=\allowbreak % @. is an end-of-sentence period. \def\.{.\spacefactor=\endofsentencespacefactor\space} % @! is an end-of-sentence bang. \def\!{!\spacefactor=\endofsentencespacefactor\space} % @? is an end-of-sentence query. \def\?{?\spacefactor=\endofsentencespacefactor\space} % @frenchspacing on|off says whether to put extra space after punctuation. % \def\onword{on} \def\offword{off} % \parseargdef\frenchspacing{% \def\temp{#1}% \ifx\temp\onword \plainfrenchspacing \else\ifx\temp\offword \plainnonfrenchspacing \else \errhelp = \EMsimple \errmessage{Unknown @frenchspacing option `\temp', must be on/off}% \fi\fi } % @w prevents a word break. Without the \leavevmode, @w at the % beginning of a paragraph, when TeX is still in vertical mode, would % produce a whole line of output instead of starting the paragraph. \def\w#1{\leavevmode\hbox{#1}} % @group ... @end group forces ... to be all on one page, by enclosing % it in a TeX vbox. We use \vtop instead of \vbox to construct the box % to keep its height that of a normal line. According to the rules for % \topskip (p.114 of the TeXbook), the glue inserted is % max (\topskip - \ht (first item), 0). If that height is large, % therefore, no glue is inserted, and the space between the headline and % the text is small, which looks bad. % % Another complication is that the group might be very large. This can % cause the glue on the previous page to be unduly stretched, because it % does not have much material. In this case, it's better to add an % explicit \vfill so that the extra space is at the bottom. The % threshold for doing this is if the group is more than \vfilllimit % percent of a page (\vfilllimit can be changed inside of @tex). % \newbox\groupbox \def\vfilllimit{0.7} % \envdef\group{% \ifnum\catcode`\^^M=\active \else \errhelp = \groupinvalidhelp \errmessage{@group invalid in context where filling is enabled}% \fi \startsavinginserts % \setbox\groupbox = \vtop\bgroup % Do @comment since we are called inside an environment such as % @example, where each end-of-line in the input causes an % end-of-line in the output. We don't want the end-of-line after % the `@group' to put extra space in the output. Since @group % should appear on a line by itself (according to the Texinfo % manual), we don't worry about eating any user text. \comment } % % The \vtop produces a box with normal height and large depth; thus, TeX puts % \baselineskip glue before it, and (when the next line of text is done) % \lineskip glue after it. Thus, space below is not quite equal to space % above. But it's pretty close. \def\Egroup{% % To get correct interline space between the last line of the group % and the first line afterwards, we have to propagate \prevdepth. \endgraf % Not \par, as it may have been set to \lisppar. \global\dimen1 = \prevdepth \egroup % End the \vtop. % \dimen0 is the vertical size of the group's box. \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox % \dimen2 is how much space is left on the page (more or less). \dimen2 = \pageheight \advance\dimen2 by -\pagetotal % if the group doesn't fit on the current page, and it's a big big % group, force a page break. \ifdim \dimen0 > \dimen2 \ifdim \pagetotal < \vfilllimit\pageheight \page \fi \fi \box\groupbox \prevdepth = \dimen1 \checkinserts } % % TeX puts in an \escapechar (i.e., `@') at the beginning of the help % message, so this ends up printing `@group can only ...'. % \newhelp\groupinvalidhelp{% group can only be used in environments such as @example,^^J% where each line of input produces a line of output.} % @need space-in-mils % forces a page break if there is not space-in-mils remaining. \newdimen\mil \mil=0.001in % Old definition--didn't work. %\parseargdef\need{\par % %% This method tries to make TeX break the page naturally %% if the depth of the box does not fit. %{\baselineskip=0pt% %\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak %\prevdepth=-1000pt %}} \parseargdef\need{% % Ensure vertical mode, so we don't make a big box in the middle of a % paragraph. \par % % If the @need value is less than one line space, it's useless. \dimen0 = #1\mil \dimen2 = \ht\strutbox \advance\dimen2 by \dp\strutbox \ifdim\dimen0 > \dimen2 % % Do a \strut just to make the height of this box be normal, so the % normal leading is inserted relative to the preceding line. % And a page break here is fine. \vtop to #1\mil{\strut\vfil}% % % TeX does not even consider page breaks if a penalty added to the % main vertical list is 10000 or more. But in order to see if the % empty box we just added fits on the page, we must make it consider % page breaks. On the other hand, we don't want to actually break the % page after the empty box. So we use a penalty of 9999. % % There is an extremely small chance that TeX will actually break the % page at this \penalty, if there are no other feasible breakpoints in % sight. (If the user is using lots of big @group commands, which % almost-but-not-quite fill up a page, TeX will have a hard time doing % good page breaking, for example.) However, I could not construct an % example where a page broke at this \penalty; if it happens in a real % document, then we can reconsider our strategy. \penalty9999 % % Back up by the size of the box, whether we did a page break or not. \kern -#1\mil % % Do not allow a page break right after this kern. \nobreak \fi } % @br forces paragraph break (and is undocumented). \let\br = \par % @page forces the start of a new page. % \def\page{\par\vfill\supereject} % @exdent text.... % outputs text on separate line in roman font, starting at standard page margin % This records the amount of indent in the innermost environment. % That's how much \exdent should take out. \newskip\exdentamount % This defn is used inside fill environments such as @defun. \parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} % This defn is used inside nofill environments such as @example. \parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount \leftline{\hskip\leftskip{\rm#1}}}} % @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current % paragraph. For more general purposes, use the \margin insertion % class. WHICH is `l' or `r'. % \newskip\inmarginspacing \inmarginspacing=1cm \def\strutdepth{\dp\strutbox} % \def\doinmargin#1#2{\strut\vadjust{% \nobreak \kern-\strutdepth \vtop to \strutdepth{% \baselineskip=\strutdepth \vss % if you have multiple lines of stuff to put here, you'll need to % make the vbox yourself of the appropriate size. \ifx#1l% \llap{\ignorespaces #2\hskip\inmarginspacing}% \else \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% \fi \null }% }} \def\inleftmargin{\doinmargin l} \def\inrightmargin{\doinmargin r} % % @inmargin{TEXT [, RIGHT-TEXT]} % (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; % else use TEXT for both). % \def\inmargin#1{\parseinmargin #1,,\finish} \def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0 > 0pt \def\lefttext{#1}% have both texts \def\righttext{#2}% \else \def\lefttext{#1}% have only one text \def\righttext{#1}% \fi % \ifodd\pageno \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin \else \def\temp{\inleftmargin\lefttext}% \fi \temp } % @include FILE -- \input text of FILE. % \def\include{\parseargusing\filenamecatcodes\includezzz} \def\includezzz#1{% \pushthisfilestack \def\thisfile{#1}% {% \makevalueexpandable % we want to expand any @value in FILE. \turnoffactive % and allow special characters in the expansion \indexnofonts % Allow `@@' and other weird things in file names. \edef\temp{\noexpand\input #1 }% % % This trickery is to read FILE outside of a group, in case it makes % definitions, etc. \expandafter }\temp \popthisfilestack } \def\filenamecatcodes{% \catcode`\\=\other \catcode`~=\other \catcode`^=\other \catcode`_=\other \catcode`|=\other \catcode`<=\other \catcode`>=\other \catcode`+=\other \catcode`-=\other \catcode`\`=\other \catcode`\'=\other } \def\pushthisfilestack{% \expandafter\pushthisfilestackX\popthisfilestack\StackTerm } \def\pushthisfilestackX{% \expandafter\pushthisfilestackY\thisfile\StackTerm } \def\pushthisfilestackY #1\StackTerm #2\StackTerm {% \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% } \def\popthisfilestack{\errthisfilestackempty} \def\errthisfilestackempty{\errmessage{Internal error: the stack of filenames is empty.}} \def\thisfile{} % @center line % outputs that line, centered. % \parseargdef\center{% \ifhmode \let\next\centerH \else \let\next\centerV \fi \next{\hfil \ignorespaces#1\unskip \hfil}% } \def\centerH#1{% {% \hfil\break \advance\hsize by -\leftskip \advance\hsize by -\rightskip \line{#1}% \break }% } \def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}} % @sp n outputs n lines of vertical space \parseargdef\sp{\vskip #1\baselineskip} % @comment ...line which is ignored... % @c is the same as @comment % @ignore ... @end ignore is another way to write a comment \def\comment{\begingroup \catcode`\^^M=\other% \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% \commentxxx} {\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} \let\c=\comment % @paragraphindent NCHARS % We'll use ems for NCHARS, close enough. % NCHARS can also be the word `asis' or `none'. % We cannot feasibly implement @paragraphindent asis, though. % \def\asisword{asis} % no translation, these are keywords \def\noneword{none} % \parseargdef\paragraphindent{% \def\temp{#1}% \ifx\temp\asisword \else \ifx\temp\noneword \defaultparindent = 0pt \else \defaultparindent = #1em \fi \fi \parindent = \defaultparindent } % @exampleindent NCHARS % We'll use ems for NCHARS like @paragraphindent. % It seems @exampleindent asis isn't necessary, but % I preserve it to make it similar to @paragraphindent. \parseargdef\exampleindent{% \def\temp{#1}% \ifx\temp\asisword \else \ifx\temp\noneword \lispnarrowing = 0pt \else \lispnarrowing = #1em \fi \fi } % @firstparagraphindent WORD % If WORD is `none', then suppress indentation of the first paragraph % after a section heading. If WORD is `insert', then do indent at such % paragraphs. % % The paragraph indentation is suppressed or not by calling % \suppressfirstparagraphindent, which the sectioning commands do. % We switch the definition of this back and forth according to WORD. % By default, we suppress indentation. % \def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} \def\insertword{insert} % \parseargdef\firstparagraphindent{% \def\temp{#1}% \ifx\temp\noneword \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent \else\ifx\temp\insertword \let\suppressfirstparagraphindent = \relax \else \errhelp = \EMsimple \errmessage{Unknown @firstparagraphindent option `\temp'}% \fi\fi } % Here is how we actually suppress indentation. Redefine \everypar to % \kern backwards by \parindent, and then reset itself to empty. % % We also make \indent itself not actually do anything until the next % paragraph. % \gdef\dosuppressfirstparagraphindent{% \gdef\indent{% \restorefirstparagraphindent \indent }% \gdef\noindent{% \restorefirstparagraphindent \noindent }% \global\everypar = {% \kern -\parindent \restorefirstparagraphindent }% } \gdef\restorefirstparagraphindent{% \global \let \indent = \ptexindent \global \let \noindent = \ptexnoindent \global \everypar = {}% } % @asis just yields its argument. Used with @table, for example. % \def\asis#1{#1} % @math outputs its argument in math mode. % % One complication: _ usually means subscripts, but it could also mean % an actual _ character, as in @math{@var{some_variable} + 1}. So make % _ active, and distinguish by seeing if the current family is \slfam, % which is what @var uses. { \catcode`\_ = \active \gdef\mathunderscore{% \catcode`\_=\active \def_{\ifnum\fam=\slfam \_\else\sb\fi}% } } % Another complication: we want \\ (and @\) to output a \ character. % FYI, plain.tex uses \\ as a temporary control sequence (why?), but % this is not advertised and we don't care. Texinfo does not % otherwise define @\. % % The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. \def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} % \def\math{% \tex \mathunderscore \let\\ = \mathbackslash \mathactive % make the texinfo accent commands work in math mode \let\"=\ddot \let\'=\acute \let\==\bar \let\^=\hat \let\`=\grave \let\u=\breve \let\v=\check \let\~=\tilde \let\dotaccent=\dot $\finishmath } \def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. % Some active characters (such as <) are spaced differently in math. % We have to reset their definitions in case the @math was an argument % to a command which sets the catcodes (such as @item or @section). % { \catcode`^ = \active \catcode`< = \active \catcode`> = \active \catcode`+ = \active \catcode`' = \active \gdef\mathactive{% \let^ = \ptexhat \let< = \ptexless \let> = \ptexgtr \let+ = \ptexplus \let' = \ptexquoteright } } % Some math mode symbols. \def\bullet{$\ptexbullet$} \def\geq{\ifmmode \ge\else $\ge$\fi} \def\leq{\ifmmode \le\else $\le$\fi} \def\minus{\ifmmode -\else $-$\fi} % @dots{} outputs an ellipsis using the current font. % We do .5em per period so that it has the same spacing in the cm % typewriter fonts as three actual period characters; on the other hand, % in other typewriter fonts three periods are wider than 1.5em. So do % whichever is larger. % \def\dots{% \leavevmode \setbox0=\hbox{...}% get width of three periods \ifdim\wd0 > 1.5em \dimen0 = \wd0 \else \dimen0 = 1.5em \fi \hbox to \dimen0{% \hskip 0pt plus.25fil .\hskip 0pt plus1fil .\hskip 0pt plus1fil .\hskip 0pt plus.5fil }% } % @enddots{} is an end-of-sentence ellipsis. % \def\enddots{% \dots \spacefactor=\endofsentencespacefactor } % @comma{} is so commas can be inserted into text without messing up % Texinfo's parsing. % \let\comma = , % @refill is a no-op. \let\refill=\relax % If working on a large document in chapters, it is convenient to % be able to disable indexing, cross-referencing, and contents, for test runs. % This is done with @novalidate (before @setfilename). % \newif\iflinks \linkstrue % by default we want the aux files. \let\novalidate = \linksfalse % @setfilename is done at the beginning of every texinfo file. % So open here the files we need to have open while reading the input. % This makes it possible to make a .fmt file for texinfo. \def\setfilename{% \fixbackslash % Turn off hack to swallow `\input texinfo'. \iflinks \tryauxfile % Open the new aux file. TeX will close it automatically at exit. \immediate\openout\auxfile=\jobname.aux \fi % \openindices needs to do some work in any case. \openindices \let\setfilename=\comment % Ignore extra @setfilename cmds. % % If texinfo.cnf is present on the system, read it. % Useful for site-wide @afourpaper, etc. \openin 1 texinfo.cnf \ifeof 1 \else \input texinfo.cnf \fi \closein 1 % \comment % Ignore the actual filename. } % Called from \setfilename. % \def\openindices{% \newindex{cp}% \newcodeindex{fn}% \newcodeindex{vr}% \newcodeindex{tp}% \newcodeindex{ky}% \newcodeindex{pg}% } % @bye. \outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} \message{pdf,} % adobe `portable' document format \newcount\tempnum \newcount\lnkcount \newtoks\filename \newcount\filenamelength \newcount\pgn \newtoks\toksA \newtoks\toksB \newtoks\toksC \newtoks\toksD \newbox\boxA \newcount\countA \newif\ifpdf \newif\ifpdfmakepagedest % when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 % can be set). So we test for \relax and 0 as well as \undefined, % borrowed from ifpdf.sty. \ifx\pdfoutput\undefined \else \ifx\pdfoutput\relax \else \ifcase\pdfoutput \else \pdftrue \fi \fi \fi % PDF uses PostScript string constants for the names of xref targets, % for display in the outlines, and in other places. Thus, we have to % double any backslashes. Otherwise, a name like "\node" will be % interpreted as a newline (\n), followed by o, d, e. Not good. % http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html % (and related messages, the final outcome is that it is up to the TeX % user to double the backslashes and otherwise make the string valid, so % that's what we do). % double active backslashes. % {\catcode`\@=0 \catcode`\\=\active @gdef@activebackslashdouble{% @catcode`@\=@active @let\=@doublebackslash} } % To handle parens, we must adopt a different approach, since parens are % not active characters. hyperref.dtx (which has the same problem as % us) handles it with this amazing macro to replace tokens, with minor % changes for Texinfo. It is included here under the GPL by permission % from the author, Heiko Oberdiek. % % #1 is the tokens to replace. % #2 is the replacement. % #3 is the control sequence with the string. % \def\HyPsdSubst#1#2#3{% \def\HyPsdReplace##1#1##2\END{% ##1% \ifx\\##2\\% \else #2% \HyReturnAfterFi{% \HyPsdReplace##2\END }% \fi }% \xdef#3{\expandafter\HyPsdReplace#3#1\END}% } \long\def\HyReturnAfterFi#1\fi{\fi#1} % #1 is a control sequence in which to do the replacements. \def\backslashparens#1{% \xdef#1{#1}% redefine it as its expansion; the definition is simply % \lastnode when called from \setref -> \pdfmkdest. \HyPsdSubst{(}{\realbackslash(}{#1}% \HyPsdSubst{)}{\realbackslash)}{#1}% } \newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images with PDF output, and none of those formats could be found. (.eps cannot be supported due to the design of the PDF format; use regular TeX (DVI output) for that.)} \ifpdf % % Color manipulation macros based on pdfcolor.tex. \def\cmykDarkRed{0.28 1 1 0.35} \def\cmykBlack{0 0 0 1} % \def\pdfsetcolor#1{\pdfliteral{#1 k}} % Set color, and create a mark which defines \thiscolor accordingly, % so that \makeheadline knows which color to restore. \def\setcolor#1{% \xdef\lastcolordefs{\gdef\noexpand\thiscolor{#1}}% \domark \pdfsetcolor{#1}% } % \def\maincolor{\cmykBlack} \pdfsetcolor{\maincolor} \edef\thiscolor{\maincolor} \def\lastcolordefs{} % \def\makefootline{% \baselineskip24pt \line{\pdfsetcolor{\maincolor}\the\footline}% } % \def\makeheadline{% \vbox to 0pt{% \vskip-22.5pt \line{% \vbox to8.5pt{}% % Extract \thiscolor definition from the marks. \getcolormarks % Typeset the headline with \maincolor, then restore the color. \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% }% \vss }% \nointerlineskip } % % \pdfcatalog{/PageMode /UseOutlines} % % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). \def\dopdfimage#1#2#3{% \def\imagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% \def\imageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% % % pdftex (and the PDF format) support .png, .jpg, .pdf (among % others). Let's try in that order. \let\pdfimgext=\empty \begingroup \openin 1 #1.png \ifeof 1 \openin 1 #1.jpg \ifeof 1 \openin 1 #1.jpeg \ifeof 1 \openin 1 #1.JPG \ifeof 1 \openin 1 #1.pdf \ifeof 1 \openin 1 #1.PDF \ifeof 1 \errhelp = \nopdfimagehelp \errmessage{Could not find image file #1 for pdf}% \else \gdef\pdfimgext{PDF}% \fi \else \gdef\pdfimgext{pdf}% \fi \else \gdef\pdfimgext{JPG}% \fi \else \gdef\pdfimgext{jpeg}% \fi \else \gdef\pdfimgext{jpg}% \fi \else \gdef\pdfimgext{png}% \fi \closein 1 \endgroup % % without \immediate, ancient pdftex seg faults when the same image is % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) \ifnum\pdftexversion < 14 \immediate\pdfimage \else \immediate\pdfximage \fi \ifdim \wd0 >0pt width \imagewidth \fi \ifdim \wd2 >0pt height \imageheight \fi \ifnum\pdftexversion<13 #1.\pdfimgext \else {#1.\pdfimgext}% \fi \ifnum\pdftexversion < 14 \else \pdfrefximage \pdflastximage \fi} % \def\pdfmkdest#1{{% % We have to set dummies so commands such as @code, and characters % such as \, aren't expanded when present in a section title. \indexnofonts \turnoffactive \activebackslashdouble \makevalueexpandable \def\pdfdestname{#1}% \backslashparens\pdfdestname \safewhatsit{\pdfdest name{\pdfdestname} xyz}% }} % % used to mark target names; must be expandable. \def\pdfmkpgn#1{#1} % % by default, use a color that is dark enough to print on paper as % nearly black, but still distinguishable for online viewing. \def\urlcolor{\cmykDarkRed} \def\linkcolor{\cmykDarkRed} \def\endlink{\setcolor{\maincolor}\pdfendlink} % % Adding outlines to PDF; macros for calculating structure of outlines % come from Petr Olsak \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% \else \csname#1\endcsname \fi} \def\advancenumber#1{\tempnum=\expnumber{#1}\relax \advance\tempnum by 1 \expandafter\xdef\csname#1\endcsname{\the\tempnum}} % % #1 is the section text, which is what will be displayed in the % outline by the pdf viewer. #2 is the pdf expression for the number % of subentries (or empty, for subsubsections). #3 is the node text, % which might be empty if this toc entry had no corresponding node. % #4 is the page number % \def\dopdfoutline#1#2#3#4{% % Generate a link to the node text if that exists; else, use the % page number. We could generate a destination for the section % text in the case where a section has no node, but it doesn't % seem worth the trouble, since most documents are normally structured. \def\pdfoutlinedest{#3}% \ifx\pdfoutlinedest\empty \def\pdfoutlinedest{#4}% \else % Doubled backslashes in the name. {\activebackslashdouble \xdef\pdfoutlinedest{#3}% \backslashparens\pdfoutlinedest}% \fi % % Also double the backslashes in the display string. {\activebackslashdouble \xdef\pdfoutlinetext{#1}% \backslashparens\pdfoutlinetext}% % \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}% } % \def\pdfmakeoutlines{% \begingroup % Thanh's hack / proper braces in bookmarks \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace % % Read toc silently, to get counts of subentries for \pdfoutline. \def\numchapentry##1##2##3##4{% \def\thischapnum{##2}% \def\thissecnum{0}% \def\thissubsecnum{0}% }% \def\numsecentry##1##2##3##4{% \advancenumber{chap\thischapnum}% \def\thissecnum{##2}% \def\thissubsecnum{0}% }% \def\numsubsecentry##1##2##3##4{% \advancenumber{sec\thissecnum}% \def\thissubsecnum{##2}% }% \def\numsubsubsecentry##1##2##3##4{% \advancenumber{subsec\thissubsecnum}% }% \def\thischapnum{0}% \def\thissecnum{0}% \def\thissubsecnum{0}% % % use \def rather than \let here because we redefine \chapentry et % al. a second time, below. \def\appentry{\numchapentry}% \def\appsecentry{\numsecentry}% \def\appsubsecentry{\numsubsecentry}% \def\appsubsubsecentry{\numsubsubsecentry}% \def\unnchapentry{\numchapentry}% \def\unnsecentry{\numsecentry}% \def\unnsubsecentry{\numsubsecentry}% \def\unnsubsubsecentry{\numsubsubsecentry}% \readdatafile{toc}% % % Read toc second time, this time actually producing the outlines. % The `-' means take the \expnumber as the absolute number of % subentries, which we calculated on our first read of the .toc above. % % We use the node names as the destinations. \def\numchapentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% \def\numsecentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% \def\numsubsecentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% \def\numsubsubsecentry##1##2##3##4{% count is always zero \dopdfoutline{##1}{}{##3}{##4}}% % % PDF outlines are displayed using system fonts, instead of % document fonts. Therefore we cannot use special characters, % since the encoding is unknown. For example, the eogonek from % Latin 2 (0xea) gets translated to a | character. Info from % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. % % xx to do this right, we have to translate 8-bit characters to % their "best" equivalent, based on the @documentencoding. Right % now, I guess we'll just let the pdf reader have its way. \indexnofonts \setupdatafile \catcode`\\=\active \otherbackslash \input \tocreadfilename \endgroup } % \def\skipspaces#1{\def\PP{#1}\def\D{|}% \ifx\PP\D\let\nextsp\relax \else\let\nextsp\skipspaces \ifx\p\space\else\addtokens{\filename}{\PP}% \advance\filenamelength by 1 \fi \fi \nextsp} \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} \ifnum\pdftexversion < 14 \let \startlink \pdfannotlink \else \let \startlink \pdfstartlink \fi % make a live url in pdf output. \def\pdfurl#1{% \begingroup % it seems we really need yet another set of dummies; have not % tried to figure out what each command should do in the context % of @url. for now, just make @/ a no-op, that's the only one % people have actually reported a problem with. % \normalturnoffactive \def\@{@}% \let\/=\empty \makevalueexpandable \leavevmode\setcolor{\urlcolor}% \startlink attr{/Border [0 0 0]}% user{/Subtype /Link /A << /S /URI /URI (#1) >>}% \endgroup} \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} \def\maketoks{% \expandafter\poptoks\the\toksA|ENDTOKS|\relax \ifx\first0\adn0 \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 \else \ifnum0=\countA\else\makelink\fi \ifx\first.\let\next=\done\else \let\next=\maketoks \addtokens{\toksB}{\the\toksD} \ifx\first,\addtokens{\toksB}{\space}\fi \fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \next} \def\makelink{\addtokens{\toksB}% {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} \def\pdflink#1{% \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} \setcolor{\linkcolor}#1\endlink} \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} \else \let\pdfmkdest = \gobble \let\pdfurl = \gobble \let\endlink = \relax \let\setcolor = \gobble \let\pdfsetcolor = \gobble \let\pdfmakeoutlines = \relax \fi % \ifx\pdfoutput \message{fonts,} % Change the current font style to #1, remembering it in \curfontstyle. % For now, we do not accumulate font styles: @b{@i{foo}} prints foo in % italics, not bold italics. % \def\setfontstyle#1{% \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. \csname ten#1\endcsname % change the current font } % Select #1 fonts with the current style. % \def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} \def\rm{\fam=0 \setfontstyle{rm}} \def\it{\fam=\itfam \setfontstyle{it}} \def\sl{\fam=\slfam \setfontstyle{sl}} \def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} \def\tt{\fam=\ttfam \setfontstyle{tt}} % Unfortunately, we have to override this for titles and the like, since % in those cases "rm" is bold. Sigh. \def\rmisbold{\rm\def\curfontstyle{bf}} % Texinfo sort of supports the sans serif font style, which plain TeX does not. % So we set up a \sf. \newfam\sffam \def\sf{\fam=\sffam \setfontstyle{sf}} \let\li = \sf % Sometimes we call it \li, not \sf. % We don't need math for this font style. \def\ttsl{\setfontstyle{ttsl}} % Default leading. \newdimen\textleading \textleading = 13.2pt % Set the baselineskip to #1, and the lineskip and strut size % correspondingly. There is no deep meaning behind these magic numbers % used as factors; they just match (closely enough) what Knuth defined. % \def\lineskipfactor{.08333} \def\strutheightpercent{.70833} \def\strutdepthpercent {.29167} % % can get a sort of poor man's double spacing by redefining this. \def\baselinefactor{1} % \def\setleading#1{% \dimen0 = #1\relax \normalbaselineskip = \baselinefactor\dimen0 \normallineskip = \lineskipfactor\normalbaselineskip \normalbaselines \setbox\strutbox =\hbox{% \vrule width0pt height\strutheightpercent\baselineskip depth \strutdepthpercent \baselineskip }% } % PDF CMaps. See also LaTeX's t1.cmap. % % do nothing with this by default. \expandafter\let\csname cmapOT1\endcsname\gobble \expandafter\let\csname cmapOT1IT\endcsname\gobble \expandafter\let\csname cmapOT1TT\endcsname\gobble % if we are producing pdf, and we have \pdffontattr, then define cmaps. % (\pdffontattr was introduced many years ago, but people still run % older pdftex's; it's easy to conditionalize, so we do.) \ifpdf \ifx\pdffontattr\undefined \else \begingroup \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap %%DocumentNeededResources: ProcSet (CIDInit) %%IncludeResource: ProcSet (CIDInit) %%BeginResource: CMap (TeX-OT1-0) %%Title: (TeX-OT1-0 TeX OT1 0) %%Version: 1.000 %%EndComments /CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo << /Registry (TeX) /Ordering (OT1) /Supplement 0 >> def /CMapName /TeX-OT1-0 def /CMapType 2 def 1 begincodespacerange <00> <7F> endcodespacerange 8 beginbfrange <00> <01> <0393> <09> <0A> <03A8> <23> <26> <0023> <28> <3B> <0028> <3F> <5B> <003F> <5D> <5E> <005D> <61> <7A> <0061> <7B> <7C> <2013> endbfrange 40 beginbfchar <02> <0398> <03> <039B> <04> <039E> <05> <03A0> <06> <03A3> <07> <03D2> <08> <03A6> <0B> <00660066> <0C> <00660069> <0D> <0066006C> <0E> <006600660069> <0F> <00660066006C> <10> <0131> <11> <0237> <12> <0060> <13> <00B4> <14> <02C7> <15> <02D8> <16> <00AF> <17> <02DA> <18> <00B8> <19> <00DF> <1A> <00E6> <1B> <0153> <1C> <00F8> <1D> <00C6> <1E> <0152> <1F> <00D8> <21> <0021> <22> <201D> <27> <2019> <3C> <00A1> <3D> <003D> <3E> <00BF> <5C> <201C> <5F> <02D9> <60> <2018> <7D> <02DD> <7E> <007E> <7F> <00A8> endbfchar endcmap CMapName currentdict /CMap defineresource pop end end %%EndResource %%EOF }\endgroup \expandafter\edef\csname cmapOT1\endcsname#1{% \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% }% % % \cmapOT1IT \begingroup \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap %%DocumentNeededResources: ProcSet (CIDInit) %%IncludeResource: ProcSet (CIDInit) %%BeginResource: CMap (TeX-OT1IT-0) %%Title: (TeX-OT1IT-0 TeX OT1IT 0) %%Version: 1.000 %%EndComments /CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo << /Registry (TeX) /Ordering (OT1IT) /Supplement 0 >> def /CMapName /TeX-OT1IT-0 def /CMapType 2 def 1 begincodespacerange <00> <7F> endcodespacerange 8 beginbfrange <00> <01> <0393> <09> <0A> <03A8> <25> <26> <0025> <28> <3B> <0028> <3F> <5B> <003F> <5D> <5E> <005D> <61> <7A> <0061> <7B> <7C> <2013> endbfrange 42 beginbfchar <02> <0398> <03> <039B> <04> <039E> <05> <03A0> <06> <03A3> <07> <03D2> <08> <03A6> <0B> <00660066> <0C> <00660069> <0D> <0066006C> <0E> <006600660069> <0F> <00660066006C> <10> <0131> <11> <0237> <12> <0060> <13> <00B4> <14> <02C7> <15> <02D8> <16> <00AF> <17> <02DA> <18> <00B8> <19> <00DF> <1A> <00E6> <1B> <0153> <1C> <00F8> <1D> <00C6> <1E> <0152> <1F> <00D8> <21> <0021> <22> <201D> <23> <0023> <24> <00A3> <27> <2019> <3C> <00A1> <3D> <003D> <3E> <00BF> <5C> <201C> <5F> <02D9> <60> <2018> <7D> <02DD> <7E> <007E> <7F> <00A8> endbfchar endcmap CMapName currentdict /CMap defineresource pop end end %%EndResource %%EOF }\endgroup \expandafter\edef\csname cmapOT1IT\endcsname#1{% \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% }% % % \cmapOT1TT \begingroup \catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char. \catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap %%DocumentNeededResources: ProcSet (CIDInit) %%IncludeResource: ProcSet (CIDInit) %%BeginResource: CMap (TeX-OT1TT-0) %%Title: (TeX-OT1TT-0 TeX OT1TT 0) %%Version: 1.000 %%EndComments /CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo << /Registry (TeX) /Ordering (OT1TT) /Supplement 0 >> def /CMapName /TeX-OT1TT-0 def /CMapType 2 def 1 begincodespacerange <00> <7F> endcodespacerange 5 beginbfrange <00> <01> <0393> <09> <0A> <03A8> <21> <26> <0021> <28> <5F> <0028> <61> <7E> <0061> endbfrange 32 beginbfchar <02> <0398> <03> <039B> <04> <039E> <05> <03A0> <06> <03A3> <07> <03D2> <08> <03A6> <0B> <2191> <0C> <2193> <0D> <0027> <0E> <00A1> <0F> <00BF> <10> <0131> <11> <0237> <12> <0060> <13> <00B4> <14> <02C7> <15> <02D8> <16> <00AF> <17> <02DA> <18> <00B8> <19> <00DF> <1A> <00E6> <1B> <0153> <1C> <00F8> <1D> <00C6> <1E> <0152> <1F> <00D8> <20> <2423> <27> <2019> <60> <2018> <7F> <00A8> endbfchar endcmap CMapName currentdict /CMap defineresource pop end end %%EndResource %%EOF }\endgroup \expandafter\edef\csname cmapOT1TT\endcsname#1{% \pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}% }% \fi\fi % Set the font macro #1 to the font named #2, adding on the % specified font prefix (normally `cm'). % #3 is the font's design size, #4 is a scale factor, #5 is the CMap % encoding (currently only OT1, OT1IT and OT1TT are allowed, pass % empty to omit). \def\setfont#1#2#3#4#5{% \font#1=\fontprefix#2#3 scaled #4 \csname cmap#5\endcsname#1% } % This is what gets called when #5 of \setfont is empty. \let\cmap\gobble % emacs-page end of cmaps % Use cm as the default font prefix. % To specify the font prefix, you must define \fontprefix % before you read in texinfo.tex. \ifx\fontprefix\undefined \def\fontprefix{cm} \fi % Support font families that don't use the same naming scheme as CM. \def\rmshape{r} \def\rmbshape{bx} %where the normal face is bold \def\bfshape{b} \def\bxshape{bx} \def\ttshape{tt} \def\ttbshape{tt} \def\ttslshape{sltt} \def\itshape{ti} \def\itbshape{bxti} \def\slshape{sl} \def\slbshape{bxsl} \def\sfshape{ss} \def\sfbshape{ss} \def\scshape{csc} \def\scbshape{csc} % Definitions for a main text size of 11pt. This is the default in % Texinfo. % \def\definetextfontsizexi{% % Text fonts (11.2pt, magstep1). \def\textnominalsize{11pt} \edef\mainmagstep{\magstephalf} \setfont\textrm\rmshape{10}{\mainmagstep}{OT1} \setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} \setfont\textbf\bfshape{10}{\mainmagstep}{OT1} \setfont\textit\itshape{10}{\mainmagstep}{OT1IT} \setfont\textsl\slshape{10}{\mainmagstep}{OT1} \setfont\textsf\sfshape{10}{\mainmagstep}{OT1} \setfont\textsc\scshape{10}{\mainmagstep}{OT1} \setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} \font\texti=cmmi10 scaled \mainmagstep \font\textsy=cmsy10 scaled \mainmagstep \def\textecsize{1095} % A few fonts for @defun names and args. \setfont\defbf\bfshape{10}{\magstep1}{OT1} \setfont\deftt\ttshape{10}{\magstep1}{OT1TT} \setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT} \def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} % Fonts for indices, footnotes, small examples (9pt). \def\smallnominalsize{9pt} \setfont\smallrm\rmshape{9}{1000}{OT1} \setfont\smalltt\ttshape{9}{1000}{OT1TT} \setfont\smallbf\bfshape{10}{900}{OT1} \setfont\smallit\itshape{9}{1000}{OT1IT} \setfont\smallsl\slshape{9}{1000}{OT1} \setfont\smallsf\sfshape{9}{1000}{OT1} \setfont\smallsc\scshape{10}{900}{OT1} \setfont\smallttsl\ttslshape{10}{900}{OT1TT} \font\smalli=cmmi9 \font\smallsy=cmsy9 \def\smallecsize{0900} % Fonts for small examples (8pt). \def\smallernominalsize{8pt} \setfont\smallerrm\rmshape{8}{1000}{OT1} \setfont\smallertt\ttshape{8}{1000}{OT1TT} \setfont\smallerbf\bfshape{10}{800}{OT1} \setfont\smallerit\itshape{8}{1000}{OT1IT} \setfont\smallersl\slshape{8}{1000}{OT1} \setfont\smallersf\sfshape{8}{1000}{OT1} \setfont\smallersc\scshape{10}{800}{OT1} \setfont\smallerttsl\ttslshape{10}{800}{OT1TT} \font\smalleri=cmmi8 \font\smallersy=cmsy8 \def\smallerecsize{0800} % Fonts for title page (20.4pt): \def\titlenominalsize{20pt} \setfont\titlerm\rmbshape{12}{\magstep3}{OT1} \setfont\titleit\itbshape{10}{\magstep4}{OT1IT} \setfont\titlesl\slbshape{10}{\magstep4}{OT1} \setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} \setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} \setfont\titlesf\sfbshape{17}{\magstep1}{OT1} \let\titlebf=\titlerm \setfont\titlesc\scbshape{10}{\magstep4}{OT1} \font\titlei=cmmi12 scaled \magstep3 \font\titlesy=cmsy10 scaled \magstep4 \def\titleecsize{2074} % Chapter (and unnumbered) fonts (17.28pt). \def\chapnominalsize{17pt} \setfont\chaprm\rmbshape{12}{\magstep2}{OT1} \setfont\chapit\itbshape{10}{\magstep3}{OT1IT} \setfont\chapsl\slbshape{10}{\magstep3}{OT1} \setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT} \setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT} \setfont\chapsf\sfbshape{17}{1000}{OT1} \let\chapbf=\chaprm \setfont\chapsc\scbshape{10}{\magstep3}{OT1} \font\chapi=cmmi12 scaled \magstep2 \font\chapsy=cmsy10 scaled \magstep3 \def\chapecsize{1728} % Section fonts (14.4pt). \def\secnominalsize{14pt} \setfont\secrm\rmbshape{12}{\magstep1}{OT1} \setfont\secit\itbshape{10}{\magstep2}{OT1IT} \setfont\secsl\slbshape{10}{\magstep2}{OT1} \setfont\sectt\ttbshape{12}{\magstep1}{OT1TT} \setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT} \setfont\secsf\sfbshape{12}{\magstep1}{OT1} \let\secbf\secrm \setfont\secsc\scbshape{10}{\magstep2}{OT1} \font\seci=cmmi12 scaled \magstep1 \font\secsy=cmsy10 scaled \magstep2 \def\sececsize{1440} % Subsection fonts (13.15pt). \def\ssecnominalsize{13pt} \setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1} \setfont\ssecit\itbshape{10}{1315}{OT1IT} \setfont\ssecsl\slbshape{10}{1315}{OT1} \setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT} \setfont\ssecttsl\ttslshape{10}{1315}{OT1TT} \setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1} \let\ssecbf\ssecrm \setfont\ssecsc\scbshape{10}{1315}{OT1} \font\sseci=cmmi12 scaled \magstephalf \font\ssecsy=cmsy10 scaled 1315 \def\ssececsize{1200} % Reduced fonts for @acro in text (10pt). \def\reducednominalsize{10pt} \setfont\reducedrm\rmshape{10}{1000}{OT1} \setfont\reducedtt\ttshape{10}{1000}{OT1TT} \setfont\reducedbf\bfshape{10}{1000}{OT1} \setfont\reducedit\itshape{10}{1000}{OT1IT} \setfont\reducedsl\slshape{10}{1000}{OT1} \setfont\reducedsf\sfshape{10}{1000}{OT1} \setfont\reducedsc\scshape{10}{1000}{OT1} \setfont\reducedttsl\ttslshape{10}{1000}{OT1TT} \font\reducedi=cmmi10 \font\reducedsy=cmsy10 \def\reducedecsize{1000} % reset the current fonts \textfonts \rm } % end of 11pt text font size definitions % Definitions to make the main text be 10pt Computer Modern, with % section, chapter, etc., sizes following suit. This is for the GNU % Press printing of the Emacs 22 manual. Maybe other manuals in the % future. Used with @smallbook, which sets the leading to 12pt. % \def\definetextfontsizex{% % Text fonts (10pt). \def\textnominalsize{10pt} \edef\mainmagstep{1000} \setfont\textrm\rmshape{10}{\mainmagstep}{OT1} \setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT} \setfont\textbf\bfshape{10}{\mainmagstep}{OT1} \setfont\textit\itshape{10}{\mainmagstep}{OT1IT} \setfont\textsl\slshape{10}{\mainmagstep}{OT1} \setfont\textsf\sfshape{10}{\mainmagstep}{OT1} \setfont\textsc\scshape{10}{\mainmagstep}{OT1} \setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT} \font\texti=cmmi10 scaled \mainmagstep \font\textsy=cmsy10 scaled \mainmagstep \def\textecsize{1000} % A few fonts for @defun names and args. \setfont\defbf\bfshape{10}{\magstephalf}{OT1} \setfont\deftt\ttshape{10}{\magstephalf}{OT1TT} \setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT} \def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} % Fonts for indices, footnotes, small examples (9pt). \def\smallnominalsize{9pt} \setfont\smallrm\rmshape{9}{1000}{OT1} \setfont\smalltt\ttshape{9}{1000}{OT1TT} \setfont\smallbf\bfshape{10}{900}{OT1} \setfont\smallit\itshape{9}{1000}{OT1IT} \setfont\smallsl\slshape{9}{1000}{OT1} \setfont\smallsf\sfshape{9}{1000}{OT1} \setfont\smallsc\scshape{10}{900}{OT1} \setfont\smallttsl\ttslshape{10}{900}{OT1TT} \font\smalli=cmmi9 \font\smallsy=cmsy9 \def\smallecsize{0900} % Fonts for small examples (8pt). \def\smallernominalsize{8pt} \setfont\smallerrm\rmshape{8}{1000}{OT1} \setfont\smallertt\ttshape{8}{1000}{OT1TT} \setfont\smallerbf\bfshape{10}{800}{OT1} \setfont\smallerit\itshape{8}{1000}{OT1IT} \setfont\smallersl\slshape{8}{1000}{OT1} \setfont\smallersf\sfshape{8}{1000}{OT1} \setfont\smallersc\scshape{10}{800}{OT1} \setfont\smallerttsl\ttslshape{10}{800}{OT1TT} \font\smalleri=cmmi8 \font\smallersy=cmsy8 \def\smallerecsize{0800} % Fonts for title page (20.4pt): \def\titlenominalsize{20pt} \setfont\titlerm\rmbshape{12}{\magstep3}{OT1} \setfont\titleit\itbshape{10}{\magstep4}{OT1IT} \setfont\titlesl\slbshape{10}{\magstep4}{OT1} \setfont\titlett\ttbshape{12}{\magstep3}{OT1TT} \setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT} \setfont\titlesf\sfbshape{17}{\magstep1}{OT1} \let\titlebf=\titlerm \setfont\titlesc\scbshape{10}{\magstep4}{OT1} \font\titlei=cmmi12 scaled \magstep3 \font\titlesy=cmsy10 scaled \magstep4 \def\titleecsize{2074} % Chapter fonts (14.4pt). \def\chapnominalsize{14pt} \setfont\chaprm\rmbshape{12}{\magstep1}{OT1} \setfont\chapit\itbshape{10}{\magstep2}{OT1IT} \setfont\chapsl\slbshape{10}{\magstep2}{OT1} \setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT} \setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT} \setfont\chapsf\sfbshape{12}{\magstep1}{OT1} \let\chapbf\chaprm \setfont\chapsc\scbshape{10}{\magstep2}{OT1} \font\chapi=cmmi12 scaled \magstep1 \font\chapsy=cmsy10 scaled \magstep2 \def\chapecsize{1440} % Section fonts (12pt). \def\secnominalsize{12pt} \setfont\secrm\rmbshape{12}{1000}{OT1} \setfont\secit\itbshape{10}{\magstep1}{OT1IT} \setfont\secsl\slbshape{10}{\magstep1}{OT1} \setfont\sectt\ttbshape{12}{1000}{OT1TT} \setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT} \setfont\secsf\sfbshape{12}{1000}{OT1} \let\secbf\secrm \setfont\secsc\scbshape{10}{\magstep1}{OT1} \font\seci=cmmi12 \font\secsy=cmsy10 scaled \magstep1 \def\sececsize{1200} % Subsection fonts (10pt). \def\ssecnominalsize{10pt} \setfont\ssecrm\rmbshape{10}{1000}{OT1} \setfont\ssecit\itbshape{10}{1000}{OT1IT} \setfont\ssecsl\slbshape{10}{1000}{OT1} \setfont\ssectt\ttbshape{10}{1000}{OT1TT} \setfont\ssecttsl\ttslshape{10}{1000}{OT1TT} \setfont\ssecsf\sfbshape{10}{1000}{OT1} \let\ssecbf\ssecrm \setfont\ssecsc\scbshape{10}{1000}{OT1} \font\sseci=cmmi10 \font\ssecsy=cmsy10 \def\ssececsize{1000} % Reduced fonts for @acro in text (9pt). \def\reducednominalsize{9pt} \setfont\reducedrm\rmshape{9}{1000}{OT1} \setfont\reducedtt\ttshape{9}{1000}{OT1TT} \setfont\reducedbf\bfshape{10}{900}{OT1} \setfont\reducedit\itshape{9}{1000}{OT1IT} \setfont\reducedsl\slshape{9}{1000}{OT1} \setfont\reducedsf\sfshape{9}{1000}{OT1} \setfont\reducedsc\scshape{10}{900}{OT1} \setfont\reducedttsl\ttslshape{10}{900}{OT1TT} \font\reducedi=cmmi9 \font\reducedsy=cmsy9 \def\reducedecsize{0900} % reduce space between paragraphs \divide\parskip by 2 % reset the current fonts \textfonts \rm } % end of 10pt text font size definitions % We provide the user-level command % @fonttextsize 10 % (or 11) to redefine the text font size. pt is assumed. % \def\xword{10} \def\xiword{11} % \parseargdef\fonttextsize{% \def\textsizearg{#1}% \wlog{doing @fonttextsize \textsizearg}% % % Set \globaldefs so that documents can use this inside @tex, since % makeinfo 4.8 does not support it, but we need it nonetheless. % \begingroup \globaldefs=1 \ifx\textsizearg\xword \definetextfontsizex \else \ifx\textsizearg\xiword \definetextfontsizexi \else \errhelp=\EMsimple \errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'} \fi\fi \endgroup } % In order for the font changes to affect most math symbols and letters, % we have to define the \textfont of the standard families. Since % texinfo doesn't allow for producing subscripts and superscripts except % in the main text, we don't bother to reset \scriptfont and % \scriptscriptfont (which would also require loading a lot more fonts). % \def\resetmathfonts{% \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf \textfont\ttfam=\tentt \textfont\sffam=\tensf } % The font-changing commands redefine the meanings of \tenSTYLE, instead % of just \STYLE. We do this because \STYLE needs to also set the % current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire % \tenSTYLE to set the current font. % % Each font-changing command also sets the names \lsize (one size lower) % and \lllsize (three sizes lower). These relative commands are used in % the LaTeX logo and acronyms. % % This all needs generalizing, badly. % \def\textfonts{% \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl \def\curfontsize{text}% \def\lsize{reduced}\def\lllsize{smaller}% \resetmathfonts \setleading{\textleading}} \def\titlefonts{% \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy \let\tenttsl=\titlettsl \def\curfontsize{title}% \def\lsize{chap}\def\lllsize{subsec}% \resetmathfonts \setleading{25pt}} \def\titlefont#1{{\titlefonts\rmisbold #1}} \def\chapfonts{% \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl \def\curfontsize{chap}% \def\lsize{sec}\def\lllsize{text}% \resetmathfonts \setleading{19pt}} \def\secfonts{% \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl \def\curfontsize{sec}% \def\lsize{subsec}\def\lllsize{reduced}% \resetmathfonts \setleading{16pt}} \def\subsecfonts{% \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl \def\curfontsize{ssec}% \def\lsize{text}\def\lllsize{small}% \resetmathfonts \setleading{15pt}} \let\subsubsecfonts = \subsecfonts \def\reducedfonts{% \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy \let\tenttsl=\reducedttsl \def\curfontsize{reduced}% \def\lsize{small}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallfonts{% \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy \let\tenttsl=\smallttsl \def\curfontsize{small}% \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallerfonts{% \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy \let\tenttsl=\smallerttsl \def\curfontsize{smaller}% \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{9.5pt}} % Set the fonts to use with the @small... environments. \let\smallexamplefonts = \smallfonts % About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample % can fit this many characters: % 8.5x11=86 smallbook=72 a4=90 a5=69 % If we use \scriptfonts (8pt), then we can fit this many characters: % 8.5x11=90+ smallbook=80 a4=90+ a5=77 % For me, subjectively, the few extra characters that fit aren't worth % the additional smallness of 8pt. So I'm making the default 9pt. % % By the way, for comparison, here's what fits with @example (10pt): % 8.5x11=71 smallbook=60 a4=75 a5=58 % % I wish the USA used A4 paper. % --karl, 24jan03. % Set up the default fonts, so we can use them for creating boxes. % \definetextfontsizexi % Define these so they can be easily changed for other fonts. \def\angleleft{$\langle$} \def\angleright{$\rangle$} % Count depth in font-changes, for error checks \newcount\fontdepth \fontdepth=0 % Fonts for short table of contents. \setfont\shortcontrm\rmshape{12}{1000}{OT1} \setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12 \setfont\shortcontsl\slshape{12}{1000}{OT1} \setfont\shortconttt\ttshape{12}{1000}{OT1TT} %% Add scribe-like font environments, plus @l for inline lisp (usually sans %% serif) and @ii for TeX italic % \smartitalic{ARG} outputs arg in italics, followed by an italic correction % unless the following character is such as not to need one. \def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else \ptexslash\fi\fi\fi} \def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} \def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} % like \smartslanted except unconditionally uses \ttsl. % @var is set to this for defun arguments. \def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx} % like \smartslanted except unconditionally use \sl. We never want % ttsl for book titles, do we? \def\cite#1{{\sl #1}\futurelet\next\smartitalicx} \let\i=\smartitalic \let\slanted=\smartslanted \def\var#1{{\setupmarkupstyle{var}\smartslanted{#1}}} \let\dfn=\smartslanted \let\emph=\smartitalic % @b, explicit bold. \def\b#1{{\bf #1}} \let\strong=\b % @sansserif, explicit sans. \def\sansserif#1{{\sf #1}} % We can't just use \exhyphenpenalty, because that only has effect at % the end of a paragraph. Restore normal hyphenation at the end of the % group within which \nohyphenation is presumably called. % \def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} \def\restorehyphenation{\hyphenchar\font = `- } % Set sfcode to normal for the chars that usually have another value. % Can't use plain's \frenchspacing because it uses the `\x notation, and % sometimes \x has an active definition that messes things up. % \catcode`@=11 \def\plainfrenchspacing{% \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m \def\endofsentencespacefactor{1000}% for @. and friends } \def\plainnonfrenchspacing{% \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000 \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 \def\endofsentencespacefactor{3000}% for @. and friends } \catcode`@=\other \def\endofsentencespacefactor{3000}% default \def\t#1{% {\tt \rawbackslash \plainfrenchspacing #1}% \null } \def\samp#1{{\setupmarkupstyle{samp}\lq\tclose{#1}\rq\null}} \setfont\keyrm\rmshape{8}{1000}{OT1} \font\keysy=cmsy9 \def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% \vbox{\hrule\kern-0.4pt \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% \kern-0.4pt\hrule}% \kern-.06em\raise0.4pt\hbox{\angleright}}}} \def\key #1{{\setupmarkupstyle{key}\nohyphenation \uppercase{#1}}\null} % The old definition, with no lozenge: %\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} \def\ctrl #1{{\tt \rawbackslash \hat}#1} % @file, @option are the same as @samp. \let\file=\samp \let\option=\samp % @code is a modification of @t, % which makes spaces the same size as normal in the surrounding text. \def\tclose#1{% {% % Change normal interword space to be same as for the current font. \spaceskip = \fontdimen2\font % % Switch to typewriter. \tt % % But `\ ' produces the large typewriter interword space. \def\ {{\spaceskip = 0pt{} }}% % % Turn off hyphenation. \nohyphenation % \rawbackslash \plainfrenchspacing #1% }% \null } % We *must* turn on hyphenation at `-' and `_' in @code. % Otherwise, it is too hard to avoid overfull hboxes % in the Emacs manual, the Library manual, etc. % Unfortunately, TeX uses one parameter (\hyphenchar) to control % both hyphenation at - and hyphenation within words. % We must therefore turn them both off (\tclose does that) % and arrange explicitly to hyphenate at a dash. % -- rms. { \catcode`\-=\active \catcode`\_=\active \catcode`\'=\active \catcode`\`=\active \global\let'=\rq \global\let`=\lq % default definitions % \global\def\code{\begingroup \setupmarkupstyle{code}% % The following should really be moved into \setupmarkupstyle handlers. \catcode\dashChar=\active \catcode\underChar=\active \ifallowcodebreaks \let-\codedash \let_\codeunder \else \let-\realdash \let_\realunder \fi \codex } } \def\realdash{-} \def\codedash{-\discretionary{}{}{}} \def\codeunder{% % this is all so @math{@code{var_name}+1} can work. In math mode, _ % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) % will therefore expand the active definition of _, which is us % (inside @code that is), therefore an endless loop. \ifusingtt{\ifmmode \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. \else\normalunderscore \fi \discretionary{}{}{}}% {\_}% } \def\codex #1{\tclose{#1}\endgroup} % An additional complication: the above will allow breaks after, e.g., % each of the four underscores in __typeof__. This is undesirable in % some manuals, especially if they don't have long identifiers in % general. @allowcodebreaks provides a way to control this. % \newif\ifallowcodebreaks \allowcodebreakstrue \def\keywordtrue{true} \def\keywordfalse{false} \parseargdef\allowcodebreaks{% \def\txiarg{#1}% \ifx\txiarg\keywordtrue \allowcodebreakstrue \else\ifx\txiarg\keywordfalse \allowcodebreaksfalse \else \errhelp = \EMsimple \errmessage{Unknown @allowcodebreaks option `\txiarg'}% \fi\fi } % @kbd is like @code, except that if the argument is just one @key command, % then @kbd has no effect. % @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), % `example' (@kbd uses ttsl only inside of @example and friends), % or `code' (@kbd uses normal tty font always). \parseargdef\kbdinputstyle{% \def\txiarg{#1}% \ifx\txiarg\worddistinct \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% \else\ifx\txiarg\wordexample \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% \else\ifx\txiarg\wordcode \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% \else \errhelp = \EMsimple \errmessage{Unknown @kbdinputstyle option `\txiarg'}% \fi\fi\fi } \def\worddistinct{distinct} \def\wordexample{example} \def\wordcode{code} % Default is `distinct.' \kbdinputstyle distinct \def\xkey{\key} \def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% \ifx\one\xkey\ifx\threex\three \key{#2}% \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi} % For @indicateurl, @env, @command quotes seem unnecessary, so use \code. \let\indicateurl=\code \let\env=\code \let\command=\code % @clicksequence{File @click{} Open ...} \def\clicksequence#1{\begingroup #1\endgroup} % @clickstyle @arrow (by default) \parseargdef\clickstyle{\def\click{#1}} \def\click{\arrow} % @uref (abbreviation for `urlref') takes an optional (comma-separated) % second argument specifying the text to display and an optional third % arg as text to display instead of (rather than in addition to) the url % itself. First (mandatory) arg is the url. Perhaps eventually put in % a hypertex \special here. % \def\uref#1{\douref #1,,,\finish} \def\douref#1,#2,#3,#4\finish{\begingroup \unsepspaces \pdfurl{#1}% \setbox0 = \hbox{\ignorespaces #3}% \ifdim\wd0 > 0pt \unhbox0 % third arg given, show only that \else \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0 > 0pt \ifpdf \unhbox0 % PDF: 2nd arg given, show only it \else \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url \fi \else \code{#1}% only url given, so show it \fi \fi \endlink \endgroup} % @url synonym for @uref, since that's how everyone uses it. % \let\url=\uref % rms does not like angle brackets --karl, 17may97. % So now @email is just like @uref, unless we are pdf. % %\def\email#1{\angleleft{\tt #1}\angleright} \ifpdf \def\email#1{\doemail#1,,\finish} \def\doemail#1,#2,#3\finish{\begingroup \unsepspaces \pdfurl{mailto:#1}% \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi \endlink \endgroup} \else \let\email=\uref \fi % Check if we are currently using a typewriter font. Since all the % Computer Modern typewriter fonts have zero interword stretch (and % shrink), and it is reasonable to expect all typewriter fonts to have % this property, we can check that font parameter. % \def\ifmonospace{\ifdim\fontdimen3\font=0pt } % Typeset a dimension, e.g., `in' or `pt'. The only reason for the % argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. % \def\dmn#1{\thinspace #1} \def\kbd#1{{\setupmarkupstyle{kbd}\def\look{#1}\expandafter\kbdfoo\look??\par}} % @l was never documented to mean ``switch to the Lisp font'', % and it is not used as such in any manual I can find. We need it for % Polish suppressed-l. --karl, 22sep96. %\def\l#1{{\li #1}\null} % Explicit font changes: @r, @sc, undocumented @ii. \def\r#1{{\rm #1}} % roman font \def\sc#1{{\smallcaps#1}} % smallcaps font \def\ii#1{{\it #1}} % italic font % @acronym for "FBI", "NATO", and the like. % We print this one point size smaller, since it's intended for % all-uppercase. % \def\acronym#1{\doacronym #1,,\finish} \def\doacronym#1,#2,#3\finish{% {\selectfonts\lsize #1}% \def\temp{#2}% \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% \fi } % @abbr for "Comput. J." and the like. % No font change, but don't do end-of-sentence spacing. % \def\abbr#1{\doabbr #1,,\finish} \def\doabbr#1,#2,#3\finish{% {\plainfrenchspacing #1}% \def\temp{#2}% \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% \fi } % @pounds{} is a sterling sign, which Knuth put in the CM italic font. % \def\pounds{{\it\$}} % @euro{} comes from a separate font, depending on the current style. % We use the free feym* fonts from the eurosym package by Henrik % Theiling, which support regular, slanted, bold and bold slanted (and % "outlined" (blackboard board, sort of) versions, which we don't need). % It is available from http://www.ctan.org/tex-archive/fonts/eurosym. % % Although only regular is the truly official Euro symbol, we ignore % that. The Euro is designed to be slightly taller than the regular % font height. % % feymr - regular % feymo - slanted % feybr - bold % feybo - bold slanted % % There is no good (free) typewriter version, to my knowledge. % A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide. % Hmm. % % Also doesn't work in math. Do we need to do math with euro symbols? % Hope not. % % \def\euro{{\eurofont e}} \def\eurofont{% % We set the font at each command, rather than predefining it in % \textfonts and the other font-switching commands, so that % installations which never need the symbol don't have to have the % font installed. % % There is only one designed size (nominal 10pt), so we always scale % that to the current nominal size. % % By the way, simply using "at 1em" works for cmr10 and the like, but % does not work for cmbx10 and other extended/shrunken fonts. % \def\eurosize{\csname\curfontsize nominalsize\endcsname}% % \ifx\curfontstyle\bfstylename % bold: \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize \else % regular: \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize \fi \thiseurofont } % Hacks for glyphs from the EC fonts similar to \euro. We don't % use \let for the aliases, because sometimes we redefine the original % macro, and the alias should reflect the redefinition. \def\guillemetleft{{\ecfont \char"13}} \def\guillemotleft{\guillemetleft} \def\guillemetright{{\ecfont \char"14}} \def\guillemotright{\guillemetright} \def\guilsinglleft{{\ecfont \char"0E}} \def\guilsinglright{{\ecfont \char"0F}} \def\quotedblbase{{\ecfont \char"12}} \def\quotesinglbase{{\ecfont \char"0D}} % % This positioning is not perfect (see the ogonek LaTeX package), but % we have the precomposed glyphs for the most common cases. We put the % tests to use those glyphs in the single \ogonek macro so we have fewer % dummy definitions to worry about for index entries, etc. % % ogonek is also used with other letters in Lithuanian (IOU), but using % the precomposed glyphs for those is not so easy since they aren't in % the same EC font. \def\ogonek#1{{% \def\temp{#1}% \ifx\temp\macrocharA\Aogonek \else\ifx\temp\macrochara\aogonek \else\ifx\temp\macrocharE\Eogonek \else\ifx\temp\macrochare\eogonek \else \ecfont \setbox0=\hbox{#1}% \ifdim\ht0=1ex\accent"0C #1% \else\ooalign{\unhbox0\crcr\hidewidth\char"0C \hidewidth}% \fi \fi\fi\fi\fi }% } \def\Aogonek{{\ecfont \char"81}}\def\macrocharA{A} \def\aogonek{{\ecfont \char"A1}}\def\macrochara{a} \def\Eogonek{{\ecfont \char"86}}\def\macrocharE{E} \def\eogonek{{\ecfont \char"A6}}\def\macrochare{e} % \def\ecfont{% % We can't distinguish serif/sans and italic/slanted, but this % is used for crude hacks anyway (like adding French and German % quotes to documents typeset with CM, where we lose kerning), so % hopefully nobody will notice/care. \edef\ecsize{\csname\curfontsize ecsize\endcsname}% \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}% \ifx\curfontstyle\bfstylename % bold: \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize \else % regular: \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize \fi \thisecfont } % @registeredsymbol - R in a circle. The font for the R should really % be smaller yet, but lllsize is the best we can do for now. % Adapted from the plain.tex definition of \copyright. % \def\registeredsymbol{% $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% \hfil\crcr\Orb}}% }$% } % @textdegree - the normal degrees sign. % \def\textdegree{$^\circ$} % Laurent Siebenmann reports \Orb undefined with: % Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 % so we'll define it if necessary. % \ifx\Orb\undefined \def\Orb{\mathhexbox20D} \fi % Quotes. \chardef\quotedblleft="5C \chardef\quotedblright=`\" \chardef\quoteleft=`\` \chardef\quoteright=`\' \message{page headings,} \newskip\titlepagetopglue \titlepagetopglue = 1.5in \newskip\titlepagebottomglue \titlepagebottomglue = 2pc % First the title page. Must do @settitle before @titlepage. \newif\ifseenauthor \newif\iffinishedtitlepage % Do an implicit @contents or @shortcontents after @end titlepage if the % user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. % \newif\ifsetcontentsaftertitlepage \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue \newif\ifsetshortcontentsaftertitlepage \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue \parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% \endgroup\page\hbox{}\page} \envdef\titlepage{% % Open one extra group, as we want to close it in the middle of \Etitlepage. \begingroup \parindent=0pt \textfonts % Leave some space at the very top of the page. \vglue\titlepagetopglue % No rule at page bottom unless we print one at the top with @title. \finishedtitlepagetrue % % Most title ``pages'' are actually two pages long, with space % at the top of the second. We don't want the ragged left on the second. \let\oldpage = \page \def\page{% \iffinishedtitlepage\else \finishtitlepage \fi \let\page = \oldpage \page \null }% } \def\Etitlepage{% \iffinishedtitlepage\else \finishtitlepage \fi % It is important to do the page break before ending the group, % because the headline and footline are only empty inside the group. % If we use the new definition of \page, we always get a blank page % after the title page, which we certainly don't want. \oldpage \endgroup % % Need this before the \...aftertitlepage checks so that if they are % in effect the toc pages will come out with page numbers. \HEADINGSon % % If they want short, they certainly want long too. \ifsetshortcontentsaftertitlepage \shortcontents \contents \global\let\shortcontents = \relax \global\let\contents = \relax \fi % \ifsetcontentsaftertitlepage \contents \global\let\contents = \relax \global\let\shortcontents = \relax \fi } \def\finishtitlepage{% \vskip4pt \hrule height 2pt width \hsize \vskip\titlepagebottomglue \finishedtitlepagetrue } %%% Macros to be used within @titlepage: \let\subtitlerm=\tenrm \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} \parseargdef\title{% \checkenv\titlepage \leftline{\titlefonts\rmisbold #1} % print a rule at the page bottom also. \finishedtitlepagefalse \vskip4pt \hrule height 4pt width \hsize \vskip4pt } \parseargdef\subtitle{% \checkenv\titlepage {\subtitlefont \rightline{#1}}% } % @author should come last, but may come many times. % It can also be used inside @quotation. % \parseargdef\author{% \def\temp{\quotation}% \ifx\thisenv\temp \def\quotationauthor{#1}% printed in \Equotation. \else \checkenv\titlepage \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi {\secfonts\rmisbold \leftline{#1}}% \fi } %%% Set up page headings and footings. \let\thispage=\folio \newtoks\evenheadline % headline on even pages \newtoks\oddheadline % headline on odd pages \newtoks\evenfootline % footline on even pages \newtoks\oddfootline % footline on odd pages % Now make TeX use those variables \headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \else \the\evenheadline \fi}} \footline={{\textfonts\rm \ifodd\pageno \the\oddfootline \else \the\evenfootline \fi}\HEADINGShook} \let\HEADINGShook=\relax % Commands to set those variables. % For example, this is what @headings on does % @evenheading @thistitle|@thispage|@thischapter % @oddheading @thischapter|@thispage|@thistitle % @evenfooting @thisfile|| % @oddfooting ||@thisfile \def\evenheading{\parsearg\evenheadingxxx} \def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} \def\evenheadingyyy #1\|#2\|#3\|#4\finish{% \global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \def\oddheading{\parsearg\oddheadingxxx} \def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} \def\oddheadingyyy #1\|#2\|#3\|#4\finish{% \global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% \def\evenfooting{\parsearg\evenfootingxxx} \def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} \def\evenfootingyyy #1\|#2\|#3\|#4\finish{% \global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \def\oddfooting{\parsearg\oddfootingxxx} \def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} \def\oddfootingyyy #1\|#2\|#3\|#4\finish{% \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% % % Leave some space for the footline. Hopefully ok to assume % @evenfooting will not be used by itself. \global\advance\pageheight by -12pt \global\advance\vsize by -12pt } \parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} % @evenheadingmarks top \thischapter <- chapter at the top of a page % @evenheadingmarks bottom \thischapter <- chapter at the bottom of a page % % The same set of arguments for: % % @oddheadingmarks % @evenfootingmarks % @oddfootingmarks % @everyheadingmarks % @everyfootingmarks \def\evenheadingmarks{\headingmarks{even}{heading}} \def\oddheadingmarks{\headingmarks{odd}{heading}} \def\evenfootingmarks{\headingmarks{even}{footing}} \def\oddfootingmarks{\headingmarks{odd}{footing}} \def\everyheadingmarks#1 {\headingmarks{even}{heading}{#1} \headingmarks{odd}{heading}{#1} } \def\everyfootingmarks#1 {\headingmarks{even}{footing}{#1} \headingmarks{odd}{footing}{#1} } % #1 = even/odd, #2 = heading/footing, #3 = top/bottom. \def\headingmarks#1#2#3 {% \expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname \global\expandafter\let\csname get#1#2marks\endcsname \temp } \everyheadingmarks bottom \everyfootingmarks bottom % @headings double turns headings on for double-sided printing. % @headings single turns headings on for single-sided printing. % @headings off turns them off. % @headings on same as @headings double, retained for compatibility. % @headings after turns on double-sided headings after this page. % @headings doubleafter turns on double-sided headings after this page. % @headings singleafter turns on single-sided headings after this page. % By default, they are off at the start of a document, % and turned `on' after @end titlepage. \def\headings #1 {\csname HEADINGS#1\endcsname} \def\HEADINGSoff{% \global\evenheadline={\hfil} \global\evenfootline={\hfil} \global\oddheadline={\hfil} \global\oddfootline={\hfil}} \HEADINGSoff % When we turn headings on, set the page number to 1. % For double-sided printing, put current file name in lower left corner, % chapter name on inside top of right hand pages, document % title on inside top of left hand pages, and page numbers on outside top % edge of all pages. \def\HEADINGSdouble{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \let\contentsalignmacro = \chappager % For single-sided printing, chapter title goes across top left of page, % page number on top right. \def\HEADINGSsingle{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\thischapter\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chappager } \def\HEADINGSon{\HEADINGSdouble} \def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} \let\HEADINGSdoubleafter=\HEADINGSafter \def\HEADINGSdoublex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} \def\HEADINGSsinglex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\thischapter\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chappager } % Subroutines used in generating headings % This produces Day Month Year style of output. % Only define if not already defined, in case a txi-??.tex file has set % up a different format (e.g., txi-cs.tex does this). \ifx\today\undefined \def\today{% \number\day\space \ifcase\month \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec \fi \space\number\year} \fi % @settitle line... specifies the title of the document, for headings. % It generates no output of its own. \def\thistitle{\putwordNoTitle} \def\settitle{\parsearg{\gdef\thistitle}} \message{tables,} % Tables -- @table, @ftable, @vtable, @item(x). % default indentation of table text \newdimen\tableindent \tableindent=.8in % default indentation of @itemize and @enumerate text \newdimen\itemindent \itemindent=.3in % margin between end of table item and start of table text. \newdimen\itemmargin \itemmargin=.1in % used internally for \itemindent minus \itemmargin \newdimen\itemmax % Note @table, @ftable, and @vtable define @item, @itemx, etc., with % these defs. % They also define \itemindex % to index the item name in whatever manner is desired (perhaps none). \newif\ifitemxneedsnegativevskip \def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} \def\internalBitem{\smallbreak \parsearg\itemzzz} \def\internalBitemx{\itemxpar \parsearg\itemzzz} \def\itemzzz #1{\begingroup % \advance\hsize by -\rightskip \advance\hsize by -\tableindent \setbox0=\hbox{\itemindicate{#1}}% \itemindex{#1}% \nobreak % This prevents a break before @itemx. % % If the item text does not fit in the space we have, put it on a line % by itself, and do not allow a page break either before or after that % line. We do not start a paragraph here because then if the next % command is, e.g., @kindex, the whatsit would get put into the % horizontal list on a line by itself, resulting in extra blank space. \ifdim \wd0>\itemmax % % Make this a paragraph so we get the \parskip glue and wrapping, % but leave it ragged-right. \begingroup \advance\leftskip by-\tableindent \advance\hsize by\tableindent \advance\rightskip by0pt plus1fil \leavevmode\unhbox0\par \endgroup % % We're going to be starting a paragraph, but we don't want the % \parskip glue -- logically it's part of the @item we just started. \nobreak \vskip-\parskip % % Stop a page break at the \parskip glue coming up. However, if % what follows is an environment such as @example, there will be no % \parskip glue; then the negative vskip we just inserted would % cause the example and the item to crash together. So we use this % bizarre value of 10001 as a signal to \aboveenvbreak to insert % \parskip glue after all. Section titles are handled this way also. % \penalty 10001 \endgroup \itemxneedsnegativevskipfalse \else % The item text fits into the space. Start a paragraph, so that the % following text (if any) will end up on the same line. \noindent % Do this with kerns and \unhbox so that if there is a footnote in % the item text, it can migrate to the main vertical list and % eventually be printed. \nobreak\kern-\tableindent \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 \unhbox0 \nobreak\kern\dimen0 \endgroup \itemxneedsnegativevskiptrue \fi } \def\item{\errmessage{@item while not in a list environment}} \def\itemx{\errmessage{@itemx while not in a list environment}} % @table, @ftable, @vtable. \envdef\table{% \let\itemindex\gobble \tablecheck{table}% } \envdef\ftable{% \def\itemindex ##1{\doind {fn}{\code{##1}}}% \tablecheck{ftable}% } \envdef\vtable{% \def\itemindex ##1{\doind {vr}{\code{##1}}}% \tablecheck{vtable}% } \def\tablecheck#1{% \ifnum \the\catcode`\^^M=\active \endgroup \errmessage{This command won't work in this context; perhaps the problem is that we are \inenvironment\thisenv}% \def\next{\doignore{#1}}% \else \let\next\tablex \fi \next } \def\tablex#1{% \def\itemindicate{#1}% \parsearg\tabley } \def\tabley#1{% {% \makevalueexpandable \edef\temp{\noexpand\tablez #1\space\space\space}% \expandafter }\temp \endtablez } \def\tablez #1 #2 #3 #4\endtablez{% \aboveenvbreak \ifnum 0#1>0 \advance \leftskip by #1\mil \fi \ifnum 0#2>0 \tableindent=#2\mil \fi \ifnum 0#3>0 \advance \rightskip by #3\mil \fi \itemmax=\tableindent \advance \itemmax by -\itemmargin \advance \leftskip by \tableindent \exdentamount=\tableindent \parindent = 0pt \parskip = \smallskipamount \ifdim \parskip=0pt \parskip=2pt \fi \let\item = \internalBitem \let\itemx = \internalBitemx } \def\Etable{\endgraf\afterenvbreak} \let\Eftable\Etable \let\Evtable\Etable \let\Eitemize\Etable \let\Eenumerate\Etable % This is the counter used by @enumerate, which is really @itemize \newcount \itemno \envdef\itemize{\parsearg\doitemize} \def\doitemize#1{% \aboveenvbreak \itemmax=\itemindent \advance\itemmax by -\itemmargin \advance\leftskip by \itemindent \exdentamount=\itemindent \parindent=0pt \parskip=\smallskipamount \ifdim\parskip=0pt \parskip=2pt \fi \def\itemcontents{#1}% % @itemize with no arg is equivalent to @itemize @bullet. \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi \let\item=\itemizeitem } % Definition of @item while inside @itemize and @enumerate. % \def\itemizeitem{% \advance\itemno by 1 % for enumerations {\let\par=\endgraf \smallbreak}% reasonable place to break {% % If the document has an @itemize directly after a section title, a % \nobreak will be last on the list, and \sectionheading will have % done a \vskip-\parskip. In that case, we don't want to zero % parskip, or the item text will crash with the heading. On the % other hand, when there is normal text preceding the item (as there % usually is), we do want to zero parskip, or there would be too much % space. In that case, we won't have a \nobreak before. At least % that's the theory. \ifnum\lastpenalty<10000 \parskip=0in \fi \noindent \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% \vadjust{\penalty 1200}}% not good to break after first line of item. \flushcr } % \splitoff TOKENS\endmark defines \first to be the first token in % TOKENS, and \rest to be the remainder. % \def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% % Allow an optional argument of an uppercase letter, lowercase letter, % or number, to specify the first label in the enumerated list. No % argument is the same as `1'. % \envparseargdef\enumerate{\enumeratey #1 \endenumeratey} \def\enumeratey #1 #2\endenumeratey{% % If we were given no argument, pretend we were given `1'. \def\thearg{#1}% \ifx\thearg\empty \def\thearg{1}\fi % % Detect if the argument is a single token. If so, it might be a % letter. Otherwise, the only valid thing it can be is a number. % (We will always have one token, because of the test we just made. % This is a good thing, since \splitoff doesn't work given nothing at % all -- the first parameter is undelimited.) \expandafter\splitoff\thearg\endmark \ifx\rest\empty % Only one token in the argument. It could still be anything. % A ``lowercase letter'' is one whose \lccode is nonzero. % An ``uppercase letter'' is one whose \lccode is both nonzero, and % not equal to itself. % Otherwise, we assume it's a number. % % We need the \relax at the end of the \ifnum lines to stop TeX from % continuing to look for a . % \ifnum\lccode\expandafter`\thearg=0\relax \numericenumerate % a number (we hope) \else % It's a letter. \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax \lowercaseenumerate % lowercase letter \else \uppercaseenumerate % uppercase letter \fi \fi \else % Multiple tokens in the argument. We hope it's a number. \numericenumerate \fi } % An @enumerate whose labels are integers. The starting integer is % given in \thearg. % \def\numericenumerate{% \itemno = \thearg \startenumeration{\the\itemno}% } % The starting (lowercase) letter is in \thearg. \def\lowercaseenumerate{% \itemno = \expandafter`\thearg \startenumeration{% % Be sure we're not beyond the end of the alphabet. \ifnum\itemno=0 \errmessage{No more lowercase letters in @enumerate; get a bigger alphabet}% \fi \char\lccode\itemno }% } % The starting (uppercase) letter is in \thearg. \def\uppercaseenumerate{% \itemno = \expandafter`\thearg \startenumeration{% % Be sure we're not beyond the end of the alphabet. \ifnum\itemno=0 \errmessage{No more uppercase letters in @enumerate; get a bigger alphabet} \fi \char\uccode\itemno }% } % Call \doitemize, adding a period to the first argument and supplying the % common last two arguments. Also subtract one from the initial value in % \itemno, since @item increments \itemno. % \def\startenumeration#1{% \advance\itemno by -1 \doitemize{#1.}\flushcr } % @alphaenumerate and @capsenumerate are abbreviations for giving an arg % to @enumerate. % \def\alphaenumerate{\enumerate{a}} \def\capsenumerate{\enumerate{A}} \def\Ealphaenumerate{\Eenumerate} \def\Ecapsenumerate{\Eenumerate} % @multitable macros % Amy Hendrickson, 8/18/94, 3/6/96 % % @multitable ... @end multitable will make as many columns as desired. % Contents of each column will wrap at width given in preamble. Width % can be specified either with sample text given in a template line, % or in percent of \hsize, the current width of text on page. % Table can continue over pages but will only break between lines. % To make preamble: % % Either define widths of columns in terms of percent of \hsize: % @multitable @columnfractions .25 .3 .45 % @item ... % % Numbers following @columnfractions are the percent of the total % current hsize to be used for each column. You may use as many % columns as desired. % Or use a template: % @multitable {Column 1 template} {Column 2 template} {Column 3 template} % @item ... % using the widest term desired in each column. % Each new table line starts with @item, each subsequent new column % starts with @tab. Empty columns may be produced by supplying @tab's % with nothing between them for as many times as empty columns are needed, % ie, @tab@tab@tab will produce two empty columns. % @item, @tab do not need to be on their own lines, but it will not hurt % if they are. % Sample multitable: % @multitable {Column 1 template} {Column 2 template} {Column 3 template} % @item first col stuff @tab second col stuff @tab third col % @item % first col stuff % @tab % second col stuff % @tab % third col % @item first col stuff @tab second col stuff % @tab Many paragraphs of text may be used in any column. % % They will wrap at the width determined by the template. % @item@tab@tab This will be in third column. % @end multitable % Default dimensions may be reset by user. % @multitableparskip is vertical space between paragraphs in table. % @multitableparindent is paragraph indent in table. % @multitablecolmargin is horizontal space to be left between columns. % @multitablelinespace is space to leave between table items, baseline % to baseline. % 0pt means it depends on current normal line spacing. % \newskip\multitableparskip \newskip\multitableparindent \newdimen\multitablecolspace \newskip\multitablelinespace \multitableparskip=0pt \multitableparindent=6pt \multitablecolspace=12pt \multitablelinespace=0pt % Macros used to set up halign preamble: % \let\endsetuptable\relax \def\xendsetuptable{\endsetuptable} \let\columnfractions\relax \def\xcolumnfractions{\columnfractions} \newif\ifsetpercent % #1 is the @columnfraction, usually a decimal number like .5, but might % be just 1. We just use it, whatever it is. % \def\pickupwholefraction#1 {% \global\advance\colcount by 1 \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% \setuptable } \newcount\colcount \def\setuptable#1{% \def\firstarg{#1}% \ifx\firstarg\xendsetuptable \let\go = \relax \else \ifx\firstarg\xcolumnfractions \global\setpercenttrue \else \ifsetpercent \let\go\pickupwholefraction \else \global\advance\colcount by 1 \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a % separator; typically that is always in the input, anyway. \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% \fi \fi \ifx\go\pickupwholefraction % Put the argument back for the \pickupwholefraction call, so % we'll always have a period there to be parsed. \def\go{\pickupwholefraction#1}% \else \let\go = \setuptable \fi% \fi \go } % multitable-only commands. % % @headitem starts a heading row, which we typeset in bold. % Assignments have to be global since we are inside the implicit group % of an alignment entry. Note that \everycr resets \everytab. \def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}% % % A \tab used to include \hskip1sp. But then the space in a template % line is not enough. That is bad. So let's go back to just `&' until % we encounter the problem it was intended to solve again. % --karl, nathan@acm.org, 20apr99. \def\tab{\checkenv\multitable &\the\everytab}% % @multitable ... @end multitable definitions: % \newtoks\everytab % insert after every tab. % \envdef\multitable{% \vskip\parskip \startsavinginserts % % @item within a multitable starts a normal row. % We use \def instead of \let so that if one of the multitable entries % contains an @itemize, we don't choke on the \item (seen as \crcr aka % \endtemplate) expanding \doitemize. \def\item{\crcr}% % \tolerance=9500 \hbadness=9500 \setmultitablespacing \parskip=\multitableparskip \parindent=\multitableparindent \overfullrule=0pt \global\colcount=0 % \everycr = {% \noalign{% \global\everytab={}% \global\colcount=0 % Reset the column counter. % Check for saved footnotes, etc. \checkinserts % Keeps underfull box messages off when table breaks over pages. %\filbreak % Maybe so, but it also creates really weird page breaks when the % table breaks over pages. Wouldn't \vfil be better? Wait until the % problem manifests itself, so it can be fixed for real --karl. }% }% % \parsearg\domultitable } \def\domultitable#1{% % To parse everything between @multitable and @item: \setuptable#1 \endsetuptable % % This preamble sets up a generic column definition, which will % be used as many times as user calls for columns. % \vtop will set a single line and will also let text wrap and % continue for many paragraphs if desired. \halign\bgroup &% \global\advance\colcount by 1 \multistrut \vtop{% % Use the current \colcount to find the correct column width: \hsize=\expandafter\csname col\the\colcount\endcsname % % In order to keep entries from bumping into each other % we will add a \leftskip of \multitablecolspace to all columns after % the first one. % % If a template has been used, we will add \multitablecolspace % to the width of each template entry. % % If the user has set preamble in terms of percent of \hsize we will % use that dimension as the width of the column, and the \leftskip % will keep entries from bumping into each other. Table will start at % left margin and final column will justify at right margin. % % Make sure we don't inherit \rightskip from the outer environment. \rightskip=0pt \ifnum\colcount=1 % The first column will be indented with the surrounding text. \advance\hsize by\leftskip \else \ifsetpercent \else % If user has not set preamble in terms of percent of \hsize % we will advance \hsize by \multitablecolspace. \advance\hsize by \multitablecolspace \fi % In either case we will make \leftskip=\multitablecolspace: \leftskip=\multitablecolspace \fi % Ignoring space at the beginning and end avoids an occasional spurious % blank line, when TeX decides to break the line at the space before the % box from the multistrut, so the strut ends up on a line by itself. % For example: % @multitable @columnfractions .11 .89 % @item @code{#} % @tab Legal holiday which is valid in major parts of the whole country. % Is automatically provided with highlighting sequences respectively % marking characters. \noindent\ignorespaces##\unskip\multistrut }\cr } \def\Emultitable{% \crcr \egroup % end the \halign \global\setpercentfalse } \def\setmultitablespacing{% \def\multistrut{\strut}% just use the standard line spacing % % Compute \multitablelinespace (if not defined by user) for use in % \multitableparskip calculation. We used define \multistrut based on % this, but (ironically) that caused the spacing to be off. % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. \ifdim\multitablelinespace=0pt \setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip \global\advance\multitablelinespace by-\ht0 \fi %% Test to see if parskip is larger than space between lines of %% table. If not, do nothing. %% If so, set to same dimension as multitablelinespace. \ifdim\multitableparskip>\multitablelinespace \global\multitableparskip=\multitablelinespace \global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller %% than skip between lines in the table. \fi% \ifdim\multitableparskip=0pt \global\multitableparskip=\multitablelinespace \global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller %% than skip between lines in the table. \fi} \message{conditionals,} % @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, % @ifnotxml always succeed. They currently do nothing; we don't % attempt to check whether the conditionals are properly nested. But we % have to remember that they are conditionals, so that @end doesn't % attempt to close an environment group. % \def\makecond#1{% \expandafter\let\csname #1\endcsname = \relax \expandafter\let\csname iscond.#1\endcsname = 1 } \makecond{iftex} \makecond{ifnotdocbook} \makecond{ifnothtml} \makecond{ifnotinfo} \makecond{ifnotplaintext} \makecond{ifnotxml} % Ignore @ignore, @ifhtml, @ifinfo, and the like. % \def\direntry{\doignore{direntry}} \def\documentdescription{\doignore{documentdescription}} \def\docbook{\doignore{docbook}} \def\html{\doignore{html}} \def\ifdocbook{\doignore{ifdocbook}} \def\ifhtml{\doignore{ifhtml}} \def\ifinfo{\doignore{ifinfo}} \def\ifnottex{\doignore{ifnottex}} \def\ifplaintext{\doignore{ifplaintext}} \def\ifxml{\doignore{ifxml}} \def\ignore{\doignore{ignore}} \def\menu{\doignore{menu}} \def\xml{\doignore{xml}} % Ignore text until a line `@end #1', keeping track of nested conditionals. % % A count to remember the depth of nesting. \newcount\doignorecount \def\doignore#1{\begingroup % Scan in ``verbatim'' mode: \obeylines \catcode`\@ = \other \catcode`\{ = \other \catcode`\} = \other % % Make sure that spaces turn into tokens that match what \doignoretext wants. \spaceisspace % % Count number of #1's that we've seen. \doignorecount = 0 % % Swallow text until we reach the matching `@end #1'. \dodoignore{#1}% } { \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. \obeylines % % \gdef\dodoignore#1{% % #1 contains the command name as a string, e.g., `ifinfo'. % % Define a command to find the next `@end #1'. \long\def\doignoretext##1^^M@end #1{% \doignoretextyyy##1^^M@#1\_STOP_}% % % And this command to find another #1 command, at the beginning of a % line. (Otherwise, we would consider a line `@c @ifset', for % example, to count as an @ifset for nesting.) \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% % % And now expand that command. \doignoretext ^^M% }% } \def\doignoreyyy#1{% \def\temp{#1}% \ifx\temp\empty % Nothing found. \let\next\doignoretextzzz \else % Found a nested condition, ... \advance\doignorecount by 1 \let\next\doignoretextyyy % ..., look for another. % If we're here, #1 ends with ^^M\ifinfo (for example). \fi \next #1% the token \_STOP_ is present just after this macro. } % We have to swallow the remaining "\_STOP_". % \def\doignoretextzzz#1{% \ifnum\doignorecount = 0 % We have just found the outermost @end. \let\next\enddoignore \else % Still inside a nested condition. \advance\doignorecount by -1 \let\next\doignoretext % Look for the next @end. \fi \next } % Finish off ignored text. { \obeylines% % Ignore anything after the last `@end #1'; this matters in verbatim % environments, where otherwise the newline after an ignored conditional % would result in a blank line in the output. \gdef\enddoignore#1^^M{\endgroup\ignorespaces}% } % @set VAR sets the variable VAR to an empty value. % @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. % % Since we want to separate VAR from REST-OF-LINE (which might be % empty), we can't just use \parsearg; we have to insert a space of our % own to delimit the rest of the line, and then take it out again if we % didn't need it. % We rely on the fact that \parsearg sets \catcode`\ =10. % \parseargdef\set{\setyyy#1 \endsetyyy} \def\setyyy#1 #2\endsetyyy{% {% \makevalueexpandable \def\temp{#2}% \edef\next{\gdef\makecsname{SET#1}}% \ifx\temp\empty \next{}% \else \setzzz#2\endsetzzz \fi }% } % Remove the trailing space \setxxx inserted. \def\setzzz#1 \endsetzzz{\next{#1}} % @clear VAR clears (i.e., unsets) the variable VAR. % \parseargdef\clear{% {% \makevalueexpandable \global\expandafter\let\csname SET#1\endcsname=\relax }% } % @value{foo} gets the text saved in variable foo. \def\value{\begingroup\makevalueexpandable\valuexxx} \def\valuexxx#1{\expandablevalue{#1}\endgroup} { \catcode`\- = \active \catcode`\_ = \active % \gdef\makevalueexpandable{% \let\value = \expandablevalue % We don't want these characters active, ... \catcode`\-=\other \catcode`\_=\other % ..., but we might end up with active ones in the argument if % we're called from @code, as @code{@value{foo-bar_}}, though. % So \let them to their normal equivalents. \let-\realdash \let_\normalunderscore } } % We have this subroutine so that we can handle at least some @value's % properly in indexes (we call \makevalueexpandable in \indexdummies). % The command has to be fully expandable (if the variable is set), since % the result winds up in the index file. This means that if the % variable's value contains other Texinfo commands, it's almost certain % it will fail (although perhaps we could fix that with sufficient work % to do a one-level expansion on the result, instead of complete). % \def\expandablevalue#1{% \expandafter\ifx\csname SET#1\endcsname\relax {[No value for ``#1'']}% \message{Variable `#1', used in @value, is not set.}% \else \csname SET#1\endcsname \fi } % @ifset VAR ... @end ifset reads the `...' iff VAR has been defined % with @set. % % To get special treatment of `@end ifset,' call \makeond and the redefine. % \makecond{ifset} \def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} \def\doifset#1#2{% {% \makevalueexpandable \let\next=\empty \expandafter\ifx\csname SET#2\endcsname\relax #1% If not set, redefine \next. \fi \expandafter }\next } \def\ifsetfail{\doignore{ifset}} % @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been % defined with @set, or has been undefined with @clear. % % The `\else' inside the `\doifset' parameter is a trick to reuse the % above code: if the variable is not set, do nothing, if it is set, % then redefine \next to \ifclearfail. % \makecond{ifclear} \def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} \def\ifclearfail{\doignore{ifclear}} % @dircategory CATEGORY -- specify a category of the dir file % which this file should belong to. Ignore this in TeX. \let\dircategory=\comment % @defininfoenclose. \let\definfoenclose=\comment \message{indexing,} % Index generation facilities % Define \newwrite to be identical to plain tex's \newwrite % except not \outer, so it can be used within macros and \if's. \edef\newwrite{\makecsname{ptexnewwrite}} % \newindex {foo} defines an index named foo. % It automatically defines \fooindex such that % \fooindex ...rest of line... puts an entry in the index foo. % It also defines \fooindfile to be the number of the output channel for % the file that accumulates this index. The file's extension is foo. % The name of an index should be no more than 2 characters long % for the sake of vms. % \def\newindex#1{% \iflinks \expandafter\newwrite \csname#1indfile\endcsname \openout \csname#1indfile\endcsname \jobname.#1 % Open the file \fi \expandafter\xdef\csname#1index\endcsname{% % Define @#1index \noexpand\doindex{#1}} } % @defindex foo == \newindex{foo} % \def\defindex{\parsearg\newindex} % Define @defcodeindex, like @defindex except put all entries in @code. % \def\defcodeindex{\parsearg\newcodeindex} % \def\newcodeindex#1{% \iflinks \expandafter\newwrite \csname#1indfile\endcsname \openout \csname#1indfile\endcsname \jobname.#1 \fi \expandafter\xdef\csname#1index\endcsname{% \noexpand\docodeindex{#1}}% } % @synindex foo bar makes index foo feed into index bar. % Do this instead of @defindex foo if you don't want it as a separate index. % % @syncodeindex foo bar similar, but put all entries made for index foo % inside @code. % \def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} \def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} % #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), % #3 the target index (bar). \def\dosynindex#1#2#3{% % Only do \closeout if we haven't already done it, else we'll end up % closing the target index. \expandafter \ifx\csname donesynindex#2\endcsname \relax % The \closeout helps reduce unnecessary open files; the limit on the % Acorn RISC OS is a mere 16 files. \expandafter\closeout\csname#2indfile\endcsname \expandafter\let\csname donesynindex#2\endcsname = 1 \fi % redefine \fooindfile: \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname \expandafter\let\csname#2indfile\endcsname=\temp % redefine \fooindex: \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% } % Define \doindex, the driver for all \fooindex macros. % Argument #1 is generated by the calling \fooindex macro, % and it is "foo", the name of the index. % \doindex just uses \parsearg; it calls \doind for the actual work. % This is because \doind is more useful to call from other macros. % There is also \dosubind {index}{topic}{subtopic} % which makes an entry in a two-level index such as the operation index. \def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} \def\singleindexer #1{\doind{\indexname}{#1}} % like the previous two, but they put @code around the argument. \def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} \def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} % Take care of Texinfo commands that can appear in an index entry. % Since there are some commands we want to expand, and others we don't, % we have to laboriously prevent expansion for those that we don't. % \def\indexdummies{% \escapechar = `\\ % use backslash in output files. \def\@{@}% change to @@ when we switch to @ as escape char in index files. \def\ {\realbackslash\space }% % % Need these in case \tex is in effect and \{ is a \delimiter again. % But can't use \lbracecmd and \rbracecmd because texindex assumes % braces and backslashes are used only as delimiters. \let\{ = \mylbrace \let\} = \myrbrace % % I don't entirely understand this, but when an index entry is % generated from a macro call, the \endinput which \scanmacro inserts % causes processing to be prematurely terminated. This is, % apparently, because \indexsorttmp is fully expanded, and \endinput % is an expandable command. The redefinition below makes \endinput % disappear altogether for that purpose -- although logging shows that % processing continues to some further point. On the other hand, it % seems \endinput does not hurt in the printed index arg, since that % is still getting written without apparent harm. % % Sample source (mac-idx3.tex, reported by Graham Percival to % help-texinfo, 22may06): % @macro funindex {WORD} % @findex xyz % @end macro % ... % @funindex commtest % % The above is not enough to reproduce the bug, but it gives the flavor. % % Sample whatsit resulting: % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}} % % So: \let\endinput = \empty % % Do the redefinitions. \commondummies } % For the aux and toc files, @ is the escape character. So we want to % redefine everything using @ as the escape character (instead of % \realbackslash, still used for index files). When everything uses @, % this will be simpler. % \def\atdummies{% \def\@{@@}% \def\ {@ }% \let\{ = \lbraceatcmd \let\} = \rbraceatcmd % % Do the redefinitions. \commondummies \otherbackslash } % Called from \indexdummies and \atdummies. % \def\commondummies{% % % \definedummyword defines \#1 as \string\#1\space, thus effectively % preventing its expansion. This is used only for control% words, % not control letters, because the \space would be incorrect for % control characters, but is needed to separate the control word % from whatever follows. % % For control letters, we have \definedummyletter, which omits the % space. % % These can be used both for control words that take an argument and % those that do not. If it is followed by {arg} in the input, then % that will dutifully get written to the index (or wherever). % \def\definedummyword ##1{\def##1{\string##1\space}}% \def\definedummyletter##1{\def##1{\string##1}}% \let\definedummyaccent\definedummyletter % \commondummiesnofonts % \definedummyletter\_% % % Non-English letters. \definedummyword\AA \definedummyword\AE \definedummyword\L \definedummyword\OE \definedummyword\O \definedummyword\aa \definedummyword\ae \definedummyword\l \definedummyword\oe \definedummyword\o \definedummyword\ss \definedummyword\exclamdown \definedummyword\questiondown \definedummyword\ordf \definedummyword\ordm % % Although these internal commands shouldn't show up, sometimes they do. \definedummyword\bf \definedummyword\gtr \definedummyword\hat \definedummyword\less \definedummyword\sf \definedummyword\sl \definedummyword\tclose \definedummyword\tt % \definedummyword\LaTeX \definedummyword\TeX % % Assorted special characters. \definedummyword\bullet \definedummyword\comma \definedummyword\copyright \definedummyword\registeredsymbol \definedummyword\dots \definedummyword\enddots \definedummyword\equiv \definedummyword\error \definedummyword\euro \definedummyword\guillemetleft \definedummyword\guillemetright \definedummyword\guilsinglleft \definedummyword\guilsinglright \definedummyword\expansion \definedummyword\minus \definedummyword\ogonek \definedummyword\pounds \definedummyword\point \definedummyword\print \definedummyword\quotedblbase \definedummyword\quotedblleft \definedummyword\quotedblright \definedummyword\quoteleft \definedummyword\quoteright \definedummyword\quotesinglbase \definedummyword\result \definedummyword\textdegree % % We want to disable all macros so that they are not expanded by \write. \macrolist % \normalturnoffactive % % Handle some cases of @value -- where it does not contain any % (non-fully-expandable) commands. \makevalueexpandable } % \commondummiesnofonts: common to \commondummies and \indexnofonts. % \def\commondummiesnofonts{% % Control letters and accents. \definedummyletter\!% \definedummyaccent\"% \definedummyaccent\'% \definedummyletter\*% \definedummyaccent\,% \definedummyletter\.% \definedummyletter\/% \definedummyletter\:% \definedummyaccent\=% \definedummyletter\?% \definedummyaccent\^% \definedummyaccent\`% \definedummyaccent\~% \definedummyword\u \definedummyword\v \definedummyword\H \definedummyword\dotaccent \definedummyword\ogonek \definedummyword\ringaccent \definedummyword\tieaccent \definedummyword\ubaraccent \definedummyword\udotaccent \definedummyword\dotless % % Texinfo font commands. \definedummyword\b \definedummyword\i \definedummyword\r \definedummyword\sc \definedummyword\t % % Commands that take arguments. \definedummyword\acronym \definedummyword\cite \definedummyword\code \definedummyword\command \definedummyword\dfn \definedummyword\emph \definedummyword\env \definedummyword\file \definedummyword\kbd \definedummyword\key \definedummyword\math \definedummyword\option \definedummyword\pxref \definedummyword\ref \definedummyword\samp \definedummyword\strong \definedummyword\tie \definedummyword\uref \definedummyword\url \definedummyword\var \definedummyword\verb \definedummyword\w \definedummyword\xref } % \indexnofonts is used when outputting the strings to sort the index % by, and when constructing control sequence names. It eliminates all % control sequences and just writes whatever the best ASCII sort string % would be for a given command (usually its argument). % \def\indexnofonts{% % Accent commands should become @asis. \def\definedummyaccent##1{\let##1\asis}% % We can just ignore other control letters. \def\definedummyletter##1{\let##1\empty}% % Hopefully, all control words can become @asis. \let\definedummyword\definedummyaccent % \commondummiesnofonts % % Don't no-op \tt, since it isn't a user-level command % and is used in the definitions of the active chars like <, >, |, etc. % Likewise with the other plain tex font commands. %\let\tt=\asis % \def\ { }% \def\@{@}% % how to handle braces? \def\_{\normalunderscore}% % % Non-English letters. \def\AA{AA}% \def\AE{AE}% \def\L{L}% \def\OE{OE}% \def\O{O}% \def\aa{aa}% \def\ae{ae}% \def\l{l}% \def\oe{oe}% \def\o{o}% \def\ss{ss}% \def\exclamdown{!}% \def\questiondown{?}% \def\ordf{a}% \def\ordm{o}% % \def\LaTeX{LaTeX}% \def\TeX{TeX}% % % Assorted special characters. % (The following {} will end up in the sort string, but that's ok.) \def\bullet{bullet}% \def\comma{,}% \def\copyright{copyright}% \def\registeredsymbol{R}% \def\dots{...}% \def\enddots{...}% \def\equiv{==}% \def\error{error}% \def\euro{euro}% \def\guillemetleft{<<}% \def\guillemetright{>>}% \def\guilsinglleft{<}% \def\guilsinglright{>}% \def\expansion{==>}% \def\minus{-}% \def\pounds{pounds}% \def\point{.}% \def\print{-|}% \def\quotedblbase{"}% \def\quotedblleft{"}% \def\quotedblright{"}% \def\quoteleft{`}% \def\quoteright{'}% \def\quotesinglbase{,}% \def\result{=>}% \def\textdegree{degrees}% % % We need to get rid of all macros, leaving only the arguments (if present). % Of course this is not nearly correct, but it is the best we can do for now. % makeinfo does not expand macros in the argument to @deffn, which ends up % writing an index entry, and texindex isn't prepared for an index sort entry % that starts with \. % % Since macro invocations are followed by braces, we can just redefine them % to take a single TeX argument. The case of a macro invocation that % goes to end-of-line is not handled. % \macrolist } \let\indexbackslash=0 %overridden during \printindex. \let\SETmarginindex=\relax % put index entries in margin (undocumented)? % Most index entries go through here, but \dosubind is the general case. % #1 is the index name, #2 is the entry text. \def\doind#1#2{\dosubind{#1}{#2}{}} % Workhorse for all \fooindexes. % #1 is name of index, #2 is stuff to put there, #3 is subentry -- % empty if called from \doind, as we usually are (the main exception % is with most defuns, which call us directly). % \def\dosubind#1#2#3{% \iflinks {% % Store the main index entry text (including the third arg). \toks0 = {#2}% % If third arg is present, precede it with a space. \def\thirdarg{#3}% \ifx\thirdarg\empty \else \toks0 = \expandafter{\the\toks0 \space #3}% \fi % \edef\writeto{\csname#1indfile\endcsname}% % \safewhatsit\dosubindwrite }% \fi } % Write the entry in \toks0 to the index file: % \def\dosubindwrite{% % Put the index entry in the margin if desired. \ifx\SETmarginindex\relax\else \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% \fi % % Remember, we are within a group. \indexdummies % Must do this here, since \bf, etc expand at this stage \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now % so it will be output as is; and it will print as backslash. % % Process the index entry with all font commands turned off, to % get the string to sort by. {\indexnofonts \edef\temp{\the\toks0}% need full expansion \xdef\indexsorttmp{\temp}% }% % % Set up the complete index entry, with both the sort key and % the original text, including any font commands. We write % three arguments to \entry to the .?? file (four in the % subentry case), texindex reduces to two when writing the .??s % sorted result. \edef\temp{% \write\writeto{% \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% }% \temp } % Take care of unwanted page breaks/skips around a whatsit: % % If a skip is the last thing on the list now, preserve it % by backing up by \lastskip, doing the \write, then inserting % the skip again. Otherwise, the whatsit generated by the % \write or \pdfdest will make \lastskip zero. The result is that % sequences like this: % @end defun % @tindex whatever % @defun ... % will have extra space inserted, because the \medbreak in the % start of the @defun won't see the skip inserted by the @end of % the previous defun. % % But don't do any of this if we're not in vertical mode. We % don't want to do a \vskip and prematurely end a paragraph. % % Avoid page breaks due to these extra skips, too. % % But wait, there is a catch there: % We'll have to check whether \lastskip is zero skip. \ifdim is not % sufficient for this purpose, as it ignores stretch and shrink parts % of the skip. The only way seems to be to check the textual % representation of the skip. % % The following is almost like \def\zeroskipmacro{0.0pt} except that % the ``p'' and ``t'' characters have catcode \other, not 11 (letter). % \edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} % \newskip\whatsitskip \newcount\whatsitpenalty % % ..., ready, GO: % \def\safewhatsit#1{% \ifhmode #1% \else % \lastskip and \lastpenalty cannot both be nonzero simultaneously. \whatsitskip = \lastskip \edef\lastskipmacro{\the\lastskip}% \whatsitpenalty = \lastpenalty % % If \lastskip is nonzero, that means the last item was a % skip. And since a skip is discardable, that means this % -\whatsitskip glue we're inserting is preceded by a % non-discardable item, therefore it is not a potential % breakpoint, therefore no \nobreak needed. \ifx\lastskipmacro\zeroskipmacro \else \vskip-\whatsitskip \fi % #1% % \ifx\lastskipmacro\zeroskipmacro % If \lastskip was zero, perhaps the last item was a penalty, and % perhaps it was >=10000, e.g., a \nobreak. In that case, we want % to re-insert the same penalty (values >10000 are used for various % signals); since we just inserted a non-discardable item, any % following glue (such as a \parskip) would be a breakpoint. For example: % % @deffn deffn-whatever % @vindex index-whatever % Description. % would allow a break between the index-whatever whatsit % and the "Description." paragraph. \ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi \else % On the other hand, if we had a nonzero \lastskip, % this make-up glue would be preceded by a non-discardable item % (the whatsit from the \write), so we must insert a \nobreak. \nobreak\vskip\whatsitskip \fi \fi } % The index entry written in the file actually looks like % \entry {sortstring}{page}{topic} % or % \entry {sortstring}{page}{topic}{subtopic} % The texindex program reads in these files and writes files % containing these kinds of lines: % \initial {c} % before the first topic whose initial is c % \entry {topic}{pagelist} % for a topic that is used without subtopics % \primary {topic} % for the beginning of a topic that is used with subtopics % \secondary {subtopic}{pagelist} % for each subtopic. % Define the user-accessible indexing commands % @findex, @vindex, @kindex, @cindex. \def\findex {\fnindex} \def\kindex {\kyindex} \def\cindex {\cpindex} \def\vindex {\vrindex} \def\tindex {\tpindex} \def\pindex {\pgindex} \def\cindexsub {\begingroup\obeylines\cindexsub} {\obeylines % \gdef\cindexsub "#1" #2^^M{\endgroup % \dosubind{cp}{#2}{#1}}} % Define the macros used in formatting output of the sorted index material. % @printindex causes a particular index (the ??s file) to get printed. % It does not print any chapter heading (usually an @unnumbered). % \parseargdef\printindex{\begingroup \dobreak \chapheadingskip{10000}% % \smallfonts \rm \tolerance = 9500 \plainfrenchspacing \everypar = {}% don't want the \kern\-parindent from indentation suppression. % % See if the index file exists and is nonempty. % Change catcode of @ here so that if the index file contains % \initial {@} % as its first line, TeX doesn't complain about mismatched braces % (because it thinks @} is a control sequence). \catcode`\@ = 11 \openin 1 \jobname.#1s \ifeof 1 % \enddoublecolumns gets confused if there is no text in the index, % and it loses the chapter title and the aux file entries for the % index. The easiest way to prevent this problem is to make sure % there is some text. \putwordIndexNonexistent \else % % If the index file exists but is empty, then \openin leaves \ifeof % false. We have to make TeX try to read something from the file, so % it can discover if there is anything in it. \read 1 to \temp \ifeof 1 \putwordIndexIsEmpty \else % Index files are almost Texinfo source, but we use \ as the escape % character. It would be better to use @, but that's too big a change % to make right now. \def\indexbackslash{\backslashcurfont}% \catcode`\\ = 0 \escapechar = `\\ \begindoublecolumns \input \jobname.#1s \enddoublecolumns \fi \fi \closein 1 \endgroup} % These macros are used by the sorted index file itself. % Change them to control the appearance of the index. \def\initial#1{{% % Some minor font changes for the special characters. \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt % % Remove any glue we may have, we'll be inserting our own. \removelastskip % % We like breaks before the index initials, so insert a bonus. \nobreak \vskip 0pt plus 3\baselineskip \penalty 0 \vskip 0pt plus -3\baselineskip % % Typeset the initial. Making this add up to a whole number of % baselineskips increases the chance of the dots lining up from column % to column. It still won't often be perfect, because of the stretch % we need before each entry, but it's better. % % No shrink because it confuses \balancecolumns. \vskip 1.67\baselineskip plus .5\baselineskip \leftline{\secbf #1}% % Do our best not to break after the initial. \nobreak \vskip .33\baselineskip plus .1\baselineskip }} % \entry typesets a paragraph consisting of the text (#1), dot leaders, and % then page number (#2) flushed to the right margin. It is used for index % and table of contents entries. The paragraph is indented by \leftskip. % % A straightforward implementation would start like this: % \def\entry#1#2{... % But this freezes the catcodes in the argument, and can cause problems to % @code, which sets - active. This problem was fixed by a kludge--- % ``-'' was active throughout whole index, but this isn't really right. % % The right solution is to prevent \entry from swallowing the whole text. % --kasal, 21nov03 \def\entry{% \begingroup % % Start a new paragraph if necessary, so our assignments below can't % affect previous text. \par % % Do not fill out the last line with white space. \parfillskip = 0in % % No extra space above this paragraph. \parskip = 0in % % Do not prefer a separate line ending with a hyphen to fewer lines. \finalhyphendemerits = 0 % % \hangindent is only relevant when the entry text and page number % don't both fit on one line. In that case, bob suggests starting the % dots pretty far over on the line. Unfortunately, a large % indentation looks wrong when the entry text itself is broken across % lines. So we use a small indentation and put up with long leaders. % % \hangafter is reset to 1 (which is the value we want) at the start % of each paragraph, so we need not do anything with that. \hangindent = 2em % % When the entry text needs to be broken, just fill out the first line % with blank space. \rightskip = 0pt plus1fil % % A bit of stretch before each entry for the benefit of balancing % columns. \vskip 0pt plus1pt % % Swallow the left brace of the text (first parameter): \afterassignment\doentry \let\temp = } \def\doentry{% \bgroup % Instead of the swallowed brace. \noindent \aftergroup\finishentry % And now comes the text of the entry. } \def\finishentry#1{% % #1 is the page number. % % The following is kludged to not output a line of dots in the index if % there are no page numbers. The next person who breaks this will be % cursed by a Unix daemon. \setbox\boxA = \hbox{#1}% \ifdim\wd\boxA = 0pt \ % \else % % If we must, put the page number on a line of its own, and fill out % this line with blank space. (The \hfil is overwhelmed with the % fill leaders glue in \indexdotfill if the page number does fit.) \hfil\penalty50 \null\nobreak\indexdotfill % Have leaders before the page number. % % The `\ ' here is removed by the implicit \unskip that TeX does as % part of (the primitive) \par. Without it, a spurious underfull % \hbox ensues. \ifpdf \pdfgettoks#1.% \ \the\toksA \else \ #1% \fi \fi \par \endgroup } % Like plain.tex's \dotfill, except uses up at least 1 em. \def\indexdotfill{\cleaders \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill} \def\primary #1{\line{#1\hfil}} \newskip\secondaryindent \secondaryindent=0.5cm \def\secondary#1#2{{% \parfillskip=0in \parskip=0in \hangindent=1in \hangafter=1 \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill \ifpdf \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. \else #2 \fi \par }} % Define two-column mode, which we use to typeset indexes. % Adapted from the TeXbook, page 416, which is to say, % the manmac.tex format used to print the TeXbook itself. \catcode`\@=11 \newbox\partialpage \newdimen\doublecolumnhsize \def\begindoublecolumns{\begingroup % ended by \enddoublecolumns % Grab any single-column material above us. \output = {% % % Here is a possibility not foreseen in manmac: if we accumulate a % whole lot of material, we might end up calling this \output % routine twice in a row (see the doublecol-lose test, which is % essentially a couple of indexes with @setchapternewpage off). In % that case we just ship out what is in \partialpage with the normal % output routine. Generally, \partialpage will be empty when this % runs and this will be a no-op. See the indexspread.tex test case. \ifvoid\partialpage \else \onepageout{\pagecontents\partialpage}% \fi % \global\setbox\partialpage = \vbox{% % Unvbox the main output page. \unvbox\PAGE \kern-\topskip \kern\baselineskip }% }% \eject % run that output routine to set \partialpage % % Use the double-column output routine for subsequent pages. \output = {\doublecolumnout}% % % Change the page size parameters. We could do this once outside this % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 % format, but then we repeat the same computation. Repeating a couple % of assignments once per index is clearly meaningless for the % execution time, so we may as well do it in one place. % % First we halve the line length, less a little for the gutter between % the columns. We compute the gutter based on the line length, so it % changes automatically with the paper format. The magic constant % below is chosen so that the gutter has the same value (well, +-<1pt) % as it did when we hard-coded it. % % We put the result in a separate register, \doublecolumhsize, so we % can restore it in \pagesofar, after \hsize itself has (potentially) % been clobbered. % \doublecolumnhsize = \hsize \advance\doublecolumnhsize by -.04154\hsize \divide\doublecolumnhsize by 2 \hsize = \doublecolumnhsize % % Double the \vsize as well. (We don't need a separate register here, % since nobody clobbers \vsize.) \vsize = 2\vsize } % The double-column output routine for all double-column pages except % the last. % \def\doublecolumnout{% \splittopskip=\topskip \splitmaxdepth=\maxdepth % Get the available space for the double columns -- the normal % (undoubled) page height minus any material left over from the % previous page. \dimen@ = \vsize \divide\dimen@ by 2 \advance\dimen@ by -\ht\partialpage % % box0 will be the left-hand column, box2 the right. \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty } % % Re-output the contents of the output page -- any previous material, % followed by the two boxes we just split, in box0 and box2. \def\pagesofar{% \unvbox\partialpage % \hsize = \doublecolumnhsize \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}% } % % All done with double columns. \def\enddoublecolumns{% % The following penalty ensures that the page builder is exercised % _before_ we change the output routine. This is necessary in the % following situation: % % The last section of the index consists only of a single entry. % Before this section, \pagetotal is less than \pagegoal, so no % break occurs before the last section starts. However, the last % section, consisting of \initial and the single \entry, does not % fit on the page and has to be broken off. Without the following % penalty the page builder will not be exercised until \eject % below, and by that time we'll already have changed the output % routine to the \balancecolumns version, so the next-to-last % double-column page will be processed with \balancecolumns, which % is wrong: The two columns will go to the main vertical list, with % the broken-off section in the recent contributions. As soon as % the output routine finishes, TeX starts reconsidering the page % break. The two columns and the broken-off section both fit on the % page, because the two columns now take up only half of the page % goal. When TeX sees \eject from below which follows the final % section, it invokes the new output routine that we've set after % \balancecolumns below; \onepageout will try to fit the two columns % and the final section into the vbox of \pageheight (see % \pagebody), causing an overfull box. % % Note that glue won't work here, because glue does not exercise the % page builder, unlike penalties (see The TeXbook, pp. 280-281). \penalty0 % \output = {% % Split the last of the double-column material. Leave it on the % current page, no automatic page break. \balancecolumns % % If we end up splitting too much material for the current page, % though, there will be another page break right after this \output % invocation ends. Having called \balancecolumns once, we do not % want to call it again. Therefore, reset \output to its normal % definition right away. (We hope \balancecolumns will never be % called on to balance too much material, but if it is, this makes % the output somewhat more palatable.) \global\output = {\onepageout{\pagecontents\PAGE}}% }% \eject \endgroup % started in \begindoublecolumns % % \pagegoal was set to the doubled \vsize above, since we restarted % the current page. We're now back to normal single-column % typesetting, so reset \pagegoal to the normal \vsize (after the % \endgroup where \vsize got restored). \pagegoal = \vsize } % % Called at the end of the double column material. \def\balancecolumns{% \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. \dimen@ = \ht0 \advance\dimen@ by \topskip \advance\dimen@ by-\baselineskip \divide\dimen@ by 2 % target to split to %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% \splittopskip = \topskip % Loop until we get a decent breakpoint. {% \vbadness = 10000 \loop \global\setbox3 = \copy0 \global\setbox1 = \vsplit3 to \dimen@ \ifdim\ht3>\dimen@ \global\advance\dimen@ by 1pt \repeat }% %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% \setbox0=\vbox to\dimen@{\unvbox1}% \setbox2=\vbox to\dimen@{\unvbox3}% % \pagesofar } \catcode`\@ = \other \message{sectioning,} % Chapters, sections, etc. % \unnumberedno is an oxymoron, of course. But we count the unnumbered % sections so that we can refer to them unambiguously in the pdf % outlines by their "section number". We avoid collisions with chapter % numbers by starting them at 10000. (If a document ever has 10000 % chapters, we're in trouble anyway, I'm sure.) \newcount\unnumberedno \unnumberedno = 10000 \newcount\chapno \newcount\secno \secno=0 \newcount\subsecno \subsecno=0 \newcount\subsubsecno \subsubsecno=0 % This counter is funny since it counts through charcodes of letters A, B, ... \newcount\appendixno \appendixno = `\@ % % \def\appendixletter{\char\the\appendixno} % We do the following ugly conditional instead of the above simple % construct for the sake of pdftex, which needs the actual % letter in the expansion, not just typeset. % \def\appendixletter{% \ifnum\appendixno=`A A% \else\ifnum\appendixno=`B B% \else\ifnum\appendixno=`C C% \else\ifnum\appendixno=`D D% \else\ifnum\appendixno=`E E% \else\ifnum\appendixno=`F F% \else\ifnum\appendixno=`G G% \else\ifnum\appendixno=`H H% \else\ifnum\appendixno=`I I% \else\ifnum\appendixno=`J J% \else\ifnum\appendixno=`K K% \else\ifnum\appendixno=`L L% \else\ifnum\appendixno=`M M% \else\ifnum\appendixno=`N N% \else\ifnum\appendixno=`O O% \else\ifnum\appendixno=`P P% \else\ifnum\appendixno=`Q Q% \else\ifnum\appendixno=`R R% \else\ifnum\appendixno=`S S% \else\ifnum\appendixno=`T T% \else\ifnum\appendixno=`U U% \else\ifnum\appendixno=`V V% \else\ifnum\appendixno=`W W% \else\ifnum\appendixno=`X X% \else\ifnum\appendixno=`Y Y% \else\ifnum\appendixno=`Z Z% % The \the is necessary, despite appearances, because \appendixletter is % expanded while writing the .toc file. \char\appendixno is not % expandable, thus it is written literally, thus all appendixes come out % with the same letter (or @) in the toc without it. \else\char\the\appendixno \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} % Each @chapter defines these (using marks) as the number+name, number % and name of the chapter. Page headings and footings can use % these. @section does likewise. \def\thischapter{} \def\thischapternum{} \def\thischaptername{} \def\thissection{} \def\thissectionnum{} \def\thissectionname{} \newcount\absseclevel % used to calculate proper heading level \newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count % @raisesections: treat @section as chapter, @subsection as section, etc. \def\raisesections{\global\advance\secbase by -1} \let\up=\raisesections % original BFox name % @lowersections: treat @chapter as section, @section as subsection, etc. \def\lowersections{\global\advance\secbase by 1} \let\down=\lowersections % original BFox name % we only have subsub. \chardef\maxseclevel = 3 % % A numbered section within an unnumbered changes to unnumbered too. % To achive this, remember the "biggest" unnum. sec. we are currently in: \chardef\unmlevel = \maxseclevel % % Trace whether the current chapter is an appendix or not: % \chapheadtype is "N" or "A", unnumbered chapters are ignored. \def\chapheadtype{N} % Choose a heading macro % #1 is heading type % #2 is heading level % #3 is text for heading \def\genhead#1#2#3{% % Compute the abs. sec. level: \absseclevel=#2 \advance\absseclevel by \secbase % Make sure \absseclevel doesn't fall outside the range: \ifnum \absseclevel < 0 \absseclevel = 0 \else \ifnum \absseclevel > 3 \absseclevel = 3 \fi \fi % The heading type: \def\headtype{#1}% \if \headtype U% \ifnum \absseclevel < \unmlevel \chardef\unmlevel = \absseclevel \fi \else % Check for appendix sections: \ifnum \absseclevel = 0 \edef\chapheadtype{\headtype}% \else \if \headtype A\if \chapheadtype N% \errmessage{@appendix... within a non-appendix chapter}% \fi\fi \fi % Check for numbered within unnumbered: \ifnum \absseclevel > \unmlevel \def\headtype{U}% \else \chardef\unmlevel = 3 \fi \fi % Now print the heading: \if \headtype U% \ifcase\absseclevel \unnumberedzzz{#3}% \or \unnumberedseczzz{#3}% \or \unnumberedsubseczzz{#3}% \or \unnumberedsubsubseczzz{#3}% \fi \else \if \headtype A% \ifcase\absseclevel \appendixzzz{#3}% \or \appendixsectionzzz{#3}% \or \appendixsubseczzz{#3}% \or \appendixsubsubseczzz{#3}% \fi \else \ifcase\absseclevel \chapterzzz{#3}% \or \seczzz{#3}% \or \numberedsubseczzz{#3}% \or \numberedsubsubseczzz{#3}% \fi \fi \fi \suppressfirstparagraphindent } % an interface: \def\numhead{\genhead N} \def\apphead{\genhead A} \def\unnmhead{\genhead U} % @chapter, @appendix, @unnumbered. Increment top-level counter, reset % all lower-level sectioning counters to zero. % % Also set \chaplevelprefix, which we prepend to @float sequence numbers % (e.g., figures), q.v. By default (before any chapter), that is empty. \let\chaplevelprefix = \empty % \outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz \def\chapterzzz#1{% % section resetting is \global in case the chapter is in a group, such % as an @include file. \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\chapno by 1 % % Used for \float. \gdef\chaplevelprefix{\the\chapno.}% \resetallfloatnos % \message{\putwordChapter\space \the\chapno}% % % Write the actual heading. \chapmacro{#1}{Ynumbered}{\the\chapno}% % % So @section and the like are numbered underneath this chapter. \global\let\section = \numberedsec \global\let\subsection = \numberedsubsec \global\let\subsubsection = \numberedsubsubsec } \outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz \def\appendixzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\appendixno by 1 \gdef\chaplevelprefix{\appendixletter.}% \resetallfloatnos % \def\appendixnum{\putwordAppendix\space \appendixletter}% \message{\appendixnum}% % \chapmacro{#1}{Yappendix}{\appendixletter}% % \global\let\section = \appendixsec \global\let\subsection = \appendixsubsec \global\let\subsubsection = \appendixsubsubsec } \outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz \def\unnumberedzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\unnumberedno by 1 % % Since an unnumbered has no number, no prefix for figures. \global\let\chaplevelprefix = \empty \resetallfloatnos % % This used to be simply \message{#1}, but TeX fully expands the % argument to \message. Therefore, if #1 contained @-commands, TeX % expanded them. For example, in `@unnumbered The @cite{Book}', TeX % expanded @cite (which turns out to cause errors because \cite is meant % to be executed, not expanded). % % Anyway, we don't want the fully-expanded definition of @cite to appear % as a result of the \message, we just want `@cite' itself. We use % \the to achieve this: TeX expands \the only once, % simply yielding the contents of . (We also do this for % the toc entries.) \toks0 = {#1}% \message{(\the\toks0)}% % \chapmacro{#1}{Ynothing}{\the\unnumberedno}% % \global\let\section = \unnumberedsec \global\let\subsection = \unnumberedsubsec \global\let\subsubsection = \unnumberedsubsubsec } % @centerchap is like @unnumbered, but the heading is centered. \outer\parseargdef\centerchap{% % Well, we could do the following in a group, but that would break % an assumption that \chapmacro is called at the outermost level. % Thus we are safer this way: --kasal, 24feb04 \let\centerparametersmaybe = \centerparameters \unnmhead0{#1}% \let\centerparametersmaybe = \relax } % @top is like @unnumbered. \let\top\unnumbered % Sections. \outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz \def\seczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% } \outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz \def\appendixsectionzzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% } \let\appendixsec\appendixsection \outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz \def\unnumberedseczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% } % Subsections. \outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz \def\numberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% } \outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz \def\appendixsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno}% } \outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz \def\unnumberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynothing}% {\the\unnumberedno.\the\secno.\the\subsecno}% } % Subsubsections. \outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz \def\numberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynumbered}% {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% } \outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz \def\appendixsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% } \outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz \def\unnumberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynothing}% {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% } % These macros control what the section commands do, according % to what kind of chapter we are in (ordinary, appendix, or unnumbered). % Define them by default for a numbered chapter. \let\section = \numberedsec \let\subsection = \numberedsubsec \let\subsubsection = \numberedsubsubsec % Define @majorheading, @heading and @subheading % NOTE on use of \vbox for chapter headings, section headings, and such: % 1) We use \vbox rather than the earlier \line to permit % overlong headings to fold. % 2) \hyphenpenalty is set to 10000 because hyphenation in a % heading is obnoxious; this forbids it. % 3) Likewise, headings look best if no \parindent is used, and % if justification is not attempted. Hence \raggedright. \def\majorheading{% {\advance\chapheadingskip by 10pt \chapbreak }% \parsearg\chapheadingzzz } \def\chapheading{\chapbreak \parsearg\chapheadingzzz} \def\chapheadingzzz#1{% {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt\raggedright \rmisbold #1\hfill}}% \bigskip \par\penalty 200\relax \suppressfirstparagraphindent } % @heading, @subheading, @subsubheading. \parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} \suppressfirstparagraphindent} \parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} \suppressfirstparagraphindent} \parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} \suppressfirstparagraphindent} % These macros generate a chapter, section, etc. heading only % (including whitespace, linebreaking, etc. around it), % given all the information in convenient, parsed form. %%% Args are the skip and penalty (usually negative) \def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} %%% Define plain chapter starts, and page on/off switching for it % Parameter controlling skip before chapter headings (if needed) \newskip\chapheadingskip \def\chapbreak{\dobreak \chapheadingskip {-4000}} \def\chappager{\par\vfill\supereject} % Because \domark is called before \chapoddpage, the filler page will % get the headings for the next chapter, which is wrong. But we don't % care -- we just disable all headings on the filler page. \def\chapoddpage{% \chappager \ifodd\pageno \else \begingroup \evenheadline={\hfil}\evenfootline={\hfil}% \oddheadline={\hfil}\oddfootline={\hfil}% \hbox to 0pt{}% \chappager \endgroup \fi } \def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} \def\CHAPPAGoff{% \global\let\contentsalignmacro = \chappager \global\let\pchapsepmacro=\chapbreak \global\let\pagealignmacro=\chappager} \def\CHAPPAGon{% \global\let\contentsalignmacro = \chappager \global\let\pchapsepmacro=\chappager \global\let\pagealignmacro=\chappager \global\def\HEADINGSon{\HEADINGSsingle}} \def\CHAPPAGodd{% \global\let\contentsalignmacro = \chapoddpage \global\let\pchapsepmacro=\chapoddpage \global\let\pagealignmacro=\chapoddpage \global\def\HEADINGSon{\HEADINGSdouble}} \CHAPPAGon % Chapter opening. % % #1 is the text, #2 is the section type (Ynumbered, Ynothing, % Yappendix, Yomitfromtoc), #3 the chapter number. % % To test against our argument. \def\Ynothingkeyword{Ynothing} \def\Yomitfromtockeyword{Yomitfromtoc} \def\Yappendixkeyword{Yappendix} % \def\chapmacro#1#2#3{% % Insert the first mark before the heading break (see notes for \domark). \let\prevchapterdefs=\lastchapterdefs \let\prevsectiondefs=\lastsectiondefs \gdef\lastsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}% \gdef\thissection{}}% % \def\temptype{#2}% \ifx\temptype\Ynothingkeyword \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% \gdef\thischapter{\thischaptername}}% \else\ifx\temptype\Yomitfromtockeyword \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% \gdef\thischapter{}}% \else\ifx\temptype\Yappendixkeyword \toks0={#1}% \xdef\lastchapterdefs{% \gdef\noexpand\thischaptername{\the\toks0}% \gdef\noexpand\thischapternum{\appendixletter}% \gdef\noexpand\thischapter{\putwordAppendix{} \noexpand\thischapternum: \noexpand\thischaptername}% }% \else \toks0={#1}% \xdef\lastchapterdefs{% \gdef\noexpand\thischaptername{\the\toks0}% \gdef\noexpand\thischapternum{\the\chapno}% \gdef\noexpand\thischapter{\putwordChapter{} \noexpand\thischapternum: \noexpand\thischaptername}% }% \fi\fi\fi % % Output the mark. Pass it through \safewhatsit, to take care of % the preceding space. \safewhatsit\domark % % Insert the chapter heading break. \pchapsepmacro % % Now the second mark, after the heading break. No break points % between here and the heading. \let\prevchapterdefs=\lastchapterdefs \let\prevsectiondefs=\lastsectiondefs \domark % {% \chapfonts \rmisbold % % Have to define \lastsection before calling \donoderef, because the % xref code eventually uses it. On the other hand, it has to be called % after \pchapsepmacro, or the headline will change too soon. \gdef\lastsection{#1}% % % Only insert the separating space if we have a chapter/appendix % number, and don't print the unnumbered ``number''. \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unnchap}% \else\ifx\temptype\Yomitfromtockeyword \setbox0 = \hbox{}% contents like unnumbered, but no toc entry \def\toctype{omit}% \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% \def\toctype{app}% \else \setbox0 = \hbox{#3\enspace}% \def\toctype{numchap}% \fi\fi\fi % % Write the toc entry for this chapter. Must come before the % \donoderef, because we include the current node name in the toc % entry, and \donoderef resets it to empty. \writetocentry{\toctype}{#1}{#3}% % % For pdftex, we have to write out the node definition (aka, make % the pdfdest) after any page break, but before the actual text has % been typeset. If the destination for the pdf outline is after the % text, then jumping from the outline may wind up with the text not % being visible, for instance under high magnification. \donoderef{#2}% % % Typeset the actual heading. \nobreak % Avoid page breaks at the interline glue. \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright \hangindent=\wd0 \centerparametersmaybe \unhbox0 #1\par}% }% \nobreak\bigskip % no page break after a chapter title \nobreak } % @centerchap -- centered and unnumbered. \let\centerparametersmaybe = \relax \def\centerparameters{% \advance\rightskip by 3\rightskip \leftskip = \rightskip \parfillskip = 0pt } % I don't think this chapter style is supported any more, so I'm not % updating it with the new noderef stuff. We'll see. --karl, 11aug03. % \def\setchapterstyle #1 {\csname CHAPF#1\endcsname} % \def\unnchfopen #1{% \chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt\raggedright \rmisbold #1\hfill}}\bigskip \par\nobreak } \def\chfopen #1#2{\chapoddpage {\chapfonts \vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% \par\penalty 5000 % } \def\centerchfopen #1{% \chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt \hfill {\rmisbold #1}\hfill}}\bigskip \par\nobreak } \def\CHAPFopen{% \global\let\chapmacro=\chfopen \global\let\centerchapmacro=\centerchfopen} % Section titles. These macros combine the section number parts and % call the generic \sectionheading to do the printing. % \newskip\secheadingskip \def\secheadingbreak{\dobreak \secheadingskip{-1000}} % Subsection titles. \newskip\subsecheadingskip \def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} % Subsubsection titles. \def\subsubsecheadingskip{\subsecheadingskip} \def\subsubsecheadingbreak{\subsecheadingbreak} % Print any size, any type, section title. % % #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is % the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the % section number. % \def\seckeyword{sec} % \def\sectionheading#1#2#3#4{% {% % Switch to the right set of fonts. \csname #2fonts\endcsname \rmisbold % \def\sectionlevel{#2}% \def\temptype{#3}% % % Insert first mark before the heading break (see notes for \domark). \let\prevsectiondefs=\lastsectiondefs \ifx\temptype\Ynothingkeyword \ifx\sectionlevel\seckeyword \gdef\lastsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}% \gdef\thissection{\thissectionname}}% \fi \else\ifx\temptype\Yomitfromtockeyword % Don't redefine \thissection. \else\ifx\temptype\Yappendixkeyword \ifx\sectionlevel\seckeyword \toks0={#1}% \xdef\lastsectiondefs{% \gdef\noexpand\thissectionname{\the\toks0}% \gdef\noexpand\thissectionnum{#4}% \gdef\noexpand\thissection{\putwordSection{} \noexpand\thissectionnum: \noexpand\thissectionname}% }% \fi \else \ifx\sectionlevel\seckeyword \toks0={#1}% \xdef\lastsectiondefs{% \gdef\noexpand\thissectionname{\the\toks0}% \gdef\noexpand\thissectionnum{#4}% \gdef\noexpand\thissection{\putwordSection{} \noexpand\thissectionnum: \noexpand\thissectionname}% }% \fi \fi\fi\fi % % Output the mark. Pass it through \safewhatsit, to take care of % the preceding space. \safewhatsit\domark % % Insert space above the heading. \csname #2headingbreak\endcsname % % Now the second mark, after the heading break. No break points % between here and the heading. \let\prevsectiondefs=\lastsectiondefs \domark % % Only insert the space after the number if we have a section number. \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unn}% \gdef\lastsection{#1}% \else\ifx\temptype\Yomitfromtockeyword % for @headings -- no section number, don't include in toc, % and don't redefine \lastsection. \setbox0 = \hbox{}% \def\toctype{omit}% \let\sectionlevel=\empty \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{#4\enspace}% \def\toctype{app}% \gdef\lastsection{#1}% \else \setbox0 = \hbox{#4\enspace}% \def\toctype{num}% \gdef\lastsection{#1}% \fi\fi\fi % % Write the toc entry (before \donoderef). See comments in \chapmacro. \writetocentry{\toctype\sectionlevel}{#1}{#4}% % % Write the node reference (= pdf destination for pdftex). % Again, see comments in \chapmacro. \donoderef{#3}% % % Interline glue will be inserted when the vbox is completed. % That glue will be a valid breakpoint for the page, since it'll be % preceded by a whatsit (usually from the \donoderef, or from the % \writetocentry if there was no node). We don't want to allow that % break, since then the whatsits could end up on page n while the % section is on page n+1, thus toc/etc. are wrong. Debian bug 276000. \nobreak % % Output the actual section heading. \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright \hangindent=\wd0 % zero if no section number \unhbox0 #1}% }% % Add extra space after the heading -- half of whatever came above it. % Don't allow stretch, though. \kern .5 \csname #2headingskip\endcsname % % Do not let the kern be a potential breakpoint, as it would be if it % was followed by glue. \nobreak % % We'll almost certainly start a paragraph next, so don't let that % glue accumulate. (Not a breakpoint because it's preceded by a % discardable item.) \vskip-\parskip % % This is purely so the last item on the list is a known \penalty > % 10000. This is so \startdefun can avoid allowing breakpoints after % section headings. Otherwise, it would insert a valid breakpoint between: % % @section sec-whatever % @deffn def-whatever \penalty 10001 } \message{toc,} % Table of contents. \newwrite\tocfile % Write an entry to the toc file, opening it if necessary. % Called from @chapter, etc. % % Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} % We append the current node name (if any) and page number as additional % arguments for the \{chap,sec,...}entry macros which will eventually % read this. The node name is used in the pdf outlines as the % destination to jump to. % % We open the .toc file for writing here instead of at @setfilename (or % any other fixed time) so that @contents can be anywhere in the document. % But if #1 is `omit', then we don't do anything. This is used for the % table of contents chapter openings themselves. % \newif\iftocfileopened \def\omitkeyword{omit}% % \def\writetocentry#1#2#3{% \edef\writetoctype{#1}% \ifx\writetoctype\omitkeyword \else \iftocfileopened\else \immediate\openout\tocfile = \jobname.toc \global\tocfileopenedtrue \fi % \iflinks {\atdummies \edef\temp{% \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}% \temp }% \fi \fi % % Tell \shipout to create a pdf destination on each page, if we're % writing pdf. These are used in the table of contents. We can't % just write one on every page because the title pages are numbered % 1 and 2 (the page numbers aren't printed), and so are the first % two pages of the document. Thus, we'd have two destinations named % `1', and two named `2'. \ifpdf \global\pdfmakepagedesttrue \fi } % These characters do not print properly in the Computer Modern roman % fonts, so we must take special care. This is more or less redundant % with the Texinfo input format setup at the end of this file. % \def\activecatcodes{% \catcode`\"=\active \catcode`\$=\active \catcode`\<=\active \catcode`\>=\active \catcode`\\=\active \catcode`\^=\active \catcode`\_=\active \catcode`\|=\active \catcode`\~=\active } % Read the toc file, which is essentially Texinfo input. \def\readtocfile{% \setupdatafile \activecatcodes \input \tocreadfilename } \newskip\contentsrightmargin \contentsrightmargin=1in \newcount\savepageno \newcount\lastnegativepageno \lastnegativepageno = -1 % Prepare to read what we've written to \tocfile. % \def\startcontents#1{% % If @setchapternewpage on, and @headings double, the contents should % start on an odd page, unlike chapters. Thus, we maintain % \contentsalignmacro in parallel with \pagealignmacro. % From: Torbjorn Granlund \contentsalignmacro \immediate\closeout\tocfile % % Don't need to put `Contents' or `Short Contents' in the headline. % It is abundantly clear what they are. \chapmacro{#1}{Yomitfromtoc}{}% % \savepageno = \pageno \begingroup % Set up to handle contents files properly. \raggedbottom % Worry more about breakpoints than the bottom. \advance\hsize by -\contentsrightmargin % Don't use the full line length. % % Roman numerals for page numbers. \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi } % redefined for the two-volume lispref. We always output on % \jobname.toc even if this is redefined. % \def\tocreadfilename{\jobname.toc} % Normal (long) toc. % \def\contents{% \startcontents{\putwordTOC}% \openin 1 \tocreadfilename\space \ifeof 1 \else \readtocfile \fi \vfill \eject \contentsalignmacro % in case @setchapternewpage odd is in effect \ifeof 1 \else \pdfmakeoutlines \fi \closein 1 \endgroup \lastnegativepageno = \pageno \global\pageno = \savepageno } % And just the chapters. \def\summarycontents{% \startcontents{\putwordShortTOC}% % \let\numchapentry = \shortchapentry \let\appentry = \shortchapentry \let\unnchapentry = \shortunnchapentry % We want a true roman here for the page numbers. \secfonts \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl \let\tt=\shortconttt \rm \hyphenpenalty = 10000 \advance\baselineskip by 1pt % Open it up a little. \def\numsecentry##1##2##3##4{} \let\appsecentry = \numsecentry \let\unnsecentry = \numsecentry \let\numsubsecentry = \numsecentry \let\appsubsecentry = \numsecentry \let\unnsubsecentry = \numsecentry \let\numsubsubsecentry = \numsecentry \let\appsubsubsecentry = \numsecentry \let\unnsubsubsecentry = \numsecentry \openin 1 \tocreadfilename\space \ifeof 1 \else \readtocfile \fi \closein 1 \vfill \eject \contentsalignmacro % in case @setchapternewpage odd is in effect \endgroup \lastnegativepageno = \pageno \global\pageno = \savepageno } \let\shortcontents = \summarycontents % Typeset the label for a chapter or appendix for the short contents. % The arg is, e.g., `A' for an appendix, or `3' for a chapter. % \def\shortchaplabel#1{% % This space should be enough, since a single number is .5em, and the % widest letter (M) is 1em, at least in the Computer Modern fonts. % But use \hss just in case. % (This space doesn't include the extra space that gets added after % the label; that gets put in by \shortchapentry above.) % % We'd like to right-justify chapter numbers, but that looks strange % with appendix letters. And right-justifying numbers and % left-justifying letters looks strange when there is less than 10 % chapters. Have to read the whole toc once to know how many chapters % there are before deciding ... \hbox to 1em{#1\hss}% } % These macros generate individual entries in the table of contents. % The first argument is the chapter or section name. % The last argument is the page number. % The arguments in between are the chapter number, section number, ... % Chapters, in the main contents. \def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} % % Chapters, in the short toc. % See comments in \dochapentry re vbox and related settings. \def\shortchapentry#1#2#3#4{% \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% } % Appendices, in the main contents. % Need the word Appendix, and a fixed-size box. % \def\appendixbox#1{% % We use M since it's probably the widest letter. \setbox0 = \hbox{\putwordAppendix{} M}% \hbox to \wd0{\putwordAppendix{} #1\hss}} % \def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} % Unnumbered chapters. \def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} \def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} % Sections. \def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} \let\appsecentry=\numsecentry \def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} % Subsections. \def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} \let\appsubsecentry=\numsubsecentry \def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} % And subsubsections. \def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} \let\appsubsubsecentry=\numsubsubsecentry \def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} % This parameter controls the indentation of the various levels. % Same as \defaultparindent. \newdimen\tocindent \tocindent = 15pt % Now for the actual typesetting. In all these, #1 is the text and #2 is the % page number. % % If the toc has to be broken over pages, we want it to be at chapters % if at all possible; hence the \penalty. \def\dochapentry#1#2{% \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip \begingroup \chapentryfonts \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup \nobreak\vskip .25\baselineskip plus.1\baselineskip } \def\dosecentry#1#2{\begingroup \secentryfonts \leftskip=\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsecentry#1#2{\begingroup \subsecentryfonts \leftskip=2\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsubsecentry#1#2{\begingroup \subsubsecentryfonts \leftskip=3\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} % We use the same \entry macro as for the index entries. \let\tocentry = \entry % Space between chapter (or whatever) number and the title. \def\labelspace{\hskip1em \relax} \def\dopageno#1{{\rm #1}} \def\doshortpageno#1{{\rm #1}} \def\chapentryfonts{\secfonts \rm} \def\secentryfonts{\textfonts} \def\subsecentryfonts{\textfonts} \def\subsubsecentryfonts{\textfonts} \message{environments,} % @foo ... @end foo. % Markup style infrastructure. \defmarkupstylesetup\INITMACRO will % define and register \INITMACRO to be called on markup style changes. % \INITMACRO can check \currentmarkupstyle for the innermost % style and the set of \ifmarkupSTYLE switches for all styles % currently in effect. \newif\ifmarkupvar \newif\ifmarkupsamp \newif\ifmarkupkey %\newif\ifmarkupfile % @file == @samp. %\newif\ifmarkupoption % @option == @samp. \newif\ifmarkupcode \newif\ifmarkupkbd %\newif\ifmarkupenv % @env == @code. %\newif\ifmarkupcommand % @command == @code. \newif\ifmarkuptex % @tex (and part of @math, for now). \newif\ifmarkupexample \newif\ifmarkupverb \newif\ifmarkupverbatim \let\currentmarkupstyle\empty \def\setupmarkupstyle#1{% \csname markup#1true\endcsname \def\currentmarkupstyle{#1}% \markupstylesetup } \let\markupstylesetup\empty \def\defmarkupstylesetup#1{% \expandafter\def\expandafter\markupstylesetup \expandafter{\markupstylesetup #1}% \def#1% } % Markup style setup for left and right quotes. \defmarkupstylesetup\markupsetuplq{% \expandafter\let\expandafter \temp \csname markupsetuplq\currentmarkupstyle\endcsname \ifx\temp\relax \markupsetuplqdefault \else \temp \fi } \defmarkupstylesetup\markupsetuprq{% \expandafter\let\expandafter \temp \csname markupsetuprq\currentmarkupstyle\endcsname \ifx\temp\relax \markupsetuprqdefault \else \temp \fi } { \catcode`\'=\active \catcode`\`=\active \gdef\markupsetuplqdefault{\let`\lq} \gdef\markupsetuprqdefault{\let'\rq} \gdef\markupsetcodequoteleft{\let`\codequoteleft} \gdef\markupsetcodequoteright{\let'\codequoteright} \gdef\markupsetnoligaturesquoteleft{\let`\noligaturesquoteleft} } \let\markupsetuplqcode \markupsetcodequoteleft \let\markupsetuprqcode \markupsetcodequoteright \let\markupsetuplqexample \markupsetcodequoteleft \let\markupsetuprqexample \markupsetcodequoteright \let\markupsetuplqverb \markupsetcodequoteleft \let\markupsetuprqverb \markupsetcodequoteright \let\markupsetuplqverbatim \markupsetcodequoteleft \let\markupsetuprqverbatim \markupsetcodequoteright \let\markupsetuplqsamp \markupsetnoligaturesquoteleft \let\markupsetuplqkbd \markupsetnoligaturesquoteleft % Allow an option to not replace quotes with a regular directed right % quote/apostrophe (char 0x27), but instead use the undirected quote % from cmtt (char 0x0d). The undirected quote is ugly, so don't make it % the default, but it works for pasting with more pdf viewers (at least % evince), the lilypond developers report. xpdf does work with the % regular 0x27. % \def\codequoteright{% \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax '% \else \char'15 \fi \else \char'15 \fi } % % and a similar option for the left quote char vs. a grave accent. % Modern fonts display ASCII 0x60 as a grave accent, so some people like % the code environments to do likewise. % \def\codequoteleft{% \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax % [Knuth] pp. 380,381,391 % \relax disables Spanish ligatures ?` and !` of \tt font. \relax`% \else \char'22 \fi \else \char'22 \fi } % [Knuth] pp. 380,381,391, disable Spanish ligatures ?` and !` of \tt font. \def\noligaturesquoteleft{\relax\lq} % @point{}, @result{}, @expansion{}, @print{}, @equiv{}. % % Since these characters are used in examples, they should be an even number of % \tt widths. Each \tt character is 1en, so two makes it 1em. % \def\point{$\star$} \def\arrow{\leavevmode\raise.05ex\hbox to 1em{\hfil$\rightarrow$\hfil}} \def\result{\leavevmode\raise.05ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} \def\expansion{\leavevmode\hbox to 1em{\hfil$\mapsto$\hfil}} \def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} \def\equiv{\leavevmode\hbox to 1em{\hfil$\ptexequiv$\hfil}} % The @error{} command. % Adapted from the TeXbook's \boxit. % \newbox\errorbox % {\tentt \global\dimen0 = 3em}% Width of the box. \dimen2 = .55pt % Thickness of rules % The text. (`r' is open on the right, `e' somewhat less so on the left.) \setbox0 = \hbox{\kern-.75pt \reducedsf error\kern-1.5pt} % \setbox\errorbox=\hbox to \dimen0{\hfil \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. \advance\hsize by -2\dimen2 % Rules. \vbox{% \hrule height\dimen2 \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. \kern3pt\vrule width\dimen2}% Space to right. \hrule height\dimen2} \hfil} % \def\error{\leavevmode\lower.7ex\copy\errorbox} % @tex ... @end tex escapes into raw Tex temporarily. % One exception: @ is still an escape character, so that @end tex works. % But \@ or @@ will get a plain tex @ character. \envdef\tex{% \setupmarkupstyle{tex}% \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie \catcode `\%=14 \catcode `\+=\other \catcode `\"=\other \catcode `\|=\other \catcode `\<=\other \catcode `\>=\other \catcode`\`=\other \catcode`\'=\other \escapechar=`\\ % \let\b=\ptexb \let\bullet=\ptexbullet \let\c=\ptexc \let\,=\ptexcomma \let\.=\ptexdot \let\dots=\ptexdots \let\equiv=\ptexequiv \let\!=\ptexexclam \let\i=\ptexi \let\indent=\ptexindent \let\noindent=\ptexnoindent \let\{=\ptexlbrace \let\+=\tabalign \let\}=\ptexrbrace \let\/=\ptexslash \let\*=\ptexstar \let\t=\ptext \expandafter \let\csname top\endcsname=\ptextop % outer \let\frenchspacing=\plainfrenchspacing % \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% \def\@{@}% } % There is no need to define \Etex. % Define @lisp ... @end lisp. % @lisp environment forms a group so it can rebind things, % including the definition of @end lisp (which normally is erroneous). % Amount to narrow the margins by for @lisp. \newskip\lispnarrowing \lispnarrowing=0.4in % This is the definition that ^^M gets inside @lisp, @example, and other % such environments. \null is better than a space, since it doesn't % have any width. \def\lisppar{\null\endgraf} % This space is always present above and below environments. \newskip\envskipamount \envskipamount = 0pt % Make spacing and below environment symmetrical. We use \parskip here % to help in doing that, since in @example-like environments \parskip % is reset to zero; thus the \afterenvbreak inserts no space -- but the % start of the next paragraph will insert \parskip. % \def\aboveenvbreak{{% % =10000 instead of <10000 because of a special case in \itemzzz and % \sectionheading, q.v. \ifnum \lastpenalty=10000 \else \advance\envskipamount by \parskip \endgraf \ifdim\lastskip<\envskipamount \removelastskip % it's not a good place to break if the last penalty was \nobreak % or better ... \ifnum\lastpenalty<10000 \penalty-50 \fi \vskip\envskipamount \fi \fi }} \let\afterenvbreak = \aboveenvbreak % \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will % also clear it, so that its embedded environments do the narrowing again. \let\nonarrowing=\relax % @cartouche ... @end cartouche: draw rectangle w/rounded corners around % environment contents. \font\circle=lcircle10 \newdimen\circthick \newdimen\cartouter\newdimen\cartinner \newskip\normbskip\newskip\normpskip\newskip\normlskip \circthick=\fontdimen8\circle % \def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth \def\ctr{{\hskip 6pt\circle\char'010}} \def\cbl{{\circle\char'012\hskip -6pt}} \def\cbr{{\hskip 6pt\circle\char'011}} \def\carttop{\hbox to \cartouter{\hskip\lskip \ctl\leaders\hrule height\circthick\hfil\ctr \hskip\rskip}} \def\cartbot{\hbox to \cartouter{\hskip\lskip \cbl\leaders\hrule height\circthick\hfil\cbr \hskip\rskip}} % \newskip\lskip\newskip\rskip \envdef\cartouche{% \ifhmode\par\fi % can't be in the midst of a paragraph. \startsavinginserts \lskip=\leftskip \rskip=\rightskip \leftskip=0pt\rightskip=0pt % we want these *outside*. \cartinner=\hsize \advance\cartinner by-\lskip \advance\cartinner by-\rskip \cartouter=\hsize \advance\cartouter by 18.4pt % allow for 3pt kerns on either % side, and for 6pt waste from % each corner char, and rule thickness \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip % Flag to tell @lisp, etc., not to narrow margin. \let\nonarrowing = t% \vbox\bgroup \baselineskip=0pt\parskip=0pt\lineskip=0pt \carttop \hbox\bgroup \hskip\lskip \vrule\kern3pt \vbox\bgroup \kern3pt \hsize=\cartinner \baselineskip=\normbskip \lineskip=\normlskip \parskip=\normpskip \vskip -\parskip \comment % For explanation, see the end of \def\group. } \def\Ecartouche{% \ifhmode\par\fi \kern3pt \egroup \kern3pt\vrule \hskip\rskip \egroup \cartbot \egroup \checkinserts } % This macro is called at the beginning of all the @example variants, % inside a group. \def\nonfillstart{% \aboveenvbreak \hfuzz = 12pt % Don't be fussy \sepspaces % Make spaces be word-separators rather than space tokens. \let\par = \lisppar % don't ignore blank lines \obeylines % each line of input is a line of output \parskip = 0pt \parindent = 0pt \emergencystretch = 0pt % don't try to avoid overfull boxes \ifx\nonarrowing\relax \advance \leftskip by \lispnarrowing \exdentamount=\lispnarrowing \else \let\nonarrowing = \relax \fi \let\exdent=\nofillexdent } % If you want all examples etc. small: @set dispenvsize small. % If you want even small examples the full size: @set dispenvsize nosmall. % This affects the following displayed environments: % @example, @display, @format, @lisp % \def\smallword{small} \def\nosmallword{nosmall} \let\SETdispenvsize\relax \def\setnormaldispenv{% \ifx\SETdispenvsize\smallword % end paragraph for sake of leading, in case document has no blank % line. This is redundant with what happens in \aboveenvbreak, but % we need to do it before changing the fonts, and it's inconvenient % to change the fonts afterward. \ifnum \lastpenalty=10000 \else \endgraf \fi \smallexamplefonts \rm \fi } \def\setsmalldispenv{% \ifx\SETdispenvsize\nosmallword \else \ifnum \lastpenalty=10000 \else \endgraf \fi \smallexamplefonts \rm \fi } % We often define two environments, @foo and @smallfoo. % Let's do it by one command: \def\makedispenv #1#2{ \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2} \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2} \expandafter\let\csname E#1\endcsname \afterenvbreak \expandafter\let\csname Esmall#1\endcsname \afterenvbreak } % Define two synonyms: \def\maketwodispenvs #1#2#3{ \makedispenv{#1}{#3} \makedispenv{#2}{#3} } % @lisp: indented, narrowed, typewriter font; @example: same as @lisp. % % @smallexample and @smalllisp: use smaller fonts. % Originally contributed by Pavel@xerox. % \maketwodispenvs {lisp}{example}{% \nonfillstart \tt\setupmarkupstyle{example}% \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. \gobble % eat return } % @display/@smalldisplay: same as @lisp except keep current font. % \makedispenv {display}{% \nonfillstart \gobble } % @format/@smallformat: same as @display except don't narrow margins. % \makedispenv{format}{% \let\nonarrowing = t% \nonfillstart \gobble } % @flushleft: same as @format, but doesn't obey \SETdispenvsize. \envdef\flushleft{% \let\nonarrowing = t% \nonfillstart \gobble } \let\Eflushleft = \afterenvbreak % @flushright. % \envdef\flushright{% \let\nonarrowing = t% \nonfillstart \advance\leftskip by 0pt plus 1fill \gobble } \let\Eflushright = \afterenvbreak % @quotation does normal linebreaking (hence we can't use \nonfillstart) % and narrows the margins. We keep \parskip nonzero in general, since % we're doing normal filling. So, when using \aboveenvbreak and % \afterenvbreak, temporarily make \parskip 0. % \def\quotationstart{% {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip \parindent=0pt % % @cartouche defines \nonarrowing to inhibit narrowing at next level down. \ifx\nonarrowing\relax \advance\leftskip by \lispnarrowing \advance\rightskip by \lispnarrowing \exdentamount = \lispnarrowing \else \let\nonarrowing = \relax \fi \parsearg\quotationlabel } \envdef\quotation{% \setnormaldispenv \quotationstart } \envdef\smallquotation{% \setsmalldispenv \quotationstart } \let\Esmallquotation = \Equotation % We have retained a nonzero parskip for the environment, since we're % doing normal filling. % \def\Equotation{% \par \ifx\quotationauthor\undefined\else % indent a bit. \leftline{\kern 2\leftskip \sl ---\quotationauthor}% \fi {\parskip=0pt \afterenvbreak}% } % If we're given an argument, typeset it in bold with a colon after. \def\quotationlabel#1{% \def\temp{#1}% \ifx\temp\empty \else {\bf #1: }% \fi } % LaTeX-like @verbatim...@end verbatim and @verb{...} % If we want to allow any as delimiter, % we need the curly braces so that makeinfo sees the @verb command, eg: % `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org % % [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. % % [Knuth] p.344; only we need to do the other characters Texinfo sets % active too. Otherwise, they get lost as the first character on a % verbatim line. \def\dospecials{% \do\ \do\\\do\{\do\}\do\$\do\&% \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% \do\<\do\>\do\|\do\@\do+\do\"% % Don't do the quotes -- if we do, @set txicodequoteundirected and % @set txicodequotebacktick will not have effect on @verb and % @verbatim, and ?` and !` ligatures won't get disabled. %\do\`\do\'% } % % [Knuth] p. 380 \def\uncatcodespecials{% \def\do##1{\catcode`##1=\other}\dospecials} % % Setup for the @verb command. % % Eight spaces for a tab \begingroup \catcode`\^^I=\active \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} \endgroup % \def\setupverb{% \tt % easiest (and conventionally used) font for verbatim \def\par{\leavevmode\endgraf}% \setupmarkupstyle{verb}% \tabeightspaces % Respect line breaks, % print special symbols as themselves, and % make each space count % must do in this order: \obeylines \uncatcodespecials \sepspaces } % Setup for the @verbatim environment % % Real tab expansion \newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount % \def\starttabbox{\setbox0=\hbox\bgroup} % \begingroup \catcode`\^^I=\active \gdef\tabexpand{% \catcode`\^^I=\active \def^^I{\leavevmode\egroup \dimen0=\wd0 % the width so far, or since the previous tab \divide\dimen0 by\tabw \multiply\dimen0 by\tabw % compute previous multiple of \tabw \advance\dimen0 by\tabw % advance to next multiple of \tabw \wd0=\dimen0 \box0 \starttabbox }% } \endgroup % start the verbatim environment. \def\setupverbatim{% \let\nonarrowing = t% \nonfillstart % Easiest (and conventionally used) font for verbatim \tt \def\par{\leavevmode\egroup\box0\endgraf}% \tabexpand \setupmarkupstyle{verbatim}% % Respect line breaks, % print special symbols as themselves, and % make each space count % must do in this order: \obeylines \uncatcodespecials \sepspaces \everypar{\starttabbox}% } % Do the @verb magic: verbatim text is quoted by unique % delimiter characters. Before first delimiter expect a % right brace, after last delimiter expect closing brace: % % \def\doverb'{'#1'}'{#1} % % [Knuth] p. 382; only eat outer {} \begingroup \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] \endgroup % \def\verb{\begingroup\setupverb\doverb} % % % Do the @verbatim magic: define the macro \doverbatim so that % the (first) argument ends when '@end verbatim' is reached, ie: % % \def\doverbatim#1@end verbatim{#1} % % For Texinfo it's a lot easier than for LaTeX, % because texinfo's \verbatim doesn't stop at '\end{verbatim}': % we need not redefine '\', '{' and '}'. % % Inspired by LaTeX's verbatim command set [latex.ltx] % \begingroup \catcode`\ =\active \obeylines % % ignore everything up to the first ^^M, that's the newline at the end % of the @verbatim input line itself. Otherwise we get an extra blank % line in the output. \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% % We really want {...\end verbatim} in the body of the macro, but % without the active space; thus we have to use \xdef and \gobble. \endgroup % \envdef\verbatim{% \setupverbatim\doverbatim } \let\Everbatim = \afterenvbreak % @verbatiminclude FILE - insert text of file in verbatim environment. % \def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} % \def\doverbatiminclude#1{% {% \makevalueexpandable \setupverbatim \indexnofonts % Allow `@@' and other weird things in file names. \input #1 \afterenvbreak }% } % @copying ... @end copying. % Save the text away for @insertcopying later. % % We save the uninterpreted tokens, rather than creating a box. % Saving the text in a box would be much easier, but then all the % typesetting commands (@smallbook, font changes, etc.) have to be done % beforehand -- and a) we want @copying to be done first in the source % file; b) letting users define the frontmatter in as flexible order as % possible is very desirable. % \def\copying{\checkenv{}\begingroup\scanargctxt\docopying} \def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} % \def\insertcopying{% \begingroup \parindent = 0pt % paragraph indentation looks wrong on title page \scanexp\copyingtext \endgroup } \message{defuns,} % @defun etc. \newskip\defbodyindent \defbodyindent=.4in \newskip\defargsindent \defargsindent=50pt \newskip\deflastargmargin \deflastargmargin=18pt \newcount\defunpenalty % Start the processing of @deffn: \def\startdefun{% \ifnum\lastpenalty<10000 \medbreak \defunpenalty=10003 % Will keep this @deffn together with the % following @def command, see below. \else % If there are two @def commands in a row, we'll have a \nobreak, % which is there to keep the function description together with its % header. But if there's nothing but headers, we need to allow a % break somewhere. Check specifically for penalty 10002, inserted % by \printdefunline, instead of 10000, since the sectioning % commands also insert a nobreak penalty, and we don't want to allow % a break between a section heading and a defun. % % As a minor refinement, we avoid "club" headers by signalling % with penalty of 10003 after the very first @deffn in the % sequence (see above), and penalty of 10002 after any following % @def command. \ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi % % Similarly, after a section heading, do not allow a break. % But do insert the glue. \medskip % preceded by discardable penalty, so not a breakpoint \fi % \parindent=0in \advance\leftskip by \defbodyindent \exdentamount=\defbodyindent } \def\dodefunx#1{% % First, check whether we are in the right environment: \checkenv#1% % % As above, allow line break if we have multiple x headers in a row. % It's not a great place, though. \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi % % And now, it's time to reuse the body of the original defun: \expandafter\gobbledefun#1% } \def\gobbledefun#1\startdefun{} % \printdefunline \deffnheader{text} % \def\printdefunline#1#2{% \begingroup % call \deffnheader: #1#2 \endheader % common ending: \interlinepenalty = 10000 \advance\rightskip by 0pt plus 1fil \endgraf \nobreak\vskip -\parskip \penalty\defunpenalty % signal to \startdefun and \dodefunx % Some of the @defun-type tags do not enable magic parentheses, % rendering the following check redundant. But we don't optimize. \checkparencounts \endgroup } \def\Edefun{\endgraf\medbreak} % \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; % the only thing remaining is to define \deffnheader. % \def\makedefun#1{% \expandafter\let\csname E#1\endcsname = \Edefun \edef\temp{\noexpand\domakedefun \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% \temp } % \domakedefun \deffn \deffnx \deffnheader % % Define \deffn and \deffnx, without parameters. % \deffnheader has to be defined explicitly. % \def\domakedefun#1#2#3{% \envdef#1{% \startdefun \parseargusing\activeparens{\printdefunline#3}% }% \def#2{\dodefunx#1}% \def#3% } %%% Untyped functions: % @deffn category name args \makedefun{deffn}{\deffngeneral{}} % @deffn category class name args \makedefun{defop}#1 {\defopon{#1\ \putwordon}} % \defopon {category on}class name args \def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } % \deffngeneral {subind}category name args % \def\deffngeneral#1#2 #3 #4\endheader{% % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. \dosubind{fn}{\code{#3}}{#1}% \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% } %%% Typed functions: % @deftypefn category type name args \makedefun{deftypefn}{\deftypefngeneral{}} % @deftypeop category class type name args \makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} % \deftypeopon {category on}class type name args \def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } % \deftypefngeneral {subind}category type name args % \def\deftypefngeneral#1#2 #3 #4 #5\endheader{% \dosubind{fn}{\code{#4}}{#1}% \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } %%% Typed variables: % @deftypevr category type var args \makedefun{deftypevr}{\deftypecvgeneral{}} % @deftypecv category class type var args \makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} % \deftypecvof {category of}class type var args \def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } % \deftypecvgeneral {subind}category type var args % \def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% \dosubind{vr}{\code{#4}}{#1}% \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } %%% Untyped variables: % @defvr category var args \makedefun{defvr}#1 {\deftypevrheader{#1} {} } % @defcv category class var args \makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} % \defcvof {category of}class var args \def\defcvof#1#2 {\deftypecvof{#1}#2 {} } %%% Type: % @deftp category name args \makedefun{deftp}#1 #2 #3\endheader{% \doind{tp}{\code{#2}}% \defname{#1}{}{#2}\defunargs{#3\unskip}% } % Remaining @defun-like shortcuts: \makedefun{defun}{\deffnheader{\putwordDeffunc} } \makedefun{defmac}{\deffnheader{\putwordDefmac} } \makedefun{defspec}{\deffnheader{\putwordDefspec} } \makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } \makedefun{defvar}{\defvrheader{\putwordDefvar} } \makedefun{defopt}{\defvrheader{\putwordDefopt} } \makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } \makedefun{defmethod}{\defopon\putwordMethodon} \makedefun{deftypemethod}{\deftypeopon\putwordMethodon} \makedefun{defivar}{\defcvof\putwordInstanceVariableof} \makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} % \defname, which formats the name of the @def (not the args). % #1 is the category, such as "Function". % #2 is the return type, if any. % #3 is the function name. % % We are followed by (but not passed) the arguments, if any. % \def\defname#1#2#3{% % Get the values of \leftskip and \rightskip as they were outside the @def... \advance\leftskip by -\defbodyindent % % How we'll format the type name. Putting it in brackets helps % distinguish it from the body text that may end up on the next line % just below it. \def\temp{#1}% \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} % % Figure out line sizes for the paragraph shape. % The first line needs space for \box0; but if \rightskip is nonzero, % we need only space for the part of \box0 which exceeds it: \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip % The continuations: \dimen2=\hsize \advance\dimen2 by -\defargsindent % (plain.tex says that \dimen1 should be used only as global.) \parshape 2 0in \dimen0 \defargsindent \dimen2 % % Put the type name to the right margin. \noindent \hbox to 0pt{% \hfil\box0 \kern-\hsize % \hsize has to be shortened this way: \kern\leftskip % Intentionally do not respect \rightskip, since we need the space. }% % % Allow all lines to be underfull without complaint: \tolerance=10000 \hbadness=10000 \exdentamount=\defbodyindent {% % defun fonts. We use typewriter by default (used to be bold) because: % . we're printing identifiers, they should be in tt in principle. % . in languages with many accents, such as Czech or French, it's % common to leave accents off identifiers. The result looks ok in % tt, but exceedingly strange in rm. % . we don't want -- and --- to be treated as ligatures. % . this still does not fix the ?` and !` ligatures, but so far no % one has made identifiers using them :). \df \tt \def\temp{#2}% return value type \ifx\temp\empty\else \tclose{\temp} \fi #3% output function name }% {\rm\enskip}% hskip 0.5 em of \tenrm % \boldbrax % arguments will be output next, if any. } % Print arguments in slanted roman (not ttsl), inconsistently with using % tt for the name. This is because literal text is sometimes needed in % the argument list (groff manual), and ttsl and tt are not very % distinguishable. Prevent hyphenation at `-' chars. % \def\defunargs#1{% % use sl by default (not ttsl), % tt for the names. \df \sl \hyphenchar\font=0 % % On the other hand, if an argument has two dashes (for instance), we % want a way to get ttsl. Let's try @var for that. \def\var##1{{\setupmarkupstyle{var}\ttslanted{##1}}}% #1% \sl\hyphenchar\font=45 } % We want ()&[] to print specially on the defun line. % \def\activeparens{% \catcode`\(=\active \catcode`\)=\active \catcode`\[=\active \catcode`\]=\active \catcode`\&=\active } % Make control sequences which act like normal parenthesis chars. \let\lparen = ( \let\rparen = ) % Be sure that we always have a definition for `(', etc. For example, % if the fn name has parens in it, \boldbrax will not be in effect yet, % so TeX would otherwise complain about undefined control sequence. { \activeparens \global\let(=\lparen \global\let)=\rparen \global\let[=\lbrack \global\let]=\rbrack \global\let& = \& \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} \gdef\magicamp{\let&=\amprm} } \newcount\parencount % If we encounter &foo, then turn on ()-hacking afterwards \newif\ifampseen \def\amprm#1 {\ampseentrue{\bf\ }} \def\parenfont{% \ifampseen % At the first level, print parens in roman, % otherwise use the default font. \ifnum \parencount=1 \rm \fi \else % The \sf parens (in \boldbrax) actually are a little bolder than % the contained text. This is especially needed for [ and ] . \sf \fi } \def\infirstlevel#1{% \ifampseen \ifnum\parencount=1 #1% \fi \fi } \def\bfafterword#1 {#1 \bf} \def\opnr{% \global\advance\parencount by 1 {\parenfont(}% \infirstlevel \bfafterword } \def\clnr{% {\parenfont)}% \infirstlevel \sl \global\advance\parencount by -1 } \newcount\brackcount \def\lbrb{% \global\advance\brackcount by 1 {\bf[}% } \def\rbrb{% {\bf]}% \global\advance\brackcount by -1 } \def\checkparencounts{% \ifnum\parencount=0 \else \badparencount \fi \ifnum\brackcount=0 \else \badbrackcount \fi } % these should not use \errmessage; the glibc manual, at least, actually % has such constructs (when documenting function pointers). \def\badparencount{% \message{Warning: unbalanced parentheses in @def...}% \global\parencount=0 } \def\badbrackcount{% \message{Warning: unbalanced square brackets in @def...}% \global\brackcount=0 } \message{macros,} % @macro. % To do this right we need a feature of e-TeX, \scantokens, % which we arrange to emulate with a temporary file in ordinary TeX. \ifx\eTeXversion\undefined \newwrite\macscribble \def\scantokens#1{% \toks0={#1}% \immediate\openout\macscribble=\jobname.tmp \immediate\write\macscribble{\the\toks0}% \immediate\closeout\macscribble \input \jobname.tmp } \fi \def\scanmacro#1{% \begingroup \newlinechar`\^^M \let\xeatspaces\eatspaces % Undo catcode changes of \startcontents and \doprintindex % When called from @insertcopying or (short)caption, we need active % backslash to get it printed correctly. Previously, we had % \catcode`\\=\other instead. We'll see whether a problem appears % with macro expansion. --kasal, 19aug04 \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ % ... and \example \spaceisspace % % Append \endinput to make sure that TeX does not see the ending newline. % I've verified that it is necessary both for e-TeX and for ordinary TeX % --kasal, 29nov03 \scantokens{#1\endinput}% \endgroup } \def\scanexp#1{% \edef\temp{\noexpand\scanmacro{#1}}% \temp } \newcount\paramno % Count of parameters \newtoks\macname % Macro name \newif\ifrecursive % Is it recursive? % List of all defined macros in the form % \definedummyword\macro1\definedummyword\macro2... % Currently is also contains all @aliases; the list can be split % if there is a need. \def\macrolist{} % Add the macro to \macrolist \def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} \def\addtomacrolistxxx#1{% \toks0 = \expandafter{\macrolist\definedummyword#1}% \xdef\macrolist{\the\toks0}% } % Utility routines. % This does \let #1 = #2, with \csnames; that is, % \let \csname#1\endcsname = \csname#2\endcsname % (except of course we have to play expansion games). % \def\cslet#1#2{% \expandafter\let \csname#1\expandafter\endcsname \csname#2\endcsname } % Trim leading and trailing spaces off a string. % Concepts from aro-bend problem 15 (see CTAN). {\catcode`\@=11 \gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} \gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} \gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} \def\unbrace#1{#1} \unbrace{\gdef\trim@@@ #1 } #2@{#1} } % Trim a single trailing ^^M off a string. {\catcode`\^^M=\other \catcode`\Q=3% \gdef\eatcr #1{\eatcra #1Q^^MQ}% \gdef\eatcra#1^^MQ{\eatcrb#1Q}% \gdef\eatcrb#1Q#2Q{#1}% } % Macro bodies are absorbed as an argument in a context where % all characters are catcode 10, 11 or 12, except \ which is active % (as in normal texinfo). It is necessary to change the definition of \. % Non-ASCII encodings make 8-bit characters active, so un-activate % them to avoid their expansion. Must do this non-globally, to % confine the change to the current group. % It's necessary to have hard CRs when the macro is executed. This is % done by making ^^M (\endlinechar) catcode 12 when reading the macro % body, and then making it the \newlinechar in \scanmacro. \def\scanctxt{% \catcode`\"=\other \catcode`\+=\other \catcode`\<=\other \catcode`\>=\other \catcode`\@=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other \catcode`\~=\other \ifx\declaredencoding\ascii \else \setnonasciicharscatcodenonglobal\other \fi } \def\scanargctxt{% \scanctxt \catcode`\\=\other \catcode`\^^M=\other } \def\macrobodyctxt{% \scanctxt \catcode`\{=\other \catcode`\}=\other \catcode`\^^M=\other \usembodybackslash } \def\macroargctxt{% \scanctxt \catcode`\\=\other } % \mbodybackslash is the definition of \ in @macro bodies. % It maps \foo\ => \csname macarg.foo\endcsname => #N % where N is the macro parameter number. % We define \csname macarg.\endcsname to be \realbackslash, so % \\ in macro replacement text gets you a backslash. {\catcode`@=0 @catcode`@\=@active @gdef@usembodybackslash{@let\=@mbodybackslash} @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} } \expandafter\def\csname macarg.\endcsname{\realbackslash} \def\macro{\recursivefalse\parsearg\macroxxx} \def\rmacro{\recursivetrue\parsearg\macroxxx} \def\macroxxx#1{% \getargs{#1}% now \macname is the macname and \argl the arglist \ifx\argl\empty % no arguments \paramno=0% \else \expandafter\parsemargdef \argl;% \fi \if1\csname ismacro.\the\macname\endcsname \message{Warning: redefining \the\macname}% \else \expandafter\ifx\csname \the\macname\endcsname \relax \else \errmessage{Macro name \the\macname\space already defined}\fi \global\cslet{macsave.\the\macname}{\the\macname}% \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% \addtomacrolist{\the\macname}% \fi \begingroup \macrobodyctxt \ifrecursive \expandafter\parsermacbody \else \expandafter\parsemacbody \fi} \parseargdef\unmacro{% \if1\csname ismacro.#1\endcsname \global\cslet{#1}{macsave.#1}% \global\expandafter\let \csname ismacro.#1\endcsname=0% % Remove the macro name from \macrolist: \begingroup \expandafter\let\csname#1\endcsname \relax \let\definedummyword\unmacrodo \xdef\macrolist{\macrolist}% \endgroup \else \errmessage{Macro #1 not defined}% \fi } % Called by \do from \dounmacro on each macro. The idea is to omit any % macro definitions that have been changed to \relax. % \def\unmacrodo#1{% \ifx #1\relax % remove this \else \noexpand\definedummyword \noexpand#1% \fi } % This makes use of the obscure feature that if the last token of a % is #, then the preceding argument is delimited by % an opening brace, and that opening brace is not consumed. \def\getargs#1{\getargsxxx#1{}} \def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} \def\getmacname #1 #2\relax{\macname={#1}} \def\getmacargs#1{\def\argl{#1}} % Parse the optional {params} list. Set up \paramno and \paramlist % so \defmacro knows what to do. Define \macarg.blah for each blah % in the params list, to be ##N where N is the position in that list. % That gets used by \mbodybackslash (above). % We need to get `macro parameter char #' into several definitions. % The technique used is stolen from LaTeX: let \hash be something % unexpandable, insert that wherever you need a #, and then redefine % it to # just before using the token list produced. % % The same technique is used to protect \eatspaces till just before % the macro is used. \def\parsemargdef#1;{\paramno=0\def\paramlist{}% \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} \def\parsemargdefxxx#1,{% \if#1;\let\next=\relax \else \let\next=\parsemargdefxxx \advance\paramno by 1% \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname {\xeatspaces{\hash\the\paramno}}% \edef\paramlist{\paramlist\hash\the\paramno,}% \fi\next} % These two commands read recursive and nonrecursive macro bodies. % (They're different since rec and nonrec macros end differently.) \long\def\parsemacbody#1@end macro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% \long\def\parsermacbody#1@end rmacro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% % This defines the macro itself. There are six cases: recursive and % nonrecursive macros of zero, one, and many arguments. % Much magic with \expandafter here. % \xdef is used so that macro definitions will survive the file % they're defined in; @include reads the file inside a group. \def\defmacro{% \let\hash=##% convert placeholders to macro parameter chars \ifrecursive \ifcase\paramno % 0 \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\scanmacro{\temp}}% \or % 1 \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\braceorline \expandafter\noexpand\csname\the\macname xxx\endcsname}% \expandafter\xdef\csname\the\macname xxx\endcsname##1{% \egroup\noexpand\scanmacro{\temp}}% \else % many \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\csname\the\macname xx\endcsname}% \expandafter\xdef\csname\the\macname xx\endcsname##1{% \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% \expandafter\expandafter \expandafter\xdef \expandafter\expandafter \csname\the\macname xxx\endcsname \paramlist{\egroup\noexpand\scanmacro{\temp}}% \fi \else \ifcase\paramno % 0 \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \or % 1 \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\braceorline \expandafter\noexpand\csname\the\macname xxx\endcsname}% \expandafter\xdef\csname\the\macname xxx\endcsname##1{% \egroup \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \else % many \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \expandafter\noexpand\csname\the\macname xx\endcsname}% \expandafter\xdef\csname\the\macname xx\endcsname##1{% \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% \expandafter\expandafter \expandafter\xdef \expandafter\expandafter \csname\the\macname xxx\endcsname \paramlist{% \egroup \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \fi \fi} \def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} % \braceorline decides whether the next nonwhitespace character is a % {. If so it reads up to the closing }, if not, it reads the whole % line. Whatever was read is then fed to the next control sequence % as an argument (by \parsebrace or \parsearg) \def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx} \def\braceorlinexxx{% \ifx\nchar\bgroup\else \expandafter\parsearg \fi \macnamexxx} % @alias. % We need some trickery to remove the optional spaces around the equal % sign. Just make them active and then expand them all to nothing. \def\alias{\parseargusing\obeyspaces\aliasxxx} \def\aliasxxx #1{\aliasyyy#1\relax} \def\aliasyyy #1=#2\relax{% {% \expandafter\let\obeyedspace=\empty \addtomacrolist{#1}% \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% }% \next } \message{cross references,} \newwrite\auxfile \newif\ifhavexrefs % True if xref values are known. \newif\ifwarnedxrefs % True if we warned once that they aren't known. % @inforef is relatively simple. \def\inforef #1{\inforefzzz #1,,,,**} \def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, node \samp{\ignorespaces#1{}}} % @node's only job in TeX is to define \lastnode, which is used in % cross-references. The @node line might or might not have commas, and % might or might not have spaces before the first comma, like: % @node foo , bar , ... % We don't want such trailing spaces in the node name. % \parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} % % also remove a trailing comma, in case of something like this: % @node Help-Cross, , , Cross-refs \def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} \def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} \let\nwnode=\node \let\lastnode=\empty % Write a cross-reference definition for the current node. #1 is the % type (Ynumbered, Yappendix, Ynothing). % \def\donoderef#1{% \ifx\lastnode\empty\else \setref{\lastnode}{#1}% \global\let\lastnode=\empty \fi } % @anchor{NAME} -- define xref target at arbitrary point. % \newcount\savesfregister % \def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} \def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} \def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} % \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an % anchor), which consists of three parts: % 1) NAME-title - the current sectioning name taken from \lastsection, % or the anchor name. % 2) NAME-snt - section number and type, passed as the SNT arg, or % empty for anchors. % 3) NAME-pg - the page number. % % This is called from \donoderef, \anchor, and \dofloat. In the case of % floats, there is an additional part, which is not written here: % 4) NAME-lof - the text as it should appear in a @listoffloats. % \def\setref#1#2{% \pdfmkdest{#1}% \iflinks {% \atdummies % preserve commands, but don't expand them \edef\writexrdef##1##2{% \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef ##1}{##2}}% these are parameters of \writexrdef }% \toks0 = \expandafter{\lastsection}% \immediate \writexrdef{title}{\the\toks0 }% \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, during \shipout }% \fi } % @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is % the node name, #2 the name of the Info cross-reference, #3 the printed % node name, #4 the name of the Info file, #5 the name of the printed % manual. All but the node name can be omitted. % \def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} \def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} \def\ref#1{\xrefX[#1,,,,,,,]} \def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup \unsepspaces \def\printedmanual{\ignorespaces #5}% \def\printedrefname{\ignorespaces #3}% \setbox1=\hbox{\printedmanual\unskip}% \setbox0=\hbox{\printedrefname\unskip}% \ifdim \wd0 = 0pt % No printed node name was explicitly given. \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax % Use the node name inside the square brackets. \def\printedrefname{\ignorespaces #1}% \else % Use the actual chapter/section title appear inside % the square brackets. Use the real section title if we have it. \ifdim \wd1 > 0pt % It is in another manual, so we don't have it. \def\printedrefname{\ignorespaces #1}% \else \ifhavexrefs % We know the real title if we have the xref values. \def\printedrefname{\refx{#1-title}{}}% \else % Otherwise just copy the Info node name. \def\printedrefname{\ignorespaces #1}% \fi% \fi \fi \fi % % Make link in pdf output. \ifpdf {\indexnofonts \turnoffactive % This expands tokens, so do it after making catcode changes, so _ % etc. don't get their TeX definitions. \getfilename{#4}% % % See comments at \activebackslashdouble. {\activebackslashdouble \xdef\pdfxrefdest{#1}% \backslashparens\pdfxrefdest}% % \leavevmode \startlink attr{/Border [0 0 0]}% \ifnum\filenamelength>0 goto file{\the\filename.pdf} name{\pdfxrefdest}% \else goto name{\pdfmkpgn{\pdfxrefdest}}% \fi }% \setcolor{\linkcolor}% \fi % % Float references are printed completely differently: "Figure 1.2" % instead of "[somenode], p.3". We distinguish them by the % LABEL-title being set to a magic string. {% % Have to otherify everything special to allow the \csname to % include an _ in the xref name, etc. \indexnofonts \turnoffactive \expandafter\global\expandafter\let\expandafter\Xthisreftitle \csname XR#1-title\endcsname }% \iffloat\Xthisreftitle % If the user specified the print name (third arg) to the ref, % print it instead of our usual "Figure 1.2". \ifdim\wd0 = 0pt \refx{#1-snt}{}% \else \printedrefname \fi % % if the user also gave the printed manual name (fifth arg), append % "in MANUALNAME". \ifdim \wd1 > 0pt \space \putwordin{} \cite{\printedmanual}% \fi \else % node/anchor (non-float) references. % % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not % insert empty discretionaries after hyphens, which means that it will % not find a line break at a hyphen in a node names. Since some manuals % are best written with fairly long node names, containing hyphens, this % is a loss. Therefore, we give the text of the node name again, so it % is as if TeX is seeing it for the first time. \ifdim \wd1 > 0pt \putwordSection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}% \else % _ (for example) has to be the character _ for the purposes of the % control sequence corresponding to the node, but it has to expand % into the usual \leavevmode...\vrule stuff for purposes of % printing. So we \turnoffactive for the \refx-snt, back on for the % printing, back off for the \refx-pg. {\turnoffactive % Only output a following space if the -snt ref is nonempty; for % @unnumbered and @anchor, it won't be. \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi }% % output the `[mynode]' via a macro so it can be overridden. \xrefprintnodename\printedrefname % % But we always want a comma and a space: ,\space % % output the `page 3'. \turnoffactive \putwordpage\tie\refx{#1-pg}{}% \fi \fi \endlink \endgroup} % This macro is called from \xrefX for the `[nodename]' part of xref % output. It's a separate macro only so it can be changed more easily, % since square brackets don't work well in some documents. Particularly % one that Bob is working on :). % \def\xrefprintnodename#1{[#1]} % Things referred to by \setref. % \def\Ynothing{} \def\Yomitfromtoc{} \def\Ynumbered{% \ifnum\secno=0 \putwordChapter@tie \the\chapno \else \ifnum\subsecno=0 \putwordSection@tie \the\chapno.\the\secno \else \ifnum\subsubsecno=0 \putwordSection@tie \the\chapno.\the\secno.\the\subsecno \else \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno \fi\fi\fi } \def\Yappendix{% \ifnum\secno=0 \putwordAppendix@tie @char\the\appendixno{}% \else \ifnum\subsecno=0 \putwordSection@tie @char\the\appendixno.\the\secno \else \ifnum\subsubsecno=0 \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno \else \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno \fi\fi\fi } % Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. % If its value is nonempty, SUFFIX is output afterward. % \def\refx#1#2{% {% \indexnofonts \otherbackslash \expandafter\global\expandafter\let\expandafter\thisrefX \csname XR#1\endcsname }% \ifx\thisrefX\relax % If not defined, say something at least. \angleleft un\-de\-fined\angleright \iflinks \ifhavexrefs \message{\linenumber Undefined cross reference `#1'.}% \else \ifwarnedxrefs\else \global\warnedxrefstrue \message{Cross reference values unknown; you must run TeX again.}% \fi \fi \fi \else % It's defined, so just use it. \thisrefX \fi #2% Output the suffix in any case. } % This is the macro invoked by entries in the aux file. Usually it's % just a \def (we prepend XR to the control sequence name to avoid % collisions). But if this is a float type, we have more work to do. % \def\xrdef#1#2{% {% The node name might contain 8-bit characters, which in our current % implementation are changed to commands like @'e. Don't let these % mess up the control sequence name. \indexnofonts \turnoffactive \xdef\safexrefname{#1}% }% % \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref % % Was that xref control sequence that we just defined for a float? \expandafter\iffloat\csname XR\safexrefname\endcsname % it was a float, and we have the (safe) float type in \iffloattype. \expandafter\let\expandafter\floatlist \csname floatlist\iffloattype\endcsname % % Is this the first time we've seen this float type? \expandafter\ifx\floatlist\relax \toks0 = {\do}% yes, so just \do \else % had it before, so preserve previous elements in list. \toks0 = \expandafter{\floatlist\do}% \fi % % Remember this xref in the control sequence \floatlistFLOATTYPE, % for later use in \listoffloats. \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0 {\safexrefname}}% \fi } % Read the last existing aux file, if any. No error if none exists. % \def\tryauxfile{% \openin 1 \jobname.aux \ifeof 1 \else \readdatafile{aux}% \global\havexrefstrue \fi \closein 1 } \def\setupdatafile{% \catcode`\^^@=\other \catcode`\^^A=\other \catcode`\^^B=\other \catcode`\^^C=\other \catcode`\^^D=\other \catcode`\^^E=\other \catcode`\^^F=\other \catcode`\^^G=\other \catcode`\^^H=\other \catcode`\^^K=\other \catcode`\^^L=\other \catcode`\^^N=\other \catcode`\^^P=\other \catcode`\^^Q=\other \catcode`\^^R=\other \catcode`\^^S=\other \catcode`\^^T=\other \catcode`\^^U=\other \catcode`\^^V=\other \catcode`\^^W=\other \catcode`\^^X=\other \catcode`\^^Z=\other \catcode`\^^[=\other \catcode`\^^\=\other \catcode`\^^]=\other \catcode`\^^^=\other \catcode`\^^_=\other % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. % in xref tags, i.e., node names. But since ^^e4 notation isn't % supported in the main text, it doesn't seem desirable. Furthermore, % that is not enough: for node names that actually contain a ^ % character, we would end up writing a line like this: 'xrdef {'hat % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first % argument, and \hat is not an expandable control sequence. It could % all be worked out, but why? Either we support ^^ or we don't. % % The other change necessary for this was to define \auxhat: % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter % and then to call \auxhat in \setq. % \catcode`\^=\other % % Special characters. Should be turned off anyway, but... \catcode`\~=\other \catcode`\[=\other \catcode`\]=\other \catcode`\"=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\$=\other \catcode`\#=\other \catcode`\&=\other \catcode`\%=\other \catcode`+=\other % avoid \+ for paranoia even though we've turned it off % % This is to support \ in node names and titles, since the \ % characters end up in a \csname. It's easier than % leaving it active and making its active definition an actual \ % character. What I don't understand is why it works in the *value* % of the xrdef. Seems like it should be a catcode12 \, and that % should not typeset properly. But it works, so I'm moving on for % now. --karl, 15jan04. \catcode`\\=\other % % Make the characters 128-255 be printing characters. {% \count1=128 \def\loop{% \catcode\count1=\other \advance\count1 by 1 \ifnum \count1<256 \loop \fi }% }% % % @ is our escape character in .aux files, and we need braces. \catcode`\{=1 \catcode`\}=2 \catcode`\@=0 } \def\readdatafile#1{% \begingroup \setupdatafile \input\jobname.#1 \endgroup} \message{insertions,} % including footnotes. \newcount \footnoteno % The trailing space in the following definition for supereject is % vital for proper filling; pages come out unaligned when you do a % pagealignmacro call if that space before the closing brace is % removed. (Generally, numeric constants should always be followed by a % space to prevent strange expansion errors.) \def\supereject{\par\penalty -20000\footnoteno =0 } % @footnotestyle is meaningful for info output only. \let\footnotestyle=\comment {\catcode `\@=11 % % Auto-number footnotes. Otherwise like plain. \gdef\footnote{% \let\indent=\ptexindent \let\noindent=\ptexnoindent \global\advance\footnoteno by \@ne \edef\thisfootno{$^{\the\footnoteno}$}% % % In case the footnote comes at the end of a sentence, preserve the % extra spacing after we do the footnote number. \let\@sf\empty \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi % % Remove inadvertent blank space before typesetting the footnote number. \unskip \thisfootno\@sf \dofootnote }% % Don't bother with the trickery in plain.tex to not require the % footnote text as a parameter. Our footnotes don't need to be so general. % % Oh yes, they do; otherwise, @ifset (and anything else that uses % \parseargline) fails inside footnotes because the tokens are fixed when % the footnote is read. --karl, 16nov96. % \gdef\dofootnote{% \insert\footins\bgroup % We want to typeset this text as a normal paragraph, even if the % footnote reference occurs in (for example) a display environment. % So reset some parameters. \hsize=\pagewidth \interlinepenalty\interfootnotelinepenalty \splittopskip\ht\strutbox % top baseline for broken footnotes \splitmaxdepth\dp\strutbox \floatingpenalty\@MM \leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip \parindent\defaultparindent % \smallfonts \rm % % Because we use hanging indentation in footnotes, a @noindent appears % to exdent this text, so make it be a no-op. makeinfo does not use % hanging indentation so @noindent can still be needed within footnote % text after an @example or the like (not that this is good style). \let\noindent = \relax % % Hang the footnote text off the number. Use \everypar in case the % footnote extends for more than one paragraph. \everypar = {\hang}% \textindent{\thisfootno}% % % Don't crash into the line above the footnote text. Since this % expands into a box, it must come within the paragraph, lest it % provide a place where TeX can split the footnote. \footstrut \futurelet\next\fo@t } }%end \catcode `\@=11 % In case a @footnote appears in a vbox, save the footnote text and create % the real \insert just after the vbox finished. Otherwise, the insertion % would be lost. % Similarly, if a @footnote appears inside an alignment, save the footnote % text to a box and make the \insert when a row of the table is finished. % And the same can be done for other insert classes. --kasal, 16nov03. % Replace the \insert primitive by a cheating macro. % Deeper inside, just make sure that the saved insertions are not spilled % out prematurely. % \def\startsavinginserts{% \ifx \insert\ptexinsert \let\insert\saveinsert \else \let\checkinserts\relax \fi } % This \insert replacement works for both \insert\footins{foo} and % \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. % \def\saveinsert#1{% \edef\next{\noexpand\savetobox \makeSAVEname#1}% \afterassignment\next % swallow the left brace \let\temp = } \def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} \def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} \def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} \def\placesaveins#1{% \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname {\box#1}% } % eat @SAVE -- beware, all of them have catcode \other: { \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) \gdef\gobblesave @SAVE{} } % initialization: \def\newsaveins #1{% \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% \next } \def\newsaveinsX #1{% \csname newbox\endcsname #1% \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts \checksaveins #1}% } % initialize: \let\checkinserts\empty \newsaveins\footins \newsaveins\margin % @image. We use the macros from epsf.tex to support this. % If epsf.tex is not installed and @image is used, we complain. % % Check for and read epsf.tex up front. If we read it only at @image % time, we might be inside a group, and then its definitions would get % undone and the next image would fail. \openin 1 = epsf.tex \ifeof 1 \else % Do not bother showing banner with epsf.tex v2.7k (available in % doc/epsf.tex and on ctan). \def\epsfannounce{\toks0 = }% \input epsf.tex \fi \closein 1 % % We will only complain once about lack of epsf.tex. \newif\ifwarnednoepsf \newhelp\noepsfhelp{epsf.tex must be installed for images to work. It is also included in the Texinfo distribution, or you can get it from ftp://tug.org/tex/epsf.tex.} % \def\image#1{% \ifx\epsfbox\undefined \ifwarnednoepsf \else \errhelp = \noepsfhelp \errmessage{epsf.tex not found, images will be ignored}% \global\warnednoepsftrue \fi \else \imagexxx #1,,,,,\finish \fi } % % Arguments to @image: % #1 is (mandatory) image filename; we tack on .eps extension. % #2 is (optional) width, #3 is (optional) height. % #4 is (ignored optional) html alt text. % #5 is (ignored optional) extension. % #6 is just the usual extra ignored arg for parsing this stuff. \newif\ifimagevmode \def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup \catcode`\^^M = 5 % in case we're inside an example \normalturnoffactive % allow _ et al. in names % If the image is by itself, center it. \ifvmode \imagevmodetrue \nobreak\medskip % Usually we'll have text after the image which will insert % \parskip glue, so insert it here too to equalize the space % above and below. \nobreak\vskip\parskip \nobreak \fi % % Leave vertical mode so that indentation from an enclosing % environment such as @quotation is respected. On the other hand, if % it's at the top level, we don't want the normal paragraph indentation. \noindent % % Output the image. \ifpdf \dopdfimage{#1}{#2}{#3}% \else % \epsfbox itself resets \epsf?size at each figure. \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi \epsfbox{#1.eps}% \fi % \ifimagevmode \medskip \fi % space after the standalone image \endgroup} % @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, % etc. We don't actually implement floating yet, we always include the % float "here". But it seemed the best name for the future. % \envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} % There may be a space before second and/or third parameter; delete it. \def\eatcommaspace#1, {#1,} % #1 is the optional FLOATTYPE, the text label for this float, typically % "Figure", "Table", "Example", etc. Can't contain commas. If omitted, % this float will not be numbered and cannot be referred to. % % #2 is the optional xref label. Also must be present for the float to % be referable. % % #3 is the optional positioning argument; for now, it is ignored. It % will somehow specify the positions allowed to float to (here, top, bottom). % % We keep a separate counter for each FLOATTYPE, which we reset at each % chapter-level command. \let\resetallfloatnos=\empty % \def\dofloat#1,#2,#3,#4\finish{% \let\thiscaption=\empty \let\thisshortcaption=\empty % % don't lose footnotes inside @float. % % BEWARE: when the floats start float, we have to issue warning whenever an % insert appears inside a float which could possibly float. --kasal, 26may04 % \startsavinginserts % % We can't be used inside a paragraph. \par % \vtop\bgroup \def\floattype{#1}% \def\floatlabel{#2}% \def\floatloc{#3}% we do nothing with this yet. % \ifx\floattype\empty \let\safefloattype=\empty \else {% % the floattype might have accents or other special characters, % but we need to use it in a control sequence name. \indexnofonts \turnoffactive \xdef\safefloattype{\floattype}% }% \fi % % If label is given but no type, we handle that as the empty type. \ifx\floatlabel\empty \else % We want each FLOATTYPE to be numbered separately (Figure 1, % Table 1, Figure 2, ...). (And if no label, no number.) % \expandafter\getfloatno\csname\safefloattype floatno\endcsname \global\advance\floatno by 1 % {% % This magic value for \lastsection is output by \setref as the % XREFLABEL-title value. \xrefX uses it to distinguish float % labels (which have a completely different output format) from % node and anchor labels. And \xrdef uses it to construct the % lists of floats. % \edef\lastsection{\floatmagic=\safefloattype}% \setref{\floatlabel}{Yfloat}% }% \fi % % start with \parskip glue, I guess. \vskip\parskip % % Don't suppress indentation if a float happens to start a section. \restorefirstparagraphindent } % we have these possibilities: % @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap % @float Foo,lbl & no caption: Foo 1.1 % @float Foo & @caption{Cap}: Foo: Cap % @float Foo & no caption: Foo % @float ,lbl & Caption{Cap}: 1.1: Cap % @float ,lbl & no caption: 1.1 % @float & @caption{Cap}: Cap % @float & no caption: % \def\Efloat{% \let\floatident = \empty % % In all cases, if we have a float type, it comes first. \ifx\floattype\empty \else \def\floatident{\floattype}\fi % % If we have an xref label, the number comes next. \ifx\floatlabel\empty \else \ifx\floattype\empty \else % if also had float type, need tie first. \appendtomacro\floatident{\tie}% \fi % the number. \appendtomacro\floatident{\chaplevelprefix\the\floatno}% \fi % % Start the printed caption with what we've constructed in % \floatident, but keep it separate; we need \floatident again. \let\captionline = \floatident % \ifx\thiscaption\empty \else \ifx\floatident\empty \else \appendtomacro\captionline{: }% had ident, so need a colon between \fi % % caption text. \appendtomacro\captionline{\scanexp\thiscaption}% \fi % % If we have anything to print, print it, with space before. % Eventually this needs to become an \insert. \ifx\captionline\empty \else \vskip.5\parskip \captionline % % Space below caption. \vskip\parskip \fi % % If have an xref label, write the list of floats info. Do this % after the caption, to avoid chance of it being a breakpoint. \ifx\floatlabel\empty \else % Write the text that goes in the lof to the aux file as % \floatlabel-lof. Besides \floatident, we include the short % caption if specified, else the full caption if specified, else nothing. {% \atdummies % % since we read the caption text in the macro world, where ^^M % is turned into a normal character, we have to scan it back, so % we don't write the literal three characters "^^M" into the aux file. \scanexp{% \xdef\noexpand\gtemp{% \ifx\thisshortcaption\empty \thiscaption \else \thisshortcaption \fi }% }% \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident \ifx\gtemp\empty \else : \gtemp \fi}}% }% \fi \egroup % end of \vtop % % place the captured inserts % % BEWARE: when the floats start floating, we have to issue warning % whenever an insert appears inside a float which could possibly % float. --kasal, 26may04 % \checkinserts } % Append the tokens #2 to the definition of macro #1, not expanding either. % \def\appendtomacro#1#2{% \expandafter\def\expandafter#1\expandafter{#1#2}% } % @caption, @shortcaption % \def\caption{\docaption\thiscaption} \def\shortcaption{\docaption\thisshortcaption} \def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} \def\defcaption#1#2{\egroup \def#1{#2}} % The parameter is the control sequence identifying the counter we are % going to use. Create it if it doesn't exist and assign it to \floatno. \def\getfloatno#1{% \ifx#1\relax % Haven't seen this figure type before. \csname newcount\endcsname #1% % % Remember to reset this floatno at the next chap. \expandafter\gdef\expandafter\resetallfloatnos \expandafter{\resetallfloatnos #1=0 }% \fi \let\floatno#1% } % \setref calls this to get the XREFLABEL-snt value. We want an @xref % to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we % first read the @float command. % \def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% % Magic string used for the XREFLABEL-title value, so \xrefX can % distinguish floats from other xref types. \def\floatmagic{!!float!!} % #1 is the control sequence we are passed; we expand into a conditional % which is true if #1 represents a float ref. That is, the magic % \lastsection value which we \setref above. % \def\iffloat#1{\expandafter\doiffloat#1==\finish} % % #1 is (maybe) the \floatmagic string. If so, #2 will be the % (safe) float type for this float. We set \iffloattype to #2. % \def\doiffloat#1=#2=#3\finish{% \def\temp{#1}% \def\iffloattype{#2}% \ifx\temp\floatmagic } % @listoffloats FLOATTYPE - print a list of floats like a table of contents. % \parseargdef\listoffloats{% \def\floattype{#1}% floattype {% % the floattype might have accents or other special characters, % but we need to use it in a control sequence name. \indexnofonts \turnoffactive \xdef\safefloattype{\floattype}% }% % % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax \ifhavexrefs % if the user said @listoffloats foo but never @float foo. \message{\linenumber No `\safefloattype' floats to list.}% \fi \else \begingroup \leftskip=\tocindent % indent these entries like a toc \let\do=\listoffloatsdo \csname floatlist\safefloattype\endcsname \endgroup \fi } % This is called on each entry in a list of floats. We're passed the % xref label, in the form LABEL-title, which is how we save it in the % aux file. We strip off the -title and look up \XRLABEL-lof, which % has the text we're supposed to typeset here. % % Figures without xref labels will not be included in the list (since % they won't appear in the aux file). % \def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} \def\listoffloatsdoentry#1-title\finish{{% % Can't fully expand XR#1-lof because it can contain anything. Just % pass the control sequence. On the other hand, XR#1-pg is just the % page number, and we want to fully expand that so we can get a link % in pdf output. \toksA = \expandafter{\csname XR#1-lof\endcsname}% % % use the same \entry macro we use to generate the TOC and index. \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% \writeentry }} \message{localization,} % For single-language documents, @documentlanguage is usually given very % early, just after @documentencoding. Single argument is the language % (de) or locale (de_DE) abbreviation. % { \catcode`\_ = \active \globaldefs=1 \parseargdef\documentlanguage{\begingroup \let_=\normalunderscore % normal _ character for filenames \tex % read txi-??.tex file in plain TeX. % Read the file by the name they passed if it exists. \openin 1 txi-#1.tex \ifeof 1 \documentlanguagetrywithoutunderscore{#1_\finish}% \else \globaldefs = 1 % everything in the txi-LL files needs to persist \input txi-#1.tex \fi \closein 1 \endgroup % end raw TeX \endgroup} } % % If they passed de_DE, and txi-de_DE.tex doesn't exist, % try txi-de.tex. % \def\documentlanguagetrywithoutunderscore#1_#2\finish{% \openin 1 txi-#1.tex \ifeof 1 \errhelp = \nolanghelp \errmessage{Cannot read language file txi-#1.tex}% \else \input txi-#1.tex \fi \closein 1 } % \newhelp\nolanghelp{The given language definition file cannot be found or is empty. Maybe you need to install it? Putting it in the current directory should work if nowhere else does.} % This macro is called from txi-??.tex files; the first argument is the % \language name to set (without the "\lang@" prefix), the second and % third args are \{left,right}hyphenmin. % % The language names to pass are determined when the format is built. % See the etex.log file created at that time, e.g., % /usr/local/texlive/2008/texmf-var/web2c/pdftex/etex.log. % % With TeX Live 2008, etex now includes hyphenation patterns for all % available languages. This means we can support hyphenation in % Texinfo, at least to some extent. (This still doesn't solve the % accented characters problem.) % \catcode`@=11 \def\txisetlanguage#1#2#3{% % do not set the language if the name is undefined in the current TeX. \expandafter\ifx\csname lang@#1\endcsname \relax \message{no patterns for #1}% \else \global\language = \csname lang@#1\endcsname \fi % but there is no harm in adjusting the hyphenmin values regardless. \global\lefthyphenmin = #2\relax \global\righthyphenmin = #3\relax } % Helpers for encodings. % Set the catcode of characters 128 through 255 to the specified number. % \def\setnonasciicharscatcode#1{% \count255=128 \loop\ifnum\count255<256 \global\catcode\count255=#1\relax \advance\count255 by 1 \repeat } \def\setnonasciicharscatcodenonglobal#1{% \count255=128 \loop\ifnum\count255<256 \catcode\count255=#1\relax \advance\count255 by 1 \repeat } % @documentencoding sets the definition of non-ASCII characters % according to the specified encoding. % \parseargdef\documentencoding{% % Encoding being declared for the document. \def\declaredencoding{\csname #1.enc\endcsname}% % % Supported encodings: names converted to tokens in order to be able % to compare them with \ifx. \def\ascii{\csname US-ASCII.enc\endcsname}% \def\latnine{\csname ISO-8859-15.enc\endcsname}% \def\latone{\csname ISO-8859-1.enc\endcsname}% \def\lattwo{\csname ISO-8859-2.enc\endcsname}% \def\utfeight{\csname UTF-8.enc\endcsname}% % \ifx \declaredencoding \ascii \asciichardefs % \else \ifx \declaredencoding \lattwo \setnonasciicharscatcode\active \lattwochardefs % \else \ifx \declaredencoding \latone \setnonasciicharscatcode\active \latonechardefs % \else \ifx \declaredencoding \latnine \setnonasciicharscatcode\active \latninechardefs % \else \ifx \declaredencoding \utfeight \setnonasciicharscatcode\active \utfeightchardefs % \else \message{Unknown document encoding #1, ignoring.}% % \fi % utfeight \fi % latnine \fi % latone \fi % lattwo \fi % ascii } % A message to be logged when using a character that isn't available % the default font encoding (OT1). % \def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}} % Take account of \c (plain) vs. \, (Texinfo) difference. \def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi} % First, make active non-ASCII characters in order for them to be % correctly categorized when TeX reads the replacement text of % macros containing the character definitions. \setnonasciicharscatcode\active % % Latin1 (ISO-8859-1) character definitions. \def\latonechardefs{% \gdef^^a0{~} \gdef^^a1{\exclamdown} \gdef^^a2{\missingcharmsg{CENT SIGN}} \gdef^^a3{{\pounds}} \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} \gdef^^a5{\missingcharmsg{YEN SIGN}} \gdef^^a6{\missingcharmsg{BROKEN BAR}} \gdef^^a7{\S} \gdef^^a8{\"{}} \gdef^^a9{\copyright} \gdef^^aa{\ordf} \gdef^^ab{\guillemetleft} \gdef^^ac{$\lnot$} \gdef^^ad{\-} \gdef^^ae{\registeredsymbol} \gdef^^af{\={}} % \gdef^^b0{\textdegree} \gdef^^b1{$\pm$} \gdef^^b2{$^2$} \gdef^^b3{$^3$} \gdef^^b4{\'{}} \gdef^^b5{$\mu$} \gdef^^b6{\P} % \gdef^^b7{$^.$} \gdef^^b8{\cedilla\ } \gdef^^b9{$^1$} \gdef^^ba{\ordm} % \gdef^^bb{\guilletright} \gdef^^bc{$1\over4$} \gdef^^bd{$1\over2$} \gdef^^be{$3\over4$} \gdef^^bf{\questiondown} % \gdef^^c0{\`A} \gdef^^c1{\'A} \gdef^^c2{\^A} \gdef^^c3{\~A} \gdef^^c4{\"A} \gdef^^c5{\ringaccent A} \gdef^^c6{\AE} \gdef^^c7{\cedilla C} \gdef^^c8{\`E} \gdef^^c9{\'E} \gdef^^ca{\^E} \gdef^^cb{\"E} \gdef^^cc{\`I} \gdef^^cd{\'I} \gdef^^ce{\^I} \gdef^^cf{\"I} % \gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER ETH}} \gdef^^d1{\~N} \gdef^^d2{\`O} \gdef^^d3{\'O} \gdef^^d4{\^O} \gdef^^d5{\~O} \gdef^^d6{\"O} \gdef^^d7{$\times$} \gdef^^d8{\O} \gdef^^d9{\`U} \gdef^^da{\'U} \gdef^^db{\^U} \gdef^^dc{\"U} \gdef^^dd{\'Y} \gdef^^de{\missingcharmsg{LATIN CAPITAL LETTER THORN}} \gdef^^df{\ss} % \gdef^^e0{\`a} \gdef^^e1{\'a} \gdef^^e2{\^a} \gdef^^e3{\~a} \gdef^^e4{\"a} \gdef^^e5{\ringaccent a} \gdef^^e6{\ae} \gdef^^e7{\cedilla c} \gdef^^e8{\`e} \gdef^^e9{\'e} \gdef^^ea{\^e} \gdef^^eb{\"e} \gdef^^ec{\`{\dotless i}} \gdef^^ed{\'{\dotless i}} \gdef^^ee{\^{\dotless i}} \gdef^^ef{\"{\dotless i}} % \gdef^^f0{\missingcharmsg{LATIN SMALL LETTER ETH}} \gdef^^f1{\~n} \gdef^^f2{\`o} \gdef^^f3{\'o} \gdef^^f4{\^o} \gdef^^f5{\~o} \gdef^^f6{\"o} \gdef^^f7{$\div$} \gdef^^f8{\o} \gdef^^f9{\`u} \gdef^^fa{\'u} \gdef^^fb{\^u} \gdef^^fc{\"u} \gdef^^fd{\'y} \gdef^^fe{\missingcharmsg{LATIN SMALL LETTER THORN}} \gdef^^ff{\"y} } % Latin9 (ISO-8859-15) encoding character definitions. \def\latninechardefs{% % Encoding is almost identical to Latin1. \latonechardefs % \gdef^^a4{\euro} \gdef^^a6{\v S} \gdef^^a8{\v s} \gdef^^b4{\v Z} \gdef^^b8{\v z} \gdef^^bc{\OE} \gdef^^bd{\oe} \gdef^^be{\"Y} } % Latin2 (ISO-8859-2) character definitions. \def\lattwochardefs{% \gdef^^a0{~} \gdef^^a1{\ogonek{A}} \gdef^^a2{\u{}} \gdef^^a3{\L} \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} \gdef^^a5{\v L} \gdef^^a6{\'S} \gdef^^a7{\S} \gdef^^a8{\"{}} \gdef^^a9{\v S} \gdef^^aa{\cedilla S} \gdef^^ab{\v T} \gdef^^ac{\'Z} \gdef^^ad{\-} \gdef^^ae{\v Z} \gdef^^af{\dotaccent Z} % \gdef^^b0{\textdegree} \gdef^^b1{\ogonek{a}} \gdef^^b2{\ogonek{ }} \gdef^^b3{\l} \gdef^^b4{\'{}} \gdef^^b5{\v l} \gdef^^b6{\'s} \gdef^^b7{\v{}} \gdef^^b8{\cedilla\ } \gdef^^b9{\v s} \gdef^^ba{\cedilla s} \gdef^^bb{\v t} \gdef^^bc{\'z} \gdef^^bd{\H{}} \gdef^^be{\v z} \gdef^^bf{\dotaccent z} % \gdef^^c0{\'R} \gdef^^c1{\'A} \gdef^^c2{\^A} \gdef^^c3{\u A} \gdef^^c4{\"A} \gdef^^c5{\'L} \gdef^^c6{\'C} \gdef^^c7{\cedilla C} \gdef^^c8{\v C} \gdef^^c9{\'E} \gdef^^ca{\ogonek{E}} \gdef^^cb{\"E} \gdef^^cc{\v E} \gdef^^cd{\'I} \gdef^^ce{\^I} \gdef^^cf{\v D} % \gdef^^d0{\missingcharmsg{LATIN CAPITAL LETTER D WITH STROKE}} \gdef^^d1{\'N} \gdef^^d2{\v N} \gdef^^d3{\'O} \gdef^^d4{\^O} \gdef^^d5{\H O} \gdef^^d6{\"O} \gdef^^d7{$\times$} \gdef^^d8{\v R} \gdef^^d9{\ringaccent U} \gdef^^da{\'U} \gdef^^db{\H U} \gdef^^dc{\"U} \gdef^^dd{\'Y} \gdef^^de{\cedilla T} \gdef^^df{\ss} % \gdef^^e0{\'r} \gdef^^e1{\'a} \gdef^^e2{\^a} \gdef^^e3{\u a} \gdef^^e4{\"a} \gdef^^e5{\'l} \gdef^^e6{\'c} \gdef^^e7{\cedilla c} \gdef^^e8{\v c} \gdef^^e9{\'e} \gdef^^ea{\ogonek{e}} \gdef^^eb{\"e} \gdef^^ec{\v e} \gdef^^ed{\'\i} \gdef^^ee{\^\i} \gdef^^ef{\v d} % \gdef^^f0{\missingcharmsg{LATIN SMALL LETTER D WITH STROKE}} \gdef^^f1{\'n} \gdef^^f2{\v n} \gdef^^f3{\'o} \gdef^^f4{\^o} \gdef^^f5{\H o} \gdef^^f6{\"o} \gdef^^f7{$\div$} \gdef^^f8{\v r} \gdef^^f9{\ringaccent u} \gdef^^fa{\'u} \gdef^^fb{\H u} \gdef^^fc{\"u} \gdef^^fd{\'y} \gdef^^fe{\cedilla t} \gdef^^ff{\dotaccent{}} } % UTF-8 character definitions. % % This code to support UTF-8 is based on LaTeX's utf8.def, with some % changes for Texinfo conventions. It is included here under the GPL by % permission from Frank Mittelbach and the LaTeX team. % \newcount\countUTFx \newcount\countUTFy \newcount\countUTFz \gdef\UTFviiiTwoOctets#1#2{\expandafter \UTFviiiDefined\csname u8:#1\string #2\endcsname} % \gdef\UTFviiiThreeOctets#1#2#3{\expandafter \UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname} % \gdef\UTFviiiFourOctets#1#2#3#4{\expandafter \UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname} \gdef\UTFviiiDefined#1{% \ifx #1\relax \message{\linenumber Unicode char \string #1 not defined for Texinfo}% \else \expandafter #1% \fi } \begingroup \catcode`\~13 \catcode`\"12 \def\UTFviiiLoop{% \global\catcode\countUTFx\active \uccode`\~\countUTFx \uppercase\expandafter{\UTFviiiTmp}% \advance\countUTFx by 1 \ifnum\countUTFx < \countUTFy \expandafter\UTFviiiLoop \fi} \countUTFx = "C2 \countUTFy = "E0 \def\UTFviiiTmp{% \xdef~{\noexpand\UTFviiiTwoOctets\string~}} \UTFviiiLoop \countUTFx = "E0 \countUTFy = "F0 \def\UTFviiiTmp{% \xdef~{\noexpand\UTFviiiThreeOctets\string~}} \UTFviiiLoop \countUTFx = "F0 \countUTFy = "F4 \def\UTFviiiTmp{% \xdef~{\noexpand\UTFviiiFourOctets\string~}} \UTFviiiLoop \endgroup \begingroup \catcode`\"=12 \catcode`\<=12 \catcode`\.=12 \catcode`\,=12 \catcode`\;=12 \catcode`\!=12 \catcode`\~=13 \gdef\DeclareUnicodeCharacter#1#2{% \countUTFz = "#1\relax \wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}% \begingroup \parseXMLCharref \def\UTFviiiTwoOctets##1##2{% \csname u8:##1\string ##2\endcsname}% \def\UTFviiiThreeOctets##1##2##3{% \csname u8:##1\string ##2\string ##3\endcsname}% \def\UTFviiiFourOctets##1##2##3##4{% \csname u8:##1\string ##2\string ##3\string ##4\endcsname}% \expandafter\expandafter\expandafter\expandafter \expandafter\expandafter\expandafter \gdef\UTFviiiTmp{#2}% \endgroup} \gdef\parseXMLCharref{% \ifnum\countUTFz < "A0\relax \errhelp = \EMsimple \errmessage{Cannot define Unicode char value < 00A0}% \else\ifnum\countUTFz < "800\relax \parseUTFviiiA,% \parseUTFviiiB C\UTFviiiTwoOctets.,% \else\ifnum\countUTFz < "10000\relax \parseUTFviiiA;% \parseUTFviiiA,% \parseUTFviiiB E\UTFviiiThreeOctets.{,;}% \else \parseUTFviiiA;% \parseUTFviiiA,% \parseUTFviiiA!% \parseUTFviiiB F\UTFviiiFourOctets.{!,;}% \fi\fi\fi } \gdef\parseUTFviiiA#1{% \countUTFx = \countUTFz \divide\countUTFz by 64 \countUTFy = \countUTFz \multiply\countUTFz by 64 \advance\countUTFx by -\countUTFz \advance\countUTFx by 128 \uccode `#1\countUTFx \countUTFz = \countUTFy} \gdef\parseUTFviiiB#1#2#3#4{% \advance\countUTFz by "#10\relax \uccode `#3\countUTFz \uppercase{\gdef\UTFviiiTmp{#2#3#4}}} \endgroup \def\utfeightchardefs{% \DeclareUnicodeCharacter{00A0}{\tie} \DeclareUnicodeCharacter{00A1}{\exclamdown} \DeclareUnicodeCharacter{00A3}{\pounds} \DeclareUnicodeCharacter{00A8}{\"{ }} \DeclareUnicodeCharacter{00A9}{\copyright} \DeclareUnicodeCharacter{00AA}{\ordf} \DeclareUnicodeCharacter{00AB}{\guillemetleft} \DeclareUnicodeCharacter{00AD}{\-} \DeclareUnicodeCharacter{00AE}{\registeredsymbol} \DeclareUnicodeCharacter{00AF}{\={ }} \DeclareUnicodeCharacter{00B0}{\ringaccent{ }} \DeclareUnicodeCharacter{00B4}{\'{ }} \DeclareUnicodeCharacter{00B8}{\cedilla{ }} \DeclareUnicodeCharacter{00BA}{\ordm} \DeclareUnicodeCharacter{00BB}{\guillemetright} \DeclareUnicodeCharacter{00BF}{\questiondown} \DeclareUnicodeCharacter{00C0}{\`A} \DeclareUnicodeCharacter{00C1}{\'A} \DeclareUnicodeCharacter{00C2}{\^A} \DeclareUnicodeCharacter{00C3}{\~A} \DeclareUnicodeCharacter{00C4}{\"A} \DeclareUnicodeCharacter{00C5}{\AA} \DeclareUnicodeCharacter{00C6}{\AE} \DeclareUnicodeCharacter{00C7}{\cedilla{C}} \DeclareUnicodeCharacter{00C8}{\`E} \DeclareUnicodeCharacter{00C9}{\'E} \DeclareUnicodeCharacter{00CA}{\^E} \DeclareUnicodeCharacter{00CB}{\"E} \DeclareUnicodeCharacter{00CC}{\`I} \DeclareUnicodeCharacter{00CD}{\'I} \DeclareUnicodeCharacter{00CE}{\^I} \DeclareUnicodeCharacter{00CF}{\"I} \DeclareUnicodeCharacter{00D1}{\~N} \DeclareUnicodeCharacter{00D2}{\`O} \DeclareUnicodeCharacter{00D3}{\'O} \DeclareUnicodeCharacter{00D4}{\^O} \DeclareUnicodeCharacter{00D5}{\~O} \DeclareUnicodeCharacter{00D6}{\"O} \DeclareUnicodeCharacter{00D8}{\O} \DeclareUnicodeCharacter{00D9}{\`U} \DeclareUnicodeCharacter{00DA}{\'U} \DeclareUnicodeCharacter{00DB}{\^U} \DeclareUnicodeCharacter{00DC}{\"U} \DeclareUnicodeCharacter{00DD}{\'Y} \DeclareUnicodeCharacter{00DF}{\ss} \DeclareUnicodeCharacter{00E0}{\`a} \DeclareUnicodeCharacter{00E1}{\'a} \DeclareUnicodeCharacter{00E2}{\^a} \DeclareUnicodeCharacter{00E3}{\~a} \DeclareUnicodeCharacter{00E4}{\"a} \DeclareUnicodeCharacter{00E5}{\aa} \DeclareUnicodeCharacter{00E6}{\ae} \DeclareUnicodeCharacter{00E7}{\cedilla{c}} \DeclareUnicodeCharacter{00E8}{\`e} \DeclareUnicodeCharacter{00E9}{\'e} \DeclareUnicodeCharacter{00EA}{\^e} \DeclareUnicodeCharacter{00EB}{\"e} \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}} \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}} \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}} \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}} \DeclareUnicodeCharacter{00F1}{\~n} \DeclareUnicodeCharacter{00F2}{\`o} \DeclareUnicodeCharacter{00F3}{\'o} \DeclareUnicodeCharacter{00F4}{\^o} \DeclareUnicodeCharacter{00F5}{\~o} \DeclareUnicodeCharacter{00F6}{\"o} \DeclareUnicodeCharacter{00F8}{\o} \DeclareUnicodeCharacter{00F9}{\`u} \DeclareUnicodeCharacter{00FA}{\'u} \DeclareUnicodeCharacter{00FB}{\^u} \DeclareUnicodeCharacter{00FC}{\"u} \DeclareUnicodeCharacter{00FD}{\'y} \DeclareUnicodeCharacter{00FF}{\"y} \DeclareUnicodeCharacter{0100}{\=A} \DeclareUnicodeCharacter{0101}{\=a} \DeclareUnicodeCharacter{0102}{\u{A}} \DeclareUnicodeCharacter{0103}{\u{a}} \DeclareUnicodeCharacter{0104}{\ogonek{A}} \DeclareUnicodeCharacter{0105}{\ogonek{a}} \DeclareUnicodeCharacter{0106}{\'C} \DeclareUnicodeCharacter{0107}{\'c} \DeclareUnicodeCharacter{0108}{\^C} \DeclareUnicodeCharacter{0109}{\^c} \DeclareUnicodeCharacter{0118}{\ogonek{E}} \DeclareUnicodeCharacter{0119}{\ogonek{e}} \DeclareUnicodeCharacter{010A}{\dotaccent{C}} \DeclareUnicodeCharacter{010B}{\dotaccent{c}} \DeclareUnicodeCharacter{010C}{\v{C}} \DeclareUnicodeCharacter{010D}{\v{c}} \DeclareUnicodeCharacter{010E}{\v{D}} \DeclareUnicodeCharacter{0112}{\=E} \DeclareUnicodeCharacter{0113}{\=e} \DeclareUnicodeCharacter{0114}{\u{E}} \DeclareUnicodeCharacter{0115}{\u{e}} \DeclareUnicodeCharacter{0116}{\dotaccent{E}} \DeclareUnicodeCharacter{0117}{\dotaccent{e}} \DeclareUnicodeCharacter{011A}{\v{E}} \DeclareUnicodeCharacter{011B}{\v{e}} \DeclareUnicodeCharacter{011C}{\^G} \DeclareUnicodeCharacter{011D}{\^g} \DeclareUnicodeCharacter{011E}{\u{G}} \DeclareUnicodeCharacter{011F}{\u{g}} \DeclareUnicodeCharacter{0120}{\dotaccent{G}} \DeclareUnicodeCharacter{0121}{\dotaccent{g}} \DeclareUnicodeCharacter{0124}{\^H} \DeclareUnicodeCharacter{0125}{\^h} \DeclareUnicodeCharacter{0128}{\~I} \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}} \DeclareUnicodeCharacter{012A}{\=I} \DeclareUnicodeCharacter{012B}{\={\dotless{i}}} \DeclareUnicodeCharacter{012C}{\u{I}} \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}} \DeclareUnicodeCharacter{0130}{\dotaccent{I}} \DeclareUnicodeCharacter{0131}{\dotless{i}} \DeclareUnicodeCharacter{0132}{IJ} \DeclareUnicodeCharacter{0133}{ij} \DeclareUnicodeCharacter{0134}{\^J} \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}} \DeclareUnicodeCharacter{0139}{\'L} \DeclareUnicodeCharacter{013A}{\'l} \DeclareUnicodeCharacter{0141}{\L} \DeclareUnicodeCharacter{0142}{\l} \DeclareUnicodeCharacter{0143}{\'N} \DeclareUnicodeCharacter{0144}{\'n} \DeclareUnicodeCharacter{0147}{\v{N}} \DeclareUnicodeCharacter{0148}{\v{n}} \DeclareUnicodeCharacter{014C}{\=O} \DeclareUnicodeCharacter{014D}{\=o} \DeclareUnicodeCharacter{014E}{\u{O}} \DeclareUnicodeCharacter{014F}{\u{o}} \DeclareUnicodeCharacter{0150}{\H{O}} \DeclareUnicodeCharacter{0151}{\H{o}} \DeclareUnicodeCharacter{0152}{\OE} \DeclareUnicodeCharacter{0153}{\oe} \DeclareUnicodeCharacter{0154}{\'R} \DeclareUnicodeCharacter{0155}{\'r} \DeclareUnicodeCharacter{0158}{\v{R}} \DeclareUnicodeCharacter{0159}{\v{r}} \DeclareUnicodeCharacter{015A}{\'S} \DeclareUnicodeCharacter{015B}{\'s} \DeclareUnicodeCharacter{015C}{\^S} \DeclareUnicodeCharacter{015D}{\^s} \DeclareUnicodeCharacter{015E}{\cedilla{S}} \DeclareUnicodeCharacter{015F}{\cedilla{s}} \DeclareUnicodeCharacter{0160}{\v{S}} \DeclareUnicodeCharacter{0161}{\v{s}} \DeclareUnicodeCharacter{0162}{\cedilla{t}} \DeclareUnicodeCharacter{0163}{\cedilla{T}} \DeclareUnicodeCharacter{0164}{\v{T}} \DeclareUnicodeCharacter{0168}{\~U} \DeclareUnicodeCharacter{0169}{\~u} \DeclareUnicodeCharacter{016A}{\=U} \DeclareUnicodeCharacter{016B}{\=u} \DeclareUnicodeCharacter{016C}{\u{U}} \DeclareUnicodeCharacter{016D}{\u{u}} \DeclareUnicodeCharacter{016E}{\ringaccent{U}} \DeclareUnicodeCharacter{016F}{\ringaccent{u}} \DeclareUnicodeCharacter{0170}{\H{U}} \DeclareUnicodeCharacter{0171}{\H{u}} \DeclareUnicodeCharacter{0174}{\^W} \DeclareUnicodeCharacter{0175}{\^w} \DeclareUnicodeCharacter{0176}{\^Y} \DeclareUnicodeCharacter{0177}{\^y} \DeclareUnicodeCharacter{0178}{\"Y} \DeclareUnicodeCharacter{0179}{\'Z} \DeclareUnicodeCharacter{017A}{\'z} \DeclareUnicodeCharacter{017B}{\dotaccent{Z}} \DeclareUnicodeCharacter{017C}{\dotaccent{z}} \DeclareUnicodeCharacter{017D}{\v{Z}} \DeclareUnicodeCharacter{017E}{\v{z}} \DeclareUnicodeCharacter{01C4}{D\v{Z}} \DeclareUnicodeCharacter{01C5}{D\v{z}} \DeclareUnicodeCharacter{01C6}{d\v{z}} \DeclareUnicodeCharacter{01C7}{LJ} \DeclareUnicodeCharacter{01C8}{Lj} \DeclareUnicodeCharacter{01C9}{lj} \DeclareUnicodeCharacter{01CA}{NJ} \DeclareUnicodeCharacter{01CB}{Nj} \DeclareUnicodeCharacter{01CC}{nj} \DeclareUnicodeCharacter{01CD}{\v{A}} \DeclareUnicodeCharacter{01CE}{\v{a}} \DeclareUnicodeCharacter{01CF}{\v{I}} \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}} \DeclareUnicodeCharacter{01D1}{\v{O}} \DeclareUnicodeCharacter{01D2}{\v{o}} \DeclareUnicodeCharacter{01D3}{\v{U}} \DeclareUnicodeCharacter{01D4}{\v{u}} \DeclareUnicodeCharacter{01E2}{\={\AE}} \DeclareUnicodeCharacter{01E3}{\={\ae}} \DeclareUnicodeCharacter{01E6}{\v{G}} \DeclareUnicodeCharacter{01E7}{\v{g}} \DeclareUnicodeCharacter{01E8}{\v{K}} \DeclareUnicodeCharacter{01E9}{\v{k}} \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}} \DeclareUnicodeCharacter{01F1}{DZ} \DeclareUnicodeCharacter{01F2}{Dz} \DeclareUnicodeCharacter{01F3}{dz} \DeclareUnicodeCharacter{01F4}{\'G} \DeclareUnicodeCharacter{01F5}{\'g} \DeclareUnicodeCharacter{01F8}{\`N} \DeclareUnicodeCharacter{01F9}{\`n} \DeclareUnicodeCharacter{01FC}{\'{\AE}} \DeclareUnicodeCharacter{01FD}{\'{\ae}} \DeclareUnicodeCharacter{01FE}{\'{\O}} \DeclareUnicodeCharacter{01FF}{\'{\o}} \DeclareUnicodeCharacter{021E}{\v{H}} \DeclareUnicodeCharacter{021F}{\v{h}} \DeclareUnicodeCharacter{0226}{\dotaccent{A}} \DeclareUnicodeCharacter{0227}{\dotaccent{a}} \DeclareUnicodeCharacter{0228}{\cedilla{E}} \DeclareUnicodeCharacter{0229}{\cedilla{e}} \DeclareUnicodeCharacter{022E}{\dotaccent{O}} \DeclareUnicodeCharacter{022F}{\dotaccent{o}} \DeclareUnicodeCharacter{0232}{\=Y} \DeclareUnicodeCharacter{0233}{\=y} \DeclareUnicodeCharacter{0237}{\dotless{j}} \DeclareUnicodeCharacter{02DB}{\ogonek{ }} \DeclareUnicodeCharacter{1E02}{\dotaccent{B}} \DeclareUnicodeCharacter{1E03}{\dotaccent{b}} \DeclareUnicodeCharacter{1E04}{\udotaccent{B}} \DeclareUnicodeCharacter{1E05}{\udotaccent{b}} \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}} \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}} \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}} \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}} \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}} \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}} \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}} \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}} \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}} \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}} \DeclareUnicodeCharacter{1E20}{\=G} \DeclareUnicodeCharacter{1E21}{\=g} \DeclareUnicodeCharacter{1E22}{\dotaccent{H}} \DeclareUnicodeCharacter{1E23}{\dotaccent{h}} \DeclareUnicodeCharacter{1E24}{\udotaccent{H}} \DeclareUnicodeCharacter{1E25}{\udotaccent{h}} \DeclareUnicodeCharacter{1E26}{\"H} \DeclareUnicodeCharacter{1E27}{\"h} \DeclareUnicodeCharacter{1E30}{\'K} \DeclareUnicodeCharacter{1E31}{\'k} \DeclareUnicodeCharacter{1E32}{\udotaccent{K}} \DeclareUnicodeCharacter{1E33}{\udotaccent{k}} \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}} \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}} \DeclareUnicodeCharacter{1E36}{\udotaccent{L}} \DeclareUnicodeCharacter{1E37}{\udotaccent{l}} \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}} \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}} \DeclareUnicodeCharacter{1E3E}{\'M} \DeclareUnicodeCharacter{1E3F}{\'m} \DeclareUnicodeCharacter{1E40}{\dotaccent{M}} \DeclareUnicodeCharacter{1E41}{\dotaccent{m}} \DeclareUnicodeCharacter{1E42}{\udotaccent{M}} \DeclareUnicodeCharacter{1E43}{\udotaccent{m}} \DeclareUnicodeCharacter{1E44}{\dotaccent{N}} \DeclareUnicodeCharacter{1E45}{\dotaccent{n}} \DeclareUnicodeCharacter{1E46}{\udotaccent{N}} \DeclareUnicodeCharacter{1E47}{\udotaccent{n}} \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}} \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}} \DeclareUnicodeCharacter{1E54}{\'P} \DeclareUnicodeCharacter{1E55}{\'p} \DeclareUnicodeCharacter{1E56}{\dotaccent{P}} \DeclareUnicodeCharacter{1E57}{\dotaccent{p}} \DeclareUnicodeCharacter{1E58}{\dotaccent{R}} \DeclareUnicodeCharacter{1E59}{\dotaccent{r}} \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}} \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}} \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}} \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}} \DeclareUnicodeCharacter{1E60}{\dotaccent{S}} \DeclareUnicodeCharacter{1E61}{\dotaccent{s}} \DeclareUnicodeCharacter{1E62}{\udotaccent{S}} \DeclareUnicodeCharacter{1E63}{\udotaccent{s}} \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}} \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}} \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}} \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}} \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}} \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}} \DeclareUnicodeCharacter{1E7C}{\~V} \DeclareUnicodeCharacter{1E7D}{\~v} \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}} \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}} \DeclareUnicodeCharacter{1E80}{\`W} \DeclareUnicodeCharacter{1E81}{\`w} \DeclareUnicodeCharacter{1E82}{\'W} \DeclareUnicodeCharacter{1E83}{\'w} \DeclareUnicodeCharacter{1E84}{\"W} \DeclareUnicodeCharacter{1E85}{\"w} \DeclareUnicodeCharacter{1E86}{\dotaccent{W}} \DeclareUnicodeCharacter{1E87}{\dotaccent{w}} \DeclareUnicodeCharacter{1E88}{\udotaccent{W}} \DeclareUnicodeCharacter{1E89}{\udotaccent{w}} \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}} \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}} \DeclareUnicodeCharacter{1E8C}{\"X} \DeclareUnicodeCharacter{1E8D}{\"x} \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}} \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}} \DeclareUnicodeCharacter{1E90}{\^Z} \DeclareUnicodeCharacter{1E91}{\^z} \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}} \DeclareUnicodeCharacter{1E93}{\udotaccent{z}} \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}} \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}} \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}} \DeclareUnicodeCharacter{1E97}{\"t} \DeclareUnicodeCharacter{1E98}{\ringaccent{w}} \DeclareUnicodeCharacter{1E99}{\ringaccent{y}} \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}} \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}} \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}} \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}} \DeclareUnicodeCharacter{1EBC}{\~E} \DeclareUnicodeCharacter{1EBD}{\~e} \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}} \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}} \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}} \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}} \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}} \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}} \DeclareUnicodeCharacter{1EF2}{\`Y} \DeclareUnicodeCharacter{1EF3}{\`y} \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}} \DeclareUnicodeCharacter{1EF8}{\~Y} \DeclareUnicodeCharacter{1EF9}{\~y} \DeclareUnicodeCharacter{2013}{--} \DeclareUnicodeCharacter{2014}{---} \DeclareUnicodeCharacter{2018}{\quoteleft} \DeclareUnicodeCharacter{2019}{\quoteright} \DeclareUnicodeCharacter{201A}{\quotesinglbase} \DeclareUnicodeCharacter{201C}{\quotedblleft} \DeclareUnicodeCharacter{201D}{\quotedblright} \DeclareUnicodeCharacter{201E}{\quotedblbase} \DeclareUnicodeCharacter{2022}{\bullet} \DeclareUnicodeCharacter{2026}{\dots} \DeclareUnicodeCharacter{2039}{\guilsinglleft} \DeclareUnicodeCharacter{203A}{\guilsinglright} \DeclareUnicodeCharacter{20AC}{\euro} \DeclareUnicodeCharacter{2192}{\expansion} \DeclareUnicodeCharacter{21D2}{\result} \DeclareUnicodeCharacter{2212}{\minus} \DeclareUnicodeCharacter{2217}{\point} \DeclareUnicodeCharacter{2261}{\equiv} }% end of \utfeightchardefs % US-ASCII character definitions. \def\asciichardefs{% nothing need be done \relax } % Make non-ASCII characters printable again for compatibility with % existing Texinfo documents that may use them, even without declaring a % document encoding. % \setnonasciicharscatcode \other \message{formatting,} \newdimen\defaultparindent \defaultparindent = 15pt \chapheadingskip = 15pt plus 4pt minus 2pt \secheadingskip = 12pt plus 3pt minus 2pt \subsecheadingskip = 9pt plus 2pt minus 2pt % Prevent underfull vbox error messages. \vbadness = 10000 % Don't be so finicky about underfull hboxes, either. \hbadness = 2000 % Following George Bush, get rid of widows and orphans. \widowpenalty=10000 \clubpenalty=10000 % Use TeX 3.0's \emergencystretch to help line breaking, but if we're % using an old version of TeX, don't do anything. We want the amount of % stretch added to depend on the line length, hence the dependence on % \hsize. We call this whenever the paper size is set. % \def\setemergencystretch{% \ifx\emergencystretch\thisisundefined % Allow us to assign to \emergencystretch anyway. \def\emergencystretch{\dimen0}% \else \emergencystretch = .15\hsize \fi } % Parameters in order: 1) textheight; 2) textwidth; % 3) voffset; 4) hoffset; 5) binding offset; 6) topskip; % 7) physical page height; 8) physical page width. % % We also call \setleading{\textleading}, so the caller should define % \textleading. The caller should also set \parskip. % \def\internalpagesizes#1#2#3#4#5#6#7#8{% \voffset = #3\relax \topskip = #6\relax \splittopskip = \topskip % \vsize = #1\relax \advance\vsize by \topskip \outervsize = \vsize \advance\outervsize by 2\topandbottommargin \pageheight = \vsize % \hsize = #2\relax \outerhsize = \hsize \advance\outerhsize by 0.5in \pagewidth = \hsize % \normaloffset = #4\relax \bindingoffset = #5\relax % \ifpdf \pdfpageheight #7\relax \pdfpagewidth #8\relax % if we don't reset these, they will remain at "1 true in" of % whatever layout pdftex was dumped with. \pdfhorigin = 1 true in \pdfvorigin = 1 true in \fi % \setleading{\textleading} % \parindent = \defaultparindent \setemergencystretch } % @letterpaper (the default). \def\letterpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt \textleading = 13.2pt % % If page is nothing but text, make it come out even. \internalpagesizes{607.2pt}{6in}% that's 46 lines {\voffset}{.25in}% {\bindingoffset}{36pt}% {11in}{8.5in}% }} % Use @smallbook to reset parameters for 7x9.25 trim size. \def\smallbook{{\globaldefs = 1 \parskip = 2pt plus 1pt \textleading = 12pt % \internalpagesizes{7.5in}{5in}% {-.2in}{0in}% {\bindingoffset}{16pt}% {9.25in}{7in}% % \lispnarrowing = 0.3in \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .5cm }} % Use @smallerbook to reset parameters for 6x9 trim size. % (Just testing, parameters still in flux.) \def\smallerbook{{\globaldefs = 1 \parskip = 1.5pt plus 1pt \textleading = 12pt % \internalpagesizes{7.4in}{4.8in}% {-.2in}{-.4in}% {0pt}{14pt}% {9in}{6in}% % \lispnarrowing = 0.25in \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .4cm }} % Use @afourpaper to print on European A4 paper. \def\afourpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt \textleading = 13.2pt % % Double-side printing via postscript on Laserjet 4050 % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. % To change the settings for a different printer or situation, adjust % \normaloffset until the front-side and back-side texts align. Then % do the same for \bindingoffset. You can set these for testing in % your texinfo source file like this: % @tex % \global\normaloffset = -6mm % \global\bindingoffset = 10mm % @end tex \internalpagesizes{673.2pt}{160mm}% that's 51 lines {\voffset}{\hoffset}% {\bindingoffset}{44pt}% {297mm}{210mm}% % \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = 5mm }} % Use @afivepaper to print on European A5 paper. % From romildo@urano.iceb.ufop.br, 2 July 2000. % He also recommends making @example and @lisp be small. \def\afivepaper{{\globaldefs = 1 \parskip = 2pt plus 1pt minus 0.1pt \textleading = 12.5pt % \internalpagesizes{160mm}{120mm}% {\voffset}{\hoffset}% {\bindingoffset}{8pt}% {210mm}{148mm}% % \lispnarrowing = 0.2in \tolerance = 800 \hfuzz = 1.2pt \contentsrightmargin = 0pt \defbodyindent = 2mm \tableindent = 12mm }} % A specific text layout, 24x15cm overall, intended for A4 paper. \def\afourlatex{{\globaldefs = 1 \afourpaper \internalpagesizes{237mm}{150mm}% {\voffset}{4.6mm}% {\bindingoffset}{7mm}% {297mm}{210mm}% % % Must explicitly reset to 0 because we call \afourpaper. \globaldefs = 0 }} % Use @afourwide to print on A4 paper in landscape format. \def\afourwide{{\globaldefs = 1 \afourpaper \internalpagesizes{241mm}{165mm}% {\voffset}{-2.95mm}% {\bindingoffset}{7mm}% {297mm}{210mm}% \globaldefs = 0 }} % @pagesizes TEXTHEIGHT[,TEXTWIDTH] % Perhaps we should allow setting the margins, \topskip, \parskip, % and/or leading, also. Or perhaps we should compute them somehow. % \parseargdef\pagesizes{\pagesizesyyy #1,,\finish} \def\pagesizesyyy#1,#2,#3\finish{{% \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi \globaldefs = 1 % \parskip = 3pt plus 2pt minus 1pt \setleading{\textleading}% % \dimen0 = #1\relax \advance\dimen0 by \voffset % \dimen2 = \hsize \advance\dimen2 by \normaloffset % \internalpagesizes{#1}{\hsize}% {\voffset}{\normaloffset}% {\bindingoffset}{44pt}% {\dimen0}{\dimen2}% }} % Set default to letter. % \letterpaper \message{and turning on texinfo input format.} % Define macros to output various characters with catcode for normal text. \catcode`\"=\other \catcode`\~=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\+=\other \catcode`\$=\other \def\normaldoublequote{"} \def\normaltilde{~} \def\normalcaret{^} \def\normalunderscore{_} \def\normalverticalbar{|} \def\normalless{<} \def\normalgreater{>} \def\normalplus{+} \def\normaldollar{$}%$ font-lock fix % This macro is used to make a character print one way in \tt % (where it can probably be output as-is), and another way in other fonts, % where something hairier probably needs to be done. % % #1 is what to print if we are indeed using \tt; #2 is what to print % otherwise. Since all the Computer Modern typewriter fonts have zero % interword stretch (and shrink), and it is reasonable to expect all % typewriter fonts to have this, we can check that font parameter. % \def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} % Same as above, but check for italic font. Actually this also catches % non-italic slanted fonts since it is impossible to distinguish them from % italic fonts. But since this is only used by $ and it uses \sl anyway % this is not a problem. \def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} % Turn off all special characters except @ % (and those which the user can use as if they were ordinary). % Most of these we simply print from the \tt font, but for some, we can % use math or other variants that look better in normal text. \catcode`\"=\active \def\activedoublequote{{\tt\char34}} \let"=\activedoublequote \catcode`\~=\active \def~{{\tt\char126}} \chardef\hat=`\^ \catcode`\^=\active \def^{{\tt \hat}} \catcode`\_=\active \def_{\ifusingtt\normalunderscore\_} \let\realunder=_ % Subroutine for the previous macro. \def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } \catcode`\|=\active \def|{{\tt\char124}} \chardef \less=`\< \catcode`\<=\active \def<{{\tt \less}} \chardef \gtr=`\> \catcode`\>=\active \def>{{\tt \gtr}} \catcode`\+=\active \def+{{\tt \char 43}} \catcode`\$=\active \def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix % If a .fmt file is being used, characters that might appear in a file % name cannot be active until we have parsed the command line. % So turn them off again, and have \everyjob (or @setfilename) turn them on. % \otherifyactive is called near the end of this file. \def\otherifyactive{\catcode`+=\other \catcode`\_=\other} % Used sometimes to turn off (effectively) the active characters even after % parsing them. \def\turnoffactive{% \normalturnoffactive \otherbackslash } \catcode`\@=0 % \backslashcurfont outputs one backslash character in current font, % as in \char`\\. \global\chardef\backslashcurfont=`\\ \global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work % \realbackslash is an actual character `\' with catcode other, and % \doublebackslash is two of them (for the pdf outlines). {\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} % In texinfo, backslash is an active character; it prints the backslash % in fixed width font. \catcode`\\=\active @def@normalbackslash{{@tt@backslashcurfont}} % On startup, @fixbackslash assigns: % @let \ = @normalbackslash % \rawbackslash defines an active \ to do \backslashcurfont. % \otherbackslash defines an active \ to be a literal `\' character with % catcode other. @gdef@rawbackslash{@let\=@backslashcurfont} @gdef@otherbackslash{@let\=@realbackslash} % Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of % the literal character `\'. % @def@normalturnoffactive{% @let\=@normalbackslash @let"=@normaldoublequote @let~=@normaltilde @let^=@normalcaret @let_=@normalunderscore @let|=@normalverticalbar @let<=@normalless @let>=@normalgreater @let+=@normalplus @let$=@normaldollar %$ font-lock fix @markupsetuplqdefault @markupsetuprqdefault @unsepspaces } % Make _ and + \other characters, temporarily. % This is canceled by @fixbackslash. @otherifyactive % If a .fmt file is being used, we don't want the `\input texinfo' to show up. % That is what \eatinput is for; after that, the `\' should revert to printing % a backslash. % @gdef@eatinput input texinfo{@fixbackslash} @global@let\ = @eatinput % On the other hand, perhaps the file did not have a `\input texinfo'. Then % the first `\' in the file would cause an error. This macro tries to fix % that, assuming it is called before the first `\' could plausibly occur. % Also turn back on active characters that might appear in the input % file name, in case not using a pre-dumped format. % @gdef@fixbackslash{% @ifx\@eatinput @let\ = @normalbackslash @fi @catcode`+=@active @catcode`@_=@active } % Say @foo, not \foo, in error messages. @escapechar = `@@ % These look ok in all fonts, so just make them not special. @catcode`@& = @other @catcode`@# = @other @catcode`@% = @other @c Finally, make ` and ' active, so that txicodequoteundirected and @c txicodequotebacktick work right in, e.g., @w{@code{`foo'}}. If we @c don't make ` and ' active, @code will not get them as active chars. @c Do this last of all since we use ` in the previous @catcode assignments. @catcode`@'=@active @catcode`@`=@active @markupsetuplqdefault @markupsetuprqdefault @c Local variables: @c eval: (add-hook 'write-file-hooks 'time-stamp) @c page-delimiter: "^\\\\message" @c time-stamp-start: "def\\\\texinfoversion{" @c time-stamp-format: "%:y-%02m-%02d.%02H" @c time-stamp-end: "}" @c End: @c vim:sw=2: @ignore arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 @end ignore pspp-master/config/000077500000000000000000000000001177044323000145775ustar00rootroot00000000000000pspp-master/config/.gitignore000066400000000000000000000000251177044323000165640ustar00rootroot00000000000000Makefile Makefile.in pspp-master/configure.ac000066400000000000000000000255411177044323000156270ustar00rootroot00000000000000dnl Process this file with autoconf to produce a configure script. dnl Initialize. AC_PREREQ(2.63) AC_INIT([GNU PSPP], [0.7.9], [bug-gnu-pspp@gnu.org], [pspp]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_TESTDIR([tests]) AM_INIT_AUTOMAKE dnl Checks for programs. AC_GNU_SOURCE AC_PROG_CC gl_EARLY AM_PROG_CC_C_O AC_LIBTOOL_WIN32_DLL AC_LIBTOOL_DLOPEN AC_PROG_LIBTOOL PKG_PROG_PKG_CONFIG m4_pattern_forbid([PKG_CHECK_MODULES]) PSPP_CHECK_CLICKSEQUENCE AC_ARG_ENABLE( anachronistic-dependencies, [AS_HELP_STRING([--enable-anachronistic-dependencies], [Attempt to allow building against older versions of dependent libraries])]) PSPP_ENABLE_OPTION(-Wdeclaration-after-statement) PSPP_ENABLE_WERROR AM_CONDITIONAL(cc_is_gcc, test x"$GCC" = x"yes" ) PSPP_CC_FOR_BUILD PSPP_PERL dnl Disable automatic po/ support, because PSPP provides its own po/ support. AC_PROVIDE([AM_PO_SUBDIRS]) AM_GNU_GETTEXT([external], [need-ngettext]) LIBS="$LIBINTL $LIBS" dnl Checks for libraries. AC_SYS_LARGEFILE AC_SEARCH_LIBS([sin], [m]) PSPP_LC_PAPER AC_ARG_VAR([PSPP_LDFLAGS], [linker flags to be used for linking the pspp binary only]) AC_ARG_VAR([PSPPIRE_LDFLAGS], [linker flags to be used for linking the psppire binary only]) # Support for Cairo and Pango. AC_ARG_WITH([cairo], [AS_HELP_STRING( [--without-cairo], [Don't build support for charts (using Cairo and Pango); implies --without-gui])], [], [with_cairo=yes]) AM_CONDITIONAL([HAVE_CAIRO], [test "$with_cairo" != no]) if test "$with_cairo" != no; then PKG_CHECK_MODULES([CAIRO], [cairo >= 1.5 pango >= 1.20 pangocairo], [CPPFLAGS="$CPPFLAGS $CAIRO_CFLAGS" AC_DEFINE([HAVE_CAIRO], 1, [Define to 1 if Cairo and Pango are available.])], [PSPP_REQUIRED_PREREQ([cairo 1.5 or later and pango 1.20 or later (or use --without-cairo)])]) AC_PATH_PROG([XMLLINT], [xmllint], [echo], [$PATH]) AC_SUBST(XMLLINT) fi # Support for GUI. AC_ARG_WITH([gui], [AS_HELP_STRING([--without-gui], [Don't build the PSPPIRE GUI (using GTK+)])], [], [with_gui=yes]) AM_CONDITIONAL([HAVE_GUI], [test "$with_cairo" != no && test "$with_gui" != "no"]) if test "$with_cairo" != no && test "$with_gui" != "no"; then PKG_CHECK_MODULES([GTHREAD], [gthread-2.0], [], [PSPP_REQUIRED_PREREQ([gthread 2.0 (or use --without-gui)])]) PKG_CHECK_MODULES([GTK], [gtk+-2.0 >= 2.16], [], [PSPP_REQUIRED_PREREQ([gtk+ 2.0 version 2.16 or later (or use --without-gui)])]) PKG_CHECK_MODULES([GTKSOURCEVIEW], [gtksourceview-2.0 >= 2.2], [], [PSPP_REQUIRED_PREREQ([gtksourceview 2.0 version 2.2 or later (or use --without-gui)])]) AC_ARG_VAR([GLIB_GENMARSHAL]) AC_CHECK_PROGS([GLIB_GENMARSHAL], [glib-genmarshal]) if test "x$GLIB_GENMARSHAL" = x; then PSPP_REQUIRED_PREREQ([glib-genmarshal (or use --without-gui)]) fi fi gl_NEXT_HEADERS([gtk/gtk.h]) dnl Checks needed for psql reader dnl The 8.x series postgres tarballs installs with a default prefix of dnl /usr/local/pgsql whereas, OSes (such as debian) install into /usr . dnl If the libpq.so file is in a non standard path, (one which the linker dnl doesn't search) then we must set the PG_LDFLAGS to -R/usr/wherever/ dnl However, if the system happens to have more than one version of other dnl dependent libraries (eg. libgtk) in different standard paths. (eg: dnl /usr and /usr/local) then the wrong one may get linked. dnl To overcome this, we first check for libpq in the standard places, and dnl only set PG_LDFLAGS if it's not found. AC_ARG_WITH( libpq, [AS_HELP_STRING([--without-libpq], [don't compile in Postgres capability])]) AC_ARG_VAR([PG_CONFIG], [Full pathname of the pg_config program shipped with Postgresql]) AC_PATH_PROG([PG_CONFIG], [pg_config], [], [$PATH:/usr/local/pgsql/bin:/usr/pgsql/bin]) if test x"$with_libpq" != x"no" && test -n "$PG_CONFIG" ; then AC_SUBST(PG_CONFIG) PG_CFLAGS=-I`$PG_CONFIG --includedir` AC_SUBST(PG_CFLAGS) AC_CHECK_LIB([pq], [PQexec], [:], [PG_LDFLAGS="-L`$PG_CONFIG --libdir` -R`$PG_CONFIG --libdir`"]) AC_SUBST(PG_LDFLAGS) PG_LIBS=-lpq AC_SUBST(PG_LIBS) PKG_CHECK_EXISTS(libssl, AC_DEFINE([USE_SSL],1, [Define to 1 if the openssl library is present.]) ,) # Now verify that we can actually link against libpq. If we are # cross-compiling and picked up a host libpq, or if libpq is just # badly installed, this will fail. AC_CACHE_CHECK( [whether -lpq links successfully], [pspp_cv_have_libpq], [save_CPPFLAGS=$CPPFLAGS save_LIBS=$LIBS save_LDFLAGS=$LDFLAGS CPPFLAGS="$PG_CFLAGS $CPPFLAGS" LIBS="$PG_LIBS $LIBS" LDFLAGS="$PG_LDFLAGS $LDFLAGS" AC_LINK_IFELSE( [AC_LANG_PROGRAM( [#include ], [PQfinish (0);])], [pspp_cv_have_libpq=yes], [pspp_cv_have_libpq=no]) CPPFLAGS=$save_CPPFLAGS LIBS=$save_LIBS LDFLAGS=$save_LDFLAGS]) if test $pspp_cv_have_libpq = yes; then PSQL_SUPPORT=yes AC_DEFINE([PSQL_SUPPORT], [1], [Define to 1 if building in support for reading from postgres databases.]) else PSQL_SUPPORT=no PG_CONFIG= PG_CFLAGS= PG_LDFLAGS= PG_LIBS= fi else PSQL_SUPPORT=no pspp_cv_have_libpq=no fi AC_SUBST([PSQL_SUPPORT]) dnl Check for libxml2 PKG_CHECK_MODULES( [LIBXML2], [libxml-2.0], [HAVE_LIBXML2=yes], [HAVE_LIBXML2=no PSPP_OPTIONAL_PREREQ([libxml2])]) dnl Check for zlib. AC_SEARCH_LIBS( [gzopen], [z], [HAVE_ZLIB=yes], [HAVE_ZLIB=no PSPP_OPTIONAL_PREREQ([zlib])]) AC_CHECK_HEADERS( [zlib.h], [], [HAVE_ZLIB=no PSPP_OPTIONAL_PREREQ([zlib])]) dnl Avoid interference between zlib's crc32() function and gnulib's dnl crc32() function, which have different signatures. PSPP calls dnl only gnulib's crc32() directly, but it calls zlib's crc32() dnl indirectly through other zlib calls. If we don't rename gnulib's dnl crc32(), then zlib will call gnulib's version instead of its own, dnl causing failures. (This can happen even if zlib isn't detected dnl directly, because other libraries that PSPP uses, e.g. libpng, dnl sometimes use zlib themselves.) AC_DEFINE( [crc32], [gl_crc32], [Avoid making zlib call gnulib's crc32() instead of its own.]) dnl Gnumeric and OpenDocument (read) support requires libxml2 and zlib. if test $HAVE_LIBXML2 = yes && test $HAVE_ZLIB = yes; then GNM_SUPPORT=yes ODF_READ_SUPPORT=yes AC_DEFINE( [GNM_SUPPORT], [1], [Define to 1 if building in support for reading Gnumeric files.]) AC_DEFINE( [ODF_READ_SUPPORT], [1], [Define to 1 if building in support for reading OpenDocument files.]) else GNM_SUPPORT=no ODF_READ_SUPPORT=no fi AC_SUBST([GNM_SUPPORT]) AC_SUBST([ODF_READ_SUPPORT]) dnl ODF support requires libxml2 (zlib is optional). if test $HAVE_LIBXML2 = yes; then AC_DEFINE( [ODF_WRITE_SUPPORT], [1], [Define to 1 if building in support for writing OpenDocument files.]) fi AM_CONDITIONAL([ODF_WRITE_SUPPORT], [test $HAVE_LIBXML2 = yes]) AC_ARG_WITH( gui_tools, [AS_HELP_STRING([--with-gui-tools], [build the gui developer tools. For DEVELOPERS only! There is no reason why users will need this flag.])]) if test x"$with_gui_tools" = x"yes" ; then PKG_CHECK_MODULES(GLADE_UI, gladeui-1.0) fi AM_CONDITIONAL(WITH_GUI_TOOLS, test x"$with_gui_tools" = x"yes") AC_ARG_WITH( [perl-module], [AS_HELP_STRING([--without-perl-module], [do not build the Perl module])], [case $with_perl_module in # ( yes|no) ;; # ( *) AC_MSG_FAILURE([--with-perl-module argument must be 'yes' or 'no']) ;; esac WITH_PERL_MODULE=$with_perl_module], [if test x"$cross_compiling" != x"yes"; then WITH_PERL_MODULE=yes else WITH_PERL_MODULE=no fi]) AC_SUBST([WITH_PERL_MODULE]) AM_CONDITIONAL(WITH_PERL_MODULE, test $WITH_PERL_MODULE = yes) AC_SEARCH_LIBS([cblas_dsdot], [gslcblas],,[PSPP_REQUIRED_PREREQ([libgslcblas])]) PKG_CHECK_MODULES([GSL], [gsl >= 1.12], [], AC_SEARCH_LIBS([gsl_linalg_cholesky_invert], [gsl],,[PSPP_REQUIRED_PREREQ([gsl 2.0 version 1.12 or later])])) PSPP_GSL_NEEDS_FGNU89_INLINE dnl Recent versions of GNU ncurses install the curses header files into dnl /usr/include/ncurses, and provide a 'ncurses5-config' program which dnl enables us to discover where they are. Earlier versions don't have dnl this, so we can't rely on it. So if ncurses5-config is present, dnl we'll trust it to find the right information. Otherwise, we'll dnl try to discover it ourselves. dnl To confound things further, Cygwin has decided to rename ncurses5-config dnl to ncurses8-config !!! AC_ARG_WITH( libncurses, [AS_HELP_STRING([--without-libncurses], [don't compile in ncurses functions])]) if test x"$with_libncurses" != x"no" ; then if test x"$cross_compiling" != x"yes" ; then AC_CHECK_PROGS([NCURSES_CONFIG], [ncurses5-config ncurses8-config]) fi if test x"$NCURSES_CONFIG" = x ; then AC_SEARCH_LIBS([tgetent], [ncurses], [curses_available=yes; AC_CHECK_HEADERS([term.h curses.h],,[curses_available=no])]) else old_cflags=$CFLAGS CFLAGS="$CFLAGS `$NCURSES_CONFIG --cflags`" AC_CHECK_HEADERS([term.h curses.h],[curses_available=yes]) CFLAGS=$old_cflags if test x"$curses_available" = x"yes" ; then NCURSES_LIBS=`$NCURSES_CONFIG --libs` NCURSES_CFLAGS=`$NCURSES_CONFIG --cflags` AC_SUBST(NCURSES_CFLAGS) AC_SUBST(NCURSES_LIBS) fi fi if test x"$curses_available" = x"yes" ; then AC_DEFINE([LIBNCURSES_USABLE], 1, [Define to 1 if the libncurses is both present and usable.]) fi AC_CHECK_HEADERS([termcap.h]) fi PSPP_READLINE dnl Checks for header files. AC_CHECK_HEADERS([sys/wait.h fpu_control.h ieeefp.h fenv.h pwd.h]) dnl Some systems dont have SIGWINCH AC_CHECK_DECLS([SIGWINCH], [], [], [#include /* NetBSD declares sys_siglist in unistd.h. */ #ifdef HAVE_UNISTD_H # include #endif ]) # For gnulib. gl_INIT AC_C_INLINE AC_CHECK_SIZEOF([size_t]) SIZEOF_SIZE_T=$ac_cv_sizeof_size_t AC_SUBST([SIZEOF_SIZE_T]) AC_C_BIGENDIAN AC_CHECK_FUNCS([__setfpucw fork execl execlp isinf isnan finite getpid feholdexcept fpsetmask popen round]) AC_PROG_LN_S AC_ARG_ENABLE( debug, [AS_HELP_STRING([--enable-debug], [Turn on diagnostic features in the program])]) if test x"$enable_debug" = x"yes" ; then AC_DEFINE(DEBUGGING, 1, [Define to 1 if debugging is enabled.]) fi # iconv is required AM_ICONV if test "$am_cv_func_iconv" != "yes"; then PSPP_REQUIRED_PREREQ([iconv (see http://www.gnu.org/software/libiconv/)]) fi LIBS="$LIBICONV $LIBS" dnl Required by the gnulib 'relocatable-prog' module. dnl See doc/relocatable-maint.texi in the gnulib tree for details. RELOCATABLE_LIBRARY_PATH='$(pkglibdir)' RELOCATABLE_STRIP=: PSPP_CHECK_PREREQS AC_CONFIG_FILES( [Makefile gl/Makefile po/Makefile tests/atlocal perl-module/lib/PSPP.pm]) AC_OUTPUT echo "PSPP configured successfully." dnl configure.ac ends here pspp-master/doc/000077500000000000000000000000001177044323000140775ustar00rootroot00000000000000pspp-master/doc/.gitignore000066400000000000000000000001701177044323000160650ustar00rootroot00000000000000Makefile Makefile.in ni.texi pspp-dev.info pspp.info* pspp.xml stamp-1 stamp-vti tut.texi version-dev.texi version.texi pspp-master/doc/OChangeLog000066400000000000000000000173261177044323000160010ustar00rootroot000000000000002008-05-15 Ben Pfaff * automake.mk: Make install-data-hook depend on yelp-check if the GUI is configured. 2008-05-08 John Darrington * automake.mk: Compress the info files, because later versions of yelp seem to crash otherwise. 2008-03-11 Jason Stover * regression.texi (REGRESSION): Fixed use of @dots in @math command. Reported by John Darrington. 2008-03-11 Jason Stover * regression.texi: Made more consistent use of math mode for description of linear regression. Added reference to the mean of the error terms being 0. 2008-03-09 Jason Stover * regression.texi (REGRESSION): Removed references to subcommand EXPORT. 2008-02-06 John Darrington * files.texi: Document the /BSIZE subcommand to the PSQL reader. 2008-02-04 John Darrington * files.texi data-io.texi: Document the GET DATA TYPE=PSQL option. Thanks to Ben Pfaff for reviewing this text. 2007-11-10 Ben Pfaff * not-implemented.texi: Fix @include command so that it works consistently, by using a file name relative to Makefile.am's srcdir instead of relative to doc. 2007-11-10 Ben Pfaff Patch #6262: New developers guide (currently incomplete). * automake.mk: Add definitions for new manual. * pspp.texinfo: Now this is the PSPP Users Guide instead of just the PSPP manual. Remove development chapters. * pspp-dev.texinfo: New file. * data-file-format.texi: Move to dev/system-file-format.texi. * portable-file-format.texi: Move to dev/. * q2c.texi: Move to dev/ * dev/concepts.texi: New file. * dev/data.texi: New file. * dev/intro.texi: New file. * dev/output.texi: New file. * dev/syntax.texi: New file. 2007-10-19 John Darrington * statistics.texi: Changed /CONTRASTS to /CONTRAST in ONEWAY which is what the command accepts. 2007-07-28 John Darrington * statistics.texi: Made the documentation for T-TEST match the behaviour. 2007-07-17 Ben Pfaff * get-commands.pl: Use strict and all warnings. Simplify parsing. Add "@c End:" line to output to suppress Emacs warning. From bug #19335. Reviewed by John Darrington. 2007-06-05 Ben Pfaff * Removed next, prev, up node names from @node lines, to make structural changes to the manual easier. (These node names are not needed by makeinfo.) 2007-03-31 John Darrington * transformation.texi: SORT CASES: elaborated on the (D) (A) flags. 2007-03-01 Ben Pfaff * automake.mk: Fix "make distcheck" by distributing doc/ni.texi, even though it's generated. Reviewed by John Darrington. (doc_pspp_TEXINFOS): Add doc/ni.texi. (nodist_doc_pspp_TEXINFOS): Remove. (am__TEXINFO_TEX_DIR) Removed (was just a kluge anyhow). ($(INFO_DEPS)): Removed. ($(HTML_DEPS)): Removed. (CLEANFILES): Removed. Wed Dec 20 18:45:31 WST 2006 John Darrington * statistics.texi: Added documentation for the NPAR TESTS command. Thu Nov 30 22:20:10 2006 Ben Pfaff * statistics.texi: Document charts supported by FREQUENCIES. Fixes bug #18297. Thanks to Mohammed Babekir Elmalik Abdalmajid for reporting this bug. Tue Nov 28 17:33:31 WST 2006 * get-commands.pl: Fixed generation of ni.texi, which was broken after commands.def was reorganised. * not-implemented.texi language.texi regression.texi statistics.texi: Added some indeces. * license.texi: Added information from GPL. Sat Oct 7 11:02:44 WST 2006 * Added documentation for RANK. Tue May 2 10:43:06 WST 2006 * data-file-format.texi: Updated information about the case_size value. Added description of Record Type 7, subtype 14. 2006-04-28 Jason Stover * regression.texi: Added description of the RESID and PRED keywords to the SAVE subcommand. * statistics.texi: Added REGRESSION node. 2006-04-21 Jason Stover * regression.texi: Initial description of the SAVE subcommand. Sun Apr 16 19:12:26 2006 Ben Pfaff Consistently write "file name" as two words, in accordance with the GNU standards. Wed Feb 15 21:53:12 2006 Ben Pfaff * data-file-format.texi: Fix values for "measure" in Auxiliary Variable Parameter Record. Thanks to Oliver Bock for reporting this bug. Fixes bug #15763. Tue Feb 14 21:34:06 2006 Ben Pfaff * data-file-format.texi: Fix description of "count" in Auxiliary Variable Parameter Record. Thanks to Oliver Bock for reporting this bug. Fixes bug #15756. Sun Sep 25 16:10:36 2005 Ben Pfaff * Makefile.am: Make ni.texi a prereq for HTML output. Thanks to James R. Van Zandt for reporting the problem. Sun Jul 24 18:47:02 2005 Ben Pfaff * portable-file-format.texi: Describe author field. Sat May 7 17:26:39 WST 2005 John Darrington * Makefile.am: Made ni.texi a nodist file Wed May 4 08:30:24 2005 Ben Pfaff * language.texi: Proofreading from Jason Stover . Tue May 3 16:22:29 WST 2005 John Darrington * get-commands.pl: New file to generate ni.texi * not-implemented.texi Makefile.am: List of not implemented commands now generated from src/command.def Sun May 1 23:20:42 2005 Ben Pfaff * language.texi: Revised lots of text to catch up with changes that have been in for a long time, and for style. Sun May 1 15:17:42 WST 2005 John Darrington * configuration.texi: Removed manpage(x) style references, because RMS doesn't like them. Wed Apr 27 07:44:57 WST 2005 John Darrington * utilities.texi: Added the ECHO command. Fri Apr 15 18:35:42 2005 Ben Pfaff * pspp.texinfo: Change manual license to GNU FDL, pursuant to advice in maintainers' guide. Thur Apr 14 2005 John Darrington * variables.texi: Corrected the entry for VARIABLE LABELS * data-file-format.texi: Added documentation about the Long Variable Names record. Thu Mar 3 22:06:54 WST 2005 John Darrington * expressions.texi: corrected some mismatched parentheses. Mon Feb 28 23:19:34 2005 Ben Pfaff * expressions.texi: Revise. Describe new functions. Sat Jan 8 16:46:28 2005 Ben Pfaff * credits.texi: Removed. * bugs.texi: Rewrote. Moved known bugs to savannah website. * not-implemented.texi: AGGREGATE and AUTORECODE are implemented. Tue Nov 16 13:18:53 WST 2004 John Darrington * statistics.texi Added documentation about the EXAMINE cmd Tue Nov 16 13:18:53 WST 2004 John Darrington * utilities.texi Added documentation for the PERMISSIONS command. * pspp.texinfo Makefile.am @included version.texi (Autogenerated) to keep the EDITION, VERSION and UPDATED flags up to date. Tue Nov 9 09:38:43 WST 2004 John Darrington * Made Makefile.am aware of pspp.texi dependencies Fri Nov 5 17:46:46 WST 2004 John Darrington * Added a note to the about SPLIT requiring adjacent cases. Sat Oct 30 17:32:53 WST 2004 John Darrington * Started this changelog * Removed the monolithic pspp.texi file and replaced with *.texi wrapped by a single pspp.texinfo file * Minor corrections to the documentation where I noticed it needed them. pspp-master/doc/automake.mk000066400000000000000000000041001177044323000162310ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in -*- makefile -*- info_TEXINFOS = doc/pspp.texinfo doc/pspp-dev.texinfo doc_pspp_TEXINFOS = doc/version.texi \ doc/bugs.texi \ doc/command-index.texi \ doc/concept-index.texi \ doc/data-io.texi \ doc/data-selection.texi \ doc/expressions.texi \ doc/files.texi \ doc/combining.texi \ doc/flow-control.texi \ doc/function-index.texi \ doc/installing.texi \ doc/introduction.texi \ doc/invoking.texi \ doc/language.texi \ doc/license.texi \ doc/ni.texi \ doc/not-implemented.texi \ doc/statistics.texi \ doc/transformation.texi \ doc/tutorial.texi \ doc/tut.texi \ doc/regression.texi \ doc/utilities.texi \ doc/variables.texi \ doc/fdl.texi doc_pspp_dev_TEXINFOS = doc/version-dev.texi \ doc/dev/intro.texi \ doc/dev/concepts.texi \ doc/dev/syntax.texi \ doc/dev/data.texi \ doc/dev/i18n.texi \ doc/dev/output.texi \ doc/dev/system-file-format.texi \ doc/dev/portable-file-format.texi \ doc/dev/q2c.texi EXTRA_DIST += doc/pspp.man \ doc/get-commands.pl $(srcdir)/doc/ni.texi: $(top_srcdir)/src/language/command.def doc/get-commands.pl @$(MKDIR_P) doc $(PERL) $(top_srcdir)/doc/get-commands.pl $(top_srcdir)/src/language/command.def > $@ $(srcdir)/doc/tut.texi: @$(MKDIR_P) doc echo "@set example-dir $(examplesdir)" > $@ $(srcdir)/doc/pspp.xml: doc/pspp.texinfo $(doc_pspp_TEXINFOS) @$(MKDIR_P) doc $(MAKEINFO) $(AM_MAKEINFOFLAGS) --docbook -I $(top_srcdir) \ $(top_srcdir)/doc/pspp.texinfo -o - \ | $(SED) -e 's/Time-&-Date/Time-\&-Date/g' \ -e 's/“/\“/g' \ -e 's/”/\”/g' \ -e 's/‘/\‘/g' \ -e 's/’/\’/g' \ -e 's/—/\—/g' \ -e 's/–/\′/g' \ -e 's/é/\é/g' \ -e 's/©/\©/g' \ -e 's/−/\−/g' \ -e 's/…/\…/g' \ -e 's/././g' \ > $@ $(XMLLINT) --output /dev/null $@ 2>&1 2> /dev/null || ( $(RM) $@ && false ) docbookdir = $(docdir) dist_docbook_DATA = doc/pspp.xml EXTRA_DIST += doc/OChangeLog CLEANFILES += pspp-dev.dvi $(docbook_DATA) pspp-master/doc/bugs.texi000066400000000000000000000024771177044323000157440ustar00rootroot00000000000000@node Bugs @chapter Bugs @cindex bugs Occasionally users encounter problems with @pspp{}. When such problems arise we do our best to fix them, but our limited resources mean that certain issues may remain for some time. If you discover a bug, please first: @itemize @bullet @item Try an up to date version of @pspp{}; it may be that the problem has recently been fixed. @item If the problem persists in the up to date version; check to see if it has already been reported. @item If the problem exists in a recent version and it has not already been reported, please file a report. @end itemize To see a list of reported bugs, visit @pspp{}'s project webpage at @uref{http://savannah.gnu.org/bugs/?group=pspp} Alternatively, bug reports may be sent by email to @email{bug-gnu-pspp@@gnu.org}. In your bug report please include: @itemize @bullet @item The version of @pspp{} which you are using. @item The operating system and type of computer on which it is running. @item A sample of the syntax which causes the problem or, if it is a user interface problem, the sequence of steps required to reproduce it. @item A description of what you think is wrong: What happened that you didn't expect, and what did you expect to happen? @end itemize For known bugs in individual language features, see the documentation for that feature. pspp-master/doc/combining.texi000066400000000000000000000334351177044323000167470ustar00rootroot00000000000000@node Combining Data Files @chapter Combining Data Files This chapter describes commands that allow data from system files, portable files, and open datasets to be combined to form a new active dataset. These commands can combine data files in the following ways: @itemize @item @cmd{ADD FILES} interleaves or appends the cases from each input file. It is used with input files that have variables in common, but distinct sets of cases. @item @cmd{MATCH FILES} adds the data together in cases that match across multiple input files. It is used with input files that have cases in common, but different information about each case. @item @cmd{UPDATE} updates a master data file from data in a set of transaction files. Each case in a transaction data file modifies a matching case in the primary data file, or it adds a new case if no matching case can be found. @end itemize These commands share the majority of their syntax, which is described in the following section, followed by one section for each command that describes its specific syntax and semantics. @menu * Combining Files Common Syntax:: * ADD FILES:: Interleave cases from multiple files. * MATCH FILES:: Merge cases from multiple files. * UPDATE:: Update cases using transactional data. @end menu @node Combining Files Common Syntax @section Common Syntax @display Per input file: /FILE=@{*,'@var{file_name}'@} [/RENAME=(@var{src_names}=@var{target_names})@dots{}] [/IN=@var{var_name}] [/SORT] Once per command: /BY @var{var_list}[(@{D|A@})] [@var{var_list}[(@{D|A@}]]@dots{} [/DROP=@var{var_list}] [/KEEP=@var{var_list}] [/FIRST=@var{var_name}] [/LAST=@var{var_name}] [/MAP] @end display This section describes the syntactical features in common among the @cmd{ADD FILES}, @cmd{MATCH FILES}, and @cmd{UPDATE} commands. The following sections describe details specific to each command. Each of these commands reads two or more input files and combines them. The command's output becomes the new active dataset. The input files are not changed on disk. The syntax of each command begins with a specification of the files to be read as input. For each input file, specify FILE with a system file or portable file's name as a string, a dataset (@pxref{Datasets}) or file handle name, (@pxref{File Handles}), or an asterisk (@samp{*}) to use the active dataset as input. Use of portable files on @subcmd{FILE} is a @pspp{} extension. At least two @subcmd{FILE} subcommands must be specified. If the active dataset is used as an input source, then @cmd{TEMPORARY} must not be in effect. Each @subcmd{FILE} subcommand may be followed by any number of @subcmd{RENAME} subcommands that specify a parenthesized group or groups of variable names as they appear in the input file, followed by those variables' new names, separated by an equals sign (@subcmd{=}), e.g. @subcmd{/RENAME=(OLD1=NEW1)(OLD2=NEW2)}. To rename a single variable, the parentheses may be omitted: @subcmd{/RENAME=@var{old}=@var{new}}. Within a parenthesized group, variables are renamed simultaneously, so that @subcmd{/RENAME=(@var{A} @var{B}=@var{B} @var{A})} exchanges the names of variables @var{A} and @var{B}. Otherwise, renaming occurs in left-to-right order. Each @subcmd{FILE} subcommand may optionally be followed by a single @subcmd{IN} subcommand, which creates a numeric variable with the specified name and format F1.0. The IN variable takes value 1 in an output case if the given input file contributed to that output case, and 0 otherwise. The @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} subcommands have no effect on IN variables. If @subcmd{BY} is used (see below), the @subcmd{SORT} keyword must be specified after a @subcmd{FILE} if that input file is not already sorted on the @subcmd{BY} variables. When @subcmd{SORT} is specified, @pspp{} sorts the input file's data on the @subcmd{BY} variables before it applies it to the command. When @subcmd{SORT} is used, @subcmd{BY} is required. @subcmd{SORT} is a @pspp{} extension. @pspp{} merges the dictionaries of all of the input files to form the dictionary of the new active dataset, like so: @itemize @bullet @item The variables in the new active dataset are the union of all the input files' variables, matched based on their name. When a single input file contains a variable with a given name, the output file will contain exactly that variable. When more than one input file contains a variable with a given name, those variables must all have the same type (numeric or string) and, for string variables, the same width. Variables are matched after renaming with the @subcmd{RENAME} subcommand. Thus, @subcmd{RENAME} can be used to resolve conflicts. @item The variable label for each output variable is taken from the first specified input file that has a variable label for that variable, and similarly for value labels and missing values. @item The file label of the new active dataset (@pxref{FILE LABEL}) is that of the first specified @subcmd{FILE} that has a file label. @item The documents in the new active dataset (@pxref{DOCUMENT}) are the concatenation of all the input files' documents, in the order in which the @subcmd{FILE} subcommands are specified. @item If all of the input files are weighted on the same variable, then the new active dataset is weighted on that variable. Otherwise, the new active dataset is not weighted. @end itemize The remaining subcommands apply to the output file as a whole, rather than to individual input files. They must be specified at the end of the command specification, following all of the @subcmd{FILE} and related subcommands. The most important of these subcommands is @subcmd{BY}, which specifies a set of one or more variables that may be used to find corresponding cases in each of the input files. The variables specified on @subcmd{BY} must be present in all of the input files. Furthermore, if any of the input files are not sorted on the @subcmd{BY} variables, then @subcmd{SORT} must be specified for those input files. The variables listed on @subcmd{BY} may include (A) or (D) annotations to specify ascending or descending sort order. @xref{SORT CASES}, for more details on this notation. Adding (A) or (D) to the @subcmd{BY} subcommand specification is a @pspp{} extension. The @subcmd{DROP} subcommand can be used to specify a list of variables to exclude from the output. By contrast, the @subcmd{KEEP} subcommand can be used to specify variables to include in the output; all variables not listed are dropped. @subcmd{DROP} and @subcmd{KEEP} are executed in left-to-right order and may be repeated any number of times. @subcmd{DROP} and @subcmd{KEEP} do not affect variables created by the @subcmd{IN}, @subcmd{FIRST}, and @subcmd{LAST} subcommands, which are always included in the new active dataset, but they can be used to drop @subcmd{BY} variables. The @subcmd{FIRST} and @subcmd{LAST} subcommands are optional. They may only be specified on @cmd{MATCH FILES} and @cmd{ADD FILES}, and only when @subcmd{BY} is used. @subcmd{FIRST} and @subcmd{LIST} each adds a numeric variable to the new active dataset, with the name given as the subcommand's argument and F1.0 print and write formats. The value of the @subcmd{FIRST} variable is 1 in the first output case with a given set of values for the @subcmd{BY} variables, and 0 in other cases. Similarly, the @subcmd{LAST} variable is 1 in the last case with a given of @subcmd{BY} values, and 0 in other cases. When any of these commands creates an output case, variables that are only in files that are not present for the current case are set to the system-missing value for numeric variables or spaces for string variables. @node ADD FILES @section ADD FILES @vindex ADD FILES @display ADD FILES Per input file: /FILE=@{*,'@var{file_name}'@} [/RENAME=(@var{src_names}=@var{target_names})@dots{}] [/IN=@var{var_name}] [/SORT] Once per command: [/BY @var{var_list}[(@{D|A@})] [@var{var_list}[(@{D|A@})]@dots{}]] [/DROP=@var{var_list}] [/KEEP=@var{var_list}] [/FIRST=@var{var_name}] [/LAST=@var{var_name}] [/MAP] @end display @cmd{ADD FILES} adds cases from multiple input files. The output, which replaces the active dataset, consists all of the cases in all of the input files. @subcmd{ADD FILES} shares the bulk of its syntax with other @pspp{} commands for combining multiple data files. @xref{Combining Files Common Syntax}, above, for an explanation of this common syntax. When @subcmd{BY} is not used, the output of @subcmd{ADD FILES} consists of all the cases from the first input file specified, followed by all the cases from the second file specified, and so on. When @subcmd{BY} is used, the output is additionally sorted on the @subcmd{BY} variables. When @subcmd{ADD FILES} creates an output case, variables that are not part of the input file from which the case was drawn are set to the system-missing value for numeric variables or spaces for string variables. @node MATCH FILES @section MATCH FILES @vindex MATCH FILES @display MATCH FILES Per input file: /@{FILE,TABLE@}=@{*,'@var{file_name}'@} [/RENAME=(@var{src_names}=@var{target_names})@dots{}] [/IN=@var{var_name}] [/SORT] Once per command: /BY @var{var_list}[(@{D|A@}] [@var{var_list}[(@{D|A@})]@dots{}] [/DROP=@var{var_list}] [/KEEP=@var{var_list}] [/FIRST=@var{var_name}] [/LAST=@var{var_name}] [/MAP] @end display @cmd{MATCH FILES} merges sets of corresponding cases in multiple input files into single cases in the output, combining their data. @cmd{MATCH FILES} shares the bulk of its syntax with other @pspp{} commands for combining multiple data files. @xref{Combining Files Common Syntax}, above, for an explanation of this common syntax. How @cmd{MATCH FILES} matches up cases from the input files depends on whether @subcmd{BY} is specified: @itemize @bullet @item If @subcmd{BY} is not used, @cmd{MATCH FILES} combines the first case from each input file to produce the first output case, then the second case from each input file for the second output case, and so on. If some input files have fewer cases than others, then the shorter files do not contribute to cases output after their input has been exhausted. @item If @subcmd{BY} is used, @cmd{MATCH FILES} combines cases from each input file that have identical values for the @subcmd{BY} variables. When @subcmd{BY} is used, @subcmd{TABLE} subcommands may be used to introduce @dfn{table lookup file}. @subcmd{TABLE} has same syntax as @subcmd{FILE}, and the @subcmd{RENAME}, @subcmd{IN}, and @subcmd{SORT} subcommands may follow a @subcmd{TABLE} in the same way as @subcmd{FILE}. Regardless of the number of @subcmd{TABLE}s, at least one @subcmd{FILE} must specified. Table lookup files are treated in the same way as other input files for most purposes and, in particular, table lookup files must be sorted on the @subcmd{BY} variables or the @subcmd{SORT} subcommand must be specified for that @subcmd{TABLE}. Cases in table lookup files are not consumed after they have been used once. This means that data in table lookup files can correspond to any number of cases in @subcmd{FILE} input files. Table lookup files are analogous to lookup tables in traditional relational database systems. If a table lookup file contains more than one case with a given set of @subcmd{BY} variables, only the first case is used. @end itemize When @cmd{MATCH FILES} creates an output case, variables that are only in files that are not present for the current case are set to the system-missing value for numeric variables or spaces for string variables. @node UPDATE @section UPDATE @vindex UPDATE @display UPDATE Per input file: /FILE=@{*,'@var{file_name}'@} [/RENAME=(@var{src_names}=@var{target_names})@dots{}] [/IN=@var{var_name}] [/SORT] Once per command: /BY @var{var_list}[(@{D|A@})] [@var{var_list}[(@{D|A@})]]@dots{} [/DROP=@var{var_list}] [/KEEP=@var{var_list}] [/MAP] @end display @cmd{UPDATE} updates a @dfn{master file} by applying modifications from one or more @dfn{transaction files}. @cmd{UPDATE} shares the bulk of its syntax with other @pspp{} commands for combining multiple data files. @xref{Combining Files Common Syntax}, above, for an explanation of this common syntax. At least two @subcmd{FILE} subcommands must be specified. The first @subcmd{FILE} subcommand names the master file, and the rest name transaction files. Every input file must either be sorted on the variables named on the @subcmd{BY} subcommand, or the @subcmd{SORT} subcommand must be used just after the @subcmd{FILE} subcommand for that input file. @cmd{UPDATE} uses the variables specified on the @subcmd{BY} subcommand, which is required, to attempt to match each case in a transaction file with a case in the master file: @itemize @bullet @item When a match is found, then the values of the variables present in the transaction file replace those variable's values in the new active file. If there are matching cases in more than more transaction file, @pspp{} applies the replacements from the first transaction file, then from the second transaction file, and so on. Similarly, if a single transaction file has cases with duplicate @subcmd{BY} values, then those are applied in order to the master file. When a variable in a transaction file has a missing value or a string variable's value is all blanks, that value is never used to update the master file. @item If a case in the master file has no matching case in any transaction file, then it is copied unchanged to the output. @item If a case in a transaction file has no matching case in the master file, then it causes a new case to be added to the output, initialized from the values in the transaction file. @end itemize pspp-master/doc/command-index.texi000066400000000000000000000000721177044323000175140ustar00rootroot00000000000000@node Command Index @chapter Command Index @printindex vr pspp-master/doc/concept-index.texi000066400000000000000000000000721177044323000175310ustar00rootroot00000000000000@node Concept Index @chapter Concept Index @printindex cp pspp-master/doc/data-io.texi000066400000000000000000001334541177044323000163220ustar00rootroot00000000000000@c (modify-syntax-entry ?_ "w") @c (modify-syntax-entry ?' "'") @c (modify-syntax-entry ?@ "'") @node Data Input and Output @chapter Data Input and Output @cindex input @cindex output @cindex data @cindex cases @cindex observations Data are the focus of the @pspp{} language. Each datum belongs to a @dfn{case} (also called an @dfn{observation}). Each case represents an individual or ``experimental unit''. For example, in the results of a survey, the names of the respondents, their sex, age, etc.@: and their responses are all data and the data pertaining to single respondent is a case. This chapter examines the @pspp{} commands for defining variables and reading and writing data. There are alternative commands to read data from predefined sources such as system files or databases (@xref{GET, GET DATA}.) @quotation Note These commands tell @pspp{} how to read data, but the data will not actually be read until a procedure is executed. @end quotation @menu * BEGIN DATA:: Embed data within a syntax file. * CLOSE FILE HANDLE:: Close a file handle. * DATAFILE ATTRIBUTE:: Set custom attributes on data files. * DATASET:: Manage multiple datasets. * DATA LIST:: Fundamental data reading command. * END CASE:: Output the current case. * END FILE:: Terminate the current input program. * FILE HANDLE:: Support for special file formats. * INPUT PROGRAM:: Support for complex input programs. * LIST:: List cases in the active dataset. * NEW FILE:: Clear the active dataset. * PRINT:: Display values in print formats. * PRINT EJECT:: Eject the current page then print. * PRINT SPACE:: Print blank lines. * REREAD:: Take another look at the previous input line. * REPEATING DATA:: Multiple cases on a single line. * WRITE:: Display values in write formats. @end menu @node BEGIN DATA @section BEGIN DATA @vindex BEGIN DATA @vindex END DATA @cindex Embedding data in syntax files @cindex Data, embedding in syntax files @display BEGIN DATA. @dots{} END DATA. @end display @cmd{BEGIN DATA} and @cmd{END DATA} can be used to embed raw ASCII data in a @pspp{} syntax file. @cmd{DATA LIST} or another input procedure must be used before @cmd{BEGIN DATA} (@pxref{DATA LIST}). @cmd{BEGIN DATA} and @cmd{END DATA} must be used together. @cmd{END DATA} must appear by itself on a single line, with no leading white space and exactly one space between the words @code{END} and @code{DATA}, like this: @example END DATA. @end example @node CLOSE FILE HANDLE @section CLOSE FILE HANDLE @display CLOSE FILE HANDLE @var{handle_name}. @end display @cmd{CLOSE FILE HANDLE} disassociates the name of a file handle with a given file. The only specification is the name of the handle to close. Afterward @cmd{FILE HANDLE}. The file named INLINE, which represents data entered between @cmd{BEGIN DATA} and @cmd{END DATA}, cannot be closed. Attempts to close it with @cmd{CLOSE FILE HANDLE} have no effect. @cmd{CLOSE FILE HANDLE} is a @pspp{} extension. @node DATAFILE ATTRIBUTE @section DATAFILE ATTRIBUTE @vindex DATAFILE ATTRIBUTE @display DATAFILE ATTRIBUTE ATTRIBUTE=@var{name}('@var{value}') [@var{name}('@var{value}')]@dots{} ATTRIBUTE=@var{name}@b{[}@var{index}@b{]}('@var{value}') [@var{name}@b{[}@var{index}@b{]}('@var{value}')]@dots{} DELETE=@var{name} [@var{name}]@dots{} DELETE=@var{name}@b{[}@var{index}@b{]} [@var{name}@b{[}@var{index}@b{]}]@dots{} @end display @cmd{DATAFILE ATTRIBUTE} adds, modifies, or removes user-defined attributes associated with the active dataset. Custom data file attributes are not interpreted by @pspp{}, but they are saved as part of system files and may be used by other software that reads them. Use the @subcmd{ATTRIBUTE} subcommand to add or modify a custom data file attribute. Specify the name of the attribute as an identifier (@pxref{Tokens}), followed by the desired value, in parentheses, as a quoted string. Attribute names that begin with @code{$} are reserved for @pspp{}'s internal use, and attribute names that begin with @code{@@} or @code{$@@} are not displayed by most @pspp{} commands that display other attributes. Other attribute names are not treated specially. Attributes may also be organized into arrays. To assign to an array element, add an integer array index enclosed in square brackets (@code{[} and @code{]}) between the attribute name and value. Array indexes start at 1, not 0. An attribute array that has a single element (number 1) is not distinguished from a non-array attribute. Use the @subcmd{DELETE} subcommand to delete an attribute. Specify an attribute name by itself to delete an entire attribute, including all array elements for attribute arrays. Specify an attribute name followed by an array index in square brackets to delete a single element of an attribute array. In the latter case, all the array elements numbered higher than the deleted element are shifted down, filling the vacated position. To associate custom attributes with particular variables, instead of with the entire active dataset, use @cmd{VARIABLE ATTRIBUTE} (@pxref{VARIABLE ATTRIBUTE}) instead. @cmd{DATAFILE ATTRIBUTE} takes effect immediately. It is not affected by conditional and looping structures such as @cmd{DO IF} or @cmd{LOOP}. @node DATASET @section DATASET commands @vindex DATASET @display DATASET NAME @var{name} [WINDOW=@{ASIS,FRONT@}]. DATASET ACTIVATE @var{name} [WINDOW=@{ASIS,FRONT@}]. DATASET COPY @var{name} [WINDOW=@{MINIMIZED,HIDDEN,FRONT@}]. DATASET DECLARE @var{name} [WINDOW=@{MINIMIZED,HIDDEN,FRONT@}]. DATASET CLOSE @{@var{name},*,ALL@}. DATASET DISPLAY. @end display The @cmd{DATASET} commands simplify use of multiple datasets within a @pspp{} session. They allow datasets to be created and destroyed. At any given time, most @pspp{} commands work with a single dataset, called the active dataset. @vindex DATASET NAME The DATASET NAME command gives the active dataset the specified name, or if it already had a name, it renames it. If another dataset already had the given name, that dataset is deleted. @vindex DATASET ACTIVATE The DATASET ACTIVATE command selects the named dataset, which must already exist, as the active dataset. Before switching the active dataset, any pending transformations are executed, as if @cmd{EXECUTE} had been specified. If the active dataset is unnamed before switching, then it is deleted and becomes unavailable after switching. @vindex DATASET COPY The DATASET COPY command creates a new dataset with the specified name, whose contents are a copy of the active dataset. Any pending transformations are executed, as if @cmd{EXECUTE} had been specified, before making the copy. If a dataset with the given name already exists, it is replaced. If the name is the name of the active dataset, then the active dataset becomes unnamed. @vindex DATASET DECLARE The DATASET DECLARE command creates a new dataset that is initially ``empty,'' that is, it has no dictionary or data. If a dataset with the given name already exists, this has no effect. The new dataset can be used with commands that support output to a dataset, e.g. AGGREGATE (@pxref{AGGREGATE}). @vindex DATASET CLOSE The DATASET CLOSE command deletes a dataset. If the active dataset is specified by name, or if @samp{*} is specified, then the active dataset becomes unnamed. If a different dataset is specified by name, then it is deleted and becomes unavailable. Specifying ALL deletes all datasets except for the active dataset, which becomes unnamed. @vindex DATASET DISPLAY The DATASET DISPLAY command lists all the currently defined datasets. Many DATASET commands accept an optional @subcmd{WINDOW} subcommand. In the @pspp{}IRE GUI, the value given for this subcommand influences how the dataset's window is displayed. Outside the GUI, the @subcmd{WINDOW} subcommand has no effect. The valid values are: @table @asis @item ASIS Do not change how the window is displayed. This is the default for DATASET NAME and DATASET ACTIVATE. @item FRONT Raise the dataset's window to the top. Make it the default dataset for running syntax. @item MINIMIZED Display the window ``minimized'' to an icon. Prefer other datasets for running syntax. This is the default for DATASET COPY and DATASET DECLARE. @item HIDDEN Hide the dataset's window. Prefer other datasets for running syntax. @end table @node DATA LIST @section DATA LIST @vindex DATA LIST @cindex reading data from a file @cindex data, reading from a file @cindex data, embedding in syntax files @cindex embedding data in syntax files Used to read text or binary data, @cmd{DATA LIST} is the most fundamental data-reading command. Even the more sophisticated input methods use @cmd{DATA LIST} commands as a building block. Understanding @cmd{DATA LIST} is important to understanding how to use @pspp{} to read your data files. There are two major variants of @cmd{DATA LIST}, which are fixed format and free format. In addition, free format has a minor variant, list format, which is discussed in terms of its differences from vanilla free format. Each form of @cmd{DATA LIST} is described in detail below. @xref{GET DATA}, for a command that offers a few enhancements over DATA LIST and that may be substituted for DATA LIST in many situations. @menu * DATA LIST FIXED:: Fixed columnar locations for data. * DATA LIST FREE:: Any spacing you like. * DATA LIST LIST:: Each case must be on a single line. @end menu @node DATA LIST FIXED @subsection DATA LIST FIXED @vindex DATA LIST FIXED @cindex reading fixed-format data @cindex fixed-format data, reading @cindex data, fixed-format, reading @cindex embedding fixed-format data @display DATA LIST [FIXED] @{TABLE,NOTABLE@} [FILE='@var{file_name}' [ENCODING='@var{encoding}']] [RECORDS=@var{record_count}] [END=@var{end_var}] [SKIP=@var{record_count}] /[line_no] @var{var_spec}@dots{} where each @var{var_spec} takes one of the forms @var{var_list} @var{start}-@var{end} [@var{type_spec}] @var{var_list} (@var{fortran_spec}) @end display @cmd{DATA LIST FIXED} is used to read data files that have values at fixed positions on each line of single-line or multiline records. The keyword FIXED is optional. The @subcmd{FILE} subcommand must be used if input is to be taken from an external file. It may be used to specify a file name as a string or a file handle (@pxref{File Handles}). If the @subcmd{FILE} subcommand is not used, then input is assumed to be specified within the command file using @cmd{BEGIN DATA}@dots{}@cmd{END DATA} (@pxref{BEGIN DATA}). The @subcmd{ENCODING} subcommand may only be used if the @subcmd{FILE} subcommand is also used. It specifies the character encoding of the file. @xref{INSERT}, for information on supported encodings. The optional @subcmd{RECORDS} subcommand, which takes a single integer as an argument, is used to specify the number of lines per record. If @subcmd{RECORDS} is not specified, then the number of lines per record is calculated from the list of variable specifications later in @cmd{DATA LIST}. The @subcmd{END} subcommand is only useful in conjunction with @cmd{INPUT PROGRAM}. @xref{INPUT PROGRAM}, for details. The optional @subcmd{SKIP} subcommand specifies a number of records to skip at the beginning of an input file. It can be used to skip over a row that contains variable names, for example. @cmd{DATA LIST} can optionally output a table describing how the data file will be read. The @subcmd{TABLE} subcommand enables this output, and @subcmd{NOTABLE} disables it. The default is to output the table. The list of variables to be read from the data list must come last. Each line in the data record is introduced by a slash (@samp{/}). Optionally, a line number may follow the slash. Following, any number of variable specifications may be present. Each variable specification consists of a list of variable names followed by a description of their location on the input line. Sets of variables may be specified using the @cmd{DATA LIST} @subcmd{TO} convention (@pxref{Sets of Variables}). There are two ways to specify the location of the variable on the line: columnar style and FORTRAN style. In columnar style, the starting column and ending column for the field are specified after the variable name, separated by a dash (@samp{-}). For instance, the third through fifth columns on a line would be specified @samp{3-5}. By default, variables are considered to be in @samp{F} format (@pxref{Input and Output Formats}). (This default can be changed; see @ref{SET} for more information.) In columnar style, to use a variable format other than the default, specify the format type in parentheses after the column numbers. For instance, for alphanumeric @samp{A} format, use @samp{(A)}. In addition, implied decimal places can be specified in parentheses after the column numbers. As an example, suppose that a data file has a field in which the characters @samp{1234} should be interpreted as having the value 12.34. Then this field has two implied decimal places, and the corresponding specification would be @samp{(2)}. If a field that has implied decimal places contains a decimal point, then the implied decimal places are not applied. Changing the variable format and adding implied decimal places can be done together; for instance, @samp{(N,5)}. When using columnar style, the input and output width of each variable is computed from the field width. The field width must be evenly divisible into the number of variables specified. FORTRAN style is an altogether different approach to specifying field locations. With this approach, a list of variable input format specifications, separated by commas, are placed after the variable names inside parentheses. Each format specifier advances as many characters into the input line as it uses. Implied decimal places also exist in FORTRAN style. A format specification with @var{d} decimal places also has @var{d} implied decimal places. In addition to the standard format specifiers (@pxref{Input and Output Formats}), FORTRAN style defines some extensions: @table @asis @item @code{X} Advance the current column on this line by one character position. @item @code{T}@var{x} Set the current column on this line to column @var{x}, with column numbers considered to begin with 1 at the left margin. @item @code{NEWREC}@var{x} Skip forward @var{x} lines in the current record, resetting the active column to the left margin. @item Repeat count Any format specifier may be preceded by a number. This causes the action of that format specifier to be repeated the specified number of times. @item (@var{spec1}, @dots{}, @var{specN}) Group the given specifiers together. This is most useful when preceded by a repeat count. Groups may be nested arbitrarily. @end table FORTRAN and columnar styles may be freely intermixed. Columnar style leaves the active column immediately after the ending column specified. Record motion using @code{NEWREC} in FORTRAN style also applies to later FORTRAN and columnar specifiers. @menu * DATA LIST FIXED Examples:: Examples of DATA LIST FIXED. @end menu @node DATA LIST FIXED Examples @unnumberedsubsubsec Examples @enumerate @item @example DATA LIST TABLE /NAME 1-10 (A) INFO1 TO INFO3 12-17 (1). BEGIN DATA. John Smith 102311 Bob Arnold 122015 Bill Yates 918 6 END DATA. @end example Defines the following variables: @itemize @bullet @item @code{NAME}, a 10-character-wide string variable, in columns 1 through 10. @item @code{INFO1}, a numeric variable, in columns 12 through 13. @item @code{INFO2}, a numeric variable, in columns 14 through 15. @item @code{INFO3}, a numeric variable, in columns 16 through 17. @end itemize The @code{BEGIN DATA}/@code{END DATA} commands cause three cases to be defined: @example Case NAME INFO1 INFO2 INFO3 1 John Smith 10 23 11 2 Bob Arnold 12 20 15 3 Bill Yates 9 18 6 @end example The @code{TABLE} keyword causes @pspp{} to print out a table describing the four variables defined. @item @example DAT LIS FIL="survey.dat" /ID 1-5 NAME 7-36 (A) SURNAME 38-67 (A) MINITIAL 69 (A) /Q01 TO Q50 7-56 /. @end example Defines the following variables: @itemize @bullet @item @code{ID}, a numeric variable, in columns 1-5 of the first record. @item @code{NAME}, a 30-character string variable, in columns 7-36 of the first record. @item @code{SURNAME}, a 30-character string variable, in columns 38-67 of the first record. @item @code{MINITIAL}, a 1-character string variable, in column 69 of the first record. @item Fifty variables @code{Q01}, @code{Q02}, @code{Q03}, @dots{}, @code{Q49}, @code{Q50}, all numeric, @code{Q01} in column 7, @code{Q02} in column 8, @dots{}, @code{Q49} in column 55, @code{Q50} in column 56, all in the second record. @end itemize Cases are separated by a blank record. Data is read from file @file{survey.dat} in the current directory. This example shows keywords abbreviated to their first 3 letters. @end enumerate @node DATA LIST FREE @subsection DATA LIST FREE @vindex DATA LIST FREE @display DATA LIST FREE [(@{TAB,'@var{c}'@}, @dots{})] [@{NOTABLE,TABLE@}] [FILE='@var{file_name}' [ENCODING='@var{encoding}']] [SKIP=@var{record_cnt}] /@var{var_spec}@dots{} where each @var{var_spec} takes one of the forms @var{var_list} [(@var{type_spec})] @var{var_list} * @end display In free format, the input data is, by default, structured as a series of fields separated by spaces, tabs, commas, or line breaks. Each field's content may be unquoted, or it may be quoted with a pairs of apostrophes (@samp{'}) or double quotes (@samp{"}). Unquoted white space separates fields but is not part of any field. Any mix of spaces, tabs, and line breaks is equivalent to a single space for the purpose of separating fields, but consecutive commas will skip a field. Alternatively, delimiters can be specified explicitly, as a parenthesized, comma-separated list of single-character strings immediately following FREE. The word TAB may also be used to specify a tab character as a delimiter. When delimiters are specified explicitly, only the given characters, plus line breaks, separate fields. Furthermore, leading spaces at the beginnings of fields are not trimmed, consecutive delimiters define empty fields, and no form of quoting is allowed. The @subcmd{NOTABLE} and @subcmd{TABLE} subcommands are as in @cmd{DATA LIST FIXED} above. @subcmd{NOTABLE} is the default. The @subcmd{FILE}, @subcmd{SKIP}, and @subcmd{ENCODING} subcommands are as in @cmd{DATA LIST FIXED} above. The variables to be parsed are given as a single list of variable names. This list must be introduced by a single slash (@samp{/}). The set of variable names may contain format specifications in parentheses (@pxref{Input and Output Formats}). Format specifications apply to all variables back to the previous parenthesized format specification. In addition, an asterisk may be used to indicate that all variables preceding it are to have input/output format @samp{F8.0}. Specified field widths are ignored on input, although all normal limits on field width apply, but they are honored on output. @node DATA LIST LIST @subsection DATA LIST LIST @vindex DATA LIST LIST @display DATA LIST LIST [(@{TAB,'@var{c}'@}, @dots{})] [@{NOTABLE,TABLE@}] [FILE='@var{file_name}' [ENCODING='@var{encoding}']] [SKIP=@var{record_count}] /@var{var_spec}@dots{} where each @var{var_spec} takes one of the forms @var{var_list} [(@var{type_spec})] @var{var_list} * @end display With one exception, @cmd{DATA LIST LIST} is syntactically and semantically equivalent to @cmd{DATA LIST FREE}. The exception is that each input line is expected to correspond to exactly one input record. If more or fewer fields are found on an input line than expected, an appropriate diagnostic is issued. @node END CASE @section END CASE @vindex END CASE @display END CASE. @end display @cmd{END CASE} is used only within @cmd{INPUT PROGRAM} to output the current case. @xref{INPUT PROGRAM}, for details. @node END FILE @section END FILE @vindex END FILE @display END FILE. @end display @cmd{END FILE} is used only within @cmd{INPUT PROGRAM} to terminate the current input program. @xref{INPUT PROGRAM}. @node FILE HANDLE @section FILE HANDLE @vindex FILE HANDLE @display For text files: FILE HANDLE @var{handle_name} /NAME='@var{file_name} [/MODE=CHARACTER] /TABWIDTH=@var{tab_width} [ENCODING='@var{encoding}'] For binary files in native encoding with fixed-length records: FILE HANDLE @var{handle_name} /NAME='@var{file_name}' /MODE=IMAGE [/LRECL=@var{rec_len}] [ENCODING='@var{encoding}'] For binary files in native encoding with variable-length records: FILE HANDLE @var{handle_name} /NAME='@var{file_name}' /MODE=BINARY [/LRECL=@var{rec_len}] [ENCODING='@var{encoding}'] For binary files encoded in EBCDIC: FILE HANDLE @var{handle_name} /NAME='@var{file_name}' /MODE=360 /RECFORM=@{FIXED,VARIABLE,SPANNED@} [/LRECL=@var{rec_len}] [ENCODING='@var{encoding}'] @end display Use @cmd{FILE HANDLE} to associate a file handle name with a file and its attributes, so that later commands can refer to the file by its handle name. Names of text files can be specified directly on commands that access files, so that @cmd{FILE HANDLE} is only needed when a file is not an ordinary file containing lines of text. However, @cmd{FILE HANDLE} may be used even for text files, and it may be easier to specify a file's name once and later refer to it by an abstract handle. Specify the file handle name as the identifier immediately following the @cmd{FILE HANDLE} command name. The identifier INLINE is reserved for representing data embedded in the syntax file (@pxref{BEGIN DATA}) The file handle name must not already have been used in a previous invocation of @cmd{FILE HANDLE}, unless it has been closed by an intervening command (@pxref{CLOSE FILE HANDLE}). The effect and syntax of @cmd{FILE HANDLE} depends on the selected MODE: @itemize @item In CHARACTER mode, the default, the data file is read as a text file, according to the local system's conventions, and each text line is read as one record. In CHARACTER mode only, tabs are expanded to spaces by input programs, except by @cmd{DATA LIST FREE} with explicitly specified delimiters. Each tab is 4 characters wide by default, but TABWIDTH (a @pspp{} extension) may be used to specify an alternate width. Use a TABWIDTH of 0 to suppress tab expansion. @item In IMAGE mode, the data file is treated as a series of fixed-length binary records. LRECL should be used to specify the record length in bytes, with a default of 1024. On input, it is an error if an IMAGE file's length is not a integer multiple of the record length. On output, each record is padded with spaces or truncated, if necessary, to make it exactly the correct length. @item In BINARY mode, the data file is treated as a series of variable-length binary records. LRECL may be specified, but its value is ignored. The data for each record is both preceded and followed by a 32-bit signed integer in little-endian byte order that specifies the length of the record. (This redundancy permits records in these files to be efficiently read in reverse order, although @pspp{} always reads them in forward order.) The length does not include either integer. @item Mode 360 reads and writes files in formats first used for tapes in the 1960s on IBM mainframe operating systems and still supported today by the modern successors of those operating systems. For more information, see @cite{OS/400 Tape and Diskette Device Programming}, available on IBM's website. Alphanumeric data in mode 360 files are encoded in EBCDIC. @pspp{} translates EBCDIC to or from the host's native format as necessary on input or output, using an ASCII/EBCDIC translation that is one-to-one, so that a ``round trip'' from ASCII to EBCDIC back to ASCII, or vice versa, always yields exactly the original data. The @subcmd{RECFORM} subcommand is required in mode 360. The precise file format depends on its setting: @table @asis @item F @itemx FIXED This record format is equivalent to IMAGE mode, except for EBCDIC translation. IBM documentation calls this @code{*F} (fixed-length, deblocked) format. @item V @itemx VARIABLE The file comprises a sequence of zero or more variable-length blocks. Each block begins with a 4-byte @dfn{block descriptor word} (BDW). The first two bytes of the BDW are an unsigned integer in big-endian byte order that specifies the length of the block, including the BDW itself. The other two bytes of the BDW are ignored on input and written as zeros on output. Following the BDW, the remainder of each block is a sequence of one or more variable-length records, each of which in turn begins with a 4-byte @dfn{record descriptor word} (RDW) that has the same format as the BDW. Following the RDW, the remainder of each record is the record data. The maximum length of a record in VARIABLE mode is 65,527 bytes: 65,535 bytes (the maximum value of a 16-bit unsigned integer), minus 4 bytes for the BDW, minus 4 bytes for the RDW. In mode VARIABLE, LRECL specifies a maximum, not a fixed, record length, in bytes. The default is 8,192. IBM documentation calls this @code{*VB} (variable-length, blocked, unspanned) format. @item VS @itemx SPANNED The file format is like that of VARIABLE mode, except that logical records may be split among multiple physical records (called @dfn{segments}) or blocks. In SPANNED mode, the third byte of each RDW is called the segment control character (SCC). Odd SCC values cause the segment to be appended to a record buffer maintained in memory; even values also append the segment and then flush its contents to the input procedure. Canonically, SCC value 0 designates a record not spanned among multiple segments, and values 1 through 3 designate the first segment, the last segment, or an intermediate segment, respectively, within a multi-segment record. The record buffer is also flushed at end of file regardless of the final record's SCC. The maximum length of a logical record in VARIABLE mode is limited only by memory available to @pspp{}. Segments are limited to 65,527 bytes, as in VARIABLE mode. This format is similar to what IBM documentation call @code{*VS} (variable-length, deblocked, spanned) format. @end table In mode 360, fields of type A that extend beyond the end of a record read from disk are padded with spaces in the host's native character set, which are then translated from EBCDIC to the native character set. Thus, when the host's native character set is based on ASCII, these fields are effectively padded with character @code{X'80'}. This wart is implemented for compatibility. @end itemize The @subcmd{NAME} subcommand specifies the name of the file associated with the handle. It is required in all modes but SCRATCH mode, in which its use is forbidden. The ENCODING subcommand specifies the encoding of text in the file. For reading text files in CHARACTER mode, all of the forms described for ENCODING on the INSERT command are supported (@pxref{INSERT}). For reading in other file-based modes, encoding autodetection is not supported; if the specified encoding requests autodetection then the default encoding will be used. This is also true when a file handle is used for writing a file in any mode. @node INPUT PROGRAM @section INPUT PROGRAM @vindex INPUT PROGRAM @display INPUT PROGRAM. @dots{} input commands @dots{} END INPUT PROGRAM. @end display @cmd{INPUT PROGRAM}@dots{}@cmd{END INPUT PROGRAM} specifies a complex input program. By placing data input commands within @cmd{INPUT PROGRAM}, @pspp{} programs can take advantage of more complex file structures than available with only @cmd{DATA LIST}. The first sort of extended input program is to simply put multiple @cmd{DATA LIST} commands within the @cmd{INPUT PROGRAM}. This will cause all of the data files to be read in parallel. Input will stop when end of file is reached on any of the data files. Transformations, such as conditional and looping constructs, can also be included within @cmd{INPUT PROGRAM}. These can be used to combine input from several data files in more complex ways. However, input will still stop when end of file is reached on any of the data files. To prevent @cmd{INPUT PROGRAM} from terminating at the first end of file, use the @subcmd{END} subcommand on @cmd{DATA LIST}. This subcommand takes a variable name, which should be a numeric scratch variable (@pxref{Scratch Variables}). (It need not be a scratch variable but otherwise the results can be surprising.) The value of this variable is set to 0 when reading the data file, or 1 when end of file is encountered. Two additional commands are useful in conjunction with @cmd{INPUT PROGRAM}. @cmd{END CASE} is the first. Normally each loop through the @cmd{INPUT PROGRAM} structure produces one case. @cmd{END CASE} controls exactly when cases are output. When @cmd{END CASE} is used, looping from the end of @cmd{INPUT PROGRAM} to the beginning does not cause a case to be output. @cmd{END FILE} is the second. When the @subcmd{END} subcommand is used on @cmd{DATA LIST}, there is no way for the @cmd{INPUT PROGRAM} construct to stop looping, so an infinite loop results. @cmd{END FILE}, when executed, stops the flow of input data and passes out of the @cmd{INPUT PROGRAM} structure. All this is very confusing. A few examples should help to clarify. @c If you change this example, change the regression test1 in @c tests/command/input-program.sh to match. @example INPUT PROGRAM. DATA LIST NOTABLE FILE='a.data'/X 1-10. DATA LIST NOTABLE FILE='b.data'/Y 1-10. END INPUT PROGRAM. LIST. @end example The example above reads variable X from file @file{a.data} and variable Y from file @file{b.data}. If one file is shorter than the other then the extra data in the longer file is ignored. @c If you change this example, change the regression test2 in @c tests/command/input-program.sh to match. @example INPUT PROGRAM. NUMERIC #A #B. DO IF NOT #A. DATA LIST NOTABLE END=#A FILE='a.data'/X 1-10. END IF. DO IF NOT #B. DATA LIST NOTABLE END=#B FILE='b.data'/Y 1-10. END IF. DO IF #A AND #B. END FILE. END IF. END CASE. END INPUT PROGRAM. LIST. @end example The above example reads variable X from @file{a.data} and variable Y from @file{b.data}. If one file is shorter than the other then the missing field is set to the system-missing value alongside the present value for the remaining length of the longer file. @c If you change this example, change the regression test3 in @c tests/command/input-program.sh to match. @example INPUT PROGRAM. NUMERIC #A #B. DO IF #A. DATA LIST NOTABLE END=#B FILE='b.data'/X 1-10. DO IF #B. END FILE. ELSE. END CASE. END IF. ELSE. DATA LIST NOTABLE END=#A FILE='a.data'/X 1-10. DO IF NOT #A. END CASE. END IF. END IF. END INPUT PROGRAM. LIST. @end example The above example reads data from file @file{a.data}, then from @file{b.data}, and concatenates them into a single active dataset. @c If you change this example, change the regression test4 in @c tests/command/input-program.sh to match. @example INPUT PROGRAM. NUMERIC #EOF. LOOP IF NOT #EOF. DATA LIST NOTABLE END=#EOF FILE='a.data'/X 1-10. DO IF NOT #EOF. END CASE. END IF. END LOOP. COMPUTE #EOF = 0. LOOP IF NOT #EOF. DATA LIST NOTABLE END=#EOF FILE='b.data'/X 1-10. DO IF NOT #EOF. END CASE. END IF. END LOOP. END FILE. END INPUT PROGRAM. LIST. @end example The above example does the same thing as the previous example, in a different way. @c If you change this example, make similar changes to the regression @c test5 in tests/command/input-program.sh. @example INPUT PROGRAM. LOOP #I=1 TO 50. COMPUTE X=UNIFORM(10). END CASE. END LOOP. END FILE. END INPUT PROGRAM. LIST/FORMAT=NUMBERED. @end example The above example causes an active dataset to be created consisting of 50 random variates between 0 and 10. @node LIST @section LIST @vindex LIST @display LIST /VARIABLES=@var{var_list} /CASES=FROM @var{start_index} TO @var{end_index} BY @var{incr_index} /FORMAT=@{UNNUMBERED,NUMBERED@} @{WRAP,SINGLE@} @end display The @cmd{LIST} procedure prints the values of specified variables to the listing file. The @subcmd{VARIABLES} subcommand specifies the variables whose values are to be printed. Keyword VARIABLES is optional. If @subcmd{VARIABLES} subcommand is not specified then all variables in the active dataset are printed. The @subcmd{CASES} subcommand can be used to specify a subset of cases to be printed. Specify @subcmd{FROM} and the case number of the first case to print, @subcmd{TO} and the case number of the last case to print, and @subcmd{BY} and the number of cases to advance between printing cases, or any subset of those settings. If @subcmd{CASES} is not specified then all cases are printed. The @subcmd{FORMAT} subcommand can be used to change the output format. @subcmd{NUMBERED} will print case numbers along with each case; @subcmd{UNNUMBERED}, the default, causes the case numbers to be omitted. The @subcmd{WRAP} and @subcmd{SINGLE} settings are currently not used. Case numbers start from 1. They are counted after all transformations have been considered. @cmd{LIST} attempts to fit all the values on a single line. If needed to make them fit, variable names are displayed vertically. If values cannot fit on a single line, then a multi-line format will be used. @cmd{LIST} is a procedure. It causes the data to be read. @node NEW FILE @section NEW FILE @vindex NEW FILE @display NEW FILE. @end display @cmd{NEW FILE} command clears the dictionary and data from the current active dataset. @node PRINT @section PRINT @vindex PRINT @display PRINT [OUTFILE='@var{file_name}'] [RECORDS=@var{n_lines}] [@{NOTABLE,TABLE@}] [ENCODING='@var{encoding}'] [/[@var{line_no}] @var{arg}@dots{}] @var{arg} takes one of the following forms: '@var{string}' [@var{start}-@var{end}] @var{var_list} @var{start}-@var{end} [@var{type_spec}] @var{var_list} (@var{fortran_spec}) @var{var_list} * @end display The @cmd{PRINT} transformation writes variable data to the listing file or an output file. @cmd{PRINT} is executed when a procedure causes the data to be read. Follow @cmd{PRINT} by @cmd{EXECUTE} to print variable data without invoking a procedure (@pxref{EXECUTE}). All @cmd{PRINT} subcommands are optional. If no strings or variables are specified, @cmd{PRINT} outputs a single blank line. The @subcmd{OUTFILE} subcommand specifies the file to receive the output. The file may be a file name as a string or a file handle (@pxref{File Handles}). If @subcmd{OUTFILE} is not present then output will be sent to @pspp{}'s output listing file. When @subcmd{OUTFILE} is present, a space is inserted at beginning of each output line, even lines that otherwise would be blank. The @subcmd{ENCODING} subcommand may only be used if the @subcmd{OUTFILE} subcommand is also used. It specifies the character encoding of the file. @xref{INSERT}, for information on supported encodings. The @subcmd{RECORDS} subcommand specifies the number of lines to be output. The number of lines may optionally be surrounded by parentheses. @subcmd{TABLE} will cause the @cmd{PRINT} command to output a table to the listing file that describes what it will print to the output file. @subcmd{NOTABLE}, the default, suppresses this output table. Introduce the strings and variables to be printed with a slash (@samp{/}). Optionally, the slash may be followed by a number indicating which output line will be specified. In the absence of this line number, the next line number will be specified. Multiple lines may be specified using multiple slashes with the intended output for a line following its respective slash. Literal strings may be printed. Specify the string itself. Optionally the string may be followed by a column number or range of column numbers, specifying the location on the line for the string to be printed. Otherwise, the string will be printed at the current position on the line. Variables to be printed can be specified in the same ways as available for @cmd{DATA LIST FIXED} (@pxref{DATA LIST FIXED}). In addition, a variable list may be followed by an asterisk (@samp{*}), which indicates that the variables should be printed in their dictionary print formats, separated by spaces. A variable list followed by a slash or the end of command will be interpreted the same way. If a FORTRAN type specification is used to move backwards on the current line, then text is written at that point on the line, the line will be truncated to that length, although additional text being added will again extend the line to that length. @node PRINT EJECT @section PRINT EJECT @vindex PRINT EJECT @display PRINT EJECT OUTFILE='@var{file_name}' RECORDS=@var{n_lines} @{NOTABLE,TABLE@} /[@var{line_no}] @var{arg}@dots{} @var{arg} takes one of the following forms: '@var{string}' [@var{start}-@var{end}] @var{var_list} @var{start}-@var{end} [@var{type_spec}] @var{var_list} (@var{fortran_spec}) @var{var_list} * @end display @cmd{PRINT EJECT} advances to the beginning of a new output page in the listing file or output file. It can also output data in the same way as @cmd{PRINT}. All @cmd{PRINT EJECT} subcommands are optional. Without @subcmd{OUTFILE}, @cmd{PRINT EJECT} ejects the current page in the listing file, then it produces other output, if any is specified. With @subcmd{OUTFILE}, @cmd{PRINT EJECT} writes its output to the specified file. The first line of output is written with @samp{1} inserted in the first column. Commonly, this is the only line of output. If additional lines of output are specified, these additional lines are written with a space inserted in the first column, as with @subcmd{PRINT}. @xref{PRINT}, for more information on syntax and usage. @node PRINT SPACE @section PRINT SPACE @vindex PRINT SPACE @display PRINT SPACE [OUTFILE='file_name'] [ENCODING='@var{encoding}'] [n_lines]. @end display @cmd{PRINT SPACE} prints one or more blank lines to an output file. The @subcmd{OUTFILE} subcommand is optional. It may be used to direct output to a file specified by file name as a string or file handle (@pxref{File Handles}). If OUTFILE is not specified then output will be directed to the listing file. The @subcmd{ENCODING} subcommand may only be used if @subcmd{OUTFILE} is also used. It specifies the character encoding of the file. @xref{INSERT}, for information on supported encodings. n_lines is also optional. If present, it is an expression (@pxref{Expressions}) specifying the number of blank lines to be printed. The expression must evaluate to a nonnegative value. @node REREAD @section REREAD @vindex REREAD @display REREAD [FILE=handle] [COLUMN=column] [ENCODING='@var{encoding}']. @end display The @cmd{REREAD} transformation allows the previous input line in a data file already processed by @cmd{DATA LIST} or another input command to be re-read for further processing. The @subcmd{FILE} subcommand, which is optional, is used to specify the file to have its line re-read. The file must be specified as the name of a file handle (@pxref{File Handles}). If FILE is not specified then the last file specified on @cmd{DATA LIST} will be assumed (last file specified lexically, not in terms of flow-of-control). By default, the line re-read is re-read in its entirety. With the @subcmd{COLUMN} subcommand, a prefix of the line can be exempted from re-reading. Specify an expression (@pxref{Expressions}) evaluating to the first column that should be included in the re-read line. Columns are numbered from 1 at the left margin. The @subcmd{ENCODING} subcommand may only be used if the @subcmd{FILE} subcommand is also used. It specifies the character encoding of the file. @xref{INSERT}, for information on supported encodings. Issuing @code{REREAD} multiple times will not back up in the data file. Instead, it will re-read the same line multiple times. @node REPEATING DATA @section REPEATING DATA @vindex REPEATING DATA @display REPEATING DATA /STARTS=@var{start}-@var{end} /OCCURS=@var{n_occurs} /FILE='@var{file_name}' /LENGTH=@var{length} /CONTINUED[=@var{cont_start}-@var{cont_end}] /ID=@var{id_start}-@var{id_end}=@var{id_var} /@{TABLE,NOTABLE@} /DATA=@var{var_spec}@dots{} where each @var{var_spec} takes one of the forms @var{var_list} @var{start}-@var{end} [@var{type_spec}] @var{var_list} (@var{fortran_spec}) @end display @cmd{REPEATING DATA} parses groups of data repeating in a uniform format, possibly with several groups on a single line. Each group of data corresponds with one case. @cmd{REPEATING DATA} may only be used within an @cmd{INPUT PROGRAM} structure (@pxref{INPUT PROGRAM}). When used with @cmd{DATA LIST}, it can be used to parse groups of cases that share a subset of variables but differ in their other data. The @subcmd{STARTS} subcommand is required. Specify a range of columns, using literal numbers or numeric variable names. This range specifies the columns on the first line that are used to contain groups of data. The ending column is optional. If it is not specified, then the record width of the input file is used. For the inline file (@pxref{BEGIN DATA}) this is 80 columns; for a file with fixed record widths it is the record width; for other files it is 1024 characters by default. The @subcmd{OCCURS} subcommand is required. It must be a number or the name of a numeric variable. Its value is the number of groups present in the current record. The @subcmd{DATA} subcommand is required. It must be the last subcommand specified. It is used to specify the data present within each repeating group. Column numbers are specified relative to the beginning of a group at column 1. Data is specified in the same way as with @cmd{DATA LIST FIXED} (@pxref{DATA LIST FIXED}). All other subcommands are optional. FILE specifies the file to read, either a file name as a string or a file handle (@pxref{File Handles}). If FILE is not present then the default is the last file handle used on @cmd{DATA LIST} (lexically, not in terms of flow of control). By default @cmd{REPEATING DATA} will output a table describing how it will parse the input data. Specifying @subcmd{NOTABLE} will disable this behavior; specifying TABLE will explicitly enable it. The @subcmd{LENGTH} subcommand specifies the length in characters of each group. If it is not present then length is inferred from the @subcmd{DATA} subcommand. LENGTH can be a number or a variable name. Normally all the data groups are expected to be present on a single line. Use the @subcmd{CONTINUED} command to indicate that data can be continued onto additional lines. If data on continuation lines starts at the left margin and continues through the entire field width, no column specifications are necessary on @subcmd{CONTINUED}. Otherwise, specify the possible range of columns in the same way as on STARTS. When data groups are continued from line to line, it is easy for cases to get out of sync through careless hand editing. The @subcmd{ID} subcommand allows a case identifier to be present on each line of repeating data groups. @cmd{REPEATING DATA} will check for the same identifier on each line and report mismatches. Specify the range of columns that the identifier will occupy, followed by an equals sign (@samp{=}) and the identifier variable name. The variable must already have been declared with @cmd{NUMERIC} or another command. @cmd{REPEATING DATA} should be the last command given within an @cmd{INPUT PROGRAM}. It should not be enclosed within a @cmd{LOOP} structure (@pxref{LOOP}). Use @cmd{DATA LIST} before, not after, @cmd{REPEATING DATA}. @node WRITE @section WRITE @vindex WRITE @display WRITE OUTFILE='@var{file_name}' RECORDS=@var{n_lines} @{NOTABLE,TABLE@} /[@var{line_no}] @var{arg}@dots{} @var{arg} takes one of the following forms: '@var{string}' [@var{start}-@var{end}] @var{var_list} @var{start}-@var{end} [@var{type_spec}] @var{var_list} (@var{fortran_spec}) @var{var_list} * @end display @code{WRITE} writes text or binary data to an output file. @xref{PRINT}, for more information on syntax and usage. @cmd{PRINT} and @cmd{WRITE} differ in only a few ways: @itemize @bullet @item @cmd{WRITE} uses write formats by default, whereas @cmd{PRINT} uses print formats. @item @cmd{PRINT} inserts a space between variables unless a format is explicitly specified, but @cmd{WRITE} never inserts space between variables in output. @item @cmd{PRINT} inserts a space at the beginning of each line that it writes to an output file (and @cmd{PRINT EJECT} inserts @samp{1} at the beginning of each line that should begin a new page), but @cmd{WRITE} does not. @item @cmd{PRINT} outputs the system-missing value according to its specified output format, whereas @cmd{WRITE} outputs the system-missing value as a field filled with spaces. Binary formats are an exception. @end itemize pspp-master/doc/data-selection.texi000066400000000000000000000223161177044323000176720ustar00rootroot00000000000000@node Data Selection @chapter Selecting data for analysis This chapter documents @pspp{} commands that temporarily or permanently select data records from the active dataset for analysis. @menu * FILTER:: Exclude cases based on a variable. * N OF CASES:: Limit the size of the active dataset. * SAMPLE:: Select a specified proportion of cases. * SELECT IF:: Permanently delete selected cases. * SPLIT FILE:: Do multiple analyses with one command. * TEMPORARY:: Make transformations' effects temporary. * WEIGHT:: Weight cases by a variable. @end menu @node FILTER @section FILTER @vindex FILTER @display FILTER BY @var{var_name}. FILTER OFF. @end display @cmd{FILTER} allows a boolean-valued variable to be used to select cases from the data stream for processing. To set up filtering, specify @subcmd{BY} and a variable name. Keyword BY is optional but recommended. Cases which have a zero or system- or user-missing value are excluded from analysis, but not deleted from the data stream. Cases with other values are analyzed. To filter based on a different condition, use transformations such as @cmd{COMPUTE} or @cmd{RECODE} to compute a filter variable of the required form, then specify that variable on @cmd{FILTER}. @code{FILTER OFF} turns off case filtering. Filtering takes place immediately before cases pass to a procedure for analysis. Only one filter variable may be active at a time. Normally, case filtering continues until it is explicitly turned off with @code{FILTER OFF}. However, if @cmd{FILTER} is placed after @cmd{TEMPORARY}, it filters only the next procedure or procedure-like command. @node N OF CASES @section N OF CASES @vindex N OF CASES @display N [OF CASES] @var{num_of_cases} [ESTIMATED]. @end display @cmd{N OF CASES} limits the number of cases processed by any procedures that follow it in the command stream. @code{N OF CASES 100}, for example, tells @pspp{} to disregard all cases after the first 100. When @cmd{N OF CASES} is specified after @cmd{TEMPORARY}, it affects only the next procedure (@pxref{TEMPORARY}). Otherwise, cases beyond the limit specified are not processed by any later procedure. If the limit specified on @cmd{N OF CASES} is greater than the number of cases in the active dataset, it has no effect. When @cmd{N OF CASES} is used along with @cmd{SAMPLE} or @cmd{SELECT IF}, the case limit is applied to the cases obtained after sampling or case selection, regardless of how @cmd{N OF CASES} is placed relative to @cmd{SAMPLE} or @cmd{SELECT IF} in the command file. Thus, the commands @code{N OF CASES 100} and @code{SAMPLE .5} will both randomly sample approximately half of the active dataset's cases, then select the first 100 of those sampled, regardless of their order in the command file. @cmd{N OF CASES} with the @code{ESTIMATED} keyword gives an estimated number of cases before @cmd{DATA LIST} or another command to read in data. @code{ESTIMATED} never limits the number of cases processed by procedures. @pspp{} currently does not make use of case count estimates. @node SAMPLE @section SAMPLE @vindex SAMPLE @display SAMPLE @var{num1} [FROM @var{num2}]. @end display @cmd{SAMPLE} randomly samples a proportion of the cases in the active file. Unless it follows @cmd{TEMPORARY}, it operates as a transformation, permanently removing cases from the active dataset. The proportion to sample can be expressed as a single number between 0 and 1. If @var{k} is the number specified, and @var{N} is the number of currently-selected cases in the active dataset, then after @subcmd{SAMPLE @var{k}.}, approximately @var{k}*@var{N} cases will be selected. The proportion to sample can also be specified in the style @subcmd{SAMPLE @var{m} FROM @var{N}}. With this style, cases are selected as follows: @enumerate @item If @var{N} is equal to the number of currently-selected cases in the active dataset, exactly @var{m} cases will be selected. @item If @var{N} is greater than the number of currently-selected cases in the active dataset, an equivalent proportion of cases will be selected. @item If @var{N} is less than the number of currently-selected cases in the active, exactly @var{m} cases will be selected @emph{from the first @var{N} cases in the active dataset.} @end enumerate @cmd{SAMPLE} and @cmd{SELECT IF} are performed in the order specified by the syntax file. @cmd{SAMPLE} is always performed before @code{N OF CASES}, regardless of ordering in the syntax file (@pxref{N OF CASES}). The same values for @cmd{SAMPLE} may result in different samples. To obtain the same sample, use the @code{SET} command to set the random number seed to the same value before each @cmd{SAMPLE}. Different samples may still result when the file is processed on systems with differing endianness or floating-point formats. By default, the random number seed is based on the system time. @node SELECT IF @section SELECT IF @vindex SELECT IF @display SELECT IF @var{expression}. @end display @cmd{SELECT IF} selects cases for analysis based on the value of @var{expression}. Cases not selected are permanently eliminated from the active dataset, unless @cmd{TEMPORARY} is in effect (@pxref{TEMPORARY}). Specify a boolean expression (@pxref{Expressions}). If the value of the expression is true for a particular case, the case will be analyzed. If the expression has a false or missing value, then the case will be deleted from the data stream. Place @cmd{SELECT IF} as early in the command file as possible. Cases that are deleted early can be processed more efficiently in time and space. When @cmd{SELECT IF} is specified following @cmd{TEMPORARY} (@pxref{TEMPORARY}), the @cmd{LAG} function may not be used (@pxref{LAG}). @node SPLIT FILE @section SPLIT FILE @vindex SPLIT FILE @display SPLIT FILE [@{LAYERED, SEPARATE@}] BY @var{var_list}. SPLIT FILE OFF. @end display @cmd{SPLIT FILE} allows multiple sets of data present in one data file to be analyzed separately using single statistical procedure commands. Specify a list of variable names to analyze multiple sets of data separately. Groups of adjacent cases having the same values for these variables are analyzed by statistical procedure commands as one group. An independent analysis is carried out for each group of cases, and the variable values for the group are printed along with the analysis. When a list of variable names is specified, one of the keywords @subcmd{LAYERED} or @subcmd{SEPARATE} may also be specified. If provided, either keyword are ignored. Groups are formed only by @emph{adjacent} cases. To create a split using a variable where like values are not adjacent in the working file, you should first sort the data by that variable (@pxref{SORT CASES}). Specify @subcmd{OFF} to disable @cmd{SPLIT FILE} and resume analysis of the entire active dataset as a single group of data. When @cmd{SPLIT FILE} is specified after @cmd{TEMPORARY}, it affects only the next procedure (@pxref{TEMPORARY}). @node TEMPORARY @section TEMPORARY @vindex TEMPORARY @display TEMPORARY. @end display @cmd{TEMPORARY} is used to make the effects of transformations following its execution temporary. These transformations will affect only the execution of the next procedure or procedure-like command. Their effects will not be saved to the active dataset. The only specification on @cmd{TEMPORARY} is the command name. @cmd{TEMPORARY} may not appear within a @cmd{DO IF} or @cmd{LOOP} construct. It may appear only once between procedures and procedure-like commands. Scratch variables cannot be used following @cmd{TEMPORARY}. An example may help to clarify: @example DATA LIST /X 1-2. BEGIN DATA. 2 4 10 15 20 24 END DATA. COMPUTE X=X/2. TEMPORARY. COMPUTE X=X+3. DESCRIPTIVES X. DESCRIPTIVES X. @end example The data read by the first @cmd{DESCRIPTIVES} are 4, 5, 8, 10.5, 13, 15. The data read by the first @cmd{DESCRIPTIVES} are 1, 2, 5, 7.5, 10, 12. @node WEIGHT @section WEIGHT @vindex WEIGHT @display WEIGHT BY @var{var_name}. WEIGHT OFF. @end display @cmd{WEIGHT} assigns cases varying weights, changing the frequency distribution of the active dataset. Execution of @cmd{WEIGHT} is delayed until data have been read. If a variable name is specified, @cmd{WEIGHT} causes the values of that variable to be used as weighting factors for subsequent statistical procedures. Use of keyword @subcmd{BY} is optional but recommended. Weighting variables must be numeric. Scratch variables may not be used for weighting (@pxref{Scratch Variables}). When @subcmd{OFF} is specified, subsequent statistical procedures will weight all cases equally. A positive integer weighting factor @var{w} on a case will yield the same statistical output as would replicating the case @var{w} times. A weighting factor of 0 is treated for statistical purposes as if the case did not exist in the input. Weighting values need not be integers, but negative and system-missing values for the weighting variable are interpreted as weighting factors of 0. User-missing values are not treated specially. When @cmd{WEIGHT} is specified after @cmd{TEMPORARY}, it affects only the next procedure (@pxref{TEMPORARY}). @cmd{WEIGHT} does not cause cases in the active dataset to be replicated in memory. pspp-master/doc/dev/000077500000000000000000000000001177044323000146555ustar00rootroot00000000000000pspp-master/doc/dev/concepts.texi000066400000000000000000003067161177044323000174030ustar00rootroot00000000000000@node Basic Concepts @chapter Basic Concepts This chapter introduces basic data structures and other concepts needed for developing in PSPP. @menu * Values:: * Input and Output Formats:: * User-Missing Values:: * Value Labels:: * Variables:: * Dictionaries:: * Coding Conventions:: * Cases:: * Data Sets:: * Pools:: @end menu @node Values @section Values @cindex value The unit of data in PSPP is a @dfn{value}. @cindex width @cindex string value @cindex numeric value @cindex MAX_STRING Values are classified by @dfn{type} and @dfn{width}. The type of a value is either @dfn{numeric} or @dfn{string} (sometimes called alphanumeric). The width of a string value ranges from 1 to @code{MAX_STRING} bytes. The width of a numeric value is artificially defined to be 0; thus, the type of a value can be inferred from its width. Some support is provided for working with value types and widths, in @file{data/val-type.h}: @deftypefn Macro int MAX_STRING Maximum width of a string value, in bytes, currently 32,767. @end deftypefn @deftypefun bool val_type_is_valid (enum val_type @var{val_type}) Returns true if @var{val_type} is a valid value type, that is, either @code{VAL_NUMERIC} or @code{VAL_STRING}. Useful for assertions. @end deftypefun @deftypefun {enum val_type} val_type_from_width (int @var{width}) Returns @code{VAL_NUMERIC} if @var{width} is 0 and thus represents the width of a numeric value, otherwise @code{VAL_STRING} to indicate that @var{width} is the width of a string value. @end deftypefun The following subsections describe how values of each type are represented. @menu * Numeric Values:: * String Values:: * Runtime Typed Values:: @end menu @node Numeric Values @subsection Numeric Values A value known to be numeric at compile time is represented as a @code{double}. PSPP provides three values of @code{double} for special purposes, defined in @file{data/val-type.h}: @deftypefn Macro double SYSMIS The @dfn{system-missing value}, used to represent a datum whose true value is unknown, such as a survey question that was not answered by the respondent, or undefined, such as the result of division by zero. PSPP propagates the system-missing value through calculations and compensates for missing values in statistical analyses. @xref{Missing Observations,,,pspp, PSPP Users Guide}, for a PSPP user's view of missing values. PSPP currently defines @code{SYSMIS} as @code{-DBL_MAX}, that is, the greatest finite negative value of @code{double}. It is best not to depend on this definition, because PSPP may transition to using an IEEE NaN (not a number) instead at some point in the future. @end deftypefn @deftypefn Macro double LOWEST @deftypefnx Macro double HIGHEST The greatest finite negative (except for @code{SYSMIS}) and positive values of @code{double}, respectively. These values do not ordinarily appear in user data files. Instead, they are used to implement endpoints of open-ended ranges that are occasionally permitted in PSPP syntax, e.g.@: @code{5 THRU HI} as a range of missing values (@pxref{MISSING VALUES,,,pspp, PSPP Users Guide}). @end deftypefn @node String Values @subsection String Values A value known at compile time to have string type is represented as an array of @code{char}. String values do not necessarily represent readable text strings and may contain arbitrary 8-bit data, including null bytes, control codes, and bytes with the high bit set. Thus, string values are not null-terminated strings, but rather opaque arrays of bytes. @code{SYSMIS}, @code{LOWEST}, and @code{HIGHEST} have no equivalents as string values. Usually, PSPP fills an unknown or undefined string values with spaces, but PSPP does not treat such a string as a special case when it processes it later. @cindex MAX_STRING @code{MAX_STRING}, the maximum length of a string value, is defined in @file{data/val-type.h}. @node Runtime Typed Values @subsection Runtime Typed Values When a value's type is only known at runtime, it is often represented as a @union{value}, defined in @file{data/value.h}. A @union{value} does not identify the type or width of the data it contains. Code that works with @union{values}s must therefore have external knowledge of its content, often through the type and width of a @struct{variable} (@pxref{Variables}). @union{value} has one member that clients are permitted to access directly, a @code{double} named @samp{f} that stores the content of a numeric @union{value}. It has other members that store the content of string @union{value}, but client code should use accessor functions instead of referring to these directly. PSPP provides some functions for working with @union{value}s. The most useful are described below. To use these functions, recall that a numeric value has a width of 0. @deftypefun void value_init (union value *@var{value}, int @var{width}) Initializes @var{value} as a value of the given @var{width}. After initialization, the data in @var{value} are indeterminate; the caller is responsible for storing initial data in it. @end deftypefun @deftypefun void value_destroy (union value *@var{value}, int @var{width}) Frees auxiliary storage associated with @var{value}, which must have the given @var{width}. @end deftypefun @deftypefun bool value_needs_init (int @var{width}) For some widths, @func{value_init} and @func{value_destroy} do not actually do anything, because no additional storage is needed beyond the size of @union{value}. This function returns true if @var{width} is such a width, which case there is no actual need to call those functions. This can be a useful optimization if a large number of @union{value}s of such a width are to be initialized or destroyed. This function returns false if @func{value_init} and @func{value_destroy} are actually required for the given @var{width}. @end deftypefun @deftypefun double value_num (const union value *@var{value}) Returns the numeric value in @var{value}, which must have been initialized as a numeric value. Equivalent to @code{@var{value}->f}. @end deftypefun @deftypefun {const char *} value_str (const union value *@var{value}, int @var{width}) @deftypefunx {char *} value_str_rw (union value *@var{value}, int @var{width}) Returns the string value in @var{value}, which must have been initialized with positive width @var{width}. The string returned is not null-terminated. Only @var{width} bytes of returned data may be accessed. The two different functions exist only for @code{const}-correctness. Otherwise they are identical. It is important that @var{width} be the correct value that was passed to @func{value_init}. Passing a smaller or larger value (e.g.@: because that number of bytes will be accessed) will not always work and should be avoided. @end deftypefun @deftypefun void value_copy (union value *@var{dst}, @ const union value *@var{src}, @ int @var{width}) Copies the contents of @union{value} @var{src} to @var{dst}. Both @var{dst} and @var{src} must have been initialized with the specified @var{width}. @end deftypefun @deftypefun void value_set_missing (union value *@var{value}, int @var{width}) Sets @var{value} to @code{SYSMIS} if it is numeric or to all spaces if it is alphanumeric, according to @var{width}. @var{value} must have been initialized with the specified @var{width}. @end deftypefun @anchor{value_is_resizable} @deftypefun bool value_is_resizable (const union value *@var{value}, int @var{old_width}, int @var{new_width}) Determines whether @var{value}, which must have been initialized with the specified @var{old_width}, may be resized to @var{new_width}. Resizing is possible if the following criteria are met. First, @var{old_width} and @var{new_width} must be both numeric or both string widths. Second, if @var{new_width} is a short string width and less than @var{old_width}, resizing is allowed only if bytes @var{new_width} through @var{old_width} in @var{value} contain only spaces. These rules are part of those used by @func{mv_is_resizable} and @func{val_labs_can_set_width}. @end deftypefun @deftypefun void value_resize (union value *@var{value}, int @var{old_width}, int @var{new_width}) Resizes @var{value} from @var{old_width} to @var{new_width}, which must be allowed by the rules stated above. @var{value} must have been initialized with the specified @var{old_width} before calling this function. After resizing, @var{value} has width @var{new_width}. If @var{new_width} is greater than @var{old_width}, @var{value} will be padded on the right with spaces to the new width. If @var{new_width} is less than @var{old_width}, the rightmost bytes of @var{value} are truncated. @end deftypefun @deftypefun bool value_equal (const union value *@var{a}, const union value *@var{b}, int @var{width}) Compares of @var{a} and @var{b}, which must both have width @var{width}. Returns true if their contents are the same, false if they differ. @end deftypefun @deftypefun int value_compare_3way (const union value *@var{a}, const union value *@var{b}, int @var{width}) Compares of @var{a} and @var{b}, which must both have width @var{width}. Returns -1 if @var{a} is less than @var{b}, 0 if they are equal, or 1 if @var{a} is greater than @var{b}. Numeric values are compared numerically, with @code{SYSMIS} comparing less than any real number. String values are compared lexicographically byte-by-byte. @end deftypefun @deftypefun size_t value_hash (const union value *@var{value}, int @var{width}, unsigned int @var{basis}) Computes and returns a hash of @var{value}, which must have the specified @var{width}. The value in @var{basis} is folded into the hash. @end deftypefun @node Input and Output Formats @section Input and Output Formats Input and output formats specify how to convert data fields to and from data values (@pxref{Input and Output Formats,,,pspp, PSPP Users Guide}). PSPP uses @struct{fmt_spec} to represent input and output formats. Function prototypes and other declarations related to formats are in the @file{} header. @deftp {Structure} {struct fmt_spec} An input or output format, with the following members: @table @code @item enum fmt_type type The format type (see below). @item int w Field width, in bytes. The width of numeric fields is always between 1 and 40 bytes, and the width of string fields is always between 1 and 65534 bytes. However, many individual types of formats place stricter limits on field width (see @ref{fmt_max_input_width}, @ref{fmt_max_output_width}). @item int d Number of decimal places, in character positions. For format types that do not allow decimal places to be specified, this value must be 0. Format types that do allow decimal places have type-specific and often width-specific restrictions on @code{d} (see @ref{fmt_max_input_decimals}, @ref{fmt_max_output_decimals}). @end table @end deftp @deftp {Enumeration} {enum fmt_type} An enumerated type representing an input or output format type. Each PSPP input and output format has a corresponding enumeration constant prefixed by @samp{FMT}: @code{FMT_F}, @code{FMT_COMMA}, @code{FMT_DOT}, and so on. @end deftp The following sections describe functions for manipulating formats and the data in fields represented by formats. @menu * Constructing and Verifying Formats:: * Format Utility Functions:: * Obtaining Properties of Format Types:: * Numeric Formatting Styles:: * Formatted Data Input and Output:: @end menu @node Constructing and Verifying Formats @subsection Constructing and Verifying Formats These functions construct @struct{fmt_spec}s and verify that they are valid. @deftypefun {struct fmt_spec} fmt_for_input (enum fmt_type @var{type}, int @var{w}, int @var{d}) @deftypefunx {struct fmt_spec} fmt_for_output (enum fmt_type @var{type}, int @var{w}, int @var{d}) Constructs a @struct{fmt_spec} with the given @var{type}, @var{w}, and @var{d}, asserts that the result is a valid input (or output) format, and returns it. @end deftypefun @anchor{fmt_for_output_from_input} @deftypefun {struct fmt_spec} fmt_for_output_from_input (const struct fmt_spec *@var{input}) Given @var{input}, which must be a valid input format, returns the equivalent output format. @xref{Input and Output Formats,,,pspp, PSPP Users Guide}, for the rules for converting input formats into output formats. @end deftypefun @deftypefun {struct fmt_spec} fmt_default_for_width (int @var{width}) Returns the default output format for a variable of the given @var{width}. For a numeric variable, this is F8.2 format; for a string variable, it is the A format of the given @var{width}. @end deftypefun The following functions check whether a @struct{fmt_spec} is valid for various uses and return true if so, false otherwise. When any of them returns false, it also outputs an explanatory error message using @func{msg}. To suppress error output, enclose a call to one of these functions by a @func{msg_disable}/@func{msg_enable} pair. @deftypefun bool fmt_check (const struct fmt_spec *@var{format}, bool @var{for_input}) @deftypefunx bool fmt_check_input (const struct fmt_spec *@var{format}) @deftypefunx bool fmt_check_output (const struct fmt_spec *@var{format}) Checks whether @var{format} is a valid input format (for @func{fmt_check_input}, or @func{fmt_check} if @var{for_input}) or output format (for @func{fmt_check_output}, or @func{fmt_check} if not @var{for_input}). @end deftypefun @deftypefun bool fmt_check_type_compat (const struct fmt_spec *@var{format}, enum val_type @var{type}) Checks whether @var{format} matches the value type @var{type}, that is, if @var{type} is @code{VAL_NUMERIC} and @var{format} is a numeric format or @var{type} is @code{VAL_STRING} and @var{format} is a string format. @end deftypefun @deftypefun bool fmt_check_width_compat (const struct fmt_spec *@var{format}, int @var{width}) Checks whether @var{format} may be used as an output format for a value of the given @var{width}. @func{fmt_var_width}, described in the following section, can be also be used to determine the value width needed by a format. @end deftypefun @node Format Utility Functions @subsection Format Utility Functions These functions work with @struct{fmt_spec}s. @deftypefun int fmt_var_width (const struct fmt_spec *@var{format}) Returns the width for values associated with @var{format}. If @var{format} is a numeric format, the width is 0; if @var{format} is an A format, then the width @code{@var{format}->w}; otherwise, @var{format} is an AHEX format and its width is @code{@var{format}->w / 2}. @end deftypefun @deftypefun char *fmt_to_string (const struct fmt_spec *@var{format}, char @var{s}[FMT_STRING_LEN_MAX + 1]) Converts @var{format} to a human-readable format specifier in @var{s} and returns @var{s}. @var{format} need not be a valid input or output format specifier, e.g.@: it is allowed to have an excess width or decimal places. In particular, if @var{format} has decimals, they are included in the output string, even if @var{format}'s type does not allow decimals, to allow accurately presenting incorrect formats to the user. @end deftypefun @deftypefun bool fmt_equal (const struct fmt_spec *@var{a}, const struct fmt_spec *@var{b}) Compares @var{a} and @var{b} memberwise and returns true if they are identical, false otherwise. @var{format} need not be a valid input or output format specifier. @end deftypefun @deftypefun void fmt_resize (struct fmt_spec *@var{fmt}, int @var{width}) Sets the width of @var{fmt} to a valid format for a @union{value} of size @var{width}. @end deftypefun @node Obtaining Properties of Format Types @subsection Obtaining Properties of Format Types These functions work with @enum{fmt_type}s instead of the higher-level @struct{fmt_spec}s. Their primary purpose is to report properties of each possible format type, which in turn allows clients to abstract away many of the details of the very heterogeneous requirements of each format type. The first group of functions works with format type names. @deftypefun const char *fmt_name (enum fmt_type @var{type}) Returns the name for the given @var{type}, e.g.@: @code{"COMMA"} for @code{FMT_COMMA}. @end deftypefun @deftypefun bool fmt_from_name (const char *@var{name}, enum fmt_type *@var{type}) Tries to find the @enum{fmt_type} associated with @var{name}. If successful, sets @code{*@var{type}} to the type and returns true; otherwise, returns false without modifying @code{*@var{type}}. @end deftypefun The functions below query basic limits on width and decimal places for each kind of format. @deftypefun bool fmt_takes_decimals (enum fmt_type @var{type}) Returns true if a format of the given @var{type} is allowed to have a nonzero number of decimal places (the @code{d} member of @struct{fmt_spec}), false if not. @end deftypefun @anchor{fmt_min_input_width} @anchor{fmt_max_input_width} @anchor{fmt_min_output_width} @anchor{fmt_max_output_width} @deftypefun int fmt_min_input_width (enum fmt_type @var{type}) @deftypefunx int fmt_max_input_width (enum fmt_type @var{type}) @deftypefunx int fmt_min_output_width (enum fmt_type @var{type}) @deftypefunx int fmt_max_output_width (enum fmt_type @var{type}) Returns the minimum or maximum width (the @code{w} member of @struct{fmt_spec}) allowed for an input or output format of the specified @var{type}. @end deftypefun @anchor{fmt_max_input_decimals} @anchor{fmt_max_output_decimals} @deftypefun int fmt_max_input_decimals (enum fmt_type @var{type}, int @var{width}) @deftypefunx int fmt_max_output_decimals (enum fmt_type @var{type}, int @var{width}) Returns the maximum number of decimal places allowed for an input or output format, respectively, of the given @var{type} and @var{width}. Returns 0 if the specified @var{type} does not allow any decimal places or if @var{width} is too narrow to allow decimal places. @end deftypefun @deftypefun int fmt_step_width (enum fmt_type @var{type}) Returns the ``width step'' for a @struct{fmt_spec} of the given @var{type}. A @struct{fmt_spec}'s width must be a multiple of its type's width step. Most format types have a width step of 1, so that their formats' widths may be any integer within the valid range, but hexadecimal numeric formats and AHEX string formats have a width step of 2. @end deftypefun These functions allow clients to broadly determine how each kind of input or output format behaves. @deftypefun bool fmt_is_string (enum fmt_type @var{type}) @deftypefunx bool fmt_is_numeric (enum fmt_type @var{type}) Returns true if @var{type} is a format for numeric or string values, respectively, false otherwise. @end deftypefun @deftypefun enum fmt_category fmt_get_category (enum fmt_type @var{type}) Returns the category within which @var{type} falls. @deftp {Enumeration} {enum fmt_category} A group of format types. Format type categories correspond to the input and output categories described in the PSPP user documentation (@pxref{Input and Output Formats,,,pspp, PSPP Users Guide}). Each format is in exactly one category. The categories have bitwise disjoint values to make it easy to test whether a format type is in one of multiple categories, e.g.@: @example if (fmt_get_category (type) & (FMT_CAT_DATE | FMT_CAT_TIME)) @{ /* @dots{}@r{@code{type} is a date or time format}@dots{} */ @} @end example The format categories are: @table @code @item FMT_CAT_BASIC Basic numeric formats. @item FMT_CAT_CUSTOM Custom currency formats. @item FMT_CAT_LEGACY Legacy numeric formats. @item FMT_CAT_BINARY Binary formats. @item FMT_CAT_HEXADECIMAL Hexadecimal formats. @item FMT_CAT_DATE Date formats. @item FMT_CAT_TIME Time formats. @item FMT_CAT_DATE_COMPONENT Date component formats. @item FMT_CAT_STRING String formats. @end table @end deftp @end deftypefun The PSPP input and output routines use the following pair of functions to convert @enum{fmt_type}s to and from the separate set of codes used in system and portable files: @deftypefun int fmt_to_io (enum fmt_type @var{type}) Returns the format code used in system and portable files that corresponds to @var{type}. @end deftypefun @deftypefun bool fmt_from_io (int @var{io}, enum fmt_type *@var{type}) Converts @var{io}, a format code used in system and portable files, into a @enum{fmt_type} in @code{*@var{type}}. Returns true if successful, false if @var{io} is not valid. @end deftypefun These functions reflect the relationship between input and output formats. @deftypefun enum fmt_type fmt_input_to_output (enum fmt_type @var{type}) Returns the output format type that is used by default by DATA LIST and other input procedures when @var{type} is specified as an input format. The conversion from input format to output format is more complicated than simply changing the format. @xref{fmt_for_output_from_input}, for a function that performs the entire conversion. @end deftypefun @deftypefun bool fmt_usable_for_input (enum fmt_type @var{type}) Returns true if @var{type} may be used as an input format type, false otherwise. The custom currency formats, in particular, may be used for output but not for input. All format types are valid for output. @end deftypefun The final group of format type property functions obtain human-readable templates that illustrate the formats graphically. @deftypefun const char *fmt_date_template (enum fmt_type @var{type}) Returns a formatting template for @var{type}, which must be a date or time format type. These formats are used by @func{data_in} and @func{data_out} to guide parsing and formatting date and time data. @end deftypefun @deftypefun char *fmt_dollar_template (const struct fmt_spec *@var{format}) Returns a string of the form @code{$#,###.##} according to @var{format}, which must be of type @code{FMT_DOLLAR}. The caller must free the string with @code{free}. @end deftypefun @node Numeric Formatting Styles @subsection Numeric Formatting Styles Each of the basic numeric formats (F, E, COMMA, DOT, DOLLAR, PCT) and custom currency formats (CCA, CCB, CCC, CCD, CCE) has an associated numeric formatting style, represented by @struct{fmt_number_style}. Input and output conversion of formats that have numeric styles is determined mainly by the style, although the formatting rules have special cases that are not represented within the style. @deftp {Structure} {struct fmt_number_style} A structure type with the following members: @table @code @item struct substring neg_prefix @itemx struct substring prefix @itemx struct substring suffix @itemx struct substring neg_suffix A set of strings used a prefix to negative numbers, a prefix to every number, a suffix to every number, and a suffix to negative numbers, respectively. Each of these strings is no more than @code{FMT_STYLE_AFFIX_MAX} bytes (currently 16) bytes in length. These strings must be freed with @func{ss_dealloc} when no longer needed. @item decimal The character used as a decimal point. It must be either @samp{.} or @samp{,}. @item grouping The character used for grouping digits to the left of the decimal point. It may be @samp{.} or @samp{,}, in which case it must not be equal to @code{decimal}, or it may be set to 0 to disable grouping. @end table @end deftp The following functions are provided for working with numeric formatting styles. @deftypefun void fmt_number_style_init (struct fmt_number_style *@var{style}) Initialises a @struct{fmt_number_style} with all of the prefixes and suffixes set to the empty string, @samp{.} as the decimal point character, and grouping disables. @end deftypefun @deftypefun void fmt_number_style_destroy (struct fmt_number_style *@var{style}) Destroys @var{style}, freeing its storage. @end deftypefun @deftypefun {struct fmt_number_style} *fmt_create (void) A function which creates an array of all the styles used by pspp, and calls fmt_number_style_init on each of them. @end deftypefun @deftypefun void fmt_done (struct fmt_number_style *@var{styles}) A wrapper function which takes an array of @struct{fmt_number_style}, calls fmt_number_style_destroy on each of them, and then frees the array. @end deftypefun @deftypefun int fmt_affix_width (const struct fmt_number_style *@var{style}) Returns the total length of @var{style}'s @code{prefix} and @code{suffix}. @end deftypefun @deftypefun int fmt_neg_affix_width (const struct fmt_number_style *@var{style}) Returns the total length of @var{style}'s @code{neg_prefix} and @code{neg_suffix}. @end deftypefun PSPP maintains a global set of number styles for each of the basic numeric formats and custom currency formats. The following functions work with these global styles: @deftypefun {const struct fmt_number_style *} fmt_get_style (enum fmt_type @var{type}) Returns the numeric style for the given format @var{type}. @end deftypefun @deftypefun {const char *} fmt_name (enum fmt_type @var{type}) Returns the name of the given format @var{type}. @end deftypefun @node Formatted Data Input and Output @subsection Formatted Data Input and Output These functions provide the ability to convert data fields into @union{value}s and vice versa. @deftypefun bool data_in (struct substring @var{input}, const char *@var{encoding}, enum fmt_type @var{type}, int @var{implied_decimals}, int @var{first_column}, const struct dictionary *@var{dict}, union value *@var{output}, int @var{width}) Parses @var{input} as a field containing data in the given format @var{type}. The resulting value is stored in @var{output}, which the caller must have initialized with the given @var{width}. For consistency, @var{width} must be 0 if @var{type} is a numeric format type and greater than 0 if @var{type} is a string format type. @var{encoding} should be set to indicate the character encoding of @var{input}. @var{dict} must be a pointer to the dictionary with which @var{output} is associated. If @var{input} is the empty string (with length 0), @var{output} is set to the value set on SET BLANKS (@pxref{SET BLANKS,,,pspp, PSPP Users Guide}) for a numeric value, or to all spaces for a string value. This applies regardless of the usual parsing requirements for @var{type}. If @var{implied_decimals} is greater than zero, then the numeric result is shifted right by @var{implied_decimals} decimal places if @var{input} does not contain a decimal point character or an exponent. Only certain numeric format types support implied decimal places; for string formats and other numeric formats, @var{implied_decimals} has no effect. DATA LIST FIXED is the primary user of this feature (@pxref{DATA LIST FIXED,,,pspp, PSPP Users Guide}). Other callers should generally specify 0 for @var{implied_decimals}, to disable this feature. When @var{input} contains invalid input data, @func{data_in} outputs a message using @func{msg}. @c (@pxref{msg}). If @var{first_column} is nonzero, it is included in any such error message as the 1-based column number of the start of the field. The last column in the field is calculated as @math{@var{first_column} + @var{input} - 1}. To suppress error output, enclose the call to @func{data_in} by calls to @func{msg_disable} and @func{msg_enable}. This function returns true on success, false if a message was output (even if suppressed). Overflow and underflow provoke warnings but are not propagated to the caller as errors. This function is declared in @file{data/data-in.h}. @end deftypefun @deftypefun char * data_out (const union value *@var{input}, const struct fmt_spec *@var{format}) @deftypefunx char * data_out_legacy (const union value *@var{input}, const char *@var{encoding}, const struct fmt_spec *@var{format}) Converts the data pointed to by @var{input} into a string value, which will be encoded in UTF-8, according to output format specifier @var{format}. Format must be a valid output format. The width of @var{input} is inferred from @var{format} using an algorithm equivalent to @func{fmt_var_width}. When @var{input} contains data that cannot be represented in the given @var{format}, @func{data_out} may output a message using @func{msg}, @c (@pxref{msg}), although the current implementation does not consistently do so. To suppress error output, enclose the call to @func{data_out} by calls to @func{msg_disable} and @func{msg_enable}. This function is declared in @file{data/data-out.h}. @end deftypefun @node User-Missing Values @section User-Missing Values In addition to the system-missing value for numeric values, each variable has a set of user-missing values (@pxref{MISSING VALUES,,,pspp, PSPP Users Guide}). A set of user-missing values is represented by @struct{missing_values}. It is rarely necessary to interact directly with a @struct{missing_values} object. Instead, the most common operation, querying whether a particular value is a missing value for a given variable, is most conveniently executed through functions on @struct{variable}. @xref{Variable Missing Values}, for details. A @struct{missing_values} is essentially a set of @union{value}s that have a common value width (@pxref{Values}). For a set of missing values associated with a variable (the common case), the set's width is the same as the variable's width. Function prototypes and other declarations related to missing values are declared in @file{data/missing-values.h}. @deftp {Structure} {struct missing_values} Opaque type that represents a set of missing values. @end deftp The contents of a set of missing values is subject to some restrictions. Regardless of width, a set of missing values is allowed to be empty. A set of numeric missing values may contain up to three discrete numeric values, or a range of numeric values (which includes both ends of the range), or a range plus one discrete numeric value. A set of string missing values may contain up to three discrete string values (with the same width as the set), but ranges are not supported. In addition, values in string missing values wider than @code{MV_MAX_STRING} bytes may contain non-space characters only in their first @code{MV_MAX_STRING} bytes; all the bytes after the first @code{MV_MAX_STRING} must be spaces. @xref{mv_is_acceptable}, for a function that tests a value against these constraints. @deftypefn Macro int MV_MAX_STRING Number of bytes in a string missing value that are not required to be spaces. The current value is 8, a value which is fixed by the system file format. In PSPP we could easily eliminate this restriction, but doing so would also require us to extend the system file format in an incompatible way, which we consider a bad tradeoff. @end deftypefn The most often useful functions for missing values are those for testing whether a given value is missing, described in the following section. Several other functions for creating, inspecting, and modifying @struct{missing_values} objects are described afterward, but these functions are much more rarely useful. @menu * Testing for Missing Values:: * Creating and Destroying User-Missing Values:: * Changing User-Missing Value Set Width:: * Inspecting User-Missing Value Sets:: * Modifying User-Missing Value Sets:: @end menu @node Testing for Missing Values @subsection Testing for Missing Values The most often useful functions for missing values are those for testing whether a given value is missing, described here. However, using one of the corresponding missing value testing functions for variables can be even easier (@pxref{Variable Missing Values}). @deftypefun bool mv_is_value_missing (const struct missing_values *@var{mv}, const union value *@var{value}, enum mv_class @var{class}) @deftypefunx bool mv_is_num_missing (const struct missing_values *@var{mv}, double @var{value}, enum mv_class @var{class}) @deftypefunx bool mv_is_str_missing (const struct missing_values *@var{mv}, const char @var{value}[], enum mv_class @var{class}) Tests whether @var{value} is in one of the categories of missing values given by @var{class}. Returns true if so, false otherwise. @var{mv} determines the width of @var{value} and provides the set of user-missing values to test. The only difference among these functions in the form in which @var{value} is provided, so you may use whichever function is most convenient. The @var{class} argument determines the exact kinds of missing values that the functions test for: @deftp Enumeration {enum mv_class} @table @t @item MV_USER Returns true if @var{value} is in the set of user-missing values given by @var{mv}. @item MV_SYSTEM Returns true if @var{value} is system-missing. (If @var{mv} represents a set of string values, then @var{value} is never system-missing.) @item MV_ANY @itemx MV_USER | MV_SYSTEM Returns true if @var{value} is user-missing or system-missing. @item MV_NONE Always returns false, that is, @var{value} is never considered missing. @end table @end deftp @end deftypefun @node Creating and Destroying User-Missing Values @subsection Creation and Destruction These functions create and destroy @struct{missing_values} objects. @deftypefun void mv_init (struct missing_values *@var{mv}, int @var{width}) Initializes @var{mv} as a set of user-missing values. The set is initially empty. Any values added to it must have the specified @var{width}. @end deftypefun @deftypefun void mv_destroy (struct missing_values *@var{mv}) Destroys @var{mv}, which must not be referred to again. @end deftypefun @deftypefun void mv_copy (struct missing_values *@var{mv}, const struct missing_values *@var{old}) Initializes @var{mv} as a copy of the existing set of user-missing values @var{old}. @end deftypefun @deftypefun void mv_clear (struct missing_values *@var{mv}) Empties the user-missing value set @var{mv}, retaining its existing width. @end deftypefun @node Changing User-Missing Value Set Width @subsection Changing User-Missing Value Set Width A few PSPP language constructs copy sets of user-missing values from one variable to another. When the source and target variables have the same width, this is simple. But when the target variable's width might be different from the source variable's, it takes a little more work. The functions described here can help. In fact, it is usually unnecessary to call these functions directly. Most of the time @func{var_set_missing_values}, which uses @func{mv_resize} internally to resize the new set of missing values to the required width, may be used instead. @xref{var_set_missing_values}, for more information. @deftypefun bool mv_is_resizable (const struct missing_values *@var{mv}, int @var{new_width}) Tests whether @var{mv}'s width may be changed to @var{new_width} using @func{mv_resize}. Returns true if it is allowed, false otherwise. If @var{mv} contains any missing values, then it may be resized only if each missing value may be resized, as determined by @func{value_is_resizable} (@pxref{value_is_resizable}). @end deftypefun @anchor{mv_resize} @deftypefun void mv_resize (struct missing_values *@var{mv}, int @var{width}) Changes @var{mv}'s width to @var{width}. @var{mv} and @var{width} must satisfy the constraints explained above. When a string missing value set's width is increased, each user-missing value is padded on the right with spaces to the new width. @end deftypefun @node Inspecting User-Missing Value Sets @subsection Inspecting User-Missing Value Sets These functions inspect the properties and contents of @struct{missing_values} objects. The first set of functions inspects the discrete values that sets of user-missing values may contain: @deftypefun bool mv_is_empty (const struct missing_values *@var{mv}) Returns true if @var{mv} contains no user-missing values, false if it contains at least one user-missing value (either a discrete value or a numeric range). @end deftypefun @deftypefun int mv_get_width (const struct missing_values *@var{mv}) Returns the width of the user-missing values that @var{mv} represents. @end deftypefun @deftypefun int mv_n_values (const struct missing_values *@var{mv}) Returns the number of discrete user-missing values included in @var{mv}. The return value will be between 0 and 3. For sets of numeric user-missing values that include a range, the return value will be 0 or 1. @end deftypefun @deftypefun bool mv_has_value (const struct missing_values *@var{mv}) Returns true if @var{mv} has at least one discrete user-missing values, that is, if @func{mv_n_values} would return nonzero for @var{mv}. @end deftypefun @deftypefun {const union value *} mv_get_value (const struct missing_values *@var{mv}, int @var{index}) Returns the discrete user-missing value in @var{mv} with the given @var{index}. The caller must not modify or free the returned value or refer to it after modifying or freeing @var{mv}. The index must be less than the number of discrete user-missing values in @var{mv}, as reported by @func{mv_n_values}. @end deftypefun The second set of functions inspects the single range of values that numeric sets of user-missing values may contain: @deftypefun bool mv_has_range (const struct missing_values *@var{mv}) Returns true if @var{mv} includes a range, false otherwise. @end deftypefun @deftypefun void mv_get_range (const struct missing_values *@var{mv}, double *@var{low}, double *@var{high}) Stores the low endpoint of @var{mv}'s range in @code{*@var{low}} and the high endpoint of the range in @code{*@var{high}}. @var{mv} must include a range. @end deftypefun @node Modifying User-Missing Value Sets @subsection Modifying User-Missing Value Sets These functions modify the contents of @struct{missing_values} objects. The next set of functions applies to all sets of user-missing values: @deftypefun bool mv_add_value (struct missing_values *@var{mv}, const union value *@var{value}) @deftypefunx bool mv_add_str (struct missing_values *@var{mv}, const char @var{value}[]) @deftypefunx bool mv_add_num (struct missing_values *@var{mv}, double @var{value}) Attempts to add the given discrete @var{value} to set of user-missing values @var{mv}. @var{value} must have the same width as @var{mv}. Returns true if @var{value} was successfully added, false if the set could not accept any more discrete values or if @var{value} is not an acceptable user-missing value (see @func{mv_is_acceptable} below). These functions are equivalent, except for the form in which @var{value} is provided, so you may use whichever function is most convenient. @end deftypefun @deftypefun void mv_pop_value (struct missing_values *@var{mv}, union value *@var{value}) Removes a discrete value from @var{mv} (which must contain at least one discrete value) and stores it in @var{value}. @end deftypefun @deftypefun bool mv_replace_value (struct missing_values *@var{mv}, const union value *@var{value}, int @var{index}) Attempts to replace the discrete value with the given @var{index} in @var{mv} (which must contain at least @var{index} + 1 discrete values) by @var{value}. Returns true if successful, false if @var{value} is not an acceptable user-missing value (see @func{mv_is_acceptable} below). @end deftypefun @deftypefun bool mv_is_acceptable (const union value *@var{value}, int @var{width}) @anchor{mv_is_acceptable} Returns true if @var{value}, which must have the specified @var{width}, may be added to a missing value set of the same @var{width}, false if it cannot. As described above, all numeric values and string values of width @code{MV_MAX_STRING} or less may be added, but string value of greater width may be added only if bytes beyond the first @code{MV_MAX_STRING} are all spaces. @end deftypefun The second set of functions applies only to numeric sets of user-missing values: @deftypefun bool mv_add_range (struct missing_values *@var{mv}, double @var{low}, double @var{high}) Attempts to add a numeric range covering @var{low}@dots{}@var{high} (inclusive on both ends) to @var{mv}, which must be a numeric set of user-missing values. Returns true if the range is successful added, false on failure. Fails if @var{mv} already contains a range, or if @var{mv} contains more than one discrete value, or if @var{low} > @var{high}. @end deftypefun @deftypefun void mv_pop_range (struct missing_values *@var{mv}, double *@var{low}, double *@var{high}) Given @var{mv}, which must be a numeric set of user-missing values that contains a range, removes that range from @var{mv} and stores its low endpoint in @code{*@var{low}} and its high endpoint in @code{*@var{high}}. @end deftypefun @node Value Labels @section Value Labels Each variable has a set of value labels (@pxref{VALUE LABELS,,,pspp, PSPP Users Guide}), represented as @struct{val_labs}. A @struct{val_labs} is essentially a map from @union{value}s to strings. All of the values in a set of value labels have the same width, which for a set of value labels owned by a variable (the common case) is the same as its variable. Sets of value labels may contain any number of entries. It is rarely necessary to interact directly with a @struct{val_labs} object. Instead, the most common operation, looking up the label for a value of a given variable, can be conveniently executed through functions on @struct{variable}. @xref{Variable Value Labels}, for details. Function prototypes and other declarations related to missing values are declared in @file{data/value-labels.h}. @deftp {Structure} {struct val_labs} Opaque type that represents a set of value labels. @end deftp The most often useful function for value labels is @func{val_labs_find}, for looking up the label associated with a value. @deftypefun {char *} val_labs_find (const struct val_labs *@var{val_labs}, union value @var{value}) Looks in @var{val_labs} for a label for the given @var{value}. Returns the label, if one is found, or a null pointer otherwise. @end deftypefun Several other functions for working with value labels are described in the following section, but these are more rarely useful. @menu * Value Labels Creation and Destruction:: * Value Labels Properties:: * Value Labels Adding and Removing Labels:: * Value Labels Iteration:: @end menu @node Value Labels Creation and Destruction @subsection Creation and Destruction These functions create and destroy @struct{val_labs} objects. @deftypefun {struct val_labs *} val_labs_create (int @var{width}) Creates and returns an initially empty set of value labels with the given @var{width}. @end deftypefun @deftypefun {struct val_labs *} val_labs_clone (const struct val_labs *@var{val_labs}) Creates and returns a set of value labels whose width and contents are the same as those of @var{var_labs}. @end deftypefun @deftypefun void val_labs_clear (struct val_labs *@var{var_labs}) Deletes all value labels from @var{var_labs}. @end deftypefun @deftypefun void val_labs_destroy (struct val_labs *@var{var_labs}) Destroys @var{var_labs}, which must not be referenced again. @end deftypefun @node Value Labels Properties @subsection Value Labels Properties These functions inspect and manipulate basic properties of @struct{val_labs} objects. @deftypefun size_t val_labs_count (const struct val_labs *@var{val_labs}) Returns the number of value labels in @var{val_labs}. @end deftypefun @deftypefun bool val_labs_can_set_width (const struct val_labs *@var{val_labs}, int @var{new_width}) Tests whether @var{val_labs}'s width may be changed to @var{new_width} using @func{val_labs_set_width}. Returns true if it is allowed, false otherwise. A set of value labels may be resized to a given width only if each value in it may be resized to that width, as determined by @func{value_is_resizable} (@pxref{value_is_resizable}). @end deftypefun @deftypefun void val_labs_set_width (struct val_labs *@var{val_labs}, int @var{new_width}) Changes the width of @var{val_labs}'s values to @var{new_width}, which must be a valid new width as determined by @func{val_labs_can_set_width}. @end deftypefun @node Value Labels Adding and Removing Labels @subsection Adding and Removing Labels These functions add and remove value labels from a @struct{val_labs} object. @deftypefun bool val_labs_add (struct val_labs *@var{val_labs}, union value @var{value}, const char *@var{label}) Adds @var{label} to in @var{var_labs} as a label for @var{value}, which must have the same width as the set of value labels. Returns true if successful, false if @var{value} already has a label. @end deftypefun @deftypefun void val_labs_replace (struct val_labs *@var{val_labs}, union value @var{value}, const char *@var{label}) Adds @var{label} to in @var{var_labs} as a label for @var{value}, which must have the same width as the set of value labels. If @var{value} already has a label in @var{var_labs}, it is replaced. @end deftypefun @deftypefun bool val_labs_remove (struct val_labs *@var{val_labs}, union value @var{value}) Removes from @var{val_labs} any label for @var{value}, which must have the same width as the set of value labels. Returns true if a label was removed, false otherwise. @end deftypefun @node Value Labels Iteration @subsection Iterating through Value Labels These functions allow iteration through the set of value labels represented by a @struct{val_labs} object. They may be used in the context of a @code{for} loop: @example struct val_labs val_labs; const struct val_lab *vl; @dots{} for (vl = val_labs_first (val_labs); vl != NULL; vl = val_labs_next (val_labs, vl)) @{ @dots{}@r{do something with @code{vl}}@dots{} @} @end example Value labels should not be added or deleted from a @struct{val_labs} as it is undergoing iteration. @deftypefun {const struct val_lab *} val_labs_first (const struct val_labs *@var{val_labs}) Returns the first value label in @var{var_labs}, if it contains at least one value label, or a null pointer if it does not contain any value labels. @end deftypefun @deftypefun {const struct val_lab *} val_labs_next (const struct val_labs *@var{val_labs}, const struct val_labs_iterator **@var{vl}) Returns the value label in @var{var_labs} following @var{vl}, if @var{vl} is not the last value label in @var{val_labs}, or a null pointer if there are no value labels following @var{vl}. @end deftypefun @deftypefun {const struct val_lab **} val_labs_sorted (const struct val_labs *@var{val_labs}) Allocates and returns an array of pointers to value labels, which are sorted in increasing order by value. The array has @code{val_labs_count (@var{val_labs})} elements. The caller is responsible for freeing the array with @func{free} (but must not free any of the @struct{val_lab} elements that the array points to). @end deftypefun The iteration functions above work with pointers to @struct{val_lab} which is an opaque data structure that users of @struct{val_labs} must not modify or free directly. The following functions work with objects of this type: @deftypefun {const union value *} val_lab_get_value (const struct val_lab *@var{vl}) Returns the value of value label @var{vl}. The caller must not modify or free the returned value. (To achieve a similar result, remove the value label with @func{val_labs_remove}, then add the new value with @func{val_labs_add}.) The width of the returned value cannot be determined directly from @var{vl}. It may be obtained by calling @func{val_labs_get_width} on the @struct{val_labs} that @var{vl} is in. @end deftypefun @deftypefun {const char *} val_lab_get_label (const struct val_lab *@var{vl}) Returns the label in @var{vl} as a null-terminated string. The caller must not modify or free the returned string. (Use @func{val_labs_replace} to change a value label.) @end deftypefun @node Variables @section Variables A PSPP variable is represented by @struct{variable}, an opaque type declared in @file{data/variable.h} along with related declarations. @xref{Variables,,,pspp, PSPP Users Guide}, for a description of PSPP variables from a user perspective. PSPP is unusual among computer languages in that, by itself, a PSPP variable does not have a value. Instead, a variable in PSPP takes on a value only in the context of a case, which supplies one value for each variable in a set of variables (@pxref{Cases}). The set of variables in a case, in turn, are ordinarily part of a dictionary (@pxref{Dictionaries}). Every variable has several attributes, most of which correspond directly to one of the variable attributes visible to PSPP users (@pxref{Attributes,,,pspp, PSPP Users Guide}). The following sections describe variable-related functions and macros. @menu * Variable Name:: * Variable Type and Width:: * Variable Missing Values:: * Variable Value Labels:: * Variable Print and Write Formats:: * Variable Labels:: * Variable GUI Attributes:: * Variable Leave Status:: * Dictionary Class:: * Variable Creation and Destruction:: * Variable Short Names:: * Variable Relationships:: * Variable Auxiliary Data:: * Variable Categorical Values:: @end menu @node Variable Name @subsection Variable Name A variable name is a string between 1 and @code{ID_MAX_LEN} bytes long that satisfies the rules for PSPP identifiers (@pxref{Tokens,,,pspp, PSPP Users Guide}). Variable names are mixed-case and treated case-insensitively. @deftypefn Macro int ID_MAX_LEN Maximum length of a variable name, in bytes, currently 64. @end deftypefn Only one commonly useful function relates to variable names: @deftypefun {const char *} var_get_name (const struct variable *@var{var}) Returns @var{var}'s variable name as a C string. @end deftypefun A few other functions are much more rarely used. Some of these functions are used internally by the dictionary implementation: @anchor{var_set_name} @deftypefun {void} var_set_name (struct variable *@var{var}, const char *@var{new_name}) Changes the name of @var{var} to @var{new_name}, which must be a ``plausible'' name as defined below. This function cannot be applied to a variable that is part of a dictionary. Use @func{dict_rename_var} instead (@pxref{Dictionary Renaming Variables}). @end deftypefun @deftypefun {enum dict_class} var_get_dict_class (const struct variable *@var{var}) Returns the dictionary class of @var{var}'s name (@pxref{Dictionary Class}). @end deftypefun @node Variable Type and Width @subsection Variable Type and Width A variable's type and width are the type and width of its values (@pxref{Values}). @deftypefun {enum val_type} var_get_type (const struct variable *@var{var}) Returns the type of variable @var{var}. @end deftypefun @deftypefun int var_get_width (const struct variable *@var{var}) Returns the width of variable @var{var}. @end deftypefun @deftypefun void var_set_width (struct variable *@var{var}, int @var{width}) Sets the width of variable @var{var} to @var{width}. The width of a variable should not normally be changed after the variable is created, so this function is rarely used. This function cannot be applied to a variable that is part of a dictionary. @end deftypefun @deftypefun bool var_is_numeric (const struct variable *@var{var}) Returns true if @var{var} is a numeric variable, false otherwise. @end deftypefun @deftypefun bool var_is_alpha (const struct variable *@var{var}) Returns true if @var{var} is an alphanumeric (string) variable, false otherwise. @end deftypefun @node Variable Missing Values @subsection Variable Missing Values A numeric or short string variable may have a set of user-missing values (@pxref{MISSING VALUES,,,pspp, PSPP Users Guide}), represented as a @struct{missing_values} (@pxref{User-Missing Values}). The most frequent operation on a variable's missing values is to query whether a value is user- or system-missing: @deftypefun bool var_is_value_missing (const struct variable *@var{var}, const union value *@var{value}, enum mv_class @var{class}) @deftypefunx bool var_is_num_missing (const struct variable *@var{var}, double @var{value}, enum mv_class @var{class}) @deftypefunx bool var_is_str_missing (const struct variable *@var{var}, const char @var{value}[], enum mv_class @var{class}) Tests whether @var{value} is a missing value of the given @var{class} for variable @var{var} and returns true if so, false otherwise. @func{var_is_num_missing} may only be applied to numeric variables; @func{var_is_str_missing} may only be applied to string variables. @var{value} must have been initialized with the same width as @var{var}. @code{var_is_@var{type}_missing (@var{var}, @var{value}, @var{class})} is equivalent to @code{mv_is_@var{type}_missing (var_get_missing_values (@var{var}), @var{value}, @var{class})}. @end deftypefun In addition, a few functions are provided to work more directly with a variable's @struct{missing_values}: @deftypefun {const struct missing_values *} var_get_missing_values (const struct variable *@var{var}) Returns the @struct{missing_values} associated with @var{var}. The caller must not modify the returned structure. The return value is always non-null. @end deftypefun @anchor{var_set_missing_values} @deftypefun {void} var_set_missing_values (struct variable *@var{var}, const struct missing_values *@var{miss}) Changes @var{var}'s missing values to a copy of @var{miss}, or if @var{miss} is a null pointer, clears @var{var}'s missing values. If @var{miss} is non-null, it must have the same width as @var{var} or be resizable to @var{var}'s width (@pxref{mv_resize}). The caller retains ownership of @var{miss}. @end deftypefun @deftypefun void var_clear_missing_values (struct variable *@var{var}) Clears @var{var}'s missing values. Equivalent to @code{var_set_missing_values (@var{var}, NULL)}. @end deftypefun @deftypefun bool var_has_missing_values (const struct variable *@var{var}) Returns true if @var{var} has any missing values, false if it has none. Equivalent to @code{mv_is_empty (var_get_missing_values (@var{var}))}. @end deftypefun @node Variable Value Labels @subsection Variable Value Labels A numeric or short string variable may have a set of value labels (@pxref{VALUE LABELS,,,pspp, PSPP Users Guide}), represented as a @struct{val_labs} (@pxref{Value Labels}). The most commonly useful functions for value labels return the value label associated with a value: @deftypefun {const char *} var_lookup_value_label (const struct variable *@var{var}, const union value *@var{value}) Looks for a label for @var{value} in @var{var}'s set of value labels. @var{value} must have the same width as @var{var}. Returns the label if one exists, otherwise a null pointer. @end deftypefun @deftypefun void var_append_value_name (const struct variable *@var{var}, const union value *@var{value}, struct string *@var{str}) Looks for a label for @var{value} in @var{var}'s set of value labels. @var{value} must have the same width as @var{var}. If a label exists, it will be appended to the string pointed to by @var{str}. Otherwise, it formats @var{value} using @var{var}'s print format (@pxref{Input and Output Formats}) and appends the formatted string. @end deftypefun The underlying @struct{val_labs} structure may also be accessed directly using the functions described below. @deftypefun bool var_has_value_labels (const struct variable *@var{var}) Returns true if @var{var} has at least one value label, false otherwise. @end deftypefun @deftypefun {const struct val_labs *} var_get_value_labels (const struct variable *@var{var}) Returns the @struct{val_labs} associated with @var{var}. If @var{var} has no value labels, then the return value may or may not be a null pointer. The variable retains ownership of the returned @struct{val_labs}, which the caller must not attempt to modify. @end deftypefun @deftypefun void var_set_value_labels (struct variable *@var{var}, const struct val_labs *@var{val_labs}) Replaces @var{var}'s value labels by a copy of @var{val_labs}. The caller retains ownership of @var{val_labs}. If @var{val_labs} is a null pointer, then @var{var}'s value labels, if any, are deleted. @end deftypefun @deftypefun void var_clear_value_labels (struct variable *@var{var}) Deletes @var{var}'s value labels. Equivalent to @code{var_set_value_labels (@var{var}, NULL)}. @end deftypefun A final group of functions offers shorthands for operations that would otherwise require getting the value labels from a variable, copying them, modifying them, and then setting the modified value labels into the variable (making a second copy): @deftypefun bool var_add_value_label (struct variable *@var{var}, const union value *@var{value}, const char *@var{label}) Attempts to add a copy of @var{label} as a label for @var{value} for the given @var{var}. @var{value} must have the same width as @var{var}. If @var{value} already has a label, then the old label is retained. Returns true if a label is added, false if there was an existing label for @var{value}. Either way, the caller retains ownership of @var{value} and @var{label}. @end deftypefun @deftypefun void var_replace_value_label (struct variable *@var{var}, const union value *@var{value}, const char *@var{label}) Attempts to add a copy of @var{label} as a label for @var{value} for the given @var{var}. @var{value} must have the same width as @var{var}. If @var{value} already has a label, then @var{label} replaces the old label. Either way, the caller retains ownership of @var{value} and @var{label}. @end deftypefun @node Variable Print and Write Formats @subsection Variable Print and Write Formats Each variable has an associated pair of output formats, called its @dfn{print format} and @dfn{write format}. @xref{Input and Output Formats,,,pspp, PSPP Users Guide}, for an introduction to formats. @xref{Input and Output Formats}, for a developer's description of format representation. The print format is used to convert a variable's data values to strings for human-readable output. The write format is used similarly for machine-readable output, primarily by the WRITE transformation (@pxref{WRITE,,,pspp, PSPP Users Guide}). Most often a variable's print and write formats are the same. A newly created variable by default has format F8.2 if it is numeric or an A format with the same width as the variable if it is string. Many creators of variables override these defaults. Both the print format and write format are output formats. Input formats are not part of @struct{variable}. Instead, input programs and transformations keep track of variable input formats themselves. The following functions work with variable print and write formats. @deftypefun {const struct fmt_spec *} var_get_print_format (const struct variable *@var{var}) @deftypefunx {const struct fmt_spec *} var_get_write_format (const struct variable *@var{var}) Returns @var{var}'s print or write format, respectively. @end deftypefun @deftypefun void var_set_print_format (struct variable *@var{var}, const struct fmt_spec *@var{format}) @deftypefunx void var_set_write_format (struct variable *@var{var}, const struct fmt_spec *@var{format}) @deftypefunx void var_set_both_formats (struct variable *@var{var}, const struct fmt_spec *@var{format}) Sets @var{var}'s print format, write format, or both formats, respectively, to a copy of @var{format}. @end deftypefun @node Variable Labels @subsection Variable Labels A variable label is a string that describes a variable. Variable labels may contain spaces and punctuation not allowed in variable names. @xref{VARIABLE LABELS,,,pspp, PSPP Users Guide}, for a user-level description of variable labels. The most commonly useful functions for variable labels are those to retrieve a variable's label: @deftypefun {const char *} var_to_string (const struct variable *@var{var}) Returns @var{var}'s variable label, if it has one, otherwise @var{var}'s name. In either case the caller must not attempt to modify or free the returned string. This function is useful for user output. @end deftypefun @deftypefun {const char *} var_get_label (const struct variable *@var{var}) Returns @var{var}'s variable label, if it has one, or a null pointer otherwise. @end deftypefun A few other variable label functions are also provided: @deftypefun void var_set_label (struct variable *@var{var}, const char *@var{label}) Sets @var{var}'s variable label to a copy of @var{label}, or removes any label from @var{var} if @var{label} is a null pointer or contains only spaces. Leading and trailing spaces are removed from the variable label and its remaining content is truncated at 255 bytes. @end deftypefun @deftypefun void var_clear_label (struct variable *@var{var}) Removes any variable label from @var{var}. @end deftypefun @deftypefun bool var_has_label (const struct variable *@var{var}) Returns true if @var{var} has a variable label, false otherwise. @end deftypefun @node Variable GUI Attributes @subsection GUI Attributes These functions and types access and set attributes that are mainly used by graphical user interfaces. Their values are also stored in and retrieved from system files (but not portable files). The first group of functions relate to the measurement level of numeric data. New variables are assigned a nominal level of measurement by default. @deftp {Enumeration} {enum measure} Measurement level. Available values are: @table @code @item MEASURE_NOMINAL Numeric data values are arbitrary. Arithmetic operations and numerical comparisons of such data are not meaningful. @item MEASURE_ORDINAL Numeric data values indicate progression along a rank order. Arbitrary arithmetic operations such as addition are not meaningful on such data, but inequality comparisons (less, greater, etc.) have straightforward interpretations. @item MEASURE_SCALE Ratios, sums, etc. of numeric data values have meaningful interpretations. @end table PSPP does not have a separate category for interval data, which would naturally fall between the ordinal and scale measurement levels. @end deftp @deftypefun bool measure_is_valid (enum measure @var{measure}) Returns true if @var{measure} is a valid level of measurement, that is, if it is one of the @code{enum measure} constants listed above, and false otherwise. @end deftypefun @deftypefun enum measure var_get_measure (const struct variable *@var{var}) @deftypefunx void var_set_measure (struct variable *@var{var}, enum measure @var{measure}) Gets or sets @var{var}'s measurement level. @end deftypefun The following set of functions relates to the width of on-screen columns used for displaying variable data in a graphical user interface environment. The unit of measurement is the width of a character. For proportionally spaced fonts, this is based on the average width of a character. @deftypefun int var_get_display_width (const struct variable *@var{var}) @deftypefunx void var_set_display_width (struct variable *@var{var}, int @var{display_width}) Gets or sets @var{var}'s display width. @end deftypefun @anchor{var_default_display_width} @deftypefun int var_default_display_width (int @var{width}) Returns the default display width for a variable with the given @var{width}. The default width of a numeric variable is 8. The default width of a string variable is @var{width} or 32, whichever is less. @end deftypefun The final group of functions work with the justification of data when it is displayed in on-screen columns. New variables are by default right-justified. @deftp {Enumeration} {enum alignment} Text justification. Possible values are @code{ALIGN_LEFT}, @code{ALIGN_RIGHT}, and @code{ALIGN_CENTRE}. @end deftp @deftypefun bool alignment_is_valid (enum alignment @var{alignment}) Returns true if @var{alignment} is a valid alignment, that is, if it is one of the @code{enum alignment} constants listed above, and false otherwise. @end deftypefun @deftypefun enum alignment var_get_alignment (const struct variable *@var{var}) @deftypefunx void var_set_alignment (struct variable *@var{var}, enum alignment @var{alignment}) Gets or sets @var{var}'s alignment. @end deftypefun @node Variable Leave Status @subsection Variable Leave Status Commonly, most or all data in a case come from an input file, read with a command such as DATA LIST or GET, but data can also be generated with transformations such as COMPUTE. In the latter case the question of a datum's ``initial value'' can arise. For example, the value of a piece of generated data can recursively depend on its own value: @example COMPUTE X = X + 1. @end example Another situation where the initial value of a variable arises is when its value is not set at all for some cases, e.g.@: below, @code{Y} is set only for the first 10 cases: @example DO IF #CASENUM <= 10. + COMPUTE Y = 1. END IF. @end example By default, the initial value of a datum in either of these situations is the system-missing value for numeric values and spaces for string values. This means that, above, X would be system-missing and that Y would be 1 for the first 10 cases and system-missing for the remainder. PSPP also supports retaining the value of a variable from one case to another, using the LEAVE command (@pxref{LEAVE,,,pspp, PSPP Users Guide}). The initial value of such a variable is 0 if it is numeric and spaces if it is a string. If the command @samp{LEAVE X Y} is appended to the above example, then X would have value 1 in the first case and increase by 1 in every succeeding case, and Y would have value 1 for the first 10 cases and 0 for later cases. The LEAVE command has no effect on data that comes from an input file or whose values do not depend on a variable's initial value. The value of scratch variables (@pxref{Scratch Variables,,,pspp, PSPP Users Guide}) are always left from one case to another. The following functions work with a variable's leave status. @deftypefun bool var_get_leave (const struct variable *@var{var}) Returns true if @var{var}'s value is to be retained from case to case, false if it is reinitialized to system-missing or spaces. @end deftypefun @deftypefun void var_set_leave (struct variable *@var{var}, bool @var{leave}) If @var{leave} is true, marks @var{var} to be left from case to case; if @var{leave} is false, marks @var{var} to be reinitialized for each case. If @var{var} is a scratch variable, @var{leave} must be true. @end deftypefun @deftypefun bool var_must_leave (const struct variable *@var{var}) Returns true if @var{var} must be left from case to case, that is, if @var{var} is a scratch variable. @end deftypefun @node Dictionary Class @subsection Dictionary Class Occasionally it is useful to classify variables into @dfn{dictionary classes} based on their names. Dictionary classes are represented by @enum{dict_class}. This type and other declarations for dictionary classes are in the @file{} header. @deftp {Enumeration} {enum dict_class} The dictionary classes are: @table @code @item DC_ORDINARY An ordinary variable, one whose name does not begin with @samp{$} or @samp{#}. @item DC_SYSTEM A system variable, one whose name begins with @samp{$}. @xref{System Variables,,,pspp, PSPP Users Guide}. @item DC_SCRATCH A scratch variable, one whose name begins with @samp{#}. @xref{Scratch Variables,,,pspp, PSPP Users Guide}. @end table The values for dictionary classes are bitwise disjoint, which allows them to be used in bit-masks. An extra enumeration constant @code{DC_ALL}, whose value is the bitwise-@i{or} of all of the above constants, is provided to aid in this purpose. @end deftp One example use of dictionary classes arises in connection with PSPP syntax that uses @code{@var{a} TO @var{b}} to name the variables in a dictionary from @var{a} to @var{b} (@pxref{Sets of Variables,,,pspp, PSPP Users Guide}). This syntax requires @var{a} and @var{b} to be in the same dictionary class. It limits the variables that it includes to those in that dictionary class. The following functions relate to dictionary classes. @deftypefun {enum dict_class} dict_class_from_id (const char *@var{name}) Returns the ``dictionary class'' for the given variable @var{name}, by looking at its first letter. @end deftypefun @deftypefun {const char *} dict_class_to_name (enum dict_class @var{dict_class}) Returns a name for the given @var{dict_class} as an adjective, e.g.@: @code{"scratch"}. This function should probably not be used in new code as it can lead to difficulties for internationalization. @end deftypefun @node Variable Creation and Destruction @subsection Variable Creation and Destruction Only rarely should PSPP code create or destroy variables directly. Ordinarily, variables are created within a dictionary and destroying by individual deletion from the dictionary or by destroying the entire dictionary at once. The functions here enable the exceptional case, of creation and destruction of variables that are not associated with any dictionary. These functions are used internally in the dictionary implementation. @anchor{var_create} @deftypefun {struct variable *} var_create (const char *@var{name}, int @var{width}) Creates and returns a new variable with the given @var{name} and @var{width}. The new variable is not part of any dictionary. Use @func{dict_create_var}, instead, to create a variable in a dictionary (@pxref{Dictionary Creating Variables}). @var{name} should be a valid variable name and must be a ``plausible'' variable name (@pxref{Variable Name}). @var{width} must be between 0 and @code{MAX_STRING}, inclusive (@pxref{Values}). The new variable has no user-missing values, value labels, or variable label. Numeric variables initially have F8.2 print and write formats, right-justified display alignment, and scale level of measurement. String variables are created with A print and write formats, left-justified display alignment, and nominal level of measurement. The initial display width is determined by @func{var_default_display_width} (@pxref{var_default_display_width}). The new variable initially has no short name (@pxref{Variable Short Names}) and no auxiliary data (@pxref{Variable Auxiliary Data}). @end deftypefun @anchor{var_clone} @deftypefun {struct variable *} var_clone (const struct variable *@var{old_var}) Creates and returns a new variable with the same attributes as @var{old_var}, with a few exceptions. First, the new variable is not part of any dictionary, regardless of whether @var{old_var} was in a dictionary. Use @func{dict_clone_var}, instead, to add a clone of a variable to a dictionary. Second, the new variable is not given any short name, even if @var{old_var} had a short name. This is because the new variable is likely to be immediately renamed, in which case the short name would be incorrect (@pxref{Variable Short Names}). Finally, @var{old_var}'s auxiliary data, if any, is not copied to the new variable (@pxref{Variable Auxiliary Data}). @end deftypefun @deftypefun {void} var_destroy (struct variable *@var{var}) Destroys @var{var} and frees all associated storage, including its auxiliary data, if any. @var{var} must not be part of a dictionary. To delete a variable from a dictionary and destroy it, use @func{dict_delete_var} (@pxref{Dictionary Deleting Variables}). @end deftypefun @node Variable Short Names @subsection Variable Short Names PSPP variable names may be up to 64 (@code{ID_MAX_LEN}) bytes long. The system and portable file formats, however, were designed when variable names were limited to 8 bytes in length. Since then, the system file format has been augmented with an extension record that explains how the 8-byte short names map to full-length names (@pxref{Long Variable Names Record}), but the short names are still present. Thus, the continued presence of the short names is more or less invisible to PSPP users, but every variable in a system file still has a short name that must be unique. PSPP can generate unique short names for variables based on their full names at the time it creates the data file. If all variables' full names are unique in their first 8 bytes, then the short names are simply prefixes of the full names; otherwise, PSPP changes them so that they are unique. By itself this algorithm interoperates well with other software that can read system files, as long as that software understands the extension record that maps short names to long names. When the other software does not understand the extension record, it can produce surprising results. Consider a situation where PSPP reads a system file that contains two variables named RANKINGSCORE, then the user adds a new variable named RANKINGSTATUS, then saves the modified data as a new system file. A program that does not understand long names would then see one of these variables under the name RANKINGS---either one, depending on the algorithm's details---and the other under a different name. The effect could be very confusing: by adding a new and apparently unrelated variable in PSPP, the user effectively renamed the existing variable. To counteract this potential problem, every @struct{variable} may have a short name. A variable created by the system or portable file reader receives the short name from that data file. When a variable with a short name is written to a system or portable file, that variable receives priority over other long names whose names begin with the same 8 bytes but which were not read from a data file under that short name. Variables not created by the system or portable file reader have no short name by default. A variable with a full name of 8 bytes or less in length has absolute priority for that name when the variable is written to a system file, even over a second variable with that assigned short name. PSPP does not enforce uniqueness of short names, although the short names read from any given data file will always be unique. If two variables with the same short name are written to a single data file, neither one receives priority. The following macros and functions relate to short names. @defmac SHORT_NAME_LEN Maximum length of a short name, in bytes. Its value is 8. @end defmac @deftypefun {const char *} var_get_short_name (const struct variable *@var{var}) Returns @var{var}'s short name, or a null pointer if @var{var} has not been assigned a short name. @end deftypefun @deftypefun void var_set_short_name (struct variable *@var{var}, const char *@var{short_name}) Sets @var{var}'s short name to @var{short_name}, or removes @var{var}'s short name if @var{short_name} is a null pointer. If it is non-null, then @var{short_name} must be a plausible name for a variable. The name will be truncated to 8 bytes in length and converted to all-uppercase. @end deftypefun @deftypefun void var_clear_short_name (struct variable *@var{var}) Removes @var{var}'s short name. @end deftypefun @node Variable Relationships @subsection Variable Relationships Variables have close relationships with dictionaries (@pxref{Dictionaries}) and cases (@pxref{Cases}). A variable is usually a member of some dictionary, and a case is often used to store data for the set of variables in a dictionary. These functions report on these relationships. They may be applied only to variables that are in a dictionary. @deftypefun size_t var_get_dict_index (const struct variable *@var{var}) Returns @var{var}'s index within its dictionary. The first variable in a dictionary has index 0, the next variable index 1, and so on. The dictionary index can be influenced using dictionary functions such as dict_reorder_var (@pxref{dict_reorder_var}). @end deftypefun @deftypefun size_t var_get_case_index (const struct variable *@var{var}) Returns @var{var}'s index within a case. The case index is an index into an array of @union{value} large enough to contain all the data in the dictionary. The returned case index can be used to access the value of @var{var} within a case for its dictionary, as in e.g.@: @code{case_data_idx (case, var_get_case_index (@var{var}))}, but ordinarily it is more convenient to use the data access functions that do variable-to-index translation internally, as in e.g.@: @code{case_data (case, @var{var})}. @end deftypefun @node Variable Auxiliary Data @subsection Variable Auxiliary Data Each @struct{variable} can have a single pointer to auxiliary data of type @code{void *}. These functions manipulate a variable's auxiliary data. Use of auxiliary data is discouraged because of its lack of flexibility. Only one client can make use of auxiliary data on a given variable at any time, even though many clients could usefully associate data with a variable. To prevent multiple clients from attempting to use a variable's single auxiliary data field at the same time, we adopt the convention that use of auxiliary data in the active dataset dictionary is restricted to the currently executing command. In particular, transformations must not attach auxiliary data to a variable in the active dataset in the expectation that it can be used later when the active dataset is read and the transformation is executed. To help enforce this restriction, auxiliary data is deleted from all variables in the active dataset dictionary after the execution of each PSPP command. This convention for safe use of auxiliary data applies only to the active dataset dictionary. Rules for other dictionaries may be established separately. Auxiliary data should be replaced by a more flexible mechanism at some point, but no replacement mechanism has been designed or implemented so far. The following functions work with variable auxiliary data. @deftypefun {void *} var_get_aux (const struct variable *@var{var}) Returns @var{var}'s auxiliary data, or a null pointer if none has been assigned. @end deftypefun @deftypefun {void *} var_attach_aux (const struct variable *@var{var}, void *@var{aux}, void (*@var{aux_dtor}) (struct variable *)) Sets @var{var}'s auxiliary data to @var{aux}, which must not be null. @var{var} must not already have auxiliary data. Before @var{var}'s auxiliary data is cleared by @code{var_clear_aux}, @var{aux_dtor}, if non-null, will be called with @var{var} as its argument. It should free any storage associated with @var{aux}, if necessary. @code{var_dtor_free} may be appropriate for use as @var{aux_dtor}: @deffn {Function} void var_dtor_free (struct variable *@var{var}) Frees @var{var}'s auxiliary data by calling @code{free}. @end deffn @end deftypefun @deftypefun void var_clear_aux (struct variable *@var{var}) Removes auxiliary data, if any, from @var{var}, first calling the destructor passed to @code{var_attach_aux}, if one was provided. Use @code{dict_clear_aux} to remove auxiliary data from every variable in a dictionary. @c (@pxref{dict_clear_aux}). @end deftypefun @deftypefun {void *} var_detach_aux (struct variable *@var{var}) Removes auxiliary data, if any, from @var{var}, and returns it. Returns a null pointer if @var{var} had no auxiliary data. Any destructor passed to @code{var_attach_aux} is not called, so the caller is responsible for freeing storage associated with the returned auxiliary data. @end deftypefun @node Variable Categorical Values @subsection Variable Categorical Values Some statistical procedures require a list of all the values that a categorical variable takes on. Arranging such a list requires making a pass through the data, so PSPP caches categorical values in @struct{variable}. When variable auxiliary data is revamped to support multiple clients as described in the previous section, categorical values are an obvious candidate. The form in which they are currently supported is inelegant. Categorical values are not robust against changes in the data. That is, there is currently no way to detect that a transformation has changed data values, meaning that categorical values lists for the changed variables must be recomputed. PSPP is in fact in need of a general-purpose caching and cache-invalidation mechanism, but none has yet been designed and built. The following functions work with cached categorical values. @deftypefun {struct cat_vals *} var_get_obs_vals (const struct variable *@var{var}) Returns @var{var}'s set of categorical values. Yields undefined behavior if @var{var} does not have any categorical values. @end deftypefun @deftypefun void var_set_obs_vals (const struct variable *@var{var}, struct cat_vals *@var{cat_vals}) Destroys @var{var}'s categorical values, if any, and replaces them by @var{cat_vals}, ownership of which is transferred to @var{var}. If @var{cat_vals} is a null pointer, then @var{var}'s categorical values are cleared. @end deftypefun @deftypefun bool var_has_obs_vals (const struct variable *@var{var}) Returns true if @var{var} has a set of categorical values, false otherwise. @end deftypefun @node Dictionaries @section Dictionaries Each data file in memory or on disk has an associated dictionary, whose primary purpose is to describe the data in the file. @xref{Variables,,,pspp, PSPP Users Guide}, for a PSPP user's view of a dictionary. A data file stored in a PSPP format, either as a system or portable file, has a representation of its dictionary embedded in it. Other kinds of data files are usually not self-describing enough to construct a dictionary unassisted, so the dictionaries for these files must be specified explicitly with PSPP commands such as @cmd{DATA LIST}. The most important content of a dictionary is an array of variables, which must have unique names. A dictionary also conceptually contains a mapping from each of its variables to a location within a case (@pxref{Cases}), although in fact these mappings are stored within individual variables. System variables are not members of any dictionary (@pxref{System Variables,,,pspp, PSPP Users Guide}). Dictionaries are represented by @struct{dictionary}. Declarations related to dictionaries are in the @file{} header. The following sections describe functions for use with dictionaries. @menu * Dictionary Variable Access:: * Dictionary Creating Variables:: * Dictionary Deleting Variables:: * Dictionary Reordering Variables:: * Dictionary Renaming Variables:: * Dictionary Weight Variable:: * Dictionary Filter Variable:: * Dictionary Case Limit:: * Dictionary Split Variables:: * Dictionary File Label:: * Dictionary Documents:: @end menu @node Dictionary Variable Access @subsection Accessing Variables The most common operations on a dictionary simply retrieve a @code{struct variable *} of an individual variable based on its name or position. @deftypefun {struct variable *} dict_lookup_var (const struct dictionary *@var{dict}, const char *@var{name}) @deftypefunx {struct variable *} dict_lookup_var_assert (const struct dictionary *@var{dict}, const char *@var{name}) Looks up and returns the variable with the given @var{name} within @var{dict}. Name lookup is not case-sensitive. @code{dict_lookup_var} returns a null pointer if @var{dict} does not contain a variable named @var{name}. @code{dict_lookup_var_assert} asserts that such a variable exists. @end deftypefun @deftypefun {struct variable *} dict_get_var (const struct dictionary *@var{dict}, size_t @var{position}) Returns the variable at the given @var{position} in @var{dict}. @var{position} must be less than the number of variables in @var{dict} (see below). @end deftypefun @deftypefun size_t dict_get_var_cnt (const struct dictionary *@var{dict}) Returns the number of variables in @var{dict}. @end deftypefun Another pair of functions allows retrieving a number of variables at once. These functions are more rarely useful. @deftypefun void dict_get_vars (const struct dictionary *@var{dict}, const struct variable ***@var{vars}, size_t *@var{cnt}, enum dict_class @var{exclude}) @deftypefunx void dict_get_vars_mutable (const struct dictionary *@var{dict}, struct variable ***@var{vars}, size_t *@var{cnt}, enum dict_class @var{exclude}) Retrieves all of the variables in @var{dict}, in their original order, except that any variables in the dictionary classes specified @var{exclude}, if any, are excluded (@pxref{Dictionary Class}). Pointers to the variables are stored in an array allocated with @code{malloc}, and a pointer to the first element of this array is stored in @code{*@var{vars}}. The caller is responsible for freeing this memory when it is no longer needed. The number of variables retrieved is stored in @code{*@var{cnt}}. The presence or absence of @code{DC_SYSTEM} in @var{exclude} has no effect, because dictionaries never include system variables. @end deftypefun One additional function is available. This function is most often used in assertions, but it is not restricted to such use. @deftypefun bool dict_contains_var (const struct dictionary *@var{dict}, const struct variable *@var{var}) Tests whether @var{var} is one of the variables in @var{dict}. Returns true if so, false otherwise. @end deftypefun @node Dictionary Creating Variables @subsection Creating Variables These functions create a new variable and insert it into a dictionary in a single step. There is no provision for inserting an already created variable into a dictionary. There is no reason that such a function could not be written, but so far there has been no need for one. The names provided to one of these functions should be valid variable names and must be plausible variable names. @c (@pxref{Variable Names}). If a variable with the same name already exists in the dictionary, the non-@code{assert} variants of these functions return a null pointer, without modifying the dictionary. The @code{assert} variants, on the other hand, assert that no duplicate name exists. A variable may be in only one dictionary at any given time. @deftypefun {struct variable *} dict_create_var (struct dictionary *@var{dict}, const char *@var{name}, int @var{width}) @deftypefunx {struct variable *} dict_create_var_assert (struct dictionary *@var{dict}, const char *@var{name}, int @var{width}) Creates a new variable with the given @var{name} and @var{width}, as if through a call to @code{var_create} with those arguments (@pxref{var_create}), appends the new variable to @var{dict}'s array of variables, and returns the new variable. @end deftypefun @deftypefun {struct variable *} dict_clone_var (struct dictionary *@var{dict}, const struct variable *@var{old_var}) @deftypefunx {struct variable *} dict_clone_var_assert (struct dictionary *@var{dict}, const struct variable *@var{old_var}) Creates a new variable as a clone of @var{var}, inserts the new variable into @var{dict}, and returns the new variable. Other properties of the new variable are copied from @var{old_var}, except for those not copied by @code{var_clone} (@pxref{var_clone}). @var{var} does not need to be a member of any dictionary. @end deftypefun @deftypefun {struct variable *} dict_clone_var_as (struct dictionary *@var{dict}, const struct variable *@var{old_var}, const char *@var{name}) @deftypefunx {struct variable *} dict_clone_var_as_assert (struct dictionary *@var{dict}, const struct variable *@var{old_var}, const char *@var{name}) These functions are similar to @code{dict_clone_var} and @code{dict_clone_var_assert}, respectively, except that the new variable is named @var{name} instead of keeping @var{old_var}'s name. @end deftypefun @node Dictionary Deleting Variables @subsection Deleting Variables These functions remove variables from a dictionary's array of variables. They also destroy the removed variables and free their associated storage. Deleting a variable to which there might be external pointers is a bad idea. In particular, deleting variables from the active dataset dictionary is a risky proposition, because transformations can retain references to arbitrary variables. Therefore, no variable should be deleted from the active dataset dictionary when any transformations are active, because those transformations might reference the variable to be deleted. The safest time to delete a variable is just after a procedure has been executed, as done by @cmd{DELETE VARIABLES}. Deleting a variable automatically removes references to that variable from elsewhere in the dictionary as a weighting variable, filter variable, @cmd{SPLIT FILE} variable, or member of a vector. No functions are provided for removing a variable from a dictionary without destroying that variable. As with insertion of an existing variable, there is no reason that this could not be implemented, but so far there has been no need. @deftypefun void dict_delete_var (struct dictionary *@var{dict}, struct variable *@var{var}) Deletes @var{var} from @var{dict}, of which it must be a member. @end deftypefun @deftypefun void dict_delete_vars (struct dictionary *@var{dict}, struct variable *const *@var{vars}, size_t @var{count}) Deletes the @var{count} variables in array @var{vars} from @var{dict}. All of the variables in @var{vars} must be members of @var{dict}. No variable may be included in @var{vars} more than once. @end deftypefun @deftypefun void dict_delete_consecutive_vars (struct dictionary *@var{dict}, size_t @var{idx}, size_t @var{count}) Deletes the variables in sequential positions @var{idx}@dots{}@var{idx} + @var{count} (exclusive) from @var{dict}, which must contain at least @var{idx} + @var{count} variables. @end deftypefun @deftypefun void dict_delete_scratch_vars (struct dictionary *@var{dict}) Deletes all scratch variables from @var{dict}. @end deftypefun @node Dictionary Reordering Variables @subsection Changing Variable Order The variables in a dictionary are stored in an array. These functions change the order of a dictionary's array of variables without changing which variables are in the dictionary. @anchor{dict_reorder_var} @deftypefun void dict_reorder_var (struct dictionary *@var{dict}, struct variable *@var{var}, size_t @var{new_index}) Moves @var{var}, which must be in @var{dict}, so that it is at position @var{new_index} in @var{dict}'s array of variables. Other variables in @var{dict}, if any, retain their relative positions. @var{new_index} must be less than the number of variables in @var{dict}. @end deftypefun @deftypefun void dict_reorder_vars (struct dictionary *@var{dict}, struct variable *const *@var{new_order}, size_t @var{count}) Moves the @var{count} variables in @var{new_order} to the beginning of @var{dict}'s array of variables in the specified order. Other variables in @var{dict}, if any, retain their relative positions. All of the variables in @var{new_order} must be in @var{dict}. No duplicates are allowed within @var{new_order}, which means that @var{count} must be no greater than the number of variables in @var{dict}. @end deftypefun @node Dictionary Renaming Variables @subsection Renaming Variables These functions change the names of variables within a dictionary. The @func{var_set_name} function (@pxref{var_set_name}) cannot be applied directly to a variable that is in a dictionary, because @struct{dictionary} contains an index by name that @func{var_set_name} would not update. The following functions take care to update the index as well. They also ensure that variable renaming does not cause a dictionary to contain a duplicate variable name. @deftypefun void dict_rename_var (struct dictionary *@var{dict}, struct variable *@var{var}, const char *@var{new_name}) Changes the name of @var{var}, which must be in @var{dict}, to @var{new_name}. A variable named @var{new_name} must not already be in @var{dict}, unless @var{new_name} is the same as @var{var}'s current name. @end deftypefun @deftypefun bool dict_rename_vars (struct dictionary *@var{dicT}, struct variable **@var{vars}, char **@var{new_names}, size_t @var{count}, char **@var{err_name}) Renames each of the @var{count} variables in @var{vars} to the name in the corresponding position of @var{new_names}. If the renaming would result in a duplicate variable name, returns false and stores one of the names that would be be duplicated into @code{*@var{err_name}}, if @var{err_name} is non-null. Otherwise, the renaming is successful, and true is returned. @end deftypefun @node Dictionary Weight Variable @subsection Weight Variable A data set's cases may optionally be weighted by the value of a numeric variable. @xref{WEIGHT,,,pspp, PSPP Users Guide}, for a user view of weight variables. The weight variable is written to and read from system and portable files. The most commonly useful function related to weighting is a convenience function to retrieve a weighting value from a case. @deftypefun double dict_get_case_weight (const struct dictionary *@var{dict}, const struct ccase *@var{case}, bool *@var{warn_on_invalid}) Retrieves and returns the value of the weighting variable specified by @var{dict} from @var{case}. Returns 1.0 if @var{dict} has no weighting variable. Returns 0.0 if @var{c}'s weight value is user- or system-missing, zero, or negative. In such a case, if @var{warn_on_invalid} is non-null and @code{*@var{warn_on_invalid}} is true, @func{dict_get_case_weight} also issues an error message and sets @code{*@var{warn_on_invalid}} to false. To disable error reporting, pass a null pointer or a pointer to false as @var{warn_on_invalid} or use a @func{msg_disable}/@func{msg_enable} pair. @end deftypefun The dictionary also has a pair of functions for getting and setting the weight variable. @deftypefun {struct variable *} dict_get_weight (const struct dictionary *@var{dict}) Returns @var{dict}'s current weighting variable, or a null pointer if the dictionary does not have a weighting variable. @end deftypefun @deftypefun void dict_set_weight (struct dictionary *@var{dict}, struct variable *@var{var}) Sets @var{dict}'s weighting variable to @var{var}. If @var{var} is non-null, it must be a numeric variable in @var{dict}. If @var{var} is null, then @var{dict}'s weighting variable, if any, is cleared. @end deftypefun @node Dictionary Filter Variable @subsection Filter Variable When the active dataset is read by a procedure, cases can be excluded from analysis based on the values of a @dfn{filter variable}. @xref{FILTER,,,pspp, PSPP Users Guide}, for a user view of filtering. These functions store and retrieve the filter variable. They are rarely useful, because the data analysis framework automatically excludes from analysis the cases that should be filtered. @deftypefun {struct variable *} dict_get_filter (const struct dictionary *@var{dict}) Returns @var{dict}'s current filter variable, or a null pointer if the dictionary does not have a filter variable. @end deftypefun @deftypefun void dict_set_filter (struct dictionary *@var{dict}, struct variable *@var{var}) Sets @var{dict}'s filter variable to @var{var}. If @var{var} is non-null, it must be a numeric variable in @var{dict}. If @var{var} is null, then @var{dict}'s filter variable, if any, is cleared. @end deftypefun @node Dictionary Case Limit @subsection Case Limit The limit on cases analyzed by a procedure, set by the @cmd{N OF CASES} command (@pxref{N OF CASES,,,pspp, PSPP Users Guide}), is stored as part of the dictionary. The dictionary does not, on the other hand, play any role in enforcing the case limit (a job done by data analysis framework code). A case limit of 0 means that the number of cases is not limited. These functions are rarely useful, because the data analysis framework automatically excludes from analysis any cases beyond the limit. @deftypefun casenumber dict_get_case_limit (const struct dictionary *@var{dict}) Returns the current case limit for @var{dict}. @end deftypefun @deftypefun void dict_set_case_limit (struct dictionary *@var{dict}, casenumber @var{limit}) Sets @var{dict}'s case limit to @var{limit}. @end deftypefun @node Dictionary Split Variables @subsection Split Variables The user may use the @cmd{SPLIT FILE} command (@pxref{SPLIT FILE,,,pspp, PSPP Users Guide}) to select a set of variables on which to split the active dataset into groups of cases to be analyzed independently in each statistical procedure. The set of split variables is stored as part of the dictionary, although the effect on data analysis is implemented by each individual statistical procedure. Split variables may be numeric or short or long string variables. The most useful functions for split variables are those to retrieve them. Even these functions are rarely useful directly: for the purpose of breaking cases into groups based on the values of the split variables, it is usually easier to use @func{casegrouper_create_splits}. @deftypefun {const struct variable *const *} dict_get_split_vars (const struct dictionary *@var{dict}) Returns a pointer to an array of pointers to split variables. If and only if there are no split variables, returns a null pointer. The caller must not modify or free the returned array. @end deftypefun @deftypefun size_t dict_get_split_cnt (const struct dictionary *@var{dict}) Returns the number of split variables. @end deftypefun The following functions are also available for working with split variables. @deftypefun void dict_set_split_vars (struct dictionary *@var{dict}, struct variable *const *@var{vars}, size_t @var{cnt}) Sets @var{dict}'s split variables to the @var{cnt} variables in @var{vars}. If @var{cnt} is 0, then @var{dict} will not have any split variables. The caller retains ownership of @var{vars}. @end deftypefun @deftypefun void dict_unset_split_var (struct dictionary *@var{dict}, struct variable *@var{var}) Removes @var{var}, which must be a variable in @var{dict}, from @var{dict}'s split of split variables. @end deftypefun @node Dictionary File Label @subsection File Label A dictionary may optionally have an associated string that describes its contents, called its file label. The user may set the file label with the @cmd{FILE LABEL} command (@pxref{FILE LABEL,,,pspp, PSPP Users Guide}). These functions set and retrieve the file label. @deftypefun {const char *} dict_get_label (const struct dictionary *@var{dict}) Returns @var{dict}'s file label. If @var{dict} does not have a label, returns a null pointer. @end deftypefun @deftypefun void dict_set_label (struct dictionary *@var{dict}, const char *@var{label}) Sets @var{dict}'s label to @var{label}. If @var{label} is non-null, then its content, truncated to at most 60 bytes, becomes the new file label. If @var{label} is null, then @var{dict}'s label is removed. The caller retains ownership of @var{label}. @end deftypefun @node Dictionary Documents @subsection Documents A dictionary may include an arbitrary number of lines of explanatory text, called the dictionary's documents. For compatibility, document lines have a fixed width, and lines that are not exactly this width are truncated or padded with spaces as necessary to bring them to the correct width. PSPP users can use the @cmd{DOCUMENT} (@pxref{DOCUMENT,,,pspp, PSPP Users Guide}), @cmd{ADD DOCUMENT} (@pxref{ADD DOCUMENT,,,pspp, PSPP Users Guide}), and @cmd{DROP DOCUMENTS} (@pxref{DROP DOCUMENTS,,,pspp, PSPP Users Guide}) commands to manipulate documents. @deftypefn Macro int DOC_LINE_LENGTH The fixed length of a document line, in bytes, defined to 80. @end deftypefn The following functions work with whole sets of documents. They accept or return sets of documents formatted as null-terminated strings that are an exact multiple of @code{DOC_LINE_LENGTH} bytes in length. @deftypefun {const char *} dict_get_documents (const struct dictionary *@var{dict}) Returns the documents in @var{dict}, or a null pointer if @var{dict} has no documents. @end deftypefun @deftypefun void dict_set_documents (struct dictionary *@var{dict}, const char *@var{new_documents}) Sets @var{dict}'s documents to @var{new_documents}. If @var{new_documents} is a null pointer or an empty string, then @var{dict}'s documents are cleared. The caller retains ownership of @var{new_documents}. @end deftypefun @deftypefun void dict_clear_documents (struct dictionary *@var{dict}) Clears the documents from @var{dict}. @end deftypefun The following functions work with individual lines in a dictionary's set of documents. @deftypefun void dict_add_document_line (struct dictionary *@var{dict}, const char *@var{content}) Appends @var{content} to the documents in @var{dict}. The text in @var{content} will be truncated or padded with spaces as necessary to make it exactly @code{DOC_LINE_LENGTH} bytes long. The caller retains ownership of @var{content}. If @var{content} is over @code{DOC_LINE_LENGTH}, this function also issues a warning using @func{msg}. To suppress the warning, enclose a call to one of this function in a @func{msg_disable}/@func{msg_enable} pair. @end deftypefun @deftypefun size_t dict_get_document_line_cnt (const struct dictionary *@var{dict}) Returns the number of line of documents in @var{dict}. If the dictionary contains no documents, returns 0. @end deftypefun @deftypefun void dict_get_document_line (const struct dictionary *@var{dict}, size_t @var{idx}, struct string *@var{content}) Replaces the text in @var{content} (which must already have been initialized by the caller) by the document line in @var{dict} numbered @var{idx}, which must be less than the number of lines of documents in @var{dict}. Any trailing white space in the document line is trimmed, so that @var{content} will have a length between 0 and @code{DOC_LINE_LENGTH}. @end deftypefun @node Coding Conventions @section Coding Conventions Every @file{.c} file should have @samp{#include } as its first non-comment line. No @file{.h} file should include @file{config.h}. This section needs to be finished. @node Cases @section Cases This section needs to be written. @node Data Sets @section Data Sets This section needs to be written. @node Pools @section Pools This section needs to be written. @c LocalWords: bool pspp-master/doc/dev/data.texi000066400000000000000000000022471177044323000164660ustar00rootroot00000000000000@node Processing Data @chapter Processing Data Developer's Guide Proposed outline: @example * Introduction * Basic concepts ** Data sets ** Variables ** Dictionaries ** Coding conventions ** Pools * Syntax parsing * Data processing ** Reading data *** Casereaders generalities *** Casereaders from data files *** Casereaders from the active dataset *** Other casereaders ** Writing data *** Casewriters generally *** Casewriters to data files *** Modifying the active dataset **** Modifying cases obtained from active dataset casereaders has no real effect **** Transformations; procedures that transform ** Transforming data *** Sorting and merging *** Filtering *** Grouping **** Ordering and interaction of filtering and grouping *** Multiple passes over data *** Counting cases and case weights ** Best practices *** Multiple passes with filters versus single pass with loops *** Sequential versus random access *** Managing memory *** Passing cases around *** Renaming casereaders *** Avoiding excessive buffering *** Propagating errors *** Avoid static/global data *** Don't worry about null filters, groups, etc. *** Be aware of reference counting semantics for cases @end example pspp-master/doc/dev/i18n.texi000066400000000000000000000134741177044323000163400ustar00rootroot00000000000000@node Internationalisation @chapter Internationalisation Internationalisation in pspp is complicated. The most annoying aspect is that of character-encoding. This chapter attempts to describe the problems and current ways in which they are addressed. @section The working locales Pspp has three ``working'' locales: @itemize @item The locale of the user interface. @item The locale of the output. @item The locale of the data. Only the character encoding is relevant. @end itemize Each of these locales may, at different times take separate (or identical) values. So for example, a French statistician can use pspp to prepare a report in the English language, using a datafile which has been created by a Japanese researcher hence uses a Japanese character set. It's rarely, if ever, necessary to interrogate the system to find out the values of the 3 locales. However it's important to be aware of the source (destination) locale when reading (writing) string data. When transfering data between a source and a destination, the appropriate recoding must be performed. @subsection The user interface locale This is the locale which is visible to the person using pspp. Error messages and confidence indications are written in this locale. For example ``Cannot open file'' will be written in the user interface locale. This locale is set from the environment of the user who starts pspp@{ire@} or from the system locale if not set. @subsection The output locale This locale is the one that should be visible to the person reading a report generated by pspp. Non-data related strings (Eg: ``Page number'', ``Standard Deviation'' etc.) will appear in this locale. @subsection The data locale This locale is the one associated with the data being analysed with pspp. The only important aspect of this locale is the character encoding. @footnote {It might also be desirable for the LC_COLLATE category to be used for the purposes of sorting data.} The dictionary pertaining to the data contains a field denoting the encoding. Any string data stored in a @union{value} will be encoded in the dictionary's character set. @section System files @file{*.sav} files contain a field which is supposed to identify the encoding of the data they contain (@pxref{Machine Integer Info Record}). However, many files produced by early versions of spss set this to ``2'' (ASCII) regardless of the encoding of the data. Later versions contain an additional record (@pxref{Character Encoding Record}) describing the encoding. When a system file is read, the dictionary's encoding is set using information gleened from the system file. If the encoding cannot be determined or would be unreliable, then it remains unset. @section GUI The psppire graphic user interface is written using the Gtk+ api, for which all strings must be encoded in UTF8. All strings passed to the GTK+/GLib library functions (except for filenames) must be UTF-8 encoded otherwise errors will occur. Thus, for the purposes of the programming psppire, the user interface locale should be assumed to be UTF8, even if setlocale and/or nl_langinfo indicates otherwise. @subsection Filenames The GLib API has some special functions for dealing with filenames. Strings returned from functions like gtk_file_chooser_dialog_get_name are not, in general, encoded in UTF8, but in ``filename'' encoding. If that filename is passed to another GLib function which expects a filename, no conversion is necessary. If it's passed to a function for the purposes of displaying it (eg. in a window's title-bar) it must be converted to UTF8 --- there is a special function for this: g_filename_display_name or g_filename_basename. If however, a filename needs to be passed outside of GTK+/GLib (for example to fopen) it must be converted to the local system encoding. @section Existing locale handling functions The major aspect of locale handling which the programmer has to consider is that of character encoding. The following function is used to recode strings: @deftypefun char * recode_string (const char *@var{to}, const char *@var{from}, const char *@var{text}, int @var{len}); Converts the string @var{text}, which is encoded in @var{from} to a new string encoded in @var{to} encoding. If @var{len} is not -1, then it must be the number of bytes in @var{text}. It is the caller's responsibility to free the returned string when no longer required. @end deftypefun In order to minimise the number of conversions required, and to simplify design, PSPP attempts to store all internal strings in UTF8 encoding. Thus, when reading system and portable files (or any other data source), the following items are immediately converted to UTF8 encoding: @itemize @item Variable names @item Variable labels @item Value labels @end itemize Conversely, when writing system files, these are converted back to the encoding of that system file. String data stored in union values are left in their original encoding. These will be converted by the data_in/data_out functions. @section Quirks For historical reasons, not all locale handling follows posix conventions. This makes it difficult (impossible?) to elegantly handle the issues. For example, it would make sense for the gui's datasheet to display numbers formatted according to the LC_NUMERIC category of the data locale. Instead however there is the @func{data_out} function (@pxref{Obtaining Properties of Format Types}) which uses the @func{settings_get_decimal_char} function instead of the decimal separator of the locale. Similarly, formatting of monetary values is displayed in a pspp/spss specific fashion instead of using the LC_MONETARY category. @c LocalWords: pspp itemize Eg LC Spss cmd sav pxref spss GUI psppire Gtk api @c LocalWords: UTF gtk setlocale nl langinfo deftypefun enum conv var const @c LocalWords: int len gui struct val utf GtkWidget posix gui's datasheet @c LocalWords: func pspp-master/doc/dev/intro.texi000066400000000000000000000021371177044323000167060ustar00rootroot00000000000000@node Introduction @chapter Introduction This manual is a guide to PSPP internals. Its intended audience is developers who wish to modify or extend PSPP's capabilities. The use of PSPP is documented in a separate manual. @xref{Top, , Introduction, pspp, PSPP Users Guide}. This manual is both a tutorial and a reference manual for PSPP developers. It is ultimately intended to cover everything that developers who wish to implement new PSPP statistical procedures and other commands should know. It is currently incomplete, partly because existing developers have not yet spent enough time on writing, and partly because the interfaces not yet documented are not yet mature enough to making documenting them worthwhile. PSPP developers should have some familiarity with the basics of PSPP from a user's perspective. This manual attempts to refer to the PSPP user manual's descriptions of concepts that PSPP users should find familiar at the time of their first reference. However, it is probably a good idea to at least skim the PSPP manual before reading this one, if you are not already familiar with PSPP. pspp-master/doc/dev/output.texi000066400000000000000000000000631177044323000171070ustar00rootroot00000000000000@node Presenting Output @chapter Presenting Output pspp-master/doc/dev/portable-file-format.texi000066400000000000000000000304121177044323000215630ustar00rootroot00000000000000@node Portable File Format @appendix Portable File Format These days, most computers use the same internal data formats for integer and floating-point data, if one ignores little differences like big- versus little-endian byte ordering. However, occasionally it is necessary to exchange data between systems with incompatible data formats. This is what portable files are designed to do. @strong{Please note:} This information is gleaned from examination of ASCII-formatted portable files only, so some of it may be incorrect for portable files formatted in EBCDIC or other character sets. @menu * Portable File Characters:: * Portable File Structure:: * Portable File Header:: * Version and Date Info Record:: * Identification Records:: * Variable Count Record:: * Case Weight Variable Record:: * Variable Records:: * Value Label Records:: * Portable File Document Record:: * Portable File Data:: @end menu @node Portable File Characters @section Portable File Characters Portable files are arranged as a series of lines of 80 characters each. Each line is terminated by a carriage-return, line-feed sequence (``new-lines''). New-lines are only used to avoid line length limits imposed by some OSes; they are not meaningful. Most lines in portable files are exactly 80 characters long. The only exception is a line that ends in one or more spaces, in which the spaces may optionally be omitted. Thus, a portable file reader must act as though a line shorter than 80 characters is padded to that length with spaces. The file must be terminated with a @samp{Z} character. In addition, if the final line in the file does not have exactly 80 characters, then it is padded on the right with @samp{Z} characters. (The file contents may be in any character set; the file contains a description of its own character set, as explained in the next section. Therefore, the @samp{Z} character is not necessarily an ASCII @samp{Z}.) For the rest of the description of the portable file format, new-lines and the trailing @samp{Z}s will be ignored, as if they did not exist, because they are not an important part of understanding the file contents. @node Portable File Structure @section Portable File Structure Every portable file consists of the following records, in sequence: @itemize @bullet @item File header. @item Version and date info. @item Product identification. @item Author identification (optional). @item Subproduct identification (optional). @item Variable count. @item Case weight variable (optional). @item Variables. Each variable record may optionally be followed by a missing value record and a variable label record. @item Value labels (optional). @item Documents (optional). @item Data. @end itemize Most records are identified by a single-character tag code. The file header and version info record do not have a tag. Other than these single-character codes, there are three types of fields in a portable file: floating-point, integer, and string. Floating-point fields have the following format: @itemize @bullet @item Zero or more leading spaces. @item Optional asterisk (@samp{*}), which indicates a missing value. The asterisk must be followed by a single character, generally a period (@samp{.}), but it appears that other characters may also be possible. This completes the specification of a missing value. @item Optional minus sign (@samp{-}) to indicate a negative number. @item A whole number, consisting of one or more base-30 digits: @samp{0} through @samp{9} plus capital letters @samp{A} through @samp{T}. @item Optional fraction, consisting of a radix point (@samp{.}) followed by one or more base-30 digits. @item Optional exponent, consisting of a plus or minus sign (@samp{+} or @samp{-}) followed by one or more base-30 digits. @item A forward slash (@samp{/}). @end itemize Integer fields take a form identical to floating-point fields, but they may not contain a fraction. String fields take the form of a integer field having value @var{n}, followed by exactly @var{n} characters, which are the string content. @node Portable File Header @section Portable File Header Every portable file begins with a 464-byte header, consisting of a 200-byte collection of vanity splash strings, followed by a 256-byte character set translation table, followed by an 8-byte tag string. The 200-byte segment is divided into five 40-byte sections, each of which represents the string @code{@var{charset} SPSS PORT FILE} in a different character set encoding, where @var{charset} is the name of the character set used in the file, e.g.@: @code{ASCII} or @code{EBCDIC}. Each string is padded on the right with spaces in its respective character set. It appears that these strings exist only to inform those who might view the file on a screen, and that they are not parsed by SPSS products. Thus, they can be safely ignored. For those interested, the strings are supposed to be in the following character sets, in the specified order: EBCDIC, 7-bit ASCII, CDC 6-bit ASCII, 6-bit ASCII, Honeywell 6-bit ASCII. The 256-byte segment describes a mapping from the character set used in the portable file to an arbitrary character set having characters at the following positions: @table @asis @item 0--60 Control characters. Not important enough to describe in full here. @item 61--63 Reserved. @item 64--73 Digits @samp{0} through @samp{9}. @item 74--99 Capital letters @samp{A} through @samp{Z}. @item 100--125 Lowercase letters @samp{a} through @samp{z}. @item 126 Space. @item 127--130 Symbols @code{.<(+} @item 131 Solid vertical pipe. @item 132--142 Symbols @code{&[]!$*);^-/} @item 143 Broken vertical pipe. @item 144--150 Symbols @code{,%_>}?@code{`:} @c @code{?} is an inverted question mark @item 151 British pound symbol. @item 152--155 Symbols @code{@@'="}. @item 156 Less than or equal symbol. @item 157 Empty box. @item 158 Plus or minus. @item 159 Filled box. @item 160 Degree symbol. @item 161 Dagger. @item 162 Symbol @samp{~}. @item 163 En dash. @item 164 Lower left corner box draw. @item 165 Upper left corner box draw. @item 166 Greater than or equal symbol. @item 167--176 Superscript @samp{0} through @samp{9}. @item 177 Lower right corner box draw. @item 178 Upper right corner box draw. @item 179 Not equal symbol. @item 180 Em dash. @item 181 Superscript @samp{(}. @item 182 Superscript @samp{)}. @item 183 Horizontal dagger (?). @item 184--186 Symbols @samp{@{@}\}. @item 187 Cents symbol. @item 188 Centered dot, or bullet. @item 189--255 Reserved. @end table Symbols that are not defined in a particular character set are set to the same value as symbol 64; i.e., to @samp{0}. The 8-byte tag string consists of the exact characters @code{SPSSPORT} in the portable file's character set, which can be used to verify that the file is indeed a portable file. @node Version and Date Info Record @section Version and Date Info Record This record does not have a tag code. It has the following structure: @itemize @bullet @item A single character identifying the file format version. The letter A represents version 0, and so on. @item An 8-character string field giving the file creation date in the format YYYYMMDD. @item A 6-character string field giving the file creation time in the format HHMMSS. @end itemize @node Identification Records @section Identification Records The product identification record has tag code @samp{1}. It consists of a single string field giving the name of the product that wrote the portable file. The author identification record has tag code @samp{2}. It is optional. If present, it consists of a single string field giving the name of the person who caused the portable file to be written. The subproduct identification record has tag code @samp{3}. It is optional. If present, it consists of a single string field giving additional information on the product that wrote the portable file. @node Variable Count Record @section Variable Count Record The variable count record has tag code @samp{4}. It consists of two integer fields. The first contains the number of variables in the file dictionary. The purpose of the second is unknown; it contains the value 161 in all portable files examined so far. @node Case Weight Variable Record @section Case Weight Variable Record The case weight variable record is optional. If it is present, it indicates the variable used for weighting cases; if it is absent, cases are unweighted. It has tag code @samp{6}. It consists of a single string field that names the weighting variable. @node Variable Records @section Variable Records Each variable record represents a single variable. Variable records have tag code @samp{7}. They have the following structure: @itemize @bullet @item Width (integer). This is 0 for a numeric variable, and a number between 1 and 255 for a string variable. @item Name (string). 1--8 characters long. Must be in all capitals. A few portable files that contain duplicate variable names have been spotted in the wild. PSPP handles these by renaming the duplicates with numeric extensions: @code{@var{var}_1}, @code{@var{var}_2}, and so on. @item Print format. This is a set of three integer fields: @itemize @minus @item Format type (@pxref{Variable Record}). @item Format width. 1--40. @item Number of decimal places. 1--40. @end itemize A few portable files with invalid format types or formats that are not of the appropriate width for their variables have been spotted in the wild. PSPP assigns a default F or A format to a variable with an invalid format. @item Write format. Same structure as the print format described above. @end itemize Each variable record can optionally be followed by a missing value record, which has tag code @samp{8}. A missing value record has one field, the missing value itself (a floating-point or string, as appropriate). Up to three of these missing value records can be used. There is also a record for missing value ranges, which has tag code @samp{B}. It is followed by two fields representing the range, which are floating-point or string as appropriate. If a missing value range is present, it may be followed by a single missing value record. Tag codes @samp{9} and @samp{A} represent @code{LO THRU @var{x}} and @code{@var{x} THRU HI} ranges, respectively. Each is followed by a single field representing @var{x}. If one of the ranges is present, it may be followed by a single missing value record. In addition, each variable record can optionally be followed by a variable label record, which has tag code @samp{C}. A variable label record has one field, the variable label itself (string). @node Value Label Records @section Value Label Records Value label records have tag code @samp{D}. They have the following format: @itemize @bullet @item Variable count (integer). @item List of variables (strings). The variable count specifies the number in the list. Variables are specified by their names. All variables must be of the same type (numeric or string), but string variables do not necessarily have the same width. @item Label count (integer). @item List of (value, label) tuples. The label count specifies the number of tuples. Each tuple consists of a value, which is numeric or string as appropriate to the variables, followed by a label (string). @end itemize A few portable files that specify duplicate value labels, that is, two different labels for a single value of a single variable, have been spotted in the wild. PSPP uses the last value label specified in these cases. @node Portable File Document Record @section Document Record One document record may optionally follow the value label record. The document record consists of tag code @samp{E}, following by the number of document lines as an integer, followed by that number of strings, each of which represents one document line. Document lines must be 80 bytes long or shorter. @node Portable File Data @section Portable File Data The data record has tag code @samp{F}. There is only one tag for all the data; thus, all the data must follow the dictionary. The data is terminated by the end-of-file marker @samp{Z}, which is not valid as the beginning of a data element. Data elements are output in the same order as the variable records describing them. String variables are output as string fields, and numeric variables are output as floating-point fields. @setfilename ignored pspp-master/doc/dev/q2c.texi000066400000000000000000000224631177044323000162440ustar00rootroot00000000000000@node q2c Input Format @appendix @code{q2c} Input Format PSPP statistical procedures have a bizarre and somewhat irregular syntax. Despite this, a parser generator has been written that adequately addresses many of the possibilities and tries to provide hooks for the exceptional cases. This parser generator is named @code{q2c}. @menu * Invoking q2c:: q2c command-line syntax. * q2c Input Structure:: High-level layout of the input file. * Grammar Rules:: Syntax of the grammar rules. @end menu @node Invoking q2c @section Invoking q2c @example q2c @var{input.q} @var{output.c} @end example @code{q2c} translates a @samp{.q} file into a @samp{.c} file. It takes exactly two command-line arguments, which are the input file name and output file name, respectively. @code{q2c} does not accept any command-line options. @node q2c Input Structure @section @code{q2c} Input Structure @code{q2c} input files are divided into two sections: the grammar rules and the supporting code. The @dfn{grammar rules}, which make up the first part of the input, are used to define the syntax of the statistical procedure to be parsed. The @dfn{supporting code}, following the grammar rules, are copied largely unchanged to the output file, except for certain escapes. The most important lines in the grammar rules are used for defining procedure syntax. These lines can be prefixed with a dollar sign (@samp{$}), which prevents Emacs' CC-mode from munging them. Besides this, a bang (@samp{!}) at the beginning of a line causes the line, minus the bang, to be written verbatim to the output file (useful for comments). As a third special case, any line that begins with the exact characters @code{/* *INDENT} is ignored and not written to the output. This allows @code{.q} files to be processed through @code{indent} without being munged. The syntax of the grammar rules themselves is given in the following sections. The supporting code is passed into the output file largely unchanged. However, the following escapes are supported. Each escape must appear on a line by itself. @table @code @item /* (header) */ Expands to a series of C @code{#include} directives which include the headers that are required for the parser generated by @code{q2c}. @item /* (decls @var{scope}) */ Expands to C variable and data type declarations for the variables and @code{enum}s input and output by the @code{q2c} parser. @var{scope} must be either @code{local} or @code{global}. @code{local} causes the declarations to be output as function locals. @code{global} causes them to be declared as @code{static} module variables; thus, @code{global} is a bit of a misnomer. @item /* (parser) */ Expands to the entire parser. Must be enclosed within a C function. @item /* (free) */ Expands to a set of calls to the @code{free} function for variables declared by the parser. Only needs to be invoked if subcommands of type @code{string} are used in the grammar rules. @end table @node Grammar Rules @section Grammar Rules The grammar rules describe the format of the syntax that the parser generated by @code{q2c} will understand. The way that the grammar rules are included in @code{q2c} input file are described above. The grammar rules are divided into tokens of the following types: @table @asis @item Identifier (@code{ID}) An identifier token is a sequence of letters, digits, and underscores (@samp{_}). Identifiers are @emph{not} case-sensitive. @item String (@code{STRING}) String tokens are initiated by a double-quote character (@samp{"}) and consist of all the characters between that double quote and the next double quote, which must be on the same line as the first. Within a string, a backslash can be used as a ``literal escape''. The only reasons to use a literal escape are to include a double quote or a backslash within a string. @item Special character Other characters, other than white space, constitute tokens in themselves. @end table The syntax of the grammar rules is as follows: @example grammar-rules ::= command-name opt-prefix : subcommands . command-name ::= ID ::= STRING opt-prefix ::= ::= ( ID ) subcommands ::= subcommand ::= subcommands ; subcommand @end example The syntax begins with an ID token that gives the name of the procedure to be parsed. For command names that contain multiple words, a STRING token may be used instead, e.g.@: @samp{"FILE HANDLE"}. Optionally, an ID in parentheses specifies a prefix used for all file-scope identifiers declared by the emitted code. The rest of the syntax consists of subcommands separated by semicolons (@samp{;}) and terminated with a full stop (@samp{.}). @example subcommand ::= default-opt arity-opt ID sbc-defn default-opt ::= ::= * arity-opt ::= ::= + ::= ^ sbc-defn ::= opt-prefix = specifiers ::= [ ID ] = array-sbc ::= opt-prefix = sbc-special-form @end example A subcommand that begins with an asterisk (@samp{*}) is the default subcommand. The keyword used for the default subcommand can be omitted in the PSPP syntax file. A plus sign (@samp{+}) indicates that a subcommand can appear more than once. A caret (@samp{^}) indicate that a subcommand must appear exactly once. A subcommand marked with neither character may appear once or not at all, but not more than once. The subcommand name appears after the leading option characters. There are three forms of subcommands. The first and most common form simply gives an equals sign (@samp{=}) and a list of specifiers, which can each be set to a single setting. The second form declares an array, which is a set of flags that can be individually turned on by the user. There are also several special forms that do not take a list of specifiers. Arrays require an additional @code{ID} argument. This is used as a prefix, prepended to the variable names constructed from the specifiers. The other forms also allow an optional prefix to be specified. @example array-sbc ::= alternatives ::= array-sbc , alternatives alternatives ::= ID ::= alternatives | ID @end example An array subcommand is a set of Boolean values that can independently be turned on by the user, listed separated by commas (@samp{,}). If an value has more than one name then these names are separated by pipes (@samp{|}). @example specifiers ::= specifier ::= specifiers , specifier specifier ::= opt-id : settings opt-id ::= ::= ID @end example Ordinary subcommands (other than arrays and special forms) require a list of specifiers. Each specifier has an optional name and a list of settings. If the name is given then a correspondingly named variable will be used to store the user's choice of setting. If no name is given then there is no way to tell which setting the user picked; in this case the settings should probably have values attached. @example settings ::= setting ::= settings / setting setting ::= setting-options ID setting-value setting-options ::= ::= * ::= ! ::= * ! @end example Individual settings are separated by forward slashes (@samp{/}). Each setting can be as little as an @code{ID} token, but options and values can optionally be included. The @samp{*} option means that, for this setting, the @code{ID} can be omitted. The @samp{!} option means that this option is the default for its specifier. @example setting-value ::= ::= ( setting-value-2 ) ::= setting-value-2 setting-value-2 ::= setting-value-options setting-value-type : ID setting-value-options ::= ::= * setting-value-type ::= N ::= D ::= S @end example Settings may have values. If the value must be enclosed in parentheses, then enclose the value declaration in parentheses. Declare the setting type as @samp{n}, @samp{d}, or @samp{s} for integer, floating-point, or string type, respectively. The given @code{ID} is used to construct a variable name. If option @samp{*} is given, then the value is optional; otherwise it must be specified whenever the corresponding setting is specified. @example sbc-special-form ::= VAR ::= VARLIST varlist-options ::= INTEGER opt-list ::= DOUBLE opt-list ::= PINT ::= STRING @r{(the literal word STRING)} ::= CUSTOM varlist-options ::= ::= ( STRING ) opt-list ::= ::= LIST @end example The special forms are of the following types: @table @code @item VAR A single variable name. @item VARLIST A list of variables. If given, the string can be used to provide @code{PV_@var{*}} options to the call to @code{parse_variables}. @item INTEGER A single integer value. @item INTEGER LIST A list of integers separated by spaces or commas. @item DOUBLE A single floating-point value. @item DOUBLE LIST A list of floating-point values. @item PINT A single positive integer value. @item STRING A string value. @item CUSTOM A custom function is used to parse this subcommand. The function must have prototype @code{int custom_@var{name} (void)}. It should return 0 on failure (when it has already issued an appropriate diagnostic), 1 on success, or 2 if it fails and the calling function should issue a syntax error on behalf of the custom handler. @end table @setfilename ignored pspp-master/doc/dev/syntax.texi000066400000000000000000000000751177044323000171000ustar00rootroot00000000000000@node Parsing Command Syntax @chapter Parsing Command Syntax pspp-master/doc/dev/system-file-format.texi000066400000000000000000001211131177044323000212760ustar00rootroot00000000000000@node System File Format @appendix System File Format A system file encapsulates a set of cases and dictionary information that describes how they may be interpreted. This chapter describes the format of a system file. System files use four data types: 8-bit characters, 32-bit integers, 64-bit integers, and 64-bit floating points, called here @code{char}, @code{int32}, @code{int64}, and @code{flt64}, respectively. Data is not necessarily aligned on a word or double-word boundary: the long variable name record (@pxref{Long Variable Names Record}) and very long string records (@pxref{Very Long String Record}) have arbitrary byte length and can therefore cause all data coming after them in the file to be misaligned. Integer data in system files may be big-endian or little-endian. A reader may detect the endianness of a system file by examining @code{layout_code} in the file header record (@pxref{layout_code,,@code{layout_code}}). Floating-point data in system files may nominally be in IEEE 754, IBM, or VAX formats. A reader may detect the floating-point format in use by examining @code{bias} in the file header record (@pxref{bias,,@code{bias}}). PSPP detects big-endian and little-endian integer formats in system files and translates as necessary. PSPP also detects the floating-point format in use, as well as the endianness of IEEE 754 floating-point numbers, and translates as needed. However, only IEEE 754 numbers with the same endianness as integer data in the same file has actually been observed in system files, and it is likely that other formats are obsolete or were never used. The PSPP system-missing value is represented by the largest possible negative number in the floating point format (@code{-DBL_MAX}). Two other values are important for use as missing values: @code{HIGHEST}, represented by the largest possible positive number (@code{DBL_MAX}), and @code{LOWEST}, represented by the second-largest negative number (in IEEE 754 format, @code{0xffeffffffffffffe}). System files are divided into records, each of which begins with a 4-byte record type, usually regarded as an @code{int32}. The records must appear in the following order: @itemize @bullet @item File header record. @item Variable records. @item All pairs of value labels records and value label variables records, if present. @item Document record, if present. @item Extension (type 7) records, in ascending numerical order of their subtypes. @item Dictionary termination record. @item Data record. @end itemize Each type of record is described separately below. @menu * File Header Record:: * Variable Record:: * Value Labels Records:: * Document Record:: * Machine Integer Info Record:: * Machine Floating-Point Info Record:: * Multiple Response Sets Records:: * Variable Display Parameter Record:: * Long Variable Names Record:: * Very Long String Record:: * Character Encoding Record:: * Long String Value Labels Record:: * Data File and Variable Attributes Records:: * Extended Number of Cases Record:: * Miscellaneous Informational Records:: * Dictionary Termination Record:: * Data Record:: @end menu @node File Header Record @section File Header Record The file header is always the first record in the file. It has the following format: @example char rec_type[4]; char prod_name[60]; int32 layout_code; int32 nominal_case_size; int32 compressed; int32 weight_index; int32 ncases; flt64 bias; char creation_date[9]; char creation_time[8]; char file_label[64]; char padding[3]; @end example @table @code @item char rec_type[4]; Record type code, set to @samp{$FL2}, that is, either @code{24 46 4c 32} if the file uses an ASCII-based character encoding, or @code{5b c6 d3 f2} if the file uses an EBCDIC-based character encoding. @item char prod_name[60]; Product identification string. This always begins with the characters @samp{@@(#) SPSS DATA FILE}. PSPP uses the remaining characters to give its version and the operating system name; for example, @samp{GNU pspp 0.1.4 - sparc-sun-solaris2.5.2}. The string is truncated if it would be longer than 60 characters; otherwise it is padded on the right with spaces. @anchor{layout_code} @item int32 layout_code; Normally set to 2, although a few system files have been spotted in the wild with a value of 3 here. PSPP use this value to determine the file's integer endianness (@pxref{System File Format}). @item int32 nominal_case_size; Number of data elements per case. This is the number of variables, except that long string variables add extra data elements (one for every 8 characters after the first 8). However, string variables do not contribute to this value beyond the first 255 bytes. Further, system files written by some systems set this value to -1. In general, it is unsafe for systems reading system files to rely upon this value. @item int32 compressed; Set to 1 if the data in the file is compressed, 0 otherwise. @item int32 weight_index; If one of the variables in the data set is used as a weighting variable, set to the dictionary index of that variable, plus 1 (@pxref{Dictionary Index}). Otherwise, set to 0. @item int32 ncases; Set to the number of cases in the file if it is known, or -1 otherwise. In the general case it is not possible to determine the number of cases that will be output to a system file at the time that the header is written. The way that this is dealt with is by writing the entire system file, including the header, then seeking back to the beginning of the file and writing just the @code{ncases} field. For files in which this is not valid, the seek operation fails. In this case, @code{ncases} remains -1. @anchor{bias} @item flt64 bias; Compression bias, ordinarily set to 100. Only integers between @code{1 - bias} and @code{251 - bias} can be compressed. By assuming that its value is 100, PSPP uses @code{bias} to determine the file's floating-point format and endianness (@pxref{System File Format}). If the compression bias is not 100, PSPP cannot auto-detect the floating-point format and assumes that it is IEEE 754 format with the same endianness as the system file's integers, which is correct for all known system files. @item char creation_date[9]; Date of creation of the system file, in @samp{dd mmm yy} format, with the month as standard English abbreviations, using an initial capital letter and following with lowercase. If the date is not available then this field is arbitrarily set to @samp{01 Jan 70}. @item char creation_time[8]; Time of creation of the system file, in @samp{hh:mm:ss} format and using 24-hour time. If the time is not available then this field is arbitrarily set to @samp{00:00:00}. @item char file_label[64]; File label declared by the user, if any (@pxref{FILE LABEL,,,pspp, PSPP Users Guide}). Padded on the right with spaces. @item char padding[3]; Ignored padding bytes to make the structure a multiple of 32 bits in length. Set to zeros. @end table @node Variable Record @section Variable Record There must be one variable record for each numeric variable and each string variable with width 8 bytes or less. String variables wider than 8 bytes have one variable record for each 8 bytes, rounding up. The first variable record for a long string specifies the variable's correct dictionary information. Subsequent variable records for a long string are filled with dummy information: a type of -1, no variable label or missing values, print and write formats that are ignored, and an empty string as name. A few system files have been encountered that include a variable label on dummy variable records, so readers should take care to parse dummy variable records in the same way as other variable records. @anchor{Dictionary Index} The @dfn{dictionary index} of a variable is its offset in the set of variable records, including dummy variable records for long string variables. The first variable record has a dictionary index of 0, the second has a dictionary index of 1, and so on. The system file format does not directly support string variables wider than 255 bytes. Such very long string variables are represented by a number of narrower string variables. @xref{Very Long String Record}, for details. @example int32 rec_type; int32 type; int32 has_var_label; int32 n_missing_values; int32 print; int32 write; char name[8]; /* @r{Present only if @code{has_var_label} is 1.} */ int32 label_len; char label[]; /* @r{Present only if @code{n_missing_values} is nonzero}. */ flt64 missing_values[]; @end example @table @code @item int32 rec_type; Record type code. Always set to 2. @item int32 type; Variable type code. Set to 0 for a numeric variable. For a short string variable or the first part of a long string variable, this is set to the width of the string. For the second and subsequent parts of a long string variable, set to -1, and the remaining fields in the structure are ignored. @item int32 has_var_label; If this variable has a variable label, set to 1; otherwise, set to 0. @item int32 n_missing_values; If the variable has no missing values, set to 0. If the variable has one, two, or three discrete missing values, set to 1, 2, or 3, respectively. If the variable has a range for missing variables, set to -2; if the variable has a range for missing variables plus a single discrete value, set to -3. @item int32 print; Print format for this variable. See below. @item int32 write; Write format for this variable. See below. @item char name[8]; Variable name. The variable name must begin with a capital letter or the at-sign (@samp{@@}). Subsequent characters may also be digits, octothorpes (@samp{#}), dollar signs (@samp{$}), underscores (@samp{_}), or full stops (@samp{.}). The variable name is padded on the right with spaces. @item int32 label_len; This field is present only if @code{has_var_label} is set to 1. It is set to the length, in characters, of the variable label. The documented maximum length varies from 120 to 255 based on SPSS version, but some files have been seen with longer labels. PSPP accepts longer labels and truncates them to 255 bytes on input. @item char label[]; This field is present only if @code{has_var_label} is set to 1. It has length @code{label_len}, rounded up to the nearest multiple of 32 bits. The first @code{label_len} characters are the variable's variable label. @item flt64 missing_values[]; This field is present only if @code{n_missing_values} is nonzero. It has the same number of 8-byte elements as the absolute value of @code{n_missing_values}. Each element is interpreted as a number for numeric variables (with HIGHEST and LOWEST indicated as described in the chapter introduction). For string variables of width less than 8 bytes, elements are right-padded with spaces; for string variables wider than 8 bytes, only the first 8 bytes of each missing value are specified, with the remainder implicitly all spaces. For discrete missing values, each element represents one missing value. When a range is present, the first element denotes the minimum value in the range, and the second element denotes the maximum value in the range. When a range plus a value are present, the third element denotes the additional discrete missing value. @end table The @code{print} and @code{write} members of sysfile_variable are output formats coded into @code{int32} types. The least-significant byte of the @code{int32} represents the number of decimal places, and the next two bytes in order of increasing significance represent field width and format type, respectively. The most-significant byte is not used and should be set to zero. Format types are defined as follows: @quotation @multitable {Value} {@code{DATETIME}} @headitem Value @tab Meaning @item 0 @tab Not used. @item 1 @tab @code{A} @item 2 @tab @code{AHEX} @item 3 @tab @code{COMMA} @item 4 @tab @code{DOLLAR} @item 5 @tab @code{F} @item 6 @tab @code{IB} @item 7 @tab @code{PIBHEX} @item 8 @tab @code{P} @item 9 @tab @code{PIB} @item 10 @tab @code{PK} @item 11 @tab @code{RB} @item 12 @tab @code{RBHEX} @item 13 @tab Not used. @item 14 @tab Not used. @item 15 @tab @code{Z} @item 16 @tab @code{N} @item 17 @tab @code{E} @item 18 @tab Not used. @item 19 @tab Not used. @item 20 @tab @code{DATE} @item 21 @tab @code{TIME} @item 22 @tab @code{DATETIME} @item 23 @tab @code{ADATE} @item 24 @tab @code{JDATE} @item 25 @tab @code{DTIME} @item 26 @tab @code{WKDAY} @item 27 @tab @code{MONTH} @item 28 @tab @code{MOYR} @item 29 @tab @code{QYR} @item 30 @tab @code{WKYR} @item 31 @tab @code{PCT} @item 32 @tab @code{DOT} @item 33 @tab @code{CCA} @item 34 @tab @code{CCB} @item 35 @tab @code{CCC} @item 36 @tab @code{CCD} @item 37 @tab @code{CCE} @item 38 @tab @code{EDATE} @item 39 @tab @code{SDATE} @end multitable @end quotation A few system files have been observed in the wild with invalid @code{write} fields, in particular with value 0. Readers should probably treat invalid @code{print} or @code{write} fields as some default format. @node Value Labels Records @section Value Labels Records The value label records documented in this section are used for numeric and short string variables only. Long string variables may have value labels, but their value labels are recorded using a different record type (@pxref{Long String Value Labels Record}). The value label record has the following format: @example int32 rec_type; int32 label_count; /* @r{Repeated @code{label_cnt} times}. */ char value[8]; char label_len; char label[]; @end example @table @code @item int32 rec_type; Record type. Always set to 3. @item int32 label_count; Number of value labels present in this record. @end table The remaining fields are repeated @code{count} times. Each repetition specifies one value label. @table @code @item char value[8]; A numeric value or a short string value padded as necessary to 8 bytes in length. Its type and width cannot be determined until the following value label variables record (see below) is read. @item char label_len; The label's length, in bytes. The documented maximum length varies from 60 to 120 based on SPSS version. PSPP supports value labels up to 255 bytes long. @item char label[]; @code{label_len} bytes of the actual label, followed by up to 7 bytes of padding to bring @code{label} and @code{label_len} together to a multiple of 8 bytes in length. @end table The value label record is always immediately followed by a value label variables record with the following format: @example int32 rec_type; int32 var_count; int32 vars[]; @end example @table @code @item int32 rec_type; Record type. Always set to 4. @item int32 var_count; Number of variables that the associated value labels from the value label record are to be applied. @item int32 vars[]; A list of dictionary indexes of variables to which to apply the value labels (@pxref{Dictionary Index}). There are @code{var_count} elements. String variables wider than 8 bytes may not be specified in this list. @end table @node Document Record @section Document Record The document record, if present, has the following format: @example int32 rec_type; int32 n_lines; char lines[][80]; @end example @table @code @item int32 rec_type; Record type. Always set to 6. @item int32 n_lines; Number of lines of documents present. @item char lines[][80]; Document lines. The number of elements is defined by @code{n_lines}. Lines shorter than 80 characters are padded on the right with spaces. @end table @node Machine Integer Info Record @section Machine Integer Info Record The integer info record, if present, has the following format: @example /* @r{Header.} */ int32 rec_type; int32 subtype; int32 size; int32 count; /* @r{Data.} */ int32 version_major; int32 version_minor; int32 version_revision; int32 machine_code; int32 floating_point_rep; int32 compression_code; int32 endianness; int32 character_code; @end example @table @code @item int32 rec_type; Record type. Always set to 7. @item int32 subtype; Record subtype. Always set to 3. @item int32 size; Size of each piece of data in the data part, in bytes. Always set to 4. @item int32 count; Number of pieces of data in the data part. Always set to 8. @item int32 version_major; PSPP major version number. In version @var{x}.@var{y}.@var{z}, this is @var{x}. @item int32 version_minor; PSPP minor version number. In version @var{x}.@var{y}.@var{z}, this is @var{y}. @item int32 version_revision; PSPP version revision number. In version @var{x}.@var{y}.@var{z}, this is @var{z}. @item int32 machine_code; Machine code. PSPP always set this field to value to -1, but other values may appear. @item int32 floating_point_rep; Floating point representation code. For IEEE 754 systems this is 1. IBM 370 sets this to 2, and DEC VAX E to 3. @item int32 compression_code; Compression code. Always set to 1. @item int32 endianness; Machine endianness. 1 indicates big-endian, 2 indicates little-endian. @item int32 character_code; @anchor{character-code} Character code. The following values have been actually observed in system files: @table @asis @item 1 EBCDIC. @item 2 7-bit ASCII. @item 1250 The @code{windows-1250} code page for Central European and Eastern European languages. @item 1252 The @code{windows-1252} code page for Western European languages. @item 28591 ISO 8859-1. @item 65001 UTF-8. @end table The following additional values are known to be defined: @table @asis @item 3 8-bit ``ASCII''. @item 4 DEC Kanji. @end table Other Windows code page numbers are known to be generally valid. Old versions of SPSS for Unix and Windows always wrote value 2 in this field, regardless of the encoding in use. Newer versions also write the character encoding as a string (see @ref{Character Encoding Record}). @end table @node Machine Floating-Point Info Record @section Machine Floating-Point Info Record The floating-point info record, if present, has the following format: @example /* @r{Header.} */ int32 rec_type; int32 subtype; int32 size; int32 count; /* @r{Data.} */ flt64 sysmis; flt64 highest; flt64 lowest; @end example @table @code @item int32 rec_type; Record type. Always set to 7. @item int32 subtype; Record subtype. Always set to 4. @item int32 size; Size of each piece of data in the data part, in bytes. Always set to 8. @item int32 count; Number of pieces of data in the data part. Always set to 3. @item flt64 sysmis; The system missing value. @item flt64 highest; The value used for HIGHEST in missing values. @item flt64 lowest; The value used for LOWEST in missing values. @end table @node Multiple Response Sets Records @section Multiple Response Sets Records The system file format has two different types of records that represent multiple response sets (@pxref{MRSETS,,,pspp, PSPP Users Guide}). The first type of record describes multiple response sets that can be understood by SPSS before version 14. The second type of record, with a closely related format, is used for multiple dichotomy sets that use the CATEGORYLABELS=COUNTEDVALUES feature added in version 14. @example /* @r{Header.} */ int32 rec_type; int32 subtype; int32 size; int32 count; /* @r{Exactly @code{count} bytes of data.} */ char mrsets[]; @end example @table @code @item int32 rec_type; Record type. Always set to 7. @item int32 subtype; Record subtype. Set to 7 for records that describe multiple response sets understood by SPSS before version 14, or to 19 for records that describe dichotomy sets that use the CATEGORYLABELS=COUNTEDVALUES feature added in version 14. @item int32 size; The size of each element in the @code{mrsets} member. Always set to 1. @item int32 count; The total number of bytes in @code{mrsets}. @item char mrsets[]; A series of multiple response sets, each of which consists of the following: @itemize @bullet @item The set's name (an identifier that begins with @samp{$}), in mixed upper and lower case. @item An equals sign (@samp{=}). @item @samp{C} for a multiple category set, @samp{D} for a multiple dichotomy set with CATEGORYLABELS=VARLABELS, or @samp{E} for a multiple dichotomy set with CATEGORYLABELS=COUNTEDVALUES. @item For a multiple dichotomy set with CATEGORYLABELS=COUNTEDVALUES, a space, followed by a number expressed as decimal digits, followed by a space. If LABELSOURCE=VARLABEL was specified on MRSETS, then the number is 11; otherwise it is 1.@footnote{This part of the format may not be fully understood, because only a single example of each possibility has been examined.} @item For either kind of multiple dichotomy set, the counted value, as a positive integer count specified as decimal digits, followed by a space, followed by as many string bytes as specified in the count. If the set contains numeric variables, the string consists of the counted integer value expressed as decimal digits. If the set contains string variables, the string contains the counted string value. Either way, the string may be padded on the right with spaces (older versions of SPSS seem to always pad to a width of 8 bytes; newer versions don't). @item A space. @item The multiple response set's label, using the same format as for the counted value for multiple dichotomy sets. A string of length 0 means that the set does not have a label. A string of length 0 is also written if LABELSOURCE=VARLABEL was specified. @item A space. @item The short names of the variables in the set, converted to lowercase, each separated from the previous by a single space. @item A line feed (byte 0x0a). @end itemize @end table Example: Given appropriate variable definitions, consider the following MRSETS command: @example MRSETS /MCGROUP NAME=$a LABEL='my mcgroup' VARIABLES=a b c /MDGROUP NAME=$b VARIABLES=g e f d VALUE=55 /MDGROUP NAME=$c LABEL='mdgroup #2' VARIABLES=h i j VALUE='Yes' /MDGROUP NAME=$d LABEL='third mdgroup' CATEGORYLABELS=COUNTEDVALUES VARIABLES=k l m VALUE=34 /MDGROUP NAME=$e CATEGORYLABELS=COUNTEDVALUES LABELSOURCE=VARLABEL VARIABLES=n o p VALUE='choice'. @end example The above would generate the following multiple response set record of subtype 7: @example $a=C 10 my mcgroup a b c $b=D2 55 0 g e f d $c=D3 Yes 10 mdgroup #2 h i j @end example It would also generate the following multiple response set record with subtype 19: @example $d=E 1 2 34 13 third mdgroup k l m $e=E 11 6 choice 0 n o p @end example @node Variable Display Parameter Record @section Variable Display Parameter Record The variable display parameter record, if present, has the following format: @example /* @r{Header.} */ int32 rec_type; int32 subtype; int32 size; int32 count; /* @r{Repeated @code{count} times}. */ int32 measure; int32 width; /* @r{Not always present.} */ int32 alignment; @end example @table @code @item int32 rec_type; Record type. Always set to 7. @item int32 subtype; Record subtype. Always set to 11. @item int32 size; The size of @code{int32}. Always set to 4. @item int32 count; The number of sets of variable display parameters (ordinarily the number of variables in the dictionary), times 2 or 3. @end table The remaining members are repeated @code{count} times, in the same order as the variable records. No element corresponds to variable records that continue long string variables. The meanings of these members are as follows: @table @code @item int32 measure; The measurement type of the variable: @table @asis @item 1 Nominal Scale @item 2 Ordinal Scale @item 3 Continuous Scale @end table SPSS 14 sometimes writes a @code{measure} of 0 for string variables. PSPP interprets this as nominal scale. @item int32 width; The width of the display column for the variable in characters. This field is present if @var{count} is 3 times the number of variables in the dictionary. It is omitted if @var{count} is 2 times the number of variables. @item int32 alignment; The alignment of the variable for display purposes: @table @asis @item 0 Left aligned @item 1 Right aligned @item 2 Centre aligned @end table @end table @node Long Variable Names Record @section Long Variable Names Record If present, the long variable names record has the following format: @example /* @r{Header.} */ int32 rec_type; int32 subtype; int32 size; int32 count; /* @r{Exactly @code{count} bytes of data.} */ char var_name_pairs[]; @end example @table @code @item int32 rec_type; Record type. Always set to 7. @item int32 subtype; Record subtype. Always set to 13. @item int32 size; The size of each element in the @code{var_name_pairs} member. Always set to 1. @item int32 count; The total number of bytes in @code{var_name_pairs}. @item char var_name_pairs[]; A list of @var{key}--@var{value} tuples, where @var{key} is the name of a variable, and @var{value} is its long variable name. The @var{key} field is at most 8 bytes long and must match the name of a variable which appears in the variable record (@pxref{Variable Record}). The @var{value} field is at most 64 bytes long. The @var{key} and @var{value} fields are separated by a @samp{=} byte. Each tuple is separated by a byte whose value is 09. There is no trailing separator following the last tuple. The total length is @code{count} bytes. @end table @node Very Long String Record @section Very Long String Record Old versions of SPSS limited string variables to a width of 255 bytes. For backward compatibility with these older versions, the system file format represents a string longer than 255 bytes, called a @dfn{very long string}, as a collection of strings no longer than 255 bytes each. The strings concatenated to make a very long string are called its @dfn{segments}; for consistency, variables other than very long strings are considered to have a single segment. A very long string with a width of @var{w} has @var{n} = (@var{w} + 251) / 252 segments, that is, one segment for every 252 bytes of width, rounding up. It would be logical, then, for each of the segments except the last to have a width of 252 and the last segment to have the remainder, but this is not the case. In fact, each segment except the last has a width of 255 bytes. The last segment has width @var{w} - (@var{n} - 1) * 252; some versions of SPSS make it slightly wider, but not wide enough to make the last segment require another 8 bytes of data. Data is packed tightly into segments of a very long string, 255 bytes per segment. Because 255 bytes of segment data are allocated for every 252 bytes of the very long string's width (approximately), some unused space is left over at the end of the allocated segments. Data in unused space is ignored. Example: Consider a very long string of width 20,000. Such a very long string has 20,000 / 252 = 80 (rounding up) segments. The first 79 segments have width 255; the last segment has width 20,000 - 79 * 252 = 92 or slightly wider (up to 96 bytes, the next multiple of 8). The very long string's data is actually stored in the 19,890 bytes in the first 78 segments, plus the first 110 bytes of the 79th segment (19,890 + 110 = 20,000). The remaining 145 bytes of the 79th segment and all 92 bytes of the 80th segment are unused. The very long string record explains how to stitch together segments to obtain very long string data. For each of the very long string variables in the dictionary, it specifies the name of its first segment's variable and the very long string variable's actual width. The remaining segments immediately follow the named variable in the system file's dictionary. The very long string record, which is present only if the system file contains very long string variables, has the following format: @example /* @r{Header.} */ int32 rec_type; int32 subtype; int32 size; int32 count; /* @r{Exactly @code{count} bytes of data.} */ char string_lengths[]; @end example @table @code @item int32 rec_type; Record type. Always set to 7. @item int32 subtype; Record subtype. Always set to 14. @item int32 size; The size of each element in the @code{string_lengths} member. Always set to 1. @item int32 count; The total number of bytes in @code{string_lengths}. @item char string_lengths[]; A list of @var{key}--@var{value} tuples, where @var{key} is the name of a variable, and @var{value} is its length. The @var{key} field is at most 8 bytes long and must match the name of a variable which appears in the variable record (@pxref{Variable Record}). The @var{value} field is exactly 5 bytes long. It is a zero-padded, ASCII-encoded string that is the length of the variable. The @var{key} and @var{value} fields are separated by a @samp{=} byte. Tuples are delimited by a two-byte sequence @{00, 09@}. After the last tuple, there may be a single byte 00, or @{00, 09@}. The total length is @code{count} bytes. @end table @node Character Encoding Record @section Character Encoding Record This record, if present, indicates the character encoding for string data, long variable names, variable labels, value labels and other strings in the file. @example /* @r{Header.} */ int32 rec_type; int32 subtype; int32 size; int32 count; /* @r{Exactly @code{count} bytes of data.} */ char encoding[]; @end example @table @code @item int32 rec_type; Record type. Always set to 7. @item int32 subtype; Record subtype. Always set to 20. @item int32 size; The size of each element in the @code{encoding} member. Always set to 1. @item int32 count; The total number of bytes in @code{encoding}. @item char encoding[]; The name of the character encoding. Normally this will be an official IANA character set name or alias. See @url{http://www.iana.org/assignments/character-sets}. Character set names are not case-sensitive, but SPSS appears to write them in all-uppercase. @end table This record is not present in files generated by older software. See also the @code{character_code} field in the machine integer info record (@pxref{character-code}). When the character encoding record and the machine integer info record are both present, all system files observed in practice indicate the same character encoding, e.g.@: 1252 as @code{character_code} and @code{windows-1252} as @code{encoding}, 65001 and @code{UTF-8}, etc. If, for testing purposes, a file is crafted with different @code{character_code} and @code{encoding}, it seems that @code{character_code} controls the encoding for all strings in the system file before the dictionary termination record, including strings in data (e.g.@: string missing values), and @code{encoding} controls the encoding for strings following the dictionary termination record. @node Long String Value Labels Record @section Long String Value Labels Record This record, if present, specifies value labels for long string variables. @example /* @r{Header.} */ int32 rec_type; int32 subtype; int32 size; int32 count; /* @r{Repeated up to exactly @code{count} bytes.} */ int32 var_name_len; char var_name[]; int32 var_width; int32 n_labels; long_string_label labels[]; @end example @table @code @item int32 rec_type; Record type. Always set to 7. @item int32 subtype; Record subtype. Always set to 21. @item int32 size; Always set to 1. @item int32 count; The number of bytes following the header until the next header. @item int32 var_name_len; @itemx char var_name[]; The number of bytes in the name of the variable that has long string value labels, plus the variable name itself, which consists of exactly @code{var_name_len} bytes. The variable name is not padded to any particular boundary, nor is it null-terminated. @item int32 var_width; The width of the variable, in bytes, which will be between 9 and 32767. @item int32 n_labels; @itemx long_string_label labels[]; The long string labels themselves. The @code{labels} array contains exactly @code{n_labels} elements, each of which has the following substructure: @example int32 value_len; char value[]; int32 label_len; char label[]; @end example @table @code @item int32 value_len; @itemx char value[]; The string value being labeled. @code{value_len} is the number of bytes in @code{value}; it is equal to @code{var_width}. The @code{value} array is not padded or null-terminated. @item int32 label_len; @itemx char label[]; The label for the string value. @code{label_len}, which must be between 0 and 120, is the number of bytes in @code{label}. The @code{label} array is not padded or null-terminated. @end table @end table @node Data File and Variable Attributes Records @section Data File and Variable Attributes Records The data file and variable attributes records represent custom attributes for the system file or for individual variables in the system file, as defined on the DATAFILE ATTRIBUTE (@pxref{DATAFILE ATTRIBUTE,,,pspp, PSPP Users Guide}) and VARIABLE ATTRIBUTE commands (@pxref{VARIABLE ATTRIBUTE,,,pspp, PSPP Users Guide}), respectively. @example /* @r{Header.} */ int32 rec_type; int32 subtype; int32 size; int32 count; /* @r{Exactly @code{count} bytes of data.} */ char attributes[]; @end example @table @code @item int32 rec_type; Record type. Always set to 7. @item int32 subtype; Record subtype. Always set to 17 for a data file attribute record or to 18 for a variable attributes record. @item int32 size; The size of each element in the @code{attributes} member. Always set to 1. @item int32 count; The total number of bytes in @code{attributes}. @item char attributes[]; The attributes, in a text-based format. In record type 17, this field contains a single attribute set. An attribute set is a sequence of one or more attributes concatenated together. Each attribute consists of a name, which has the same syntax as a variable name, followed by, inside parentheses, a sequence of one or more values. Each value consists of a string enclosed in single quotes (@code{'}) followed by a line feed (byte 0x0a). A value may contain single quote characters, which are not themselves escaped or quoted or required to be present in pairs. There is no apparent way to embed a line feed in a value. There is no distinction between an attribute with a single value and an attribute array with one element. In record type 18, this field contains a sequence of one or more variable attribute sets. If more than one variable attribute set is present, each one after the first is delimited from the previous by @code{/}. Each variable attribute set consists of a long variable name, followed by @code{:}, followed by an attribute set with the same syntax as on record type 17. The total length is @code{count} bytes. @end table @subheading Example A system file produced with the following VARIABLE ATTRIBUTE commands in effect: @example VARIABLE ATTRIBUTE VARIABLES=dummy ATTRIBUTE=fred[1]('23') fred[2]('34'). VARIABLE ATTRIBUTE VARIABLES=dummy ATTRIBUTE=bert('123'). @end example @noindent will contain a variable attribute record with the following contents: @example 00000000 07 00 00 00 12 00 00 00 01 00 00 00 22 00 00 00 |............"...| 00000010 64 75 6d 6d 79 3a 66 72 65 64 28 27 32 33 27 0a |dummy:fred('23'.| 00000020 27 33 34 27 0a 29 62 65 72 74 28 27 31 32 33 27 |'34'.)bert('123'| 00000030 0a 29 |.) | @end example @node Extended Number of Cases Record @section Extended Number of Cases Record The file header record expresses the number of cases in the system file as an int32 (@pxref{File Header Record}). This record allows the number of cases in the system file to be expressed as a 64-bit number. @example int32 rec_type; int32 subtype; int32 size; int32 count; int64 unknown; int64 ncases64; @end example @table @code @item int32 rec_type; Record type. Always set to 7. @item int32 subtype; Record subtype. Always set to 16. @item int32 size; Size of each element. Always set to 8. @item int32 count; Number of pieces of data in the data part. Alway set to 2. @item int64 unknown; Meaning unknown. Always set to 1. @item int64 ncases64; Number of cases in the file as a 64-bit integer. Presumably this could be -1 to indicate that the number of cases is unknown, for the same reason as @code{ncases} in the file header record, but this has not been observed in the wild. @end table @node Miscellaneous Informational Records @section Miscellaneous Informational Records Some specific types of miscellaneous informational records are documented here, but others are known to exist. PSPP ignores unknown miscellaneous informational records when reading system files. @example /* @r{Header.} */ int32 rec_type; int32 subtype; int32 size; int32 count; /* @r{Exactly @code{size * count} bytes of data.} */ char data[]; @end example @table @code @item int32 rec_type; Record type. Always set to 7. @item int32 subtype; Record subtype. May take any value. According to Aapi H@"am@"al@"ainen, value 5 indicates a set of grouped variables and 6 indicates date info (probably related to USE). @item int32 size; Size of each piece of data in the data part. Should have the value 1, 4, or 8, for @code{char}, @code{int32}, and @code{flt64} format data, respectively. @item int32 count; Number of pieces of data in the data part. @item char data[]; Arbitrary data. There must be @code{size} times @code{count} bytes of data. @end table @node Dictionary Termination Record @section Dictionary Termination Record The dictionary termination record separates all other records from the data records. @example int32 rec_type; int32 filler; @end example @table @code @item int32 rec_type; Record type. Always set to 999. @item int32 filler; Ignored padding. Should be set to 0. @end table @node Data Record @section Data Record Data records must follow all other records in the system file. There must be at least one data record in every system file. The format of data records varies depending on whether the data is compressed. Regardless, the data is arranged in a series of 8-byte elements. When data is not compressed, each element corresponds to the variable declared in the respective variable record (@pxref{Variable Record}). Numeric values are given in @code{flt64} format; string values are literal characters string, padded on the right when necessary to fill out 8-byte units. Compressed data is arranged in the following manner: the first 8 bytes in the data section is divided into a series of 1-byte command codes. These codes have meanings as described below: @table @asis @item 0 Ignored. If the program writing the system file accumulates compressed data in blocks of fixed length, 0 bytes can be used to pad out extra bytes remaining at the end of a fixed-size block. @item 1 through 251 A number with value @var{code} - @var{bias}, where @var{code} is the value of the compression code and @var{bias} is the variable @code{bias} from the file header. For example, code 105 with bias 100.0 (the normal value) indicates a numeric variable of value 5. One file has been seen written by SPSS 14 that contained such a code in a @emph{string} field with the value 0 (after the bias is subtracted) as a way of encoding null bytes. @item 252 End of file. This code may or may not appear at the end of the data stream. PSPP always outputs this code but its use is not required. @item 253 A numeric or string value that is not compressible. The value is stored in the 8 bytes following the current block of command bytes. If this value appears twice in a block of command bytes, then it indicates the second group of 8 bytes following the command bytes, and so on. @item 254 An 8-byte string value that is all spaces. @item 255 The system-missing value. @end table When the end of the an 8-byte group of command bytes is reached, any blocks of non-compressible values indicated by code 253 are skipped, and the next element of command bytes is read and interpreted, until the end of the file or a code with value 252 is reached. @setfilename ignored pspp-master/doc/expressions.texi000066400000000000000000001612021177044323000173560ustar00rootroot00000000000000@c Use @func when refering to a function. @c Use @deftypefn for their definitions @macro func{NAME} @code{/NAME/} @end macro @node Expressions @chapter Mathematical Expressions @cindex expressions, mathematical @cindex mathematical expressions Expressions share a common syntax each place they appear in @pspp{} commands. Expressions are made up of @dfn{operands}, which can be numbers, strings, or variable names, separated by @dfn{operators}. There are five types of operators: grouping, arithmetic, logical, relational, and functions. Every operator takes one or more operands as input and yields exactly one result as output. Depending on the operator, operands accept strings or numbers as operands. With few exceptions, operands may be full-fledged expressions in themselves. @menu * Boolean Values:: Boolean values * Missing Values in Expressions:: Using missing values in expressions * Grouping Operators:: parentheses * Arithmetic Operators:: add sub mul div pow * Logical Operators:: AND NOT OR * Relational Operators:: EQ GE GT LE LT NE * Functions:: More-sophisticated operators * Order of Operations:: Operator precedence @end menu @node Boolean Values @section Boolean Values @cindex Boolean @cindex values, Boolean Some @pspp{} operators and expressions work with Boolean values, which represent true/false conditions. Booleans have only three possible values: 0 (false), 1 (true), and system-missing (unknown). System-missing is neither true nor false and indicates that the true value is unknown. Boolean-typed operands or function arguments must take on one of these three values. Other values are considered false, but provoke a warning when the expression is evaluated. Strings and Booleans are not compatible, and neither may be used in place of the other. @node Missing Values in Expressions @section Missing Values in Expressions Most numeric operators yield system-missing when given any system-missing operand. A string operator given any system-missing operand typically results in the empty string. Exceptions are listed under particular operator descriptions. String user-missing values are not treated specially in expressions. User-missing values for numeric variables are always transformed into the system-missing value, except inside the arguments to the @code{VALUE} and @code{SYSMIS} functions. The missing-value functions can be used to precisely control how missing values are treated in expressions. @xref{Missing Value Functions}, for more details. @node Grouping Operators @section Grouping Operators @cindex parentheses @cindex @samp{( )} @cindex grouping operators @cindex operators, grouping Parentheses (@samp{()}) are the grouping operators. Surround an expression with parentheses to force early evaluation. Parentheses also surround the arguments to functions, but in that situation they act as punctuators, not as operators. @node Arithmetic Operators @section Arithmetic Operators @cindex operators, arithmetic @cindex arithmetic operators The arithmetic operators take numeric operands and produce numeric results. @table @code @cindex @samp{+} @cindex addition @item @var{a} + @var{b} Yields the sum of @var{a} and @var{b}. @cindex @samp{-} @cindex subtraction @item @var{a} - @var{b} Subtracts @var{b} from @var{a} and yields the difference. @cindex @samp{*} @cindex multiplication @item @var{a} * @var{b} Yields the product of @var{a} and @var{b}. If either @var{a} or @var{b} is 0, then the result is 0, even if the other operand is missing. @cindex @samp{/} @cindex division @item @var{a} / @var{b} Divides @var{a} by @var{b} and yields the quotient. If @var{a} is 0, then the result is 0, even if @var{b} is missing. If @var{b} is zero, the result is system-missing. @cindex @samp{**} @cindex exponentiation @item @var{a} ** @var{b} Yields the result of raising @var{a} to the power @var{b}. If @var{a} is negative and @var{b} is not an integer, the result is system-missing. The result of @code{0**0} is system-missing as well. @cindex @samp{-} @cindex negation @item - @var{a} Reverses the sign of @var{a}. @end table @node Logical Operators @section Logical Operators @cindex logical operators @cindex operators, logical @cindex true @cindex false @cindex Boolean @cindex values, system-missing @cindex system-missing The logical operators take logical operands and produce logical results, meaning ``true or false.'' Logical operators are not true Boolean operators because they may also result in a system-missing value. @xref{Boolean Values}, for more information. @table @code @cindex @code{AND} @cindex @samp{&} @cindex intersection, logical @cindex logical intersection @item @var{a} AND @var{b} @itemx @var{a} & @var{b} True if both @var{a} and @var{b} are true, false otherwise. If one operand is false, the result is false even if the other is missing. If both operands are missing, the result is missing. @cindex @code{OR} @cindex @samp{|} @cindex union, logical @cindex logical union @item @var{a} OR @var{b} @itemx @var{a} | @var{b} True if at least one of @var{a} and @var{b} is true. If one operand is true, the result is true even if the other operand is missing. If both operands are missing, the result is missing. @cindex @code{NOT} @cindex @samp{~} @cindex inversion, logical @cindex logical inversion @item NOT @var{a} @itemx ~ @var{a} True if @var{a} is false. If the operand is missing, then the result is missing. @end table @node Relational Operators @section Relational Operators The relational operators take numeric or string operands and produce Boolean results. Strings cannot be compared to numbers. When strings of different lengths are compared, the shorter string is right-padded with spaces to match the length of the longer string. The results of string comparisons, other than tests for equality or inequality, depend on the character set in use. String comparisons are case-sensitive. @table @code @cindex equality, testing @cindex testing for equality @cindex @code{EQ} @cindex @samp{=} @item @var{a} EQ @var{b} @itemx @var{a} = @var{b} True if @var{a} is equal to @var{b}. @cindex less than or equal to @cindex @code{LE} @cindex @code{<=} @item @var{a} LE @var{b} @itemx @var{a} <= @var{b} True if @var{a} is less than or equal to @var{b}. @cindex less than @cindex @code{LT} @cindex @code{<} @item @var{a} LT @var{b} @itemx @var{a} < @var{b} True if @var{a} is less than @var{b}. @cindex greater than or equal to @cindex @code{GE} @cindex @code{>=} @item @var{a} GE @var{b} @itemx @var{a} >= @var{b} True if @var{a} is greater than or equal to @var{b}. @cindex greater than @cindex @code{GT} @cindex @samp{>} @item @var{a} GT @var{b} @itemx @var{a} > @var{b} True if @var{a} is greater than @var{b}. @cindex inequality, testing @cindex testing for inequality @cindex @code{NE} @cindex @code{~=} @cindex @code{<>} @item @var{a} NE @var{b} @itemx @var{a} ~= @var{b} @itemx @var{a} <> @var{b} True if @var{a} is not equal to @var{b}. @end table @node Functions @section Functions @cindex functions @cindex mathematics @cindex operators @cindex parentheses @cindex @code{(} @cindex @code{)} @cindex names, of functions @pspp{} functions provide mathematical abilities above and beyond those possible using simple operators. Functions have a common syntax: each is composed of a function name followed by a left parenthesis, one or more arguments, and a right parenthesis. Function names are not reserved. Their names are specially treated only when followed by a left parenthesis, so that @samp{EXP(10)} refers to the constant value @math{e} raised to the 10th power, but @samp{EXP} by itself refers to the value of a variable called @code{EXP}. The sections below describe each function in detail. @menu * Mathematics:: EXP LG10 LN LNGAMMA SQRT * Miscellaneous Mathematics:: ABS MOD MOD10 RND TRUNC * Trigonometry:: ACOS ARCOS ARSIN ARTAN ASIN ATAN COS SIN TAN * Missing Value Functions:: MISSING NMISS NVALID SYSMIS VALUE * Set Membership:: ANY RANGE * Statistical Functions:: CFVAR MAX MEAN MIN SD SUM VARIANCE * String Functions:: CONCAT INDEX LENGTH LOWER LPAD LTRIM NUMBER RINDEX RPAD RTRIM STRING SUBSTR UPCASE * Time and Date:: CTIME.xxx DATE.xxx TIME.xxx XDATE.xxx DATEDIFF DATESUM * Miscellaneous Functions:: LAG YRMODA VALUELABEL * Statistical Distribution Functions:: PDF CDF SIG IDF RV NPDF NCDF @end menu @node Mathematics @subsection Mathematical Functions @cindex mathematics, advanced Advanced mathematical functions take numeric arguments and produce numeric results. @deftypefn {Function} {} EXP (@var{exponent}) Returns @math{e} (approximately 2.71828) raised to power @var{exponent}. @end deftypefn @cindex logarithms @deftypefn {Function} {} LG10 (@var{number}) Takes the base-10 logarithm of @var{number}. If @var{number} is not positive, the result is system-missing. @end deftypefn @deftypefn {Function} {} LN (@var{number}) Takes the base-@math{e} logarithm of @var{number}. If @var{number} is not positive, the result is system-missing. @end deftypefn @deftypefn {Function} {} LNGAMMA (@var{number}) Yields the base-@math{e} logarithm of the complete gamma of @var{number}. If @var{number} is a negative integer, the result is system-missing. @end deftypefn @cindex square roots @deftypefn {Function} {} SQRT (@var{number}) Takes the square root of @var{number}. If @var{number} is negative, the result is system-missing. @end deftypefn @node Miscellaneous Mathematics @subsection Miscellaneous Mathematical Functions @cindex mathematics, miscellaneous Miscellaneous mathematical functions take numeric arguments and produce numeric results. @cindex absolute value @deftypefn {Function} {} ABS (@var{number}) Results in the absolute value of @var{number}. @end deftypefn @cindex modulus @deftypefn {Function} {} MOD (@var{numerator}, @var{denominator}) Returns the remainder (modulus) of @var{numerator} divided by @var{denominator}. If @var{numerator} is 0, then the result is 0, even if @var{denominator} is missing. If @var{denominator} is 0, the result is system-missing. @end deftypefn @cindex modulus, by 10 @deftypefn {Function} {} MOD10 (@var{number}) Returns the remainder when @var{number} is divided by 10. If @var{number} is negative, MOD10(@var{number}) is negative or zero. @end deftypefn @cindex rounding @deftypefn {Function} {} RND (@var{number}) Takes the absolute value of @var{number} and rounds it to an integer. Then, if @var{number} was negative originally, negates the result. @end deftypefn @cindex truncation @deftypefn {Function} {} TRUNC (@var{number}) Discards the fractional part of @var{number}; that is, rounds @var{number} towards zero. @end deftypefn @node Trigonometry @subsection Trigonometric Functions @cindex trigonometry Trigonometric functions take numeric arguments and produce numeric results. @cindex arccosine @cindex inverse cosine @deftypefn {Function} {} ARCOS (@var{number}) @deftypefnx {Function} {} ACOS (@var{number}) Takes the arccosine, in radians, of @var{number}. Results in system-missing if @var{number} is not between -1 and 1 inclusive. This function is a @pspp{} extension. @end deftypefn @cindex arcsine @cindex inverse sine @deftypefn {Function} {} ARSIN (@var{number}) @deftypefnx {Function} {} ASIN (@var{number}) Takes the arcsine, in radians, of @var{number}. Results in system-missing if @var{number} is not between -1 and 1 inclusive. @end deftypefn @cindex arctangent @cindex inverse tangent @deftypefn {Function} {} ARTAN (@var{number}) @deftypefnx {Function} {} ATAN (@var{number}) Takes the arctangent, in radians, of @var{number}. @end deftypefn @cindex cosine @deftypefn {Function} {} COS (@var{angle}) Takes the cosine of @var{angle} which should be in radians. @end deftypefn @cindex sine @deftypefn {Function} {} SIN (@var{angle}) Takes the sine of @var{angle} which should be in radians. @end deftypefn @cindex tangent @deftypefn {Function} {} TAN (@var{angle}) Takes the tangent of @var{angle} which should be in radians. Results in system-missing at values of @var{angle} that are too close to odd multiples of @math{\pi/2}. Portability: none. @end deftypefn @node Missing Value Functions @subsection Missing-Value Functions @cindex missing values @cindex values, missing @cindex functions, missing-value Missing-value functions take various numeric arguments and yield various types of results. Except where otherwise stated below, the normal rules of evaluation apply within expression arguments to these functions. In particular, user-missing values for numeric variables are converted to system-missing values. @deftypefn {Function} {} MISSING (@var{expr}) Returns 1 if @var{expr} has the system-missing value, 0 otherwise. @end deftypefn @deftypefn {Function} {} NMISS (@var{expr} [, @var{expr}]@dots{}) Each argument must be a numeric expression. Returns the number of system-missing values in the list, which may include variable ranges using the @code{@var{var1} TO @var{var2}} syntax. @end deftypefn @deftypefn {Function} {} NVALID (@var{expr} [, @var{expr}]@dots{}) Each argument must be a numeric expression. Returns the number of values in the list that are not system-missing. The list may include variable ranges using the @code{@var{var1} TO @var{var2}} syntax. @end deftypefn @deftypefn {Function} {} SYSMIS (@var{expr}) When @var{expr} is simply the name of a numeric variable, returns 1 if the variable has the system-missing value, 0 if it is user-missing or not missing. If given @var{expr} takes another form, results in 1 if the value is system-missing, 0 otherwise. @end deftypefn @deftypefn {Function} {} VALUE (@var{variable}) Prevents the user-missing values of @var{variable} from being transformed into system-missing values, and always results in the actual value of @var{variable}, whether it is valid, user-missing, or system-missing. @end deftypefn @node Set Membership @subsection Set-Membership Functions @cindex set membership @cindex membership, of set Set membership functions determine whether a value is a member of a set. They take a set of numeric arguments or a set of string arguments, and produce Boolean results. String comparisons are performed according to the rules given in @ref{Relational Operators}. @deftypefn {Function} {} ANY (@var{value}, @var{set} [, @var{set}]@dots{}) Results in true if @var{value} is equal to any of the @var{set} values. Otherwise, results in false. If @var{value} is system-missing, returns system-missing. System-missing values in @var{set} do not cause @func{ANY} to return system-missing. @end deftypefn @deftypefn {Function} {} RANGE (@var{value}, @var{low}, @var{high} [, @var{low}, @var{high}]@dots{}) Results in true if @var{value} is in any of the intervals bounded by @var{low} and @var{high} inclusive. Otherwise, results in false. Each @var{low} must be less than or equal to its corresponding @var{high} value. @var{low} and @var{high} must be given in pairs. If @var{value} is system-missing, returns system-missing. System-missing values in @var{set} do not cause @func{RANGE} to return system-missing. @end deftypefn @node Statistical Functions @subsection Statistical Functions @cindex functions, statistical @cindex statistics Statistical functions compute descriptive statistics on a list of values. Some statistics can be computed on numeric or string values; other can only be computed on numeric values. Their results have the same type as their arguments. The current case's weighting factor (@pxref{WEIGHT}) has no effect on statistical functions. These functions' argument lists may include entire ranges of variables using the @code{@var{var1} TO @var{var2}} syntax. @cindex arguments, minimum valid @cindex minimum valid number of arguments Unlike most functions, statistical functions can return non-missing values even when some of their arguments are missing. Most statistical functions, by default, require only 1 non-missing value to have a non-missing return, but @func{CFVAR}, @func{SD}, and @func {VARIANCE} require 2. These defaults can be increased (but not decreased) by appending a dot and the minimum number of valid arguments to the function name. For example, @subcmd{MEAN.3(X, Y, Z)} would only return non-missing if all of @samp{X}, @samp{Y}, and @samp{Z} were valid. @cindex coefficient of variation @cindex variation, coefficient of @deftypefn {Function} {} CFVAR (@var{number}, @var{number}[, @dots{}]) Results in the coefficient of variation of the values of @var{number}. (The coefficient of variation is the standard deviation divided by the mean.) @end deftypefn @cindex maximum @deftypefn {Function} {} MAX (@var{value}, @var{value}[, @dots{}]) Results in the value of the greatest @var{value}. The @var{value}s may be numeric or string. @end deftypefn @cindex mean @deftypefn {Function} {} MEAN (@var{number}, @var{number}[, @dots{}]) Results in the mean of the values of @var{number}. @end deftypefn @cindex minimum @deftypefn {Function} {} MIN (@var{number}, @var{number}[, @dots{}]) Results in the value of the least @var{value}. The @var{value}s may be numeric or string. @end deftypefn @cindex standard deviation @cindex deviation, standard @deftypefn {Function} {} SD (@var{number}, @var{number}[, @dots{}]) Results in the standard deviation of the values of @var{number}. @end deftypefn @cindex sum @deftypefn {Function} {} SUM (@var{number}, @var{number}[, @dots{}]) Results in the sum of the values of @var{number}. @end deftypefn @cindex variance @deftypefn {Function} {} VARIANCE (@var{number}, @var{number}[, @dots{}]) Results in the variance of the values of @var{number}. @end deftypefn @node String Functions @subsection String Functions @cindex functions, string @cindex string functions String functions take various arguments and return various results. @cindex concatenation @cindex strings, concatenation of @deftypefn {Function} {} CONCAT (@var{string}, @var{string}[, @dots{}]) Returns a string consisting of each @var{string} in sequence. @code{CONCAT("abc", "def", "ghi")} has a value of @code{"abcdefghi"}. The resultant string is truncated to a maximum of 255 characters. @end deftypefn @cindex searching strings @deftypefn {Function} {} INDEX (@var{haystack}, @var{needle}) Returns a positive integer indicating the position of the first occurrence of @var{needle} in @var{haystack}. Returns 0 if @var{haystack} does not contain @var{needle}. Returns system-missing if @var{needle} is an empty string. @end deftypefn @deftypefn {Function} {} INDEX (@var{haystack}, @var{needles}, @var{needle_len}) Divides @var{needles} into one or more needles, each with length @var{needle_len}. Searches @var{haystack} for the first occurrence of each needle, and returns the smallest value. Returns 0 if @var{haystack} does not contain any part in @var{needle}. It is an error if @var{needle_len} does not evenly divide the length of @var{needles}. Returns system-missing if @var{needles} is an empty string. @end deftypefn @cindex strings, finding length of @deftypefn {Function} {} LENGTH (@var{string}) Returns the number of characters in @var{string}. @end deftypefn @cindex strings, case of @deftypefn {Function} {} LOWER (@var{string}) Returns a string identical to @var{string} except that all uppercase letters are changed to lowercase letters. The definitions of ``uppercase'' and ``lowercase'' are system-dependent. @end deftypefn @cindex strings, padding @deftypefn {Function} {} LPAD (@var{string}, @var{length}) If @var{string} is at least @var{length} characters in length, returns @var{string} unchanged. Otherwise, returns @var{string} padded with spaces on the left side to length @var{length}. Returns an empty string if @var{length} is system-missing, negative, or greater than 255. @end deftypefn @deftypefn {Function} {} LPAD (@var{string}, @var{length}, @var{padding}) If @var{string} is at least @var{length} characters in length, returns @var{string} unchanged. Otherwise, returns @var{string} padded with @var{padding} on the left side to length @var{length}. Returns an empty string if @var{length} is system-missing, negative, or greater than 255, or if @var{padding} does not contain exactly one character. @end deftypefn @cindex strings, trimming @cindex white space, trimming @deftypefn {Function} {} LTRIM (@var{string}) Returns @var{string}, after removing leading spaces. Other white space, such as tabs, carriage returns, line feeds, and vertical tabs, is not removed. @end deftypefn @deftypefn {Function} {} LTRIM (@var{string}, @var{padding}) Returns @var{string}, after removing leading @var{padding} characters. If @var{padding} does not contain exactly one character, returns an empty string. @end deftypefn @cindex numbers, converting from strings @cindex strings, converting to numbers @deftypefn {Function} {} NUMBER (@var{string}, @var{format}) Returns the number produced when @var{string} is interpreted according to format specifier @var{format}. If the format width @var{w} is less than the length of @var{string}, then only the first @var{w} characters in @var{string} are used, e.g.@: @code{NUMBER("123", F3.0)} and @code{NUMBER("1234", F3.0)} both have value 123. If @var{w} is greater than @var{string}'s length, then it is treated as if it were right-padded with spaces. If @var{string} is not in the correct format for @var{format}, system-missing is returned. @end deftypefn @cindex strings, searching backwards @deftypefn {Function} {} RINDEX (@var{string}, @var{format}) Returns a positive integer indicating the position of the last occurrence of @var{needle} in @var{haystack}. Returns 0 if @var{haystack} does not contain @var{needle}. Returns system-missing if @var{needle} is an empty string. @end deftypefn @deftypefn {Function} {} RINDEX (@var{haystack}, @var{needle}, @var{needle_len}) Divides @var{needle} into parts, each with length @var{needle_len}. Searches @var{haystack} for the last occurrence of each part, and returns the largest value. Returns 0 if @var{haystack} does not contain any part in @var{needle}. It is an error if @var{needle_len} does not evenly divide the length of @var{needle}. Returns system-missing if @var{needle} is an empty string. @end deftypefn @cindex padding strings @cindex strings, padding @deftypefn {Function} {} RPAD (@var{string}, @var{length}) If @var{string} is at least @var{length} characters in length, returns @var{string} unchanged. Otherwise, returns @var{string} padded with spaces on the right to length @var{length}. Returns an empty string if @var{length} is system-missing, negative, or greater than 255. @end deftypefn @deftypefn {Function} {} RPAD (@var{string}, @var{length}, @var{padding}) If @var{string} is at least @var{length} characters in length, returns @var{string} unchanged. Otherwise, returns @var{string} padded with @var{padding} on the right to length @var{length}. Returns an empty string if @var{length} is system-missing, negative, or greater than 255, or if @var{padding} does not contain exactly one character. @end deftypefn @cindex strings, trimming @cindex white space, trimming @deftypefn {Function} {} RTRIM (@var{string}) Returns @var{string}, after removing trailing spaces. Other types of white space are not removed. @end deftypefn @deftypefn {Function} {} RTRIM (@var{string}, @var{padding}) Returns @var{string}, after removing trailing @var{padding} characters. If @var{padding} does not contain exactly one character, returns an empty string. @end deftypefn @cindex strings, converting from numbers @cindex numbers, converting to strings @deftypefn {Function} {} STRING (@var{number}, @var{format}) Returns a string corresponding to @var{number} in the format given by format specifier @var{format}. For example, @code{STRING(123.56, F5.1)} has the value @code{"123.6"}. @end deftypefn @cindex substrings @cindex strings, taking substrings of @deftypefn {Function} {} SUBSTR (@var{string}, @var{start}) Returns a string consisting of the value of @var{string} from position @var{start} onward. Returns an empty string if @var{start} is system-missing, less than 1, or greater than the length of @var{string}. @end deftypefn @deftypefn {Function} {} SUBSTR (@var{string}, @var{start}, @var{count}) Returns a string consisting of the first @var{count} characters from @var{string} beginning at position @var{start}. Returns an empty string if @var{start} or @var{count} is system-missing, if @var{start} is less than 1 or greater than the number of characters in @var{string}, or if @var{count} is less than 1. Returns a string shorter than @var{count} characters if @var{start} + @var{count} - 1 is greater than the number of characters in @var{string}. Examples: @code{SUBSTR("abcdefg", 3, 2)} has value @code{"cd"}; @code{SUBSTR("nonsense", 4, 10)} has the value @code{"sense"}. @end deftypefn @cindex case conversion @cindex strings, case of @deftypefn {Function} {} UPCASE (@var{string}) Returns @var{string}, changing lowercase letters to uppercase letters. @end deftypefn @node Time and Date @subsection Time & Date Functions @cindex functions, time & date @cindex times @cindex dates @cindex dates, valid For compatibility, @pspp{} considers dates before 15 Oct 1582 invalid. Most time and date functions will not accept earlier dates. @menu * Time and Date Concepts:: How times & dates are defined and represented * Time Construction:: TIME.@{DAYS HMS@} * Time Extraction:: CTIME.@{DAYS HOURS MINUTES SECONDS@} * Date Construction:: DATE.@{DMY MDY MOYR QYR WKYR YRDAY@} * Date Extraction:: XDATE.@{DATE HOUR JDAY MDAY MINUTE MONTH QUARTER SECOND TDAY TIME WEEK WKDAY YEAR@} * Time and Date Arithmetic:: DATEDIFF DATESUM @end menu @node Time and Date Concepts @subsubsection How times & dates are defined and represented @cindex time, concepts @cindex time, intervals Times and dates are handled by @pspp{} as single numbers. A @dfn{time} is an interval. @pspp{} measures times in seconds. Thus, the following intervals correspond with the numeric values given: @example 10 minutes 600 1 hour 3,600 1 day, 3 hours, 10 seconds 97,210 40 days 3,456,000 @end example @cindex dates, concepts @cindex time, instants of A @dfn{date}, on the other hand, is a particular instant in the past or the future. @pspp{} represents a date as a number of seconds since midnight preceding 14 Oct 1582. Because midnight preceding the dates given below correspond with the numeric @pspp{} dates given: @example 15 Oct 1582 86,400 4 Jul 1776 6,113,318,400 1 Jan 1900 10,010,390,400 1 Oct 1978 12,495,427,200 24 Aug 1995 13,028,601,600 @end example @node Time Construction @subsubsection Functions that Produce Times @cindex times, constructing @cindex constructing times These functions take numeric arguments and return numeric values that represent times. @cindex days @cindex time, in days @deftypefn {Function} {} TIME.DAYS (@var{ndays}) Returns a time corresponding to @var{ndays} days. @end deftypefn @cindex hours-minutes-seconds @cindex time, in hours-minutes-seconds @deftypefn {Function} {} TIME.HMS (@var{nhours}, @var{nmins}, @var{nsecs}) Returns a time corresponding to @var{nhours} hours, @var{nmins} minutes, and @var{nsecs} seconds. The arguments may not have mixed signs: if any of them are positive, then none may be negative, and vice versa. @end deftypefn @node Time Extraction @subsubsection Functions that Examine Times @cindex extraction, of time @cindex time examination @cindex examination, of times @cindex time, lengths of These functions take numeric arguments in @pspp{} time format and give numeric results. @cindex days @cindex time, in days @deftypefn {Function} {} CTIME.DAYS (@var{time}) Results in the number of days and fractional days in @var{time}. @end deftypefn @cindex hours @cindex time, in hours @deftypefn {Function} {} CTIME.HOURS (@var{time}) Results in the number of hours and fractional hours in @var{time}. @end deftypefn @cindex minutes @cindex time, in minutes @deftypefn {Function} {} CTIME.MINUTES (@var{time}) Results in the number of minutes and fractional minutes in @var{time}. @end deftypefn @cindex seconds @cindex time, in seconds @deftypefn {Function} {} CTIME.SECONDS (@var{time}) Results in the number of seconds and fractional seconds in @var{time}. (@code{CTIME.SECONDS} does nothing; @code{CTIME.SECONDS(@var{x})} is equivalent to @code{@var{x}}.) @end deftypefn @node Date Construction @subsubsection Functions that Produce Dates @cindex dates, constructing @cindex constructing dates @cindex arguments, of date construction functions These functions take numeric arguments and give numeric results that represent dates. Arguments taken by these functions are: @table @var @item day Refers to a day of the month between 1 and 31. Day 0 is also accepted and refers to the final day of the previous month. Days 29, 30, and 31 are accepted even in months that have fewer days and refer to a day near the beginning of the following month. @item month Refers to a month of the year between 1 and 12. Months 0 and 13 are also accepted and refer to the last month of the preceding year and the first month of the following year, respectively. @item quarter Refers to a quarter of the year between 1 and 4. The quarters of the year begin on the first day of months 1, 4, 7, and 10. @item week Refers to a week of the year between 1 and 53. @item yday Refers to a day of the year between 1 and 366. @item year Refers to a year, 1582 or greater. Years between 0 and 99 are treated according to the epoch set on SET EPOCH, by default beginning 69 years before the current date (@pxref{SET EPOCH}). @end table @cindex arguments, invalid If these functions' arguments are out-of-range, they are correctly normalized before conversion to date format. Non-integers are rounded toward zero. @cindex day-month-year @cindex dates, day-month-year @deftypefn {Function} {} DATE.DMY (@var{day}, @var{month}, @var{year}) @deftypefnx {Function} {} DATE.MDY (@var{month}, @var{day}, @var{year}) Results in a date value corresponding to the midnight before day @var{day} of month @var{month} of year @var{year}. @end deftypefn @cindex month-year @cindex dates, month-year @deftypefn {Function} {} DATE.MOYR (@var{month}, @var{year}) Results in a date value corresponding to the midnight before the first day of month @var{month} of year @var{year}. @end deftypefn @cindex quarter-year @cindex dates, quarter-year @deftypefn {Function} {} DATE.QYR (@var{quarter}, @var{year}) Results in a date value corresponding to the midnight before the first day of quarter @var{quarter} of year @var{year}. @end deftypefn @cindex week-year @cindex dates, week-year @deftypefn {Function} {} DATE.WKYR (@var{week}, @var{year}) Results in a date value corresponding to the midnight before the first day of week @var{week} of year @var{year}. @end deftypefn @cindex year-day @cindex dates, year-day @deftypefn {Function} {} DATE.YRDAY (@var{year}, @var{yday}) Results in a date value corresponding to the day @var{yday} of year @var{year}. @end deftypefn @node Date Extraction @subsubsection Functions that Examine Dates @cindex extraction, of dates @cindex date examination @cindex arguments, of date extraction functions These functions take numeric arguments in @pspp{} date or time format and give numeric results. These names are used for arguments: @table @var @item date A numeric value in @pspp{} date format. @item time A numeric value in @pspp{} time format. @item time-or-date A numeric value in @pspp{} time or date format. @end table @cindex days @cindex dates, in days @cindex time, in days @deftypefn {Function} {} XDATE.DATE (@var{time-or-date}) For a time, results in the time corresponding to the number of whole days @var{date-or-time} includes. For a date, results in the date corresponding to the latest midnight at or before @var{date-or-time}; that is, gives the date that @var{date-or-time} is in. @end deftypefn @cindex hours @cindex dates, in hours @cindex time, in hours @deftypefn {Function} {} XDATE.HOUR (@var{time-or-date}) For a time, results in the number of whole hours beyond the number of whole days represented by @var{date-or-time}. For a date, results in the hour (as an integer between 0 and 23) corresponding to @var{date-or-time}. @end deftypefn @cindex day of the year @cindex dates, day of the year @deftypefn {Function} {} XDATE.JDAY (@var{date}) Results in the day of the year (as an integer between 1 and 366) corresponding to @var{date}. @end deftypefn @cindex day of the month @cindex dates, day of the month @deftypefn {Function} {} XDATE.MDAY (@var{date}) Results in the day of the month (as an integer between 1 and 31) corresponding to @var{date}. @end deftypefn @cindex minutes @cindex dates, in minutes @cindex time, in minutes @deftypefn {Function} {} XDATE.MINUTE (@var{time-or-date}) Results in the number of minutes (as an integer between 0 and 59) after the last hour in @var{time-or-date}. @end deftypefn @cindex months @cindex dates, in months @deftypefn {Function} {} XDATE.MONTH (@var{date}) Results in the month of the year (as an integer between 1 and 12) corresponding to @var{date}. @end deftypefn @cindex quarters @cindex dates, in quarters @deftypefn {Function} {} XDATE.QUARTER (@var{date}) Results in the quarter of the year (as an integer between 1 and 4) corresponding to @var{date}. @end deftypefn @cindex seconds @cindex dates, in seconds @cindex time, in seconds @deftypefn {Function} {} XDATE.SECOND (@var{time-or-date}) Results in the number of whole seconds after the last whole minute (as an integer between 0 and 59) in @var{time-or-date}. @end deftypefn @cindex days @cindex times, in days @deftypefn {Function} {} XDATE.TDAY (@var{date}) Results in the number of whole days from 14 Oct 1582 to @var{date}. @end deftypefn @cindex time @cindex dates, time of day @deftypefn {Function} {} XDATE.TIME (@var{date}) Results in the time of day at the instant corresponding to @var{date}, as a time value. This is the number of seconds since midnight on the day corresponding to @var{date}. @end deftypefn @cindex week @cindex dates, in weeks @deftypefn {Function} {} XDATE.WEEK (@var{date}) Results in the week of the year (as an integer between 1 and 53) corresponding to @var{date}. @end deftypefn @cindex day of the week @cindex weekday @cindex dates, day of the week @cindex dates, in weekdays @deftypefn {Function} {} XDATE.WKDAY (@var{date}) Results in the day of week (as an integer between 1 and 7) corresponding to @var{date}, where 1 represents Sunday. @end deftypefn @cindex years @cindex dates, in years @deftypefn {Function} {} XDATE.YEAR (@var{date}) Returns the year (as an integer 1582 or greater) corresponding to @var{date}. @end deftypefn @node Time and Date Arithmetic @subsubsection Time and Date Arithmetic @cindex time, mathematical properties of @cindex mathematics, applied to times & dates @cindex dates, mathematical properties of @noindent Ordinary arithmetic operations on dates and times often produce sensible results. Adding a time to, or subtracting one from, a date produces a new date that much earlier or later. The difference of two dates yields the time between those dates. Adding two times produces the combined time. Multiplying a time by a scalar produces a time that many times longer. Since times and dates are just numbers, the ordinary addition and subtraction operators are employed for these purposes. Adding two dates does not produce a useful result. Dates and times may have very large values. Thus, it is not a good idea to take powers of these values; also, the accuracy of some procedures may be affected. If necessary, convert times or dates in seconds to some other unit, like days or years, before performing analysis. @pspp{} supplies a few functions for date arithmetic: @deftypefn {Function} {} DATEDIFF (@var{date2}, @var{date1}, @var{unit}) Returns the span of time from @var{date1} to @var{date2} in terms of @var{unit}, which must be a quoted string, one of @samp{years}, @samp{quarters}, @samp{months}, @samp{weeks}, @samp{days}, @samp{hours}, @samp{minutes}, and @samp{seconds}. The result is an integer, truncated toward zero. One year is considered to span from a given date to the same month, day, and time of day the next year. Thus, from Jan.@tie{}1 of one year to Jan.@tie{}1 the next year is considered to be a full year, but Feb.@tie{}29 of a leap year to the following Feb.@tie{}28 is not. Similarly, one month spans from a given day of the month to the same day of the following month. Thus, there is never a full month from Jan.@tie{}31 of a given year to any day in the following February. @end deftypefn @deftypefn {Function} {} DATESUM (@var{date}, @var{quantity}, @var{unit}[, @var{method}]) Returns @var{date} advanced by the given @var{quantity} of the specified @var{unit}, which must be one of the strings @samp{years}, @samp{quarters}, @samp{months}, @samp{weeks}, @samp{days}, @samp{hours}, @samp{minutes}, and @samp{seconds}. When @var{unit} is @samp{years}, @samp{quarters}, or @samp{months}, only the integer part of @var{quantity} is considered. Adding one of these units can cause the day of the month to exceed the number of days in the month. In this case, the @var{method} comes into play: if it is omitted or specified as @samp{closest} (as a quoted string), then the resulting day is the last day of the month; otherwise, if it is specified as @samp{rollover}, then the extra days roll over into the following month. When @var{unit} is @samp{weeks}, @samp{days}, @samp{hours}, @samp{minutes}, or @samp{seconds}, the @var{quantity} is not rounded to an integer and @var{method}, if specified, is ignored. @end deftypefn @node Miscellaneous Functions @subsection Miscellaneous Functions @cindex functions, miscellaneous @cindex cross-case function @cindex function, cross-case @deftypefn {Function} {} LAG (@var{variable}[, @var{n}]) @anchor{LAG} @var{variable} must be a numeric or string variable name. @code{LAG} yields the value of that variable for the case @var{n} before the current one. Results in system-missing (for numeric variables) or blanks (for string variables) for the first @var{n} cases. @code{LAG} obtains values from the cases that become the new active dataset after a procedure executes. Thus, @code{LAG} will not return values from cases dropped by transformations such as @cmd{SELECT IF}, and transformations like @cmd{COMPUTE} that modify data will change the values returned by @code{LAG}. These are both the case whether these transformations precede or follow the use of @code{LAG}. If @code{LAG} is used before @cmd{TEMPORARY}, then the values it returns are those in cases just before @cmd{TEMPORARY}. @code{LAG} may not be used after @cmd{TEMPORARY}. If omitted, @var{ncases} defaults to 1. Otherwise, @var{ncases} must be a small positive constant integer. There is no explicit limit, but use of a large value will increase memory consumption. @end deftypefn @cindex date, Julian @cindex Julian date @deftypefn {Function} {} YRMODA (@var{year}, @var{month}, @var{day}) @var{year} is a year, either between 0 and 99 or at least 1582. Unlike other @pspp{} date functions, years between 0 and 99 always correspond to 1900 through 1999. @var{month} is a month between 1 and 13. @var{day} is a day between 0 and 31. A @var{day} of 0 refers to the last day of the previous month, and a @var{month} of 13 refers to the first month of the next year. @var{year} must be in range. @var{year}, @var{month}, and @var{day} must all be integers. @code{YRMODA} results in the number of days between 15 Oct 1582 and the date specified, plus one. The date passed to @code{YRMODA} must be on or after 15 Oct 1582. 15 Oct 1582 has a value of 1. @end deftypefn @cindex value label @deftypefn {Function} VALUELABEL (@var{variable}) Returns a string matching the label associated with the current value of @var{variable}. If the current value of @var{variable} has no associated label, then this function returns the empty string. @var{variable} may be a numeric or string variable. @end deftypefn @node Statistical Distribution Functions @subsection Statistical Distribution Functions @pspp{} can calculate several functions of standard statistical distributions. These functions are named systematically based on the function and the distribution. The table below describes the statistical distribution functions in general: @table @asis @item PDF.@var{dist} (@var{x}[, @var{param}@dots{}]) Probability density function for @var{dist}. The domain of @var{x} depends on @var{dist}. For continuous distributions, the result is the density of the probability function at @var{x}, and the range is nonnegative real numbers. For discrete distributions, the result is the probability of @var{x}. @item CDF.@var{dist} (@var{x}[, @var{param}@dots{}]) Cumulative distribution function for @var{dist}, that is, the probability that a random variate drawn from the distribution is less than @var{x}. The domain of @var{x} depends @var{dist}. The result is a probability. @item SIG.@var{dist} (@var{x}[, @var{param}@dots{}) Tail probability function for @var{dist}, that is, the probability that a random variate drawn from the distribution is greater than @var{x}. The domain of @var{x} depends @var{dist}. The result is a probability. Only a few distributions include an @func{SIG} function. @item IDF.@var{dist} (@var{p}[, @var{param}@dots{}]) Inverse distribution function for @var{dist}, the value of @var{x} for which the CDF would yield @var{p}. The value of @var{p} is a probability. The range depends on @var{dist} and is identical to the domain for the corresponding CDF. @item RV.@var{dist} ([@var{param}@dots{}]) Random variate function for @var{dist}. The range depends on the distribution. @item NPDF.@var{dist} (@var{x}[, @var{param}@dots{}]) Noncentral probability density function. The result is the density of the given noncentral distribution at @var{x}. The domain of @var{x} depends on @var{dist}. The range is nonnegative real numbers. Only a few distributions include an @func{NPDF} function. @item NCDF.@var{dist} (@var{x}[, @var{param}@dots{}]) Noncentral cumulative distribution function for @var{dist}, that is, the probability that a random variate drawn from the given noncentral distribution is less than @var{x}. The domain of @var{x} depends @var{dist}. The result is a probability. Only a few distributions include an NCDF function. @end table The individual distributions are described individually below. @menu * Continuous Distributions:: * Discrete Distributions:: @end menu @node Continuous Distributions @subsubsection Continuous Distributions The following continuous distributions are available: @deftypefn {Function} {} PDF.BETA (@var{x}) @deftypefnx {Function} {} CDF.BETA (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.BETA (@var{p}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.BETA (@var{a}, @var{b}) @deftypefnx {Function} {} NPDF.BETA (@var{x}, @var{a}, @var{b}, @var{lambda}) @deftypefnx {Function} {} NCDF.BETA (@var{x}, @var{a}, @var{b}, @var{lambda}) Beta distribution with shape parameters @var{a} and @var{b}. The noncentral distribution takes an additional parameter @var{lambda}. Constraints: @var{a} > 0, @var{b} > 0, @var{lambda} >= 0, 0 <= @var{x} <= 1, 0 <= @var{p} <= 1. @end deftypefn @deftypefn {Function} {} PDF.BVNOR (@var{x0}, @var{x1}, @var{rho}) @deftypefnx {Function} {} CDF.VBNOR (@var{x0}, @var{x1}, @var{rho}) Bivariate normal distribution of two standard normal variables with correlation coefficient @var{rho}. Two variates @var{x0} and @var{x1} must be provided. Constraints: 0 <= @var{rho} <= 1, 0 <= @var{p} <= 1. @end deftypefn @deftypefn {Function} {} PDF.CAUCHY (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.CAUCHY (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.CAUCHY (@var{p}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.CAUCHY (@var{a}, @var{b}) Cauchy distribution with location parameter @var{a} and scale parameter @var{b}. Constraints: @var{b} > 0, 0 < @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.CHISQ (@var{x}, @var{df}) @deftypefnx {Function} {} CDF.CHISQ (@var{x}, @var{df}) @deftypefnx {Function} {} SIG.CHISQ (@var{x}, @var{df}) @deftypefnx {Function} {} IDF.CHISQ (@var{p}, @var{df}) @deftypefnx {Function} {} RV.CHISQ (@var{df}) @deftypefnx {Function} {} NPDF.CHISQ (@var{x}, @var{df}, @var{lambda}) @deftypefnx {Function} {} NCDF.CHISQ (@var{x}, @var{df}, @var{lambda}) Chi-squared distribution with @var{df} degrees of freedom. The noncentral distribution takes an additional parameter @var{lambda}. Constraints: @var{df} > 0, @var{lambda} > 0, @var{x} >= 0, 0 <= @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.EXP (@var{x}, @var{a}) @deftypefnx {Function} {} CDF.EXP (@var{x}, @var{a}) @deftypefnx {Function} {} IDF.EXP (@var{p}, @var{a}) @deftypefnx {Function} {} RV.EXP (@var{a}) Exponential distribution with scale parameter @var{a}. The inverse of @var{a} represents the rate of decay. Constraints: @var{a} > 0, @var{x} >= 0, 0 <= @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.XPOWER (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.XPOWER (@var{a}, @var{b}) Exponential power distribution with positive scale parameter @var{a} and nonnegative power parameter @var{b}. Constraints: @var{a} > 0, @var{b} >= 0, @var{x} >= 0, 0 <= @var{p} <= 1. This distribution is a @pspp{} extension. @end deftypefn @deftypefn {Function} {} PDF.F (@var{x}, @var{df1}, @var{df2}) @deftypefnx {Function} {} CDF.F (@var{x}, @var{df1}, @var{df2}) @deftypefnx {Function} {} SIG.F (@var{x}, @var{df1}, @var{df2}) @deftypefnx {Function} {} IDF.F (@var{p}, @var{df1}, @var{df2}) @deftypefnx {Function} {} RV.F (@var{df1}, @var{df2}) @deftypefnx {Function} {} NPDF.F (@var{x}, @var{df1}, @var{df2}, @var{lambda}) @deftypefnx {Function} {} NCDF.F (@var{x}, @var{df1}, @var{df2}, @var{lambda}) F-distribution of two chi-squared deviates with @var{df1} and @var{df2} degrees of freedom. The noncentral distribution takes an additional parameter @var{lambda}. Constraints: @var{df1} > 0, @var{df2} > 0, @var{lambda} >= 0, @var{x} >= 0, 0 <= @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.GAMMA (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.GAMMA (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.GAMMA (@var{p}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.GAMMA (@var{a}, @var{b}) Gamma distribution with shape parameter @var{a} and scale parameter @var{b}. Constraints: @var{a} > 0, @var{b} > 0, @var{x} >= 0, 0 <= @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.HALFNRM (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.HALFNRM (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.HALFNRM (@var{p}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.HALFNRM (@var{a}, @var{b}) Half-normal distribution with location parameter @var{a} and shape parameter @var{b}. Constraints: @var{b} > 0, 0 < @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.IGAUSS (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.IGAUSS (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.IGAUSS (@var{p}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.IGAUSS (@var{a}, @var{b}) Inverse Gaussian distribution with parameters @var{a} and @var{b}. Constraints: @var{a} > 0, @var{b} > 0, @var{x} > 0, 0 <= @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.LANDAU (@var{x}) @deftypefnx {Function} {} RV.LANDAU () Landau distribution. @end deftypefn @deftypefn {Function} {} PDF.LAPLACE (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.LAPLACE (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.LAPLACE (@var{p}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.LAPLACE (@var{a}, @var{b}) Laplace distribution with location parameter @var{a} and scale parameter @var{b}. Constraints: @var{b} > 0, 0 < @var{p} < 1. @end deftypefn @deftypefn {Function} {} RV.LEVY (@var{c}, @var{alpha}) Levy symmetric alpha-stable distribution with scale @var{c} and exponent @var{alpha}. Constraints: 0 < @var{alpha} <= 2. @end deftypefn @deftypefn {Function} {} RV.LVSKEW (@var{c}, @var{alpha}, @var{beta}) Levy skew alpha-stable distribution with scale @var{c}, exponent @var{alpha}, and skewness parameter @var{beta}. Constraints: 0 < @var{alpha} <= 2, -1 <= @var{beta} <= 1. @end deftypefn @deftypefn {Function} {} PDF.LOGISTIC (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.LOGISTIC (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.LOGISTIC (@var{p}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.LOGISTIC (@var{a}, @var{b}) Logistic distribution with location parameter @var{a} and scale parameter @var{b}. Constraints: @var{b} > 0, 0 < @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.LNORMAL (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.LNORMAL (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.LNORMAL (@var{p}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.LNORMAL (@var{a}, @var{b}) Lognormal distribution with parameters @var{a} and @var{b}. Constraints: @var{a} > 0, @var{b} > 0, @var{x} >= 0, 0 <= @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.NORMAL (@var{x}, @var{mu}, @var{sigma}) @deftypefnx {Function} {} CDF.NORMAL (@var{x}, @var{mu}, @var{sigma}) @deftypefnx {Function} {} IDF.NORMAL (@var{p}, @var{mu}, @var{sigma}) @deftypefnx {Function} {} RV.NORMAL (@var{mu}, @var{sigma}) Normal distribution with mean @var{mu} and standard deviation @var{sigma}. Constraints: @var{b} > 0, 0 < @var{p} < 1. Three additional functions are available as shorthand: @deftypefn {Function} {} CDFNORM (@var{x}) Equivalent to CDF.NORMAL(@var{x}, 0, 1). @end deftypefn @deftypefn {Function} {} PROBIT (@var{p}) Equivalent to IDF.NORMAL(@var{p}, 0, 1). @end deftypefn @deftypefn {Function} {} NORMAL (@var{sigma}) Equivalent to RV.NORMAL(0, @var{sigma}). @end deftypefn @end deftypefn @deftypefn {Function} {} PDF.NTAIL (@var{x}, @var{a}, @var{sigma}) @deftypefnx {Function} {} RV.NTAIL (@var{a}, @var{sigma}) Normal tail distribution with lower limit @var{a} and standard deviation @var{sigma}. This distribution is a @pspp{} extension. Constraints: @var{a} > 0, @var{x} > @var{a}, 0 < @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.PARETO (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.PARETO (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.PARETO (@var{p}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.PARETO (@var{a}, @var{b}) Pareto distribution with threshold parameter @var{a} and shape parameter @var{b}. Constraints: @var{a} > 0, @var{b} > 0, @var{x} >= @var{a}, 0 <= @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.RAYLEIGH (@var{x}, @var{sigma}) @deftypefnx {Function} {} CDF.RAYLEIGH (@var{x}, @var{sigma}) @deftypefnx {Function} {} IDF.RAYLEIGH (@var{p}, @var{sigma}) @deftypefnx {Function} {} RV.RAYLEIGH (@var{sigma}) Rayleigh distribution with scale parameter @var{sigma}. This distribution is a @pspp{} extension. Constraints: @var{sigma} > 0, @var{x} > 0. @end deftypefn @deftypefn {Function} {} PDF.RTAIL (@var{x}, @var{a}, @var{sigma}) @deftypefnx {Function} {} RV.RTAIL (@var{a}, @var{sigma}) Rayleigh tail distribution with lower limit @var{a} and scale parameter @var{sigma}. This distribution is a @pspp{} extension. Constraints: @var{a} > 0, @var{sigma} > 0, @var{x} > @var{a}. @end deftypefn @deftypefn {Function} {} CDF.SMOD (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.SMOD (@var{p}, @var{a}, @var{b}) Studentized maximum modulus distribution with parameters @var{a} and @var{b}. Constraints: @var{a} > 0, @var{b} > 0, @var{x} > 0, 0 <= @var{p} < 1. @end deftypefn @deftypefn {Function} {} CDF.SRANGE (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.SRANGE (@var{p}, @var{a}, @var{b}) Studentized range distribution with parameters @var{a} and @var{b}. Constraints: @var{a} >= 1, @var{b} >= 1, @var{x} > 0, 0 <= @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.T (@var{x}, @var{df}) @deftypefnx {Function} {} CDF.T (@var{x}, @var{df}) @deftypefnx {Function} {} IDF.T (@var{p}, @var{df}) @deftypefnx {Function} {} RV.T (@var{df}) @deftypefnx {Function} {} NPDF.T (@var{x}, @var{df}, @var{lambda}) @deftypefnx {Function} {} NCDF.T (@var{x}, @var{df}, @var{lambda}) T-distribution with @var{df} degrees of freedom. The noncentral distribution takes an additional parameter @var{lambda}. Constraints: @var{df} > 0, 0 < @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.T1G (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.T1G (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.T1G (@var{p}, @var{a}, @var{b}) Type-1 Gumbel distribution with parameters @var{a} and @var{b}. This distribution is a @pspp{} extension. Constraints: 0 < @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.T2G (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.T2G (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.T2G (@var{p}, @var{a}, @var{b}) Type-2 Gumbel distribution with parameters @var{a} and @var{b}. This distribution is a @pspp{} extension. Constraints: @var{x} > 0, 0 < @var{p} < 1. @end deftypefn @deftypefn {Function} {} PDF.UNIFORM (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.UNIFORM (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.UNIFORM (@var{p}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.UNIFORM (@var{a}, @var{b}) Uniform distribution with parameters @var{a} and @var{b}. Constraints: @var{a} <= @var{x} <= @var{b}, 0 <= @var{p} <= 1. An additional function is available as shorthand: @deftypefn {Function} {} UNIFORM (@var{b}) Equivalent to RV.UNIFORM(0, @var{b}). @end deftypefn @end deftypefn @deftypefn {Function} {} PDF.WEIBULL (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} CDF.WEIBULL (@var{x}, @var{a}, @var{b}) @deftypefnx {Function} {} IDF.WEIBULL (@var{p}, @var{a}, @var{b}) @deftypefnx {Function} {} RV.WEIBULL (@var{a}, @var{b}) Weibull distribution with parameters @var{a} and @var{b}. Constraints: @var{a} > 0, @var{b} > 0, @var{x} >= 0, 0 <= @var{p} < 1. @end deftypefn @node Discrete Distributions @subsubsection Discrete Distributions The following discrete distributions are available: @deftypefn {Function} {} PDF.BERNOULLI (@var{x}) @deftypefnx {Function} {} CDF.BERNOULLI (@var{x}, @var{p}) @deftypefnx {Function} {} RV.BERNOULLI (@var{p}) Bernoulli distribution with probability of success @var{p}. Constraints: @var{x} = 0 or 1, 0 <= @var{p} <= 1. @end deftypefn @deftypefn {Function} {} PDF.BINOMIAL (@var{x}, @var{n}, @var{p}) @deftypefnx {Function} {} CDF.BINOMIAL (@var{x}, @var{n}, @var{p}) @deftypefnx {Function} {} RV.BINOMIAL (@var{n}, @var{p}) Binomial distribution with @var{n} trials and probability of success @var{p}. Constraints: integer @var{n} > 0, 0 <= @var{p} <= 1, integer @var{x} <= @var{n}. @end deftypefn @deftypefn {Function} {} PDF.GEOM (@var{x}, @var{n}, @var{p}) @deftypefnx {Function} {} CDF.GEOM (@var{x}, @var{n}, @var{p}) @deftypefnx {Function} {} RV.GEOM (@var{n}, @var{p}) Geometric distribution with probability of success @var{p}. Constraints: 0 <= @var{p} <= 1, integer @var{x} > 0. @end deftypefn @deftypefn {Function} {} PDF.HYPER (@var{x}, @var{a}, @var{b}, @var{c}) @deftypefnx {Function} {} CDF.HYPER (@var{x}, @var{a}, @var{b}, @var{c}) @deftypefnx {Function} {} RV.HYPER (@var{a}, @var{b}, @var{c}) Hypergeometric distribution when @var{b} objects out of @var{a} are drawn and @var{c} of the available objects are distinctive. Constraints: integer @var{a} > 0, integer @var{b} <= @var{a}, integer @var{c} <= @var{a}, integer @var{x} >= 0. @end deftypefn @deftypefn {Function} {} PDF.LOG (@var{x}, @var{p}) @deftypefnx {Function} {} RV.LOG (@var{p}) Logarithmic distribution with probability parameter @var{p}. Constraints: 0 <= @var{p} < 1, @var{x} >= 1. @end deftypefn @deftypefn {Function} {} PDF.NEGBIN (@var{x}, @var{n}, @var{p}) @deftypefnx {Function} {} CDF.NEGBIN (@var{x}, @var{n}, @var{p}) @deftypefnx {Function} {} RV.NEGBIN (@var{n}, @var{p}) Negative binomial distribution with number of successes parameter @var{n} and probability of success parameter @var{p}. Constraints: integer @var{n} >= 0, 0 < @var{p} <= 1, integer @var{x} >= 1. @end deftypefn @deftypefn {Function} {} PDF.POISSON (@var{x}, @var{mu}) @deftypefnx {Function} {} CDF.POISSON (@var{x}, @var{mu}) @deftypefnx {Function} {} RV.POISSON (@var{mu}) Poisson distribution with mean @var{mu}. Constraints: @var{mu} > 0, integer @var{x} >= 0. @end deftypefn @node Order of Operations @section Operator Precedence @cindex operator precedence @cindex precedence, operator @cindex order of operations @cindex operations, order of The following table describes operator precedence. Smaller-numbered levels in the table have higher precedence. Within a level, operations are always performed from left to right. The first occurrence of @samp{-} represents unary negation, the second binary subtraction. @enumerate @item @code{( )} @item @code{**} @item @code{-} @item @code{* /} @item @code{+ -} @item @code{EQ GE GT LE LT NE} @item @code{AND NOT OR} @end enumerate pspp-master/doc/fdl.texi000066400000000000000000000561341177044323000155500ustar00rootroot00000000000000@node GNU Free Documentation License @appendix GNU Free Documentation License @c The GNU Free Documentation License. @center Version 1.3, 3 November 2008 @c This file is intended to be included within another document, @c hence no sectioning command or @node. @display Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. @uref{http://fsf.org/} Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end display @enumerate 0 @item PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document @dfn{free} in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of ``copyleft'', which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. @item APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The ``Document'', below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as ``you''. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A ``Modified Version'' of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A ``Secondary Section'' is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The ``Invariant Sections'' are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The ``Cover Texts'' are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A ``Transparent'' copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not ``Transparent'' is called ``Opaque''. Examples of suitable formats for Transparent copies include plain @sc{ascii} without markup, Texinfo input format, La@TeX{} input format, @acronym{SGML} or @acronym{XML} using a publicly available @acronym{DTD}, and standard-conforming simple @acronym{HTML}, PostScript or @acronym{PDF} designed for human modification. Examples of transparent image formats include @acronym{PNG}, @acronym{XCF} and @acronym{JPG}. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, @acronym{SGML} or @acronym{XML} for which the @acronym{DTD} and/or processing tools are not generally available, and the machine-generated @acronym{HTML}, PostScript or @acronym{PDF} produced by some word processors for output purposes only. The ``Title Page'' means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, ``Title Page'' means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. The ``publisher'' means any person or entity that distributes copies of the Document to the public. A section ``Entitled XYZ'' means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as ``Acknowledgements'', ``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' of such a section when you modify the Document means that it remains a section ``Entitled XYZ'' according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. @item VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. @item COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. @item MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: @enumerate A @item Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. @item List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. @item State on the Title page the name of the publisher of the Modified Version, as the publisher. @item Preserve all the copyright notices of the Document. @item Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. @item Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. @item Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. @item Include an unaltered copy of this License. @item Preserve the section Entitled ``History'', Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled ``History'' in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. @item Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the ``History'' section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. @item For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. @item Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. @item Delete any section Entitled ``Endorsements''. Such a section may not be included in the Modified Version. @item Do not retitle any existing section to be Entitled ``Endorsements'' or to conflict in title with any Invariant Section. @item Preserve any Warranty Disclaimers. @end enumerate If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled ``Endorsements'', provided it contains nothing but endorsements of your Modified Version by various parties---for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. @item COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled ``History'' in the various original documents, forming one section Entitled ``History''; likewise combine any sections Entitled ``Acknowledgements'', and any sections Entitled ``Dedications''. You must delete all sections Entitled ``Endorsements.'' @item COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. @item AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an ``aggregate'' if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. @item TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled ``Acknowledgements'', ``Dedications'', or ``History'', the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. @item TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License. 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, receipt of a copy of some or all of the same material does not give you any rights to use it. @item FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation 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. See @uref{http://www.gnu.org/copyleft/}. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License ``or any later version'' applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Document. @item RELICENSING ``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A ``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the site means any set of copyrightable works thus published on the MMC site. ``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization. ``Incorporate'' means to publish or republish a Document, in whole or in part, as part of another Document. An MMC is ``eligible for relicensing'' if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008. The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. @end enumerate @page @heading ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: @smallexample @group Copyright (C) @var{year} @var{your name}. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. @end group @end smallexample If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the ``with@dots{}Texts.'' line with this: @smallexample @group with the Invariant Sections being @var{list their titles}, with the Front-Cover Texts being @var{list}, and with the Back-Cover Texts being @var{list}. @end group @end smallexample If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software. @c Local Variables: @c ispell-local-pdict: "ispell-dict" @c End: pspp-master/doc/files.texi000066400000000000000000001066131177044323000161030ustar00rootroot00000000000000@node System and Portable File IO @chapter System and Portable File I/O The commands in this chapter read, write, and examine system files and portable files. @menu * APPLY DICTIONARY:: Apply system file dictionary to active dataset. * EXPORT:: Write to a portable file. * GET:: Read from a system file. * GET DATA:: Read from foreign files. * IMPORT:: Read from a portable file. * SAVE:: Write to a system file. * SAVE TRANSLATE:: Write data in foreign file formats. * SYSFILE INFO:: Display system file dictionary. * XEXPORT:: Write to a portable file, as a transformation. * XSAVE:: Write to a system file, as a transformation. @end menu @node APPLY DICTIONARY @section APPLY DICTIONARY @vindex APPLY DICTIONARY @display APPLY DICTIONARY FROM=@{'@var{file_name}',@var{file_handle}@}. @end display @cmd{APPLY DICTIONARY} applies the variable labels, value labels, and missing values taken from a file to corresponding variables in the active dataset. In some cases it also updates the weighting variable. Specify a system file or portable file's name, a data set name (@pxref{Datasets}), or a file handle name (@pxref{File Handles}). The dictionary in the file will be read, but it will not replace the active dataset's dictionary. The file's data will not be read. Only variables with names that exist in both the active dataset and the system file are considered. Variables with the same name but different types (numeric, string) will cause an error message. Otherwise, the system file variables' attributes will replace those in their matching active dataset variables: @itemize @bullet @item If a system file variable has a variable label, then it will replace the variable label of the active dataset variable. If the system file variable does not have a variable label, then the active dataset variable's variable label, if any, will be retained. @item If the system file variable has custom attributes (@pxref{VARIABLE ATTRIBUTE}), then those attributes replace the active dataset variable's custom attributes. If the system file variable does not have custom attributes, then the active dataset variable's custom attributes, if any, will be retained. @item If the active dataset variable is numeric or short string, then value labels and missing values, if any, will be copied to the active dataset variable. If the system file variable does not have value labels or missing values, then those in the active dataset variable, if any, will not be disturbed. @end itemize In addition to properties of variables, some properties of the active file dictionary as a whole are updated: @itemize @bullet @item If the system file has custom attributes (@pxref{DATAFILE ATTRIBUTE}), then those attributes replace the active dataset variable's custom attributes. @item If the active dataset has a weighting variable (@pxref{WEIGHT}), and the system file does not, or if the weighting variable in the system file does not exist in the active dataset, then the active dataset weighting variable, if any, is retained. Otherwise, the weighting variable in the system file becomes the active dataset weighting variable. @end itemize @cmd{APPLY DICTIONARY} takes effect immediately. It does not read the active dataset. The system file is not modified. @node EXPORT @section EXPORT @vindex EXPORT @display EXPORT /OUTFILE='@var{file_name}' /UNSELECTED=@{RETAIN,DELETE@} /DIGITS=@var{n} /DROP=@var{var_list} /KEEP=@var{var_list} /RENAME=(@var{src_names}=@var{target_names})@dots{} /TYPE=@{COMM,TAPE@} /MAP @end display The @cmd{EXPORT} procedure writes the active dataset's dictionary and data to a specified portable file. By default, cases excluded with FILTER are written to the file. These can be excluded by specifying DELETE on the @subcmd{UNSELECTED} subcommand. Specifying RETAIN makes the default explicit. Portable files express real numbers in base 30. Integers are always expressed to the maximum precision needed to make them exact. Non-integers are, by default, expressed to the machine's maximum natural precision (approximately 15 decimal digits on many machines). If many numbers require this many digits, the portable file may significantly increase in size. As an alternative, the @subcmd{DIGITS} subcommand may be used to specify the number of decimal digits of precision to write. @subcmd{DIGITS} applies only to non-integers. The @subcmd{OUTFILE} subcommand, which is the only required subcommand, specifies the portable file to be written as a file name string or a file handle (@pxref{File Handles}). @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} follow the same format as the @subcmd{SAVE} procedure (@pxref{SAVE}). The @subcmd{TYPE} subcommand specifies the character set for use in the portable file. Its value is currently not used. The @subcmd{MAP} subcommand is currently ignored. @cmd{EXPORT} is a procedure. It causes the active dataset to be read. @node GET @section GET @vindex GET @display GET /FILE=@{'@var{file_name}',@var{file_handle}@} /DROP=@var{var_list} /KEEP=@var{var_list} /RENAME=(@var{src_names}=@var{target_names})@dots{} /ENCODING='@var{encoding}' @end display @cmd{GET} clears the current dictionary and active dataset and replaces them with the dictionary and data from a specified file. The @subcmd{FILE} subcommand is the only required subcommand. Specify the system file or portable file to be read as a string file name or a file handle (@pxref{File Handles}). By default, all the variables in a file are read. The DROP subcommand can be used to specify a list of variables that are not to be read. By contrast, the @subcmd{KEEP} subcommand can be used to specify variable that are to be read, with all other variables not read. Normally variables in a file retain the names that they were saved under. Use the @subcmd{RENAME} subcommand to change these names. Specify, within parentheses, a list of variable names followed by an equals sign (@samp{=}) and the names that they should be renamed to. Multiple parenthesized groups of variable names can be included on a single @subcmd{RENAME} subcommand. Variables' names may be swapped using a @subcmd{RENAME} subcommand of the form @subcmd{/RENAME=(@var{A} @var{B}=@var{B} @var{A})}. Alternate syntax for the @subcmd{RENAME} subcommand allows the parentheses to be eliminated. When this is done, only a single variable may be renamed at once. For instance, @subcmd{/RENAME=@var{A}=@var{B}}. This alternate syntax is deprecated. @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} are executed in left-to-right order. Each may be present any number of times. @cmd{GET} never modifies a file on disk. Only the active dataset read from the file is affected by these subcommands. @pspp{} tries to automatically detect the encoding of string data in the file. Sometimes, however, this does not work well encoding, especially for files written by old versions of SPSS or @pspp{}. Specify the @subcmd{ENCODING} subcommand with an @acronym{IANA} character set name as its string argument to override the default. The @subcmd{ENCODING} subcommand is a @pspp{} extension. @cmd{GET} does not cause the data to be read, only the dictionary. The data is read later, when a procedure is executed. Use of @cmd{GET} to read a portable file is a @pspp{} extension. @node GET DATA @section GET DATA @vindex GET DATA @display GET DATA /TYPE=@{GNM,ODS,PSQL,TXT@} @dots{}additional subcommands depending on TYPE@dots{} @end display The @cmd{GET DATA} command is used to read files and other data sources created by other applications. When this command is executed, the current dictionary and active dataset are replaced with variables and data read from the specified source. The @subcmd{TYPE} subcommand is mandatory and must be the first subcommand specified. It determines the type of the file or source to read. @pspp{} currently supports the following file types: @table @asis @item GNM Spreadsheet files created by Gnumeric (@url{http://gnumeric.org}). @item ODS Spreadsheet files in OpenDocument format. @item PSQL Relations from PostgreSQL databases (@url{http://postgresql.org}). @item TXT Textual data files in columnar and delimited formats. @end table Each supported file type has additional subcommands, explained in separate sections below. @menu * GET DATA /TYPE=GNM/ODS:: Spreadsheets * GET DATA /TYPE=PSQL:: Databases * GET DATA /TYPE=TXT:: Delimited Text Files @end menu @node GET DATA /TYPE=GNM/ODS @subsection Spreadsheet Files @display GET DATA /TYPE=@{GNM, ODS@} /FILE=@{'@var{file_name}'@} /SHEET=@{NAME '@var{sheet_name}', INDEX @var{n}@} /CELLRANGE=@{RANGE '@var{range}', FULL@} /READNAMES=@{ON, OFF@} /ASSUMEDVARWIDTH=@var{n}. @end display @cindex Gnumeric @cindex OpenDocument @cindex spreadsheet files Gnumeric spreadsheets (@url{http://gnumeric.org}), and spreadsheets in OpenDocument format (@url{http://libreplanet.org/wiki/Group:OpenDocument/Software}) can be read using the @cmd{GET DATA} command. Use the @subcmd{TYPE} subcommand to indicate the file's format. /TYPE=GNM indicates Gnumeric files, /TYPE=ODS indicates OpenDocument. The @subcmd{FILE} subcommand is mandatory. Use it to specify the name file to be read. All other subcommands are optional. The format of each variable is determined by the format of the spreadsheet cell containing the first datum for the variable. If this cell is of string (text) format, then the width of the variable is determined from the length of the string it contains, unless the @subcmd{ASSUMEDVARWIDTH} subcommand is given. The @subcmd{SHEET} subcommand specifies the sheet within the spreadsheet file to read. There are two forms of the @subcmd{SHEET} subcommand. In the first form, @subcmd{/SHEET=name @var{sheet_name}}, the string @var{sheet_name} is the name of the sheet to read. In the second form, @subcmd{/SHEET=index @var{idx}}, @var{idx} is a integer which is the index of the sheet to read. The first sheet has the index 1. If the @subcmd{SHEET} subcommand is omitted, then the command will read the first sheet in the file. The @subcmd{CELLRANGE} subcommand specifies the range of cells within the sheet to read. If the subcommand is given as @subcmd{/CELLRANGE=FULL}, then the entire sheet is read. To read only part of a sheet, use the form @subcmd{/CELLRANGE=range '@var{top_left_cell}:@var{bottom_right_cell}'}. For example, the subcommand @subcmd{/CELLRANGE=range 'C3:P19'} reads columns C--P, and rows 3--19 inclusive. If no @subcmd{CELLRANGE} subcommand is given, then the entire sheet is read. If @subcmd{/READNAMES=ON} is specified, then the contents of cells of the first row are used as the names of the variables in which to store the data from subsequent rows. This is the default. If @subcmd{/READNAMES=OFF} is used, then the variables receive automatically assigned names. The @subcmd{ASSUMEDVARWIDTH} subcommand specifies the maximum width of string variables read from the file. If omitted, the default value is determined from the length of the string in the first spreadsheet cell for each variable. @node GET DATA /TYPE=PSQL @subsection Postgres Database Queries @display GET DATA /TYPE=PSQL /CONNECT=@{@var{connection info}@} /SQL=@{@var{query}@} [/ASSUMEDVARWIDTH=@var{w}] [/UNENCRYPTED] [/BSIZE=@var{n}]. @end display @cindex postgres @cindex databases The PSQL type is used to import data from a postgres database server. The server may be located locally or remotely. Variables are automatically created based on the table column names or the names specified in the SQL query. Postgres data types of high precision, will loose precision when imported into @pspp{}. Not all the postgres data types are able to be represented in @pspp{}. If a datum cannot be represented a warning will be issued and that datum will be set to SYSMIS. The @subcmd{CONNECT} subcommand is mandatory. It is a string specifying the parameters of the database server from which the data should be fetched. The format of the string is given in the postgres manual @url{http://www.postgresql.org/docs/8.0/static/libpq.html#LIBPQ-CONNECT}. The @subcmd{SQL} subcommand is mandatory. It must be a valid SQL string to retrieve data from the database. The @subcmd{ASSUMEDVARWIDTH} subcommand specifies the maximum width of string variables read from the database. If omitted, the default value is determined from the length of the string in the first value read for each variable. The @subcmd{UNENCRYPTED} subcommand allows data to be retrieved over an insecure connection. If the connection is not encrypted, and the @subcmd{UNENCRYPTED} subcommand is not given, then an error will occur. Whether or not the connection is encrypted depends upon the underlying psql library and the capabilities of the database server. The @subcmd{BSIZE} subcommand serves only to optimise the speed of data transfer. It specifies an upper limit on number of cases to fetch from the database at once. The default value is 4096. If your SQL statement fetches a large number of cases but only a small number of variables, then the data transfer may be faster if you increase this value. Conversely, if the number of variables is large, or if the machine on which @pspp{} is running has only a small amount of memory, then a smaller value will be better. The following syntax is an example: @example GET DATA /TYPE=PSQL /CONNECT='host=example.com port=5432 dbname=product user=fred passwd=xxxx' /SQL='select * from manufacturer'. @end example @node GET DATA /TYPE=TXT @subsection Textual Data Files @display GET DATA /TYPE=TXT /FILE=@{'@var{file_name}',@var{file_handle}@} [ENCODING='@var{encoding}'] [/ARRANGEMENT=@{DELIMITED,FIXED@}] [/FIRSTCASE=@{@var{first_case}@}] [/IMPORTCASE=@{ALL,FIRST @var{max_cases},PERCENT @var{percent}@}] @dots{}additional subcommands depending on ARRANGEMENT@dots{} @end display @cindex text files @cindex data files When TYPE=TXT is specified, GET DATA reads data in a delimited or fixed columnar format, much like DATA LIST (@pxref{DATA LIST}). The @subcmd{FILE} subcommand is mandatory. Specify the file to be read as a string file name or (for textual data only) a file handle (@pxref{File Handles}). The @subcmd{ENCODING} subcommand specifies the character encoding of the file to be read. @xref{INSERT}, for information on supported encodings. The @subcmd{ARRANGEMENT} subcommand determines the file's basic format. DELIMITED, the default setting, specifies that fields in the input data are separated by spaces, tabs, or other user-specified delimiters. FIXED specifies that fields in the input data appear at particular fixed column positions within records of a case. By default, cases are read from the input file starting from the first line. To skip lines at the beginning of an input file, set @subcmd{FIRSTCASE} to the number of the first line to read: 2 to skip the first line, 3 to skip the first two lines, and so on. @subcmd{IMPORTCASE} can be used to limit the number of cases read from the input file. With the default setting, ALL, all cases in the file are read. Specify FIRST @var{max_cases} to read at most @var{max_cases} cases from the file. Use @subcmd{PERCENT @var{percent}} to read only @var{percent} percent, approximately, of the cases contained in the file. (The percentage is approximate, because there is no way to accurately count the number of cases in the file without reading the entire file. The number of cases in some kinds of unusual files cannot be estimated; @pspp{} will read all cases in such files.) @subcmd{FIRSTCASE} and @subcmd{IMPORTCASE} may be used with delimited and fixed-format data. The remaining subcommands, which apply only to one of the two file arrangements, are described below. @menu * GET DATA /TYPE=TXT /ARRANGEMENT=DELIMITED:: * GET DATA /TYPE=TXT /ARRANGEMENT=FIXED:: @end menu @node GET DATA /TYPE=TXT /ARRANGEMENT=DELIMITED @subsubsection Reading Delimited Data @display GET DATA /TYPE=TXT /FILE=@{'@var{file_name}',@var{file_handle}@} [/ARRANGEMENT=@{DELIMITED,FIXED@}] [/FIRSTCASE=@{@var{first_case}@}] [/IMPORTCASE=@{ALL,FIRST @var{max_cases},PERCENT @var{percent}@}] /DELIMITERS="@var{delimiters}" [/QUALIFIER="@var{quotes}" [/ESCAPE]] [/DELCASE=@{LINE,VARIABLES @var{n_variables}@}] /VARIABLES=@var{del_var1} [@var{del_var2}]@dots{} where each @var{del_var} takes the form: variable format @end display The GET DATA command with TYPE=TXT and ARRANGEMENT=DELIMITED reads input data from text files in delimited format, where fields are separated by a set of user-specified delimiters. Its capabilities are similar to those of DATA LIST FREE (@pxref{DATA LIST FREE}), with a few enhancements. The required @subcmd{FILE} subcommand and optional @subcmd{FIRSTCASE} and @subcmd{IMPORTCASE} subcommands are described above (@pxref{GET DATA /TYPE=TXT}). @subcmd{DELIMITERS}, which is required, specifies the set of characters that may separate fields. Each character in the string specified on @subcmd{DELIMITERS} separates one field from the next. The end of a line also separates fields, regardless of @subcmd{DELIMITERS}. Two consecutive delimiters in the input yield an empty field, as does a delimiter at the end of a line. A space character as a delimiter is an exception: consecutive spaces do not yield an empty field and neither does any number of spaces at the end of a line. To use a tab as a delimiter, specify @samp{\t} at the beginning of the @subcmd{DELIMITERS} string. To use a backslash as a delimiter, specify @samp{\\} as the first delimiter or, if a tab should also be a delimiter, immediately following @samp{\t}. To read a data file in which each field appears on a separate line, specify the empty string for @subcmd{DELIMITERS}. The optional @subcmd{QUALIFIER} subcommand names one or more characters that can be used to quote values within fields in the input. A field that begins with one of the specified quote characters ends at the next matching quote. Intervening delimiters become part of the field, instead of terminating it. The ability to specify more than one quote character is a @pspp{} extension. By default, a character specified on @subcmd{QUALIFIER} cannot itself be embedded within a field that it quotes, because the quote character always terminates the quoted field. With ESCAPE, however, a doubled quote character within a quoted field inserts a single instance of the quote into the field. For example, if @samp{'} is specified on @subcmd{QUALIFIER}, then without ESCAPE @code{'a''b'} specifies a pair of fields that contain @samp{a} and @samp{b}, but with ESCAPE it specifies a single field that contains @samp{a'b}. ESCAPE is a @pspp{} extension. The @subcmd{DELCASE} subcommand controls how data may be broken across lines in the data file. With LINE, the default setting, each line must contain all the data for exactly one case. For additional flexibility, to allow a single case to be split among lines or multiple cases to be contained on a single line, specify VARIABLES @i{n_variables}, where @i{n_variables} is the number of variables per case. The @subcmd{VARIABLES} subcommand is required and must be the last subcommand. Specify the name of each variable and its input format (@pxref{Input and Output Formats}) in the order they should be read from the input file. @subsubheading Examples @noindent On a Unix-like system, the @samp{/etc/passwd} file has a format similar to this: @example root:$1$nyeSP5gD$pDq/:0:0:,,,:/root:/bin/bash blp:$1$BrP/pFg4$g7OG:1000:1000:Ben Pfaff,,,:/home/blp:/bin/bash john:$1$JBuq/Fioq$g4A:1001:1001:John Darrington,,,:/home/john:/bin/bash jhs:$1$D3li4hPL$88X1:1002:1002:Jason Stover,,,:/home/jhs:/bin/csh @end example @noindent The following syntax reads a file in the format used by @samp{/etc/passwd}: @c If you change this example, change the regression test in @c tests/language/data-io/get-data.at to match. @example GET DATA /TYPE=TXT /FILE='/etc/passwd' /DELIMITERS=':' /VARIABLES=username A20 password A40 uid F10 gid F10 gecos A40 home A40 shell A40. @end example @noindent Consider the following data on used cars: @example model year mileage price type age Civic 2002 29883 15900 Si 2 Civic 2003 13415 15900 EX 1 Civic 1992 107000 3800 n/a 12 Accord 2002 26613 17900 EX 1 @end example @noindent The following syntax can be used to read the used car data: @c If you change this example, change the regression test in @c tests/language/data-io/get-data.at to match. @example GET DATA /TYPE=TXT /FILE='cars.data' /DELIMITERS=' ' /FIRSTCASE=2 /VARIABLES=model A8 year F4 mileage F6 price F5 type A4 age F2. @end example @noindent Consider the following information on animals in a pet store: @example 'Pet''s Name', "Age", "Color", "Date Received", "Price", "Height", "Type" , (Years), , , (Dollars), , "Rover", 4.5, Brown, "12 Feb 2004", 80, '1''4"', "Dog" "Charlie", , Gold, "5 Apr 2007", 12.3, "3""", "Fish" "Molly", 2, Black, "12 Dec 2006", 25, '5"', "Cat" "Gilly", , White, "10 Apr 2007", 10, "3""", "Guinea Pig" @end example @noindent The following syntax can be used to read the pet store data: @c If you change this example, change the regression test in @c tests/language/data-io/get-data.at to match. @example GET DATA /TYPE=TXT /FILE='pets.data' /DELIMITERS=', ' /QUALIFIER='''"' /ESCAPE /FIRSTCASE=3 /VARIABLES=name A10 age F3.1 color A5 received EDATE10 price F5.2 height a5 type a10. @end example @node GET DATA /TYPE=TXT /ARRANGEMENT=FIXED @subsubsection Reading Fixed Columnar Data @c (modify-syntax-entry ?_ "w") @c (modify-syntax-entry ?' "'") @c (modify-syntax-entry ?@ "'") @display GET DATA /TYPE=TXT /FILE=@{'file_name',@var{file_handle}@} [/ARRANGEMENT=@{DELIMITED,FIXED@}] [/FIRSTCASE=@{@var{first_case}@}] [/IMPORTCASE=@{ALL,FIRST @var{max_cases},PERCENT @var{percent}@}] [/FIXCASE=@var{n}] /VARIABLES @var{fixed_var} [@var{fixed_var}]@dots{} [/rec# @var{fixed_var} [@var{fixed_var}]@dots{}]@dots{} where each @var{fixed_var} takes the form: @var{variable} @var{start}-@var{end} @var{format} @end display The @cmd{GET DATA} command with TYPE=TXT and ARRANGEMENT=FIXED reads input data from text files in fixed format, where each field is located in particular fixed column positions within records of a case. Its capabilities are similar to those of DATA LIST FIXED (@pxref{DATA LIST FIXED}), with a few enhancements. The required @subcmd{FILE} subcommand and optional @subcmd{FIRSTCASE} and @subcmd{IMPORTCASE} subcommands are described above (@pxref{GET DATA /TYPE=TXT}). The optional @subcmd{FIXCASE} subcommand may be used to specify the positive integer number of input lines that make up each case. The default value is 1. The @subcmd{VARIABLES} subcommand, which is required, specifies the positions at which each variable can be found. For each variable, specify its name, followed by its start and end column separated by @samp{-} (e.g.@: @samp{0-9}), followed by an input format type (e.g.@: @samp{F}) or a full format specification (e.g.@: @samp{DOLLAR12.2}). For this command, columns are numbered starting from 0 at the left column. Introduce the variables in the second and later lines of a case by a slash followed by the number of the line within the case, e.g.@: @samp{/2} for the second line. @subsubheading Examples @noindent Consider the following data on used cars: @example model year mileage price type age Civic 2002 29883 15900 Si 2 Civic 2003 13415 15900 EX 1 Civic 1992 107000 3800 n/a 12 Accord 2002 26613 17900 EX 1 @end example @noindent The following syntax can be used to read the used car data: @c If you change this example, change the regression test in @c tests/language/data-io/get-data.at to match. @example GET DATA /TYPE=TXT /FILE='cars.data' /ARRANGEMENT=FIXED /FIRSTCASE=2 /VARIABLES=model 0-7 A year 8-15 F mileage 16-23 F price 24-31 F type 32-40 A age 40-47 F. @end example @node IMPORT @section IMPORT @vindex IMPORT @display IMPORT /FILE='@var{file_name}' /TYPE=@{COMM,TAPE@} /DROP=@var{var_list} /KEEP=@var{var_list} /RENAME=(@var{src_names}=@var{target_names})@dots{} @end display The @cmd{IMPORT} transformation clears the active dataset dictionary and data and replaces them with a dictionary and data from a system file or portable file. The @subcmd{FILE} subcommand, which is the only required subcommand, specifies the portable file to be read as a file name string or a file handle (@pxref{File Handles}). The @subcmd{TYPE} subcommand is currently not used. @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} follow the syntax used by @cmd{GET} (@pxref{GET}). @cmd{IMPORT} does not cause the data to be read; only the dictionary. The data is read later, when a procedure is executed. Use of @cmd{IMPORT} to read a system file is a @pspp{} extension. @node SAVE @section SAVE @vindex SAVE @display SAVE /OUTFILE=@{'@var{file_name}',@var{file_handle}@} /UNSELECTED=@{RETAIN,DELETE@} /@{COMPRESSED,UNCOMPRESSED@} /PERMISSIONS=@{WRITEABLE,READONLY@} /DROP=@var{var_list} /KEEP=@var{var_list} /VERSION=@var{version} /RENAME=(@var{src_names}=@var{target_names})@dots{} /NAMES /MAP @end display The @cmd{SAVE} procedure causes the dictionary and data in the active dataset to be written to a system file. OUTFILE is the only required subcommand. Specify the system file to be written as a string file name or a file handle (@pxref{File Handles}). By default, cases excluded with FILTER are written to the system file. These can be excluded by specifying @subcmd{DELETE} on the @subcmd{UNSELECTED} subcommand. Specifying @subcmd{RETAIN} makes the default explicit. The @subcmd{COMPRESS} and @subcmd{UNCOMPRESS} subcommand determine whether the saved system file is compressed. By default, system files are compressed. This default can be changed with the SET command (@pxref{SET}). The @subcmd{PERMISSIONS} subcommand specifies permissions for the new system file. WRITEABLE, the default, creates the file with read and write permission. READONLY creates the file for read-only access. By default, all the variables in the active dataset dictionary are written to the system file. The @subcmd{DROP} subcommand can be used to specify a list of variables not to be written. In contrast, KEEP specifies variables to be written, with all variables not specified not written. Normally variables are saved to a system file under the same names they have in the active dataset. Use the @subcmd{RENAME} subcommand to change these names. Specify, within parentheses, a list of variable names followed by an equals sign (@samp{=}) and the names that they should be renamed to. Multiple parenthesized groups of variable names can be included on a single @subcmd{RENAME} subcommand. Variables' names may be swapped using a @subcmd{RENAME} subcommand of the form @subcmd{/RENAME=(@var{A} @var{B}=@var{B} @var{A})}. Alternate syntax for the @subcmd{RENAME} subcommand allows the parentheses to be eliminated. When this is done, only a single variable may be renamed at once. For instance, @subcmd{/RENAME=@var{A}=@var{B}}. This alternate syntax is deprecated. @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} are performed in left-to-right order. They each may be present any number of times. @cmd{SAVE} never modifies the active dataset. @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} only affect the system file written to disk. The @subcmd{VERSION} subcommand specifies the version of the file format. Valid versions are 2 and 3. The default version is 3. In version 2 system files, variable names longer than 8 bytes will be truncated. The two versions are otherwise identical. The @subcmd{NAMES} and @subcmd{MAP} subcommands are currently ignored. @cmd{SAVE} causes the data to be read. It is a procedure. @node SAVE TRANSLATE @section SAVE TRANSLATE @vindex SAVE TRANSLATE @display SAVE TRANSLATE /OUTFILE=@{'@var{file_name}',@var{file_handle}@} /TYPE=@{CSV,TAB@} [/REPLACE] [/MISSING=@{IGNORE,RECODE@}] [/DROP=@var{var_list}] [/KEEP=@var{var_list}] [/RENAME=(@var{src_names}=@var{target_names})@dots{}] [/UNSELECTED=@{RETAIN,DELETE@}] [/MAP] @dots{}additional subcommands depending on TYPE@dots{} @end display The @cmd{SAVE TRANSLATE} command is used to save data into various formats understood by other applications. The @subcmd{OUTFILE} and @subcmd{TYPE} subcommands are mandatory. @subcmd{OUTFILE} specifies the file to be written, as a string file name or a file handle (@pxref{File Handles}). @subcmd{TYPE} determines the type of the file or source to read. It must be one of the following: @table @asis @item CSV Comma-separated value format, @item TAB Tab-delimited format. @end table By default, @cmd{SAVE TRANSLATE} will not overwrite an existing file. Use @subcmd{REPLACE} to force an existing file to be overwritten. With MISSING=IGNORE, the default, @subcmd{SAVE TRANSLATE} treats user-missing values as if they were not missing. Specify MISSING=RECODE to output numeric user-missing values like system-missing values and string user-missing values as all spaces. By default, all the variables in the active dataset dictionary are saved to the system file, but @subcmd{DROP} or @subcmd{KEEP} can select a subset of variable to save. The @subcmd{RENAME} subcommand can also be used to change the names under which variables are saved. @subcmd{UNSELECTED} determines whether cases filtered out by the @cmd{FILTER} command are written to the output file. These subcommands have the same syntax and meaning as on the @cmd{SAVE} command (@pxref{SAVE}). Each supported file type has additional subcommands, explained in separate sections below. @cmd{SAVE TRANSLATE} causes the data to be read. It is a procedure. @menu * SAVE TRANSLATE /TYPE=CSV and TYPE=TAB:: @end menu @node SAVE TRANSLATE /TYPE=CSV and TYPE=TAB @subsection Writing Comma- and Tab-Separated Data Files @display SAVE TRANSLATE /OUTFILE=@{'@var{file_name}',@var{file_handle}@} /TYPE=CSV [/REPLACE] [/MISSING=@{IGNORE,RECODE@}] [/DROP=@var{var_list}] [/KEEP=@var{var_list}] [/RENAME=(@var{src_names}=@var{target_names})@dots{}] [/UNSELECTED=@{RETAIN,DELETE@}] [/FIELDNAMES] [/CELLS=@{VALUES,LABELS@}] [/TEXTOPTIONS DELIMITER='@var{delimiter}'] [/TEXTOPTIONS QUALIFIER='@var{qualifier}'] [/TEXTOPTIONS DECIMAL=@{DOT,COMMA@}] [/TEXTOPTIONS FORMAT=@{PLAIN,VARIABLE@}] @end display The SAVE TRANSLATE command with TYPE=CSV or TYPE=TAB writes data in a comma- or tab-separated value format similar to that described by RFC@tie{}4180. Each variable becomes one output column, and each case becomes one line of output. If FIELDNAMES is specified, an additional line at the top of the output file lists variable names. The CELLS and TEXTOPTIONS FORMAT settings determine how values are written to the output file: @table @asis @item CELLS=VALUES FORMAT=PLAIN (the default settings) Writes variables to the output in ``plain'' formats that ignore the details of variable formats. Numeric values are written as plain decimal numbers with enough digits to indicate their exact values in machine representation. Numeric values include @samp{e} followed by an exponent if the exponent value would be less than -4 or greater than 16. Dates are written in MM/DD/YYYY format and times in HH:MM:SS format. WKDAY and MONTH values are written as decimal numbers. Numeric values use, by default, the decimal point character set with SET DECIMAL (@pxref{SET DECIMAL}). Use DECIMAL=DOT or DECIMAL=COMMA to force a particular decimal point character. @item CELLS=VALUES FORMAT=VARIABLE Writes variables using their print formats. Leading and trailing spaces are removed from numeric values, and trailing spaces are removed from string values. @item CELLS=LABEL FORMAT=PLAIN @itemx CELLS=LABEL FORMAT=VARIABLE Writes value labels where they exist, and otherwise writes the values themselves as described above. @end table Regardless of CELLS and TEXTOPTIONS FORMAT, numeric system-missing values are output as a single space. For TYPE=TAB, tab characters delimit values. For TYPE=CSV, the TEXTOPTIONS DELIMITER and DECIMAL settings determine the character that separate values within a line. If DELIMITER is specified, then the specified string separate values. If DELIMITER is not specified, then the default is a comma with DECIMAL=DOT or a semicolon with DECIMAL=COMMA. If DECIMAL is not given either, it is implied by the decimal point character set with SET DECIMAL (@pxref{SET DECIMAL}). The TEXTOPTIONS QUALIFIER setting specifies a character that is output before and after a value that contains the delimiter character or the qualifier character. The default is a double quote (@samp{@@}). A qualifier character that appears within a value is doubled. @node SYSFILE INFO @section SYSFILE INFO @vindex SYSFILE INFO @display SYSFILE INFO FILE='@var{file_name}'. @end display @cmd{SYSFILE INFO} reads the dictionary in a system file and displays the information in its dictionary. Specify a file name or file handle. @cmd{SYSFILE INFO} reads that file as a system file and displays information on its dictionary. @cmd{SYSFILE INFO} does not affect the current active dataset. @node XEXPORT @section XEXPORT @vindex XEXPORT @display XEXPORT /OUTFILE='@var{file_name}' /DIGITS=@var{n} /DROP=@var{var_list} /KEEP=@var{var_list} /RENAME=(@var{src_names}=@var{target_names})@dots{} /TYPE=@{COMM,TAPE@} /MAP @end display The @cmd{EXPORT} transformation writes the active dataset dictionary and data to a specified portable file. This transformation is a @pspp{} extension. It is similar to the @cmd{EXPORT} procedure, with two differences: @itemize @item @cmd{XEXPORT} is a transformation, not a procedure. It is executed when the data is read by a procedure or procedure-like command. @item @cmd{XEXPORT} does not support the @subcmd{UNSELECTED} subcommand. @end itemize @xref{EXPORT}, for more information. @node XSAVE @section XSAVE @vindex XSAVE @display XSAVE /OUTFILE='@var{file_name}' /@{COMPRESSED,UNCOMPRESSED@} /PERMISSIONS=@{WRITEABLE,READONLY@} /DROP=@var{var_list} /KEEP=@var{var_list} /VERSION=@var{version} /RENAME=(@var{src_names}=@var{target_names})@dots{} /NAMES /MAP @end display The @cmd{XSAVE} transformation writes the active dataset's dictionary and data to a system file. It is similar to the @cmd{SAVE} procedure, with two differences: @itemize @item @cmd{XSAVE} is a transformation, not a procedure. It is executed when the data is read by a procedure or procedure-like command. @item @cmd{XSAVE} does not support the @subcmd{UNSELECTED} subcommand. @end itemize @xref{SAVE}, for more information. pspp-master/doc/flow-control.texi000066400000000000000000000152571177044323000174310ustar00rootroot00000000000000 @node Conditionals and Looping @chapter Conditional and Looping Constructs @cindex conditionals @cindex loops @cindex flow of control @cindex control flow This chapter documents @pspp{} commands used for conditional execution, looping, and flow of control. @menu * BREAK:: Exit a loop. * DO IF:: Conditionally execute a block of code. * DO REPEAT:: Textually repeat a code block. * LOOP:: Repeat a block of code. @end menu @node BREAK @section BREAK @vindex BREAK @display BREAK. @end display @cmd{BREAK} terminates execution of the innermost currently executing @cmd{LOOP} construct. @cmd{BREAK} is allowed only inside @cmd{LOOP}@dots{}@cmd{END LOOP}. @xref{LOOP}, for more details. @node DO IF @section DO IF @vindex DO IF @display DO IF condition. @dots{} [ELSE IF condition. @dots{} ]@dots{} [ELSE. @dots{}] END IF. @end display @cmd{DO IF} allows one of several sets of transformations to be executed, depending on user-specified conditions. If the specified boolean expression evaluates as true, then the block of code following @cmd{DO IF} is executed. If it evaluates as missing, then none of the code blocks is executed. If it is false, then the boolean expression on the first @cmd{ELSE IF}, if present, is tested in turn, with the same rules applied. If all expressions evaluate to false, then the @cmd{ELSE} code block is executed, if it is present. When @cmd{DO IF} or @cmd{ELSE IF} is specified following @cmd{TEMPORARY} (@pxref{TEMPORARY}), the @cmd{LAG} function may not be used (@pxref{LAG}). @node DO REPEAT @section DO REPEAT @vindex DO REPEAT @display DO REPEAT dummy_name=expansion@dots{}. @dots{} END REPEAT [PRINT]. expansion takes one of the following forms: var_list num_or_range@dots{} 'string'@dots{} ALL num_or_range takes one of the following forms: number num1 TO num2 @end display @cmd{DO REPEAT} repeats a block of code, textually substituting different variables, numbers, or strings into the block with each repetition. Specify a dummy variable name followed by an equals sign (@samp{=}) and the list of replacements. Replacements can be a list of existing or new variables, numbers, strings, or @code{ALL} to specify all existing variables. When numbers are specified, runs of increasing integers may be indicated as @code{@var{num1} TO @var{num2}}, so that @samp{1 TO 5} is short for @samp{1 2 3 4 5}. Multiple dummy variables can be specified. Each variable must have the same number of replacements. The code within @cmd{DO REPEAT} is repeated as many times as there are replacements for each variable. The first time, the first value for each dummy variable is substituted; the second time, the second value for each dummy variable is substituted; and so on. Dummy variable substitutions work like macros. They take place anywhere in a line that the dummy variable name occurs. This includes command and subcommand names, so command and subcommand names that appear in the code block should not be used as dummy variable identifiers. Dummy variable substitutions do not occur inside quoted strings, comments, unquoted strings (such as the text on the @cmd{TITLE} or @cmd{DOCUMENT} command), or inside @cmd{BEGIN DATA}@dots{}@cmd{END DATA}. New variable names used as replacements are not automatically created as variables, but only if used in the code block in a context that would create them, e.g.@: on a @cmd{NUMERIC} or @cmd{STRING} command or on the left side of a @cmd{COMPUTE} assignment. Any command may appear within @subcmd{DO REPEAT}, including nested @subcmd{DO REPEAT} commands. If @cmd{INCLUDE} or @cmd{INSERT} appears within @subcmd{DO REPEAT}, the substitutions do not apply to the included file. If @subcmd{PRINT} is specified on @cmd{END REPEAT}, the commands after substitutions are made are printed to the listing file, prefixed by a plus sign (@samp{+}). @node LOOP @section LOOP @vindex LOOP @display LOOP [@var{index_var}=@var{start} TO @var{end} [BY @var{incr}]] [IF @var{condition}]. @dots{} END LOOP [IF @var{condition}]. @end display @cmd{LOOP} iterates a group of commands. A number of termination options are offered. Specify index_var to make that variable count from one value to another by a particular increment. @var{index_var} must be a pre-existing numeric variable. @var{start}, @var{end}, and @var{incr} are numeric expressions (@pxref{Expressions}.) During the first iteration, @var{index_var} is set to the value of @var{start}. During each successive iteration, @var{index_var} is increased by the value of @var{incr}. If @var{end} > @var{start}, then the loop terminates when @var{index_var} > @var{end}; otherwise it terminates when @var{index_var} < @var{end}. If @var{incr} is not specified then it defaults to +1 or -1 as appropriate. If @var{end} > @var{start} and @var{incr} < 0, or if @var{end} < @var{start} and @var{incr} > 0, then the loop is never executed. @var{index_var} is nevertheless set to the value of start. Modifying @var{index_var} within the loop is allowed, but it has no effect on the value of @var{index_var} in the next iteration. Specify a boolean expression for the condition on @cmd{LOOP} to cause the loop to be executed only if the condition is true. If the condition is false or missing before the loop contents are executed the first time, the loop contents are not executed at all. If index and condition clauses are both present on @cmd{LOOP}, the index variable is always set before the condition is evaluated. Thus, a condition that makes use of the index variable will always see the index value to be used in the next execution of the body. Specify a boolean expression for the condition on @cmd{END LOOP} to cause the loop to terminate if the condition is true after the enclosed code block is executed. The condition is evaluated at the end of the loop, not at the beginning, so that the body of a loop with only a condition on @cmd{END LOOP} will always execute at least once. If neither the index clause nor either condition clause is present, then the loop is executed @var{max_loops} (@pxref{SET}) times. The default value of @var{max_loops} is 40. @cmd{BREAK} also terminates @cmd{LOOP} execution (@pxref{BREAK}). Loop index variables are by default reset to system-missing from one case to another, not left, unless a scratch variable is used as index. When loops are nested, this is usually undesired behavior, which can be corrected with @cmd{LEAVE} (@pxref{LEAVE}) or by using a scratch variable as the loop index. When @cmd{LOOP} or @cmd{END LOOP} is specified following @cmd{TEMPORARY} (@pxref{TEMPORARY}), the @cmd{LAG} function may not be used (@pxref{LAG}). pspp-master/doc/function-index.texi000066400000000000000000000000741177044323000177250ustar00rootroot00000000000000@node Function Index @chapter Function Index @printindex fn pspp-master/doc/get-commands.pl000077500000000000000000000011451177044323000170160ustar00rootroot00000000000000#!/usr/bin/perl # Creates Texinfo documentation from the source use strict; use warnings 'all'; my ($file) = $ARGV[0]; open(INFO, $file) || die "Cannot open \"$file\"\n" ; print "\@c Generated from $file by get-commands.pl\n"; print "\@c Do not modify!\n\n"; print "\@table \@asis\n"; while () { my ($command, $description) = /^\s*UNIMPL_CMD\s*\(\s*"([^"]*)"\s*,\s*"([^"]*)"\)\s*$/ or next; print "\@item \@cmd{$command}\n$description\n\n"; } print "\@end table\n"; print "\@c Local Variables:\n"; print "\@c buffer-read-only: t\n"; print "\@c End:\n"; close(INFO); # Close the file pspp-master/doc/installing.texi000066400000000000000000000035571177044323000171500ustar00rootroot00000000000000@node Installation @appendix Installing @pspp{} @cindex installation @cindex @pspp{}, installing @cindex GNU C compiler @cindex gcc @cindex compiler, recommended @cindex compiler, gcc @pspp{} is written in ISO C and primarily targeted at UNIX-like environments. To install @pspp{} under a UNIX-like operating system, follow the steps below. @enumerate @item @code{cd} to the directory containing the @pspp{} source. @cindex configure, GNU @cindex GNU configure @item Type @samp{./configure} to configure for your particular operating system and compiler. Running @code{configure} takes a while. While running, it displays some messages telling which features it is checking for. You can optionally supply some options to @code{configure} to give it hints about how to do its job. Type @code{./configure --help} to see a list of options. @cindex compiling @item Type @samp{make} to compile the package. If there are any errors during compilation, try to fix them. If modifications are necessary to compile correctly under your configuration, contact the author. @xref{Bugs,,Submitting Bug Reports}, for details. @cindex self-tests, running @item Type @samp{make check} to run self-tests on the compiled @pspp{} package. @cindex installation @cindex @pspp{}, installing @cindex @file{/usr/local/share/pspp/} @cindex @file{/usr/local/bin/} @cindex @file{/usr/local/info/} @cindex documentation, installing @item Become the superuser and type @samp{make install} to install the @pspp{} binaries, by default in @file{/usr/local/bin/}. The directory @file{/usr/local/share/pspp/} is created and populated with files needed by @pspp{} at runtime. This step will also cause the @pspp{} documentation to be installed in @file{/usr/local/info/}, but only if that directory already exists. @item (optional) Type @samp{make clean} to delete the @pspp{} binaries from the source tree. @end enumerate pspp-master/doc/introduction.texi000066400000000000000000000022451177044323000175160ustar00rootroot00000000000000@node Introduction @chapter Introduction @cindex introduction @cindex @pspp{} language @cindex language, @pspp{} @pspp{} is a tool for statistical analysis of sampled data. It reads a syntax file and a data file, analyzes the data, and writes the results to a listing file or to standard output. The language accepted by @pspp{} is similar to those accepted by SPSS statistical products. The details of @pspp{}'s language are given later in this manual. @cindex files, @pspp{} @cindex output, @pspp{} @cindex PostScript @cindex PDF @cindex HTML @cindex SVG @cindex graphics @cindex Ghostscript @cindex Free Software Foundation @pspp{} produces tables and charts as output, which it can produce in several formats; currently, ASCII, PostScript, PDF, HTML, and SVG are supported. The current version of @pspp{}, @value{VERSION}, is woefully incomplete in terms of its statistical procedure support. @pspp{} is a work in progress. The author hopes to fully support all features in the products that @pspp{} replaces, eventually. The author welcomes questions, comments, donations, and code submissions. @xref{Bugs,,Submitting Bug Reports}, for instructions on contacting the author. pspp-master/doc/invoking.texi000066400000000000000000000415331177044323000166240ustar00rootroot00000000000000@node Invoking PSPP @chapter Invoking @command{pspp} @cindex invocation @cindex @pspp{}, invoking @pspp{} has two separate user interfaces. This chapter describes @command{pspp}, @pspp{}'s command-line driven text-based user interface. The following chapter briefly describes PSPPIRE, the graphical user interface to @pspp{}. The sections below describe the @command{pspp} program's command-line interface. @menu * Main Options:: * PDF PostScript and SVG Output Options:: * Plain Text Output Options:: * HTML Output Options:: * OpenDocument Output Options:: * Comma-Separated Value Output Options:: @end menu @node Main Options @section Main Options Here is a summary of all the options, grouped by type, followed by explanations in the same order. In the table, arguments to long options also apply to any corresponding short options. @table @emph @item Non-option arguments @example @var{syntax-file} @end example @item Output options @example -o, --output=@var{output-file} -O @var{option}=@var{value} -O format=@var{format} -O device=@{terminal|listing@} --no-output -e, --error-file=@var{error-file} @end example @item Language options @example -I, --include=@var{dir} -I-, --no-include -b, --batch -i, --interactive -r, --no-statrc -a, --algorithm=@{compatible|enhanced@} -x, --syntax=@{compatible|enhanced@} --syntax-encoding=@var{encoding} @end example @item Informational options @example -h, --help -V, --version @end example @item Other options @example -s, --safer --testing-mode @end example @end table @table @asis @item @var{syntax-file} Read and execute the named syntax file. If no syntax files are specified, @pspp{} prompts for commands. If any syntax files are specified, @pspp{} by default exits after it runs them, but you may make it prompt for commands by specifying @samp{-} as an additional syntax file. @item @option{-o @var{output-file}} Write output to @var{output-file}. @pspp{} has several different output drivers that support output in various formats (use @option{--help} to list the available formats). Specify this option more than once to produce multiple output files, presumably in different formats. Use @samp{-} as @var{output-file} to write output to standard output. If no @option{-o} option is used, then @pspp{} writes output to standard output in plain text format. @item @option{-O @var{option}=@var{value}} Sets an option for the output file configured by a preceding @option{-o}. Most options are specific to particular output formats. A few options that apply generically are listed below. @item @option{-O format=@var{format}} @pspp{} uses the extension of the file name given on @option{-o} to select an output format. Use this option to override this choice by specifying an alternate format, e.g.@: @option{-o pspp.out -O html} to write HTML to a file named @file{pspp.out}. Use @option{--help} to list the available formats. @item @option{-O device=@{terminal|listing@}} Sets whether @pspp{} considers the output device configured by the preceding @option{-o} to be a terminal or a listing device. This affects what output will be sent to the device, as configured by the SET command's output routing subcommands (@pxref{SET}). By default, output written to standard output is considered a terminal device and other output is considered a listing device. @item @option{--no-output} Disables output entirely, if neither @option{-o} nor @option{-O} is also used. If one of those options is used, @option{--no-output} has no effect. @item @option{-e @var{error-file}} @itemx @option{--error-file=@var{error-file}} Configures a file to receive @pspp{} error, warning, and note messages in plain text format. Use @samp{-} as @var{error-file} to write messages to standard output. The default error file is standard output in the absence of these options, but this is suppressed if an output device writes to standard output (or another terminal), to avoid printing every message twice. Use @samp{none} as @var{error-file} to explicitly suppress the default. @item @option{-I @var{dir}} @itemx @option{--include=@var{dir}} Appends @var{dir} to the set of directories searched by the @cmd{INCLUDE} (@pxref{INCLUDE}) and @cmd{INSERT} (@pxref{INSERT}) commands. @item @option{-I-} @itemx @option{--no-include} Clears all directories from the include path, including directories inserted in the include path by default. The default include path is @file{.} (the current directory), followed by @file{.pspp} in the user's home directory, followed by @pspp{}'s system configuration directory (usually @file{/etc/pspp} or @file{/usr/local/etc/pspp}). @item @option{-b} @item @option{--batch} @item @option{-i} @itemx @option{--interactive} These options forces syntax files to be interpreted in batch mode or interactive mode, respectively, rather than the default ``auto'' mode. @xref{Syntax Variants}, for a description of the differences. @item @option{-r} @itemx @option{--no-statrc} Disables running @file{rc} at @pspp{} startup time. @item @option{-a @{enhanced|compatible@}} @itemx @option{--algorithm=@{enhanced|compatible@}} With @code{enhanced}, the default, @pspp{} uses the best implemented algorithms for statistical procedures. With @code{compatible}, however, @pspp{} will in some cases use inferior algorithms to produce the same results as the proprietary program SPSS. Some commands have subcommands that override this setting on a per command basis. @item @option{-x @{enhanced|compatible@}} @itemx @option{--syntax=@{enhanced|compatible@}} With @code{enhanced}, the default, @pspp{} accepts its own extensions beyond those compatible with the proprietary program SPSS. With @code{compatible}, @pspp{} rejects syntax that uses these extensions. @item @option{--syntax-encoding=@var{encoding}} Specifies @var{encoding} as the encoding for syntax files named on the command line. The @var{encoding} also becomes the default encoding for other syntax files read during the @pspp{} session by the @cmd{INCLUDE} and @cmd{INSERT} commands. @xref{INSERT}, for the accepted forms of @var{encoding}. @item @option{--help} Prints a message describing @pspp{} command-line syntax and the available device formats, then exits. @item @option{-V} @itemx @option{--version} Prints a brief message listing @pspp{}'s version, warranties you don't have, copying conditions and copyright, and e-mail address for bug reports, then exits. @item @option{-s} @itemx @option{--safer} Disables certain unsafe operations. This includes the @subcmd{ERASE} and @subcmd{HOST} commands, as well as use of pipes as input and output files. @item @option{--testing-mode} Invoke heuristics to assist with testing @pspp{}. For use by @command{make check} and similar scripts. @end table @node PDF PostScript and SVG Output Options @section PDF, PostScript, and SVG Output Options @cindex PDF @cindex Postscript @cindex SVG To produce output in PDF, PostScript, and SVG formats, specify @option{-o @var{file}} on the @pspp{} command line, optionally followed by any of the options shown in the table below to customize the output format. PDF, PostScript, and SVG output is only available if your installation of @pspp{} was compiled with the Cairo library. @table @asis @item @option{-O format=@{pdf|ps|svg@}} Specify the output format. This is only necessary if the file name given on @option{-o} does not end in @file{.pdf}, @file{.ps}, or @file{.svg}. @item @option{-O paper-size=@var{paper-size}} Paper size, as a name (e.g.@: @code{a4}, @code{letter}) or measurements (e.g.@: @code{210x297}, @code{8.5x11in}). The default paper size is taken from the @env{PAPERSIZE} environment variable or the file indicated by the @env{PAPERCONF} environment variable, if either variable is set. If not, and your system supports the @code{LC_PAPER} locale category, then the default paper size is taken from the locale. Otherwise, if @file{/etc/papersize} exists, the default paper size is read from it. As a last resort, A4 paper is assumed. @item @option{-O foreground-color=@var{color}} @itemx @option{-O background-color=@var{color}} Sets @var{color} as the color to be used for the background or foreground. Color should be given in the format @code{#@var{RRRR}@var{GGGG}@var{BBBB}}, where @var{RRRR}, @var{GGGG} and @var{BBBB} are 4 character hexadecimal representations of the red, green and blue components respectively. @item @option{-O orientation=@var{orientation}} Either @code{portrait} or @code{landscape}. Default: @code{portrait}. @item @option{-O left-margin=@var{dimension}} @itemx @option{-O right-margin=@var{dimension}} @itemx @option{-O top-margin=@var{dimension}} @itemx @option{-O bottom-margin=@var{dimension}} Sets the margins around the page. See below for the allowed forms of @var{dimension} Default: @code{0.5in}. @item @option{-O prop-font=@var{font-name}} @itemx @option{-O emph-font=@var{font-name}} @itemx @option{-O fixed-font=@var{font-name}} Sets the font used for proportional, emphasized, or fixed-pitch text. Most systems support CSS-like font names such as ``serif'' and ``monospace'', but a wide range of system-specific font are likely to be supported as well. Default: proportional font @code{serif}, emphasis font @code{serif italic}, fixed-pitch font @code{monospace}. @item @option{-O font-size=@var{font-size}} Sets the size of the default fonts, in thousandths of a point. Default: 10000 (10 point). @item @option{-O line-gutter=@var{dimension}} Sets the width of white space on either side of lines that border text or graphics objects. Default: @code{1pt}. @item @option{-O line-spacing=@var{dimension}} Sets the spacing between the lines in a double line in a table. Default: @code{1pt}. @item @option{-O line-width=@var{dimension}} Sets the width of the lines used in tables. Default: @code{0.5pt}. @end table Each @var{dimension} value above may be specified in various units based on its suffix: @samp{mm} for millimeters, @samp{in} for inches, or @samp{pt} for points. Lacking a suffix, numbers below 50 are assumed to be in inches and those about 50 are assumed to be in millimeters. @node Plain Text Output Options @section Plain Text Output Options @pspp{} can produce plain text output, drawing boxes using ASCII or Unicode line drawing characters. To produce plain text output, specify @option{-o @var{file}} on the @pspp{} command line, optionally followed by options from the table below to customize the output format. Plain text output is encoded in UTF-8. @table @asis @item @option{-O format=txt} Specify the output format. This is only necessary if the file name given on @option{-o} does not end in @file{.txt} or @file{.list}. @item @option{-O charts=@{@var{template}.png|none@}} Name for chart files included in output. The value should be a file name that includes a single @samp{#} and ends in @file{png}. When a chart is output, the @samp{#} is replaced by the chart number. The default is the file name specified on @option{-o} with the extension stripped off and replaced by @file{-#.png}. Specify @code{none} to disable chart output. Charts are always disabled if your installation of @pspp{} was compiled without the Cairo library. @item @option{-O paginate=@var{boolean}} If set, @pspp{} writes an ASCII formfeed the end of every page. Default: @code{off}. @item @option{-O headers=@var{boolean}} If enabled, @pspp{} prints two lines of header information giving title and subtitle, page number, date and time, and @pspp{} version are printed at the top of every page. These two lines are in addition to any top margin requested. Default: @code{off}. @item @option{-O length=@var{line-count}} Physical length of a page. Headers and margins are subtracted from this value. You may specify the number of lines as a number, or for screen output you may specify @code{auto} to track the height of the terminal as it changes. Default: @code{66}. @item @option{-O width=@var{character-count}} Width of a page, in characters. Margins are subtracted from this value. For screen output you may specify @code{auto} in place of a number to track the width of the terminal as it changes. Default: @code{79}. @item @option{-O top-margin=@var{top-margin-lines}} Length of the top margin, in lines. @pspp{} subtracts this value from the page length. Default: @code{0}. @item @option{-O bottom-margin=@var{bottom-margin-lines}} Length of the bottom margin, in lines. @pspp{} subtracts this value from the page length. Default: @code{0}. @item @option{-O box=@{ascii|unicode@}} Sets the characters used for lines in tables. The default, @code{ascii}, uses @samp{-}, @samp{|}, and @samp{+} for single-width lines and @samp{=} and @samp{#} for double-width lines. Specify @code{unicode} to use Unicode box drawing characters. @item @option{-O emphasis=@{none|bold|underline@}} How to emphasize text. Bold and underline emphasis are achieved with overstriking, which may not be supported by all the software to which you might pass the output. Default: @code{none}. @end table @node HTML Output Options @section HTML Output Options @cindex HTML To produce output in HTML format, specify @option{-o @var{file}} on the @pspp{} command line, optionally followed by any of the options shown in the table below to customize the output format. @table @asis @item @option{-O format=html} Specify the output format. This is only necessary if the file name given on @option{-o} does not end in @file{.html}. @item @option{-O charts=@{@var{template}.png|none@}} Sets the name used for chart files. @xref{Plain Text Output Options}, for details. @item @option{-O borders=@var{boolean}} Decorate the tables with borders. If set to false, the tables produced will have no borders. The default value is true. @item @option{-O css=@var{boolean}} Use cascading style sheets. Cascading style sheets give an improved appearance and can be used to produce pages which fit a certain web site's style. The default value is true. @end table @node OpenDocument Output Options @section OpenDocument Output Options To produce output as an OpenDocument text (ODT) document, specify @option{-o @var{file}} on the @pspp{} command line. If @var{file} does not end in @file{.odt}, you must also specify @option{-O format=odt}. ODT support is only available if your installation of @pspp{} was compiled with the libxml2 library. The OpenDocument output format does not have any configurable options. @node Comma-Separated Value Output Options @section Comma-Separated Value Output Options To produce output in comma-separated value (CSV) format, specify @option{-o @var{file}} on the @pspp{} command line, optionally followed by any of the options shown in the table below to customize the output format. @table @asis @item @option{-O format=csv} Specify the output format. This is only necessary if the file name given on @option{-o} does not end in @file{.csv}. @item @option{-O separator=@var{field-separator}} Sets the character used to separate fields. Default: a comma (@samp{,}). @item @option{-O quote=@var{qualifier}} Sets @var{qualifier} as the character used to quote fields that contain white space, the separator (or any of the characters in the separator, if it contains more than one character), or the quote character itself. If @var{qualifier} is longer than one character, only the first character is used; if @var{qualifier} is the empty string, then fields are never quoted. @item @option{-O captions=@var{boolean}} Whether table captions should be printed. Default: @code{on}. @end table The CSV format used is an extension to that specified in RFC 4180: @table @asis @item Tables Each table row is output on a separate line, and each column is output as a field. The contents of a cell that spans multiple rows or columns is output only for the top-left row and column; the rest are output as empty fields. When a table has a caption and captions are enabled, the caption is output just above the table as a single field prefixed by @samp{Table:}. @item Text Text in output is printed as a field on a line by itself. The TITLE and SUBTITLE produce similar output, prefixed by @samp{Title:} or @samp{Subtitle:}, respectively. @item Messages Errors, warnings, and notes are printed the same way as text. @item Charts Charts are not included in CSV output. @end table Successive output items are separated by a blank line. @node Invoking PSPPIRE @chapter Invoking @command{psppire} @section The graphic user interface @cindex Graphic user interface @cindex PSPPIRE The PSPPIRE graphic user interface for @pspp{} can perform all functionality of the command line interface. In addition it gives an instantaneous view of the data, variables and statistical output. The graphic user interface can be started by typing @command{psppire} at a command prompt. Alternatively many systems have a system of interactive menus or buttons from which @command{psppire} can be started by a series of mouse clicks. Once the principles of the @pspp{} system are understood, the graphic user interface is designed to be largely intuitive, and for this reason is covered only very briefly by this manual. pspp-master/doc/language.texi000066400000000000000000001553211177044323000165640ustar00rootroot00000000000000@node Language @chapter The @pspp{} language @cindex language, @pspp{} @cindex @pspp{}, language This chapter discusses elements common to many @pspp{} commands. Later chapters will describe individual commands in detail. @menu * Tokens:: Characters combine to form tokens. * Commands:: Tokens combine to form commands. * Syntax Variants:: Batch vs. Interactive mode * Types of Commands:: Commands come in several flavors. * Order of Commands:: Commands combine to form syntax files. * Missing Observations:: Handling missing observations. * Datasets:: Data organization. * Files:: Files used by @pspp{}. * File Handles:: How files are named. * BNF:: How command syntax is described. @end menu @node Tokens @section Tokens @cindex language, lexical analysis @cindex language, tokens @cindex tokens @cindex lexical analysis @pspp{} divides most syntax file lines into series of short chunks called @dfn{tokens}. Tokens are then grouped to form commands, each of which tells @pspp{} to take some action---read in data, write out data, perform a statistical procedure, etc. Each type of token is described below. @table @strong @cindex identifiers @item Identifiers Identifiers are names that typically specify variables, commands, or subcommands. The first character in an identifier must be a letter, @samp{#}, or @samp{@@}. The remaining characters in the identifier must be letters, digits, or one of the following special characters: @example @center @. _ $ # @@ @end example @cindex case-sensitivity Identifiers may be any length, but only the first 64 bytes are significant. Identifiers are not case-sensitive: @code{foobar}, @code{Foobar}, @code{FooBar}, @code{FOOBAR}, and @code{FoObaR} are different representations of the same identifier. @cindex identifiers, reserved @cindex reserved identifiers Some identifiers are reserved. Reserved identifiers may not be used in any context besides those explicitly described in this manual. The reserved identifiers are: @example @center ALL AND BY EQ GE GT LE LT NE NOT OR TO WITH @end example @item Keywords Keywords are a subclass of identifiers that form a fixed part of command syntax. For example, command and subcommand names are keywords. Keywords may be abbreviated to their first 3 characters if this abbreviation is unambiguous. (Unique abbreviations of 3 or more characters are also accepted: @samp{FRE}, @samp{FREQ}, and @samp{FREQUENCIES} are equivalent when the last is a keyword.) Reserved identifiers are always used as keywords. Other identifiers may be used both as keywords and as user-defined identifiers, such as variable names. @item Numbers @cindex numbers @cindex integers @cindex reals Numbers are expressed in decimal. A decimal point is optional. Numbers may be expressed in scientific notation by adding @samp{e} and a base-10 exponent, so that @samp{1.234e3} has the value 1234. Here are some more examples of valid numbers: @example -5 3.14159265359 1e100 -.707 8945. @end example Negative numbers are expressed with a @samp{-} prefix. However, in situations where a literal @samp{-} token is expected, what appears to be a negative number is treated as @samp{-} followed by a positive number. No white space is allowed within a number token, except for horizontal white space between @samp{-} and the rest of the number. The last example above, @samp{8945.} will be interpreted as two tokens, @samp{8945} and @samp{.}, if it is the last token on a line. @xref{Commands, , Forming commands of tokens}. @item Strings @cindex strings @cindex @samp{'} @cindex @samp{"} @cindex case-sensitivity Strings are literal sequences of characters enclosed in pairs of single quotes (@samp{'}) or double quotes (@samp{"}). To include the character used for quoting in the string, double it, e.g.@: @samp{'it''s an apostrophe'}. White space and case of letters are significant inside strings. Strings can be concatenated using @samp{+}, so that @samp{"a" + 'b' + 'c'} is equivalent to @samp{'abc'}. So that a long string may be broken across lines, a line break may precede or follow, or both precede and follow, the @samp{+}. (However, an entirely blank line preceding or following the @samp{+} is interpreted as ending the current command.) Strings may also be expressed as hexadecimal character values by prefixing the initial quote character by @samp{x} or @samp{X}. Regardless of the syntax file or active dataset's encoding, the hexadecimal digits in the string are interpreted as Unicode characters in UTF-8 encoding. Individual Unicode code points may also be expressed by specifying the hexadecimal code point number in single or double quotes preceded by @samp{u} or @samp{U}. For example, Unicode code point U+1D11E, the musical G clef character, could be expressed as @code{U'1D11E'}. Invalid Unicode code points (above U+10FFFF or in between U+D800 and U+DFFF) are not allowed. When strings are concatenated with @samp{+}, each segment's prefix is considered individually. For example, @code{'The G clef symbol is:' + u"1d11e" + "."} inserts a G clef symbol in the middle of an otherwise plain text string. @item Punctuators and Operators @cindex punctuators @cindex operators These tokens are the punctuators and operators: @example @center , / = ( ) + - * / ** < <= <> > >= ~= & | . @end example Most of these appear within the syntax of commands, but the period (@samp{.}) punctuator is used only at the end of a command. It is a punctuator only as the last character on a line (except white space). When it is the last non-space character on a line, a period is not treated as part of another token, even if it would otherwise be part of, e.g.@:, an identifier or a floating-point number. @end table @node Commands @section Forming commands of tokens @cindex @pspp{}, command structure @cindex language, command structure @cindex commands, structure Most @pspp{} commands share a common structure. A command begins with a command name, such as @cmd{FREQUENCIES}, @cmd{DATA LIST}, or @cmd{N OF CASES}. The command name may be abbreviated to its first word, and each word in the command name may be abbreviated to its first three or more characters, where these abbreviations are unambiguous. The command name may be followed by one or more @dfn{subcommands}. Each subcommand begins with a subcommand name, which may be abbreviated to its first three letters. Some subcommands accept a series of one or more specifications, which follow the subcommand name, optionally separated from it by an equals sign (@samp{=}). Specifications may be separated from each other by commas or spaces. Each subcommand must be separated from the next (if any) by a forward slash (@samp{/}). There are multiple ways to mark the end of a command. The most common way is to end the last line of the command with a period (@samp{.}) as described in the previous section (@pxref{Tokens}). A blank line, or one that consists only of white space or comments, also ends a command. @node Syntax Variants @section Syntax Variants @cindex Batch syntax @cindex Interactive syntax There are three variants of command syntax, which vary only in how they detect the end of one command and the start of the next. In @dfn{interactive mode}, which is the default for syntax typed at a command prompt, a period as the last non-blank character on a line ends a command. A blank line also ends a command. In @dfn{batch mode}, an end-of-line period or a blank line also ends a command. Additionally, it treats any line that has a non-blank character in the leftmost column as beginning a new command. Thus, in batch mode the second and subsequent lines in a command must be indented. Regardless of the syntax mode, a plus sign, minus sign, or period in the leftmost column of a line is ignored and causes that line to begin a new command. This is most useful in batch mode, in which the first line of a new command could not otherwise be indented, but it is accepted regardless of syntax mode. The default mode for reading commands from a file is @dfn{auto mode}. It is the same as batch mode, except that a line with a non-blank in the leftmost column only starts a new command if that line begins with the name of a @pspp{} command. This correctly interprets most valid @pspp{} syntax files regardless of the syntax mode for which they are intended. The @option{--interactive} (or @option{-i}) or @option{--batch} (or @option{-b}) options set the syntax mode for files listed on the @pspp{} command line. @xref{Main Options}, for more details. @node Types of Commands @section Types of Commands Commands in @pspp{} are divided roughly into six categories: @table @strong @item Utility commands @cindex utility commands Set or display various global options that affect @pspp{} operations. May appear anywhere in a syntax file. @xref{Utilities, , Utility commands}. @item File definition commands @cindex file definition commands Give instructions for reading data from text files or from special binary ``system files''. Most of these commands replace any previous data or variables with new data or variables. At least one file definition command must appear before the first command in any of the categories below. @xref{Data Input and Output}. @item Input program commands @cindex input program commands Though rarely used, these provide tools for reading data files in arbitrary textual or binary formats. @xref{INPUT PROGRAM}. @item Transformations @cindex transformations Perform operations on data and write data to output files. Transformations are not carried out until a procedure is executed. @item Restricted transformations @cindex restricted transformations Transformations that cannot appear in certain contexts. @xref{Order of Commands}, for details. @item Procedures @cindex procedures Analyze data, writing results of analyses to the listing file. Cause transformations specified earlier in the file to be performed. In a more general sense, a @dfn{procedure} is any command that causes the active dataset (the data) to be read. @end table @node Order of Commands @section Order of Commands @cindex commands, ordering @cindex order of commands @pspp{} does not place many restrictions on ordering of commands. The main restriction is that variables must be defined before they are otherwise referenced. This section describes the details of command ordering, but most users will have no need to refer to them. @pspp{} possesses five internal states, called @dfn{initial}, @dfn{input-program} @dfn{file-type}, @dfn{transformation}, and @dfn{procedure} states. (Please note the distinction between the @cmd{INPUT PROGRAM} and @cmd{FILE TYPE} @emph{commands} and the @dfn{input-program} and @dfn{file-type} @emph{states}.) @pspp{} starts in the initial state. Each successful completion of a command may cause a state transition. Each type of command has its own rules for state transitions: @table @strong @item Utility commands @itemize @bullet @item Valid in any state. @item Do not cause state transitions. Exception: when @cmd{N OF CASES} is executed in the procedure state, it causes a transition to the transformation state. @end itemize @item @cmd{DATA LIST} @itemize @bullet @item Valid in any state. @item When executed in the initial or procedure state, causes a transition to the transformation state. @item Clears the active dataset if executed in the procedure or transformation state. @end itemize @item @cmd{INPUT PROGRAM} @itemize @bullet @item Invalid in input-program and file-type states. @item Causes a transition to the intput-program state. @item Clears the active dataset. @end itemize @item @cmd{FILE TYPE} @itemize @bullet @item Invalid in intput-program and file-type states. @item Causes a transition to the file-type state. @item Clears the active dataset. @end itemize @item Other file definition commands @itemize @bullet @item Invalid in input-program and file-type states. @item Cause a transition to the transformation state. @item Clear the active dataset, except for @cmd{ADD FILES}, @cmd{MATCH FILES}, and @cmd{UPDATE}. @end itemize @item Transformations @itemize @bullet @item Invalid in initial and file-type states. @item Cause a transition to the transformation state. @end itemize @item Restricted transformations @itemize @bullet @item Invalid in initial, input-program, and file-type states. @item Cause a transition to the transformation state. @end itemize @item Procedures @itemize @bullet @item Invalid in initial, input-program, and file-type states. @item Cause a transition to the procedure state. @end itemize @end table @node Missing Observations @section Handling missing observations @cindex missing values @cindex values, missing @pspp{} includes special support for unknown numeric data values. Missing observations are assigned a special value, called the @dfn{system-missing value}. This ``value'' actually indicates the absence of a value; it means that the actual value is unknown. Procedures automatically exclude from analyses those observations or cases that have missing values. Details of missing value exclusion depend on the procedure and can often be controlled by the user; refer to descriptions of individual procedures for details. The system-missing value exists only for numeric variables. String variables always have a defined value, even if it is only a string of spaces. Variables, whether numeric or string, can have designated @dfn{user-missing values}. Every user-missing value is an actual value for that variable. However, most of the time user-missing values are treated in the same way as the system-missing value. For more information on missing values, see the following sections: @ref{Datasets}, @ref{MISSING VALUES}, @ref{Expressions}. See also the documentation on individual procedures for information on how they handle missing values. @node Datasets @section Datasets @cindex dataset @cindex variable @cindex dictionary @pspp{} works with data organized into @dfn{datasets}. A dataset consists of a set of @dfn{variables}, which taken together are said to form a @dfn{dictionary}, and one or more @dfn{cases}, each of which has one value for each variable. At any given time @pspp{} has exactly one distinguished dataset, called the @dfn{active dataset}. Most @pspp{} commands work only with the active dataset. In addition to the active dataset, @pspp{} also supports any number of additional open datasets. The @cmd{DATASET} commands can choose a new active dataset from among those that are open, as well as create and destroy datasets (@pxref{DATASET}). The sections below describe variables in more detail. @menu * Attributes:: Attributes of variables. * System Variables:: Variables automatically defined by @pspp{}. * Sets of Variables:: Lists of variable names. * Input and Output Formats:: Input and output formats. * Scratch Variables:: Variables deleted by procedures. @end menu @node Attributes @subsection Attributes of Variables @cindex variables, attributes of @cindex attributes of variables Each variable has a number of attributes, including: @table @strong @item Name An identifier, up to 64 bytes long. Each variable must have a different name. @xref{Tokens}. Some system variable names begin with @samp{$}, but user-defined variables' names may not begin with @samp{$}. @cindex @samp{.} @cindex period @cindex variable names, ending with period The final character in a variable name should not be @samp{.}, because such an identifier will be misinterpreted when it is the final token on a line: @code{FOO.} will be divided into two separate tokens, @samp{FOO} and @samp{.}, indicating end-of-command. @xref{Tokens}. @cindex @samp{_} The final character in a variable name should not be @samp{_}, because some such identifiers are used for special purposes by @pspp{} procedures. As with all @pspp{} identifiers, variable names are not case-sensitive. @pspp{} capitalizes variable names on output the same way they were capitalized at their point of definition in the input. @cindex variables, type @cindex type of variables @item Type Numeric or string. @cindex variables, width @cindex width of variables @item Width (string variables only) String variables with a width of 8 characters or fewer are called @dfn{short string variables}. Short string variables may be used in a few contexts where @dfn{long string variables} (those with widths greater than 8) are not allowed. @item Position Variables in the dictionary are arranged in a specific order. @cmd{DISPLAY} can be used to show this order: see @ref{DISPLAY}. @item Initialization Either reinitialized to 0 or spaces for each case, or left at its existing value. @xref{LEAVE}. @cindex missing values @cindex values, missing @item Missing values Optionally, up to three values, or a range of values, or a specific value plus a range, can be specified as @dfn{user-missing values}. There is also a @dfn{system-missing value} that is assigned to an observation when there is no other obvious value for that observation. Observations with missing values are automatically excluded from analyses. User-missing values are actual data values, while the system-missing value is not a value at all. @xref{Missing Observations}. @cindex variable labels @cindex labels, variable @item Variable label A string that describes the variable. @xref{VARIABLE LABELS}. @cindex value labels @cindex labels, value @item Value label Optionally, these associate each possible value of the variable with a string. @xref{VALUE LABELS}. @cindex print format @item Print format Display width, format, and (for numeric variables) number of decimal places. This attribute does not affect how data are stored, just how they are displayed. Example: a width of 8, with 2 decimal places. @xref{Input and Output Formats}. @cindex write format @item Write format Similar to print format, but used by the @cmd{WRITE} command (@pxref{WRITE}). @cindex custom attributes @item Custom attributes User-defined associations between names and values. @xref{VARIABLE ATTRIBUTE}. @end table @node System Variables @subsection Variables Automatically Defined by @pspp{} @cindex system variables @cindex variables, system There are seven system variables. These are not like ordinary variables because system variables are not always stored. They can be used only in expressions. These system variables, whose values and output formats cannot be modified, are described below. @table @code @cindex @code{$CASENUM} @item $CASENUM Case number of the case at the moment. This changes as cases are shuffled around. @cindex @code{$DATE} @item $DATE Date the @pspp{} process was started, in format A9, following the pattern @code{DD MMM YY}. @cindex @code{$JDATE} @item $JDATE Number of days between 15 Oct 1582 and the time the @pspp{} process was started. @cindex @code{$LENGTH} @item $LENGTH Page length, in lines, in format F11. @cindex @code{$SYSMIS} @item $SYSMIS System missing value, in format F1. @cindex @code{$TIME} @item $TIME Number of seconds between midnight 14 Oct 1582 and the time the active dataset was read, in format F20. @cindex @code{$WIDTH} @item $WIDTH Page width, in characters, in format F3. @end table @node Sets of Variables @subsection Lists of variable names @cindex @code{TO} convention @cindex convention, @code{TO} To refer to a set of variables, list their names one after another. Optionally, their names may be separated by commas. To include a range of variables from the dictionary in the list, write the name of the first and last variable in the range, separated by @code{TO}. For instance, if the dictionary contains six variables with the names @code{ID}, @code{X1}, @code{X2}, @code{GOAL}, @code{MET}, and @code{NEXTGOAL}, in that order, then @code{X2 TO MET} would include variables @code{X2}, @code{GOAL}, and @code{MET}. Commands that define variables, such as @cmd{DATA LIST}, give @code{TO} an alternate meaning. With these commands, @code{TO} define sequences of variables whose names end in consecutive integers. The syntax is two identifiers that begin with the same root and end with numbers, separated by @code{TO}. The syntax @code{X1 TO X5} defines 5 variables, named @code{X1}, @code{X2}, @code{X3}, @code{X4}, and @code{X5}. The syntax @code{ITEM0008 TO ITEM0013} defines 6 variables, named @code{ITEM0008}, @code{ITEM0009}, @code{ITEM0010}, @code{ITEM0011}, @code{ITEM0012}, and @code{ITEM00013}. The syntaxes @code{QUES001 TO QUES9} and @code{QUES6 TO QUES3} are invalid. After a set of variables has been defined with @cmd{DATA LIST} or another command with this method, the same set can be referenced on later commands using the same syntax. @node Input and Output Formats @subsection Input and Output Formats @cindex formats An @dfn{input format} describes how to interpret the contents of an input field as a number or a string. It might specify that the field contains an ordinary decimal number, a time or date, a number in binary or hexadecimal notation, or one of several other notations. Input formats are used by commands such as @cmd{DATA LIST} that read data or syntax files into the @pspp{} active dataset. Every input format corresponds to a default @dfn{output format} that specifies the formatting used when the value is output later. It is always possible to explicitly specify an output format that resembles the input format. Usually, this is the default, but in cases where the input format is unfriendly to human readability, such as binary or hexadecimal formats, the default output format is an easier-to-read decimal format. Every variable has two output formats, called its @dfn{print format} and @dfn{write format}. Print formats are used in most output contexts; write formats are used only by @cmd{WRITE} (@pxref{WRITE}). Newly created variables have identical print and write formats, and @cmd{FORMATS}, the most commonly used command for changing formats (@pxref{FORMATS}), sets both of them to the same value as well. Thus, most of the time, the distinction between print and write formats is unimportant. Input and output formats are specified to @pspp{} with a @dfn{format specification} of the form @subcmd{@var{TYPE}@var{w}} or @code{TYPE@var{w}.@var{d}}, where @var{TYPE} is one of the format types described later, @var{w} is a field width measured in columns, and @var{d} is an optional number of decimal places. If @var{d} is omitted, a value of 0 is assumed. Some formats do not allow a nonzero @var{d} to be specified. The following sections describe the input and output formats supported by @pspp{}. @menu * Basic Numeric Formats:: * Custom Currency Formats:: * Legacy Numeric Formats:: * Binary and Hexadecimal Numeric Formats:: * Time and Date Formats:: * Date Component Formats:: * String Formats:: @end menu @node Basic Numeric Formats @subsubsection Basic Numeric Formats @cindex numeric formats The basic numeric formats are used for input and output of real numbers in standard or scientific notation. The following table shows an example of how each format displays positive and negative numbers with the default decimal point setting: @float @multitable {DOLLAR10.2} {@code{@tie{}$3,141.59}} {@code{-$3,141.59}} @headitem Format @tab @code{@tie{}3141.59} @tab @code{-3141.59} @item F8.2 @tab @code{@tie{}3141.59} @tab @code{-3141.59} @item COMMA9.2 @tab @code{@tie{}3,141.59} @tab @code{-3,141.59} @item DOT9.2 @tab @code{@tie{}3.141,59} @tab @code{-3.141,59} @item DOLLAR10.2 @tab @code{@tie{}$3,141.59} @tab @code{-$3,141.59} @item PCT9.2 @tab @code{@tie{}3141.59%} @tab @code{-3141.59%} @item E8.1 @tab @code{@tie{}3.1E+003} @tab @code{-3.1E+003} @end multitable @end float On output, numbers in F format are expressed in standard decimal notation with the requested number of decimal places. The other formats output some variation on this style: @itemize @bullet @item Numbers in COMMA format are additionally grouped every three digits by inserting a grouping character. The grouping character is ordinarily a comma, but it can be changed to a period (@pxref{SET DECIMAL}). @item DOT format is like COMMA format, but it interchanges the role of the decimal point and grouping characters. That is, the current grouping character is used as a decimal point and vice versa. @item DOLLAR format is like COMMA format, but it prefixes the number with @samp{$}. @item PCT format is like F format, but adds @samp{%} after the number. @item The E format always produces output in scientific notation. @end itemize On input, the basic numeric formats accept positive and numbers in standard decimal notation or scientific notation. Leading and trailing spaces are allowed. An empty or all-spaces field, or one that contains only a single period, is treated as the system missing value. In scientific notation, the exponent may be introduced by a sign (@samp{+} or @samp{-}), or by one of the letters @samp{e} or @samp{d} (in uppercase or lowercase), or by a letter followed by a sign. A single space may follow the letter or the sign or both. On fixed-format @cmd{DATA LIST} (@pxref{DATA LIST FIXED}) and in a few other contexts, decimals are implied when the field does not contain a decimal point. In F6.5 format, for example, the field @code{314159} is taken as the value 3.14159 with implied decimals. Decimals are never implied if an explicit decimal point is present or if scientific notation is used. E and F formats accept the basic syntax already described. The other formats allow some additional variations: @itemize @bullet @item COMMA, DOLLAR, and DOT formats ignore grouping characters within the integer part of the input field. The identity of the grouping character depends on the format. @item DOLLAR format allows a dollar sign to precede the number. In a negative number, the dollar sign may precede or follow the minus sign. @item PCT format allows a percent sign to follow the number. @end itemize All of the basic number formats have a maximum field width of 40 and accept no more than 16 decimal places, on both input and output. Some additional restrictions apply: @itemize @bullet @item As input formats, the basic numeric formats allow no more decimal places than the field width. As output formats, the field width must be greater than the number of decimal places; that is, large enough to allow for a decimal point and the number of requested decimal places. DOLLAR and PCT formats must allow an additional column for @samp{$} or @samp{%}. @item The default output format for a given input format increases the field width enough to make room for optional input characters. If an input format calls for decimal places, the width is increased by 1 to make room for an implied decimal point. COMMA, DOT, and DOLLAR formats also increase the output width to make room for grouping characters. DOLLAR and PCT further increase the output field width by 1 to make room for @samp{$} or @samp{%}. The increased output width is capped at 40, the maximum field width. @item The E format is exceptional. For output, E format has a minimum width of 7 plus the number of decimal places. The default output format for an E input format is an E format with at least 3 decimal places and thus a minimum width of 10. @end itemize More details of basic numeric output formatting are given below: @itemize @bullet @item Output rounds to nearest, with ties rounded away from zero. Thus, 2.5 is output as @code{3} in F1.0 format, and -1.125 as @code{-1.13} in F5.1 format. @item The system-missing value is output as a period in a field of spaces, placed in the decimal point's position, or in the rightmost column if no decimal places are requested. A period is used even if the decimal point character is a comma. @item A number that does not fill its field is right-justified within the field. @item A number is too large for its field causes decimal places to be dropped to make room. If dropping decimals does not make enough room, scientific notation is used if the field is wide enough. If a number does not fit in the field, even in scientific notation, the overflow is indicated by filling the field with asterisks (@samp{*}). @item COMMA, DOT, and DOLLAR formats insert grouping characters only if space is available for all of them. Grouping characters are never inserted when all decimal places must be dropped. Thus, 1234.56 in COMMA5.2 format is output as @samp{@tie{}1235} without a comma, even though there is room for one, because all decimal places were dropped. @item DOLLAR or PCT format drop the @samp{$} or @samp{%} only if the number would not fit at all without it. Scientific notation with @samp{$} or @samp{%} is preferred to ordinary decimal notation without it. @item Except in scientific notation, a decimal point is included only when it is followed by a digit. If the integer part of the number being output is 0, and a decimal point is included, then the zero before the decimal point is dropped. In scientific notation, the number always includes a decimal point, even if it is not followed by a digit. @item A negative number includes a minus sign only in the presence of a nonzero digit: -0.01 is output as @samp{-.01} in F4.2 format but as @samp{@tie{}@tie{}.0} in F4.1 format. Thus, a ``negative zero'' never includes a minus sign. @item In negative numbers output in DOLLAR format, the dollar sign follows the negative sign. Thus, -9.99 in DOLLAR6.2 format is output as @code{-$9.99}. @item In scientific notation, the exponent is output as @samp{E} followed by @samp{+} or @samp{-} and exactly three digits. Numbers with magnitude less than 10**-999 or larger than 10**999 are not supported by most computers, but if they are supported then their output is considered to overflow the field and will be output as asterisks. @item On most computers, no more than 15 decimal digits are significant in output, even if more are printed. In any case, output precision cannot be any higher than input precision; few data sets are accurate to 15 digits of precision. Unavoidable loss of precision in intermediate calculations may also reduce precision of output. @item Special values such as infinities and ``not a number'' values are usually converted to the system-missing value before printing. In a few circumstances, these values are output directly. In fields of width 3 or greater, special values are output as however many characters will fit from @code{+Infinity} or @code{-Infinity} for infinities, from @code{NaN} for ``not a number,'' or from @code{Unknown} for other values (if any are supported by the system). In fields under 3 columns wide, special values are output as asterisks. @end itemize @node Custom Currency Formats @subsubsection Custom Currency Formats @cindex currency formats The custom currency formats are closely related to the basic numeric formats, but they allow users to customize the output format. The SET command configures custom currency formats, using the syntax @display SET CC@var{x}=@t{"}@var{string}@t{"}. @end display @noindent where @var{x} is A, B, C, D, or E, and @var{string} is no more than 16 characters long. @var{string} must contain exactly three commas or exactly three periods (but not both), except that a single quote character may be used to ``escape'' a following comma, period, or single quote. If three commas are used, commas will be used for grouping in output, and a period will be used as the decimal point. Uses of periods reverses these roles. The commas or periods divide @var{string} into four fields, called the @dfn{negative prefix}, @dfn{prefix}, @dfn{suffix}, and @dfn{negative suffix}, respectively. The prefix and suffix are added to output whenever space is available. The negative prefix and negative suffix are always added to a negative number when the output includes a nonzero digit. The following syntax shows how custom currency formats could be used to reproduce basic numeric formats: @example @group SET CCA="-,,,". /* Same as COMMA. SET CCB="-...". /* Same as DOT. SET CCC="-,$,,". /* Same as DOLLAR. SET CCD="-,,%,". /* Like PCT, but groups with commas. @end group @end example Here are some more examples of custom currency formats. The final example shows how to use a single quote to escape a delimiter: @example @group SET CCA=",EUR,,-". /* Euro. SET CCB="(,USD ,,)". /* US dollar. SET CCC="-.R$..". /* Brazilian real. SET CCD="-,, NIS,". /* Israel shekel. SET CCE="-.Rp'. ..". /* Indonesia Rupiah. @end group @end example @noindent These formats would yield the following output: @float @multitable {CCD13.2} {@code{@tie{}@tie{}USD 3,145.59}} {@code{(USD 3,145.59)}} @headitem Format @tab @code{@tie{}3145.59} @tab @code{-3145.59} @item CCA12.2 @tab @code{@tie{}EUR3,145.59} @tab @code{EUR3,145.59-} @item CCB14.2 @tab @code{@tie{}@tie{}USD 3,145.59} @tab @code{(USD 3,145.59)} @item CCC11.2 @tab @code{@tie{}R$3.145,59} @tab @code{-R$3.145,59} @item CCD13.2 @tab @code{@tie{}3,145.59 NIS} @tab @code{-3,145.59 NIS} @item CCE10.0 @tab @code{@tie{}Rp. 3.146} @tab @code{-Rp. 3.146} @end multitable @end float The default for all the custom currency formats is @samp{-,,,}, equivalent to COMMA format. @node Legacy Numeric Formats @subsubsection Legacy Numeric Formats The N and Z numeric formats provide compatibility with legacy file formats. They have much in common: @itemize @bullet @item Output is rounded to the nearest representable value, with ties rounded away from zero. @item Numbers too large to display are output as a field filled with asterisks (@samp{*}). @item The decimal point is always implicitly the specified number of digits from the right edge of the field, except that Z format input allows an explicit decimal point. @item Scientific notation may not be used. @item The system-missing value is output as a period in a field of spaces. The period is placed just to the right of the implied decimal point in Z format, or at the right end in N format or in Z format if no decimal places are requested. A period is used even if the decimal point character is a comma. @item Field width may range from 1 to 40. Decimal places may range from 0 up to the field width, to a maximum of 16. @item When a legacy numeric format used for input is converted to an output format, it is changed into the equivalent F format. The field width is increased by 1 if any decimal places are specified, to make room for a decimal point. For Z format, the field width is increased by 1 more column, to make room for a negative sign. The output field width is capped at 40 columns. @end itemize @subsubheading N Format The N format supports input and output of fields that contain only digits. On input, leading or trailing spaces, a decimal point, or any other non-digit character causes the field to be read as the system-missing value. As a special exception, an N format used on @cmd{DATA LIST FREE} or @cmd{DATA LIST LIST} is treated as the equivalent F format. On output, N pads the field on the left with zeros. Negative numbers are output like the system-missing value. @subsubheading Z Format The Z format is a ``zoned decimal'' format used on IBM mainframes. Z format encodes the sign as part of the final digit, which must be one of the following: @example 0123456789 @{ABCDEFGHI @}JKLMNOPQR @end example @noindent where the characters in each row represent digits 0 through 9 in order. Characters in the first two rows indicate a positive sign; those in the third indicate a negative sign. On output, Z fields are padded on the left with spaces. On input, leading and trailing spaces are ignored. Any character in an input field other than spaces, the digit characters above, and @samp{.} causes the field to be read as system-missing. The decimal point character for input and output is always @samp{.}, even if the decimal point character is a comma (@pxref{SET DECIMAL}). Nonzero, negative values output in Z format are marked as negative even when no nonzero digits are output. For example, -0.2 is output in Z1.0 format as @samp{J}. The ``negative zero'' value supported by most machines is output as positive. @node Binary and Hexadecimal Numeric Formats @subsubsection Binary and Hexadecimal Numeric Formats @cindex binary formats @cindex hexadecimal formats The binary and hexadecimal formats are primarily designed for compatibility with existing machine formats, not for human readability. All of them therefore have a F format as default output format. Some of these formats are only portable between machines with compatible byte ordering (endianness) or floating-point format. Binary formats use byte values that in text files are interpreted as special control functions, such as carriage return and line feed. Thus, data in binary formats should not be included in syntax files or read from data files with variable-length records, such as ordinary text files. They may be read from or written to data files with fixed-length records. @xref{FILE HANDLE}, for information on working with fixed-length records. @subsubheading P and PK Formats These are binary-coded decimal formats, in which every byte (except the last, in P format) represents two decimal digits. The most-significant 4 bits of the first byte is the most-significant decimal digit, the least-significant 4 bits of the first byte is the next decimal digit, and so on. In P format, the most-significant 4 bits of the last byte are the least-significant decimal digit. The least-significant 4 bits represent the sign: decimal 15 indicates a negative value, decimal 13 indicates a positive value. Numbers are rounded downward on output. The system-missing value and numbers outside representable range are output as zero. The maximum field width is 16. Decimal places may range from 0 up to the number of decimal digits represented by the field. The default output format is an F format with twice the input field width, plus one column for a decimal point (if decimal places were requested). @subsubheading IB and PIB Formats These are integer binary formats. IB reads and writes 2's complement binary integers, and PIB reads and writes unsigned binary integers. The byte ordering is by default the host machine's, but SET RIB may be used to select a specific byte ordering for reading (@pxref{SET RIB}) and SET WIB, similarly, for writing (@pxref{SET WIB}). The maximum field width is 8. Decimal places may range from 0 up to the number of decimal digits in the largest value representable in the field width. The default output format is an F format whose width is the number of decimal digits in the largest value representable in the field width, plus 1 if the format has decimal places. @subsubheading RB Format This is a binary format for real numbers. By default it reads and writes the host machine's floating-point format, but SET RRB may be used to select an alternate floating-point format for reading (@pxref{SET RRB}) and SET WRB, similarly, for writing (@pxref{SET WRB}). The recommended field width depends on the floating-point format. NATIVE (the default format), IDL, IDB, VD, VG, and ZL formats should use a field width of 8. ISL, ISB, VF, and ZS formats should use a field width of 4. Other field widths will not produce useful results. The maximum field width is 8. No decimal places may be specified. The default output format is F8.2. @subsubheading PIBHEX and RBHEX Formats These are hexadecimal formats, for reading and writing binary formats where each byte has been recoded as a pair of hexadecimal digits. A hexadecimal field consists solely of hexadecimal digits @samp{0}@dots{}@samp{9} and @samp{A}@dots{}@samp{F}. Uppercase and lowercase are accepted on input; output is in uppercase. Other than the hexadecimal representation, these formats are equivalent to PIB and RB formats, respectively. However, bytes in PIBHEX format are always ordered with the most-significant byte first (big-endian order), regardless of the host machine's native byte order or @pspp{} settings. Field widths must be even and between 2 and 16. RBHEX format allows no decimal places; PIBHEX allows as many decimal places as a PIB format with half the given width. @node Time and Date Formats @subsubsection Time and Date Formats @cindex time formats @cindex date formats In @pspp{}, a @dfn{time} is an interval. The time formats translate between human-friendly descriptions of time intervals and @pspp{}'s internal representation of time intervals, which is simply the number of seconds in the interval. @pspp{} has two time formats: @float @multitable {Time Format} {@code{dd-mmm-yyyy HH:MM:SS.ss}} {@code{01-OCT-1978 04:31:17.01}} @headitem Time Format @tab Template @tab Example @item TIME @tab @code{hh:MM:SS.ss} @tab @code{04:31:17.01} @item DTIME @tab @code{DD HH:MM:SS.ss} @tab @code{00 04:31:17.01} @end multitable @end float A @dfn{date} is a moment in the past or the future. Internally, @pspp{} represents a date as the number of seconds since the @dfn{epoch}, midnight, Oct. 14, 1582. The date formats translate between human-readable dates and @pspp{}'s numeric representation of dates and times. @pspp{} has several date formats: @float @multitable {Date Format} {@code{dd-mmm-yyyy HH:MM:SS.ss}} {@code{01-OCT-1978 04:31:17.01}} @headitem Date Format @tab Template @tab Example @item DATE @tab @code{dd-mmm-yyyy} @tab @code{01-OCT-1978} @item ADATE @tab @code{mm/dd/yyyy} @tab @code{10/01/1978} @item EDATE @tab @code{dd.mm.yyyy} @tab @code{01.10.1978} @item JDATE @tab @code{yyyyjjj} @tab @code{1978274} @item SDATE @tab @code{yyyy/mm/dd} @tab @code{1978/10/01} @item QYR @tab @code{q Q yyyy} @tab @code{3 Q 1978} @item MOYR @tab @code{mmm yyyy} @tab @code{OCT 1978} @item WKYR @tab @code{ww WK yyyy} @tab @code{40 WK 1978} @item DATETIME @tab @code{dd-mmm-yyyy HH:MM:SS.ss} @tab @code{01-OCT-1978 04:31:17.01} @end multitable @end float The templates in the preceding tables describe how the time and date formats are input and output: @table @code @item dd Day of month, from 1 to 31. Always output as two digits. @item mm @itemx mmm Month. In output, @code{mm} is output as two digits, @code{mmm} as the first three letters of an English month name (January, February, @dots{}). In input, both of these formats, plus Roman numerals, are accepted. @item yyyy Year. In output, DATETIME always produces a 4-digit year; other formats can produce a 2- or 4-digit year. The century assumed for 2-digit years depends on the EPOCH setting (@pxref{SET EPOCH}). In output, a year outside the epoch causes the whole field to be filled with asterisks (@samp{*}). @item jjj Day of year (Julian day), from 1 to 366. This is exactly three digits giving the count of days from the start of the year. January 1 is considered day 1. @item q Quarter of year, from 1 to 4. Quarters start on January 1, April 1, July 1, and October 1. @item ww Week of year, from 1 to 53. Output as exactly two digits. January 1 is the first day of week 1. @item DD Count of days, which may be positive or negative. Output as at least two digits. @item hh Count of hours, which may be positive or negative. Output as at least two digits. @item HH Hour of day, from 0 to 23. Output as exactly two digits. @item MM Minute of hour, from 0 to 59. Output as exactly two digits. @item SS.ss Seconds within minute, from 0 to 59. The integer part is output as exactly two digits. On output, seconds and fractional seconds may or may not be included, depending on field width and decimal places. On input, seconds and fractional seconds are optional. The DECIMAL setting controls the character accepted and displayed as the decimal point (@pxref{SET DECIMAL}). @end table For output, the date and time formats use the delimiters indicated in the table. For input, date components may be separated by spaces or by one of the characters @samp{-}, @samp{/}, @samp{.}, or @samp{,}, and time components may be separated by spaces, @samp{:}, or @samp{.}. On input, the @samp{Q} separating quarter from year and the @samp{WK} separating week from year may be uppercase or lowercase, and the spaces around them are optional. On input, all time and date formats accept any amount of leading and trailing white space. The maximum width for time and date formats is 40 columns. Minimum input and output width for each of the time and date formats is shown below: @float @multitable {DATETIME} {Min. Input Width} {Min. Output Width} {4-digit year} @headitem Format @tab Min. Input Width @tab Min. Output Width @tab Option @item DATE @tab 8 @tab 9 @tab 4-digit year @item ADATE @tab 8 @tab 8 @tab 4-digit year @item EDATE @tab 8 @tab 8 @tab 4-digit year @item JDATE @tab 5 @tab 5 @tab 4-digit year @item SDATE @tab 8 @tab 8 @tab 4-digit year @item QYR @tab 4 @tab 6 @tab 4-digit year @item MOYR @tab 6 @tab 6 @tab 4-digit year @item WKYR @tab 6 @tab 8 @tab 4-digit year @item DATETIME @tab 17 @tab 17 @tab seconds @item TIME @tab 5 @tab 5 @tab seconds @item DTIME @tab 8 @tab 8 @tab seconds @end multitable @end float @noindent In the table, ``Option'' describes what increased output width enables: @table @asis @item 4-digit year A field 2 columns wider than minimum will include a 4-digit year. (DATETIME format always includes a 4-digit year.) @item seconds A field 3 columns wider than minimum will include seconds as well as minutes. A field 5 columns wider than minimum, or more, can also include a decimal point and fractional seconds (but no more than allowed by the format's decimal places). @end table For the time and date formats, the default output format is the same as the input format, except that @pspp{} increases the field width, if necessary, to the minimum allowed for output. Time or dates narrower than the field width are right-justified within the field. When a time or date exceeds the field width, characters are trimmed from the end until it fits. This can occur in an unusual situation, e.g.@: with a year greater than 9999 (which adds an extra digit), or for a negative value on TIME or DTIME (which adds a leading minus sign). @c What about out-of-range values? The system-missing value is output as a period at the right end of the field. @node Date Component Formats @subsubsection Date Component Formats The WKDAY and MONTH formats provide input and output for the names of weekdays and months, respectively. On output, these formats convert a number between 1 and 7, for WKDAY, or between 1 and 12, for MONTH, into the English name of a day or month, respectively. If the name is longer than the field, it is trimmed to fit. If the name is shorter than the field, it is padded on the right with spaces. Values outside the valid range, and the system-missing value, are output as all spaces. On input, English weekday or month names (in uppercase or lowercase) are converted back to their corresponding numbers. Weekday and month names may be abbreviated to their first 2 or 3 letters, respectively. The field width may range from 2 to 40, for WKDAY, or from 3 to 40, for MONTH. No decimal places are allowed. The default output format is the same as the input format. @node String Formats @subsubsection String Formats @cindex string formats The A and AHEX formats are the only ones that may be assigned to string variables. Neither format allows any decimal places. In A format, the entire field is treated as a string value. The field width may range from 1 to 32,767, the maximum string width. The default output format is the same as the input format. In AHEX format, the field is composed of characters in a string encoded as hex digit pairs. On output, hex digits are output in uppercase; on input, uppercase and lowercase are both accepted. The default output format is A format with half the input width. @node Scratch Variables @subsection Scratch Variables @cindex scratch variables Most of the time, variables don't retain their values between cases. Instead, either they're being read from a data file or the active dataset, in which case they assume the value read, or, if created with @cmd{COMPUTE} or another transformation, they're initialized to the system-missing value or to blanks, depending on type. However, sometimes it's useful to have a variable that keeps its value between cases. You can do this with @cmd{LEAVE} (@pxref{LEAVE}), or you can use a @dfn{scratch variable}. Scratch variables are variables whose names begin with an octothorpe (@samp{#}). Scratch variables have the same properties as variables left with @cmd{LEAVE}: they retain their values between cases, and for the first case they are initialized to 0 or blanks. They have the additional property that they are deleted before the execution of any procedure. For this reason, scratch variables can't be used for analysis. To use a scratch variable in an analysis, use @cmd{COMPUTE} (@pxref{COMPUTE}) to copy its value into an ordinary variable, then use that ordinary variable in the analysis. @node Files @section Files Used by @pspp{} @pspp{} makes use of many files each time it runs. Some of these it reads, some it writes, some it creates. Here is a table listing the most important of these files: @table @strong @cindex file, command @cindex file, syntax file @cindex command file @cindex syntax file @item command file @itemx syntax file These names (synonyms) refer to the file that contains instructions that tell @pspp{} what to do. The syntax file's name is specified on the @pspp{} command line. Syntax files can also be read with @cmd{INCLUDE} (@pxref{INCLUDE}). @cindex file, data @cindex data file @item data file Data files contain raw data in text or binary format. Data can also be embedded in a syntax file with @cmd{BEGIN DATA} and @cmd{END DATA}. @cindex file, output @cindex output file @item listing file One or more output files are created by @pspp{} each time it is run. The output files receive the tables and charts produced by statistical procedures. The output files may be in any number of formats, depending on how @pspp{} is configured. @cindex system file @cindex file, system @item system file System files are binary files that store a dictionary and a set of cases. @cmd{GET} and @cmd{SAVE} read and write system files. @cindex portable file @cindex file, portable @item portable file Portable files are files in a text-based format that store a dictionary and a set of cases. @cmd{IMPORT} and @cmd{EXPORT} read and write portable files. @end table @node File Handles @section File Handles @cindex file handles A @dfn{file handle} is a reference to a data file, system file, or portable file. Most often, a file handle is specified as the name of a file as a string, that is, enclosed within @samp{'} or @samp{"}. A file name string that begins or ends with @samp{|} is treated as the name of a command to pipe data to or from. You can use this feature to read data over the network using a program such as @samp{curl} (e.g.@: @code{GET '|curl -s -S http://example.com/mydata.sav'}), to read compressed data from a file using a program such as @samp{zcat} (e.g.@: @code{GET '|zcat mydata.sav.gz'}), and for many other purposes. @pspp{} also supports declaring named file handles with the @cmd{FILE HANDLE} command. This command associates an identifier of your choice (the file handle's name) with a file. Later, the file handle name can be substituted for the name of the file. When @pspp{} syntax accesses a file multiple times, declaring a named file handle simplifies updating the syntax later to use a different file. Use of @cmd{FILE HANDLE} is also required to read data files in binary formats. @xref{FILE HANDLE}, for more information. In some circumstances, @pspp{} must distinguish whether a file handle refers to a system file or a portable file. When this is necessary to read a file, e.g.@: as an input file for @cmd{GET} or @cmd{MATCH FILES}, @pspp{} uses the file's contents to decide. In the context of writing a file, e.g.@: as an output file for @cmd{SAVE} or @cmd{AGGREGATE}, @pspp{} decides based on the file's name: if it ends in @samp{.por} (with any capitalization), then @pspp{} writes a portable file; otherwise, @pspp{} writes a system file. INLINE is reserved as a file handle name. It refers to the ``data file'' embedded into the syntax file between @cmd{BEGIN DATA} and @cmd{END DATA}. @xref{BEGIN DATA}, for more information. The file to which a file handle refers may be reassigned on a later @cmd{FILE HANDLE} command if it is first closed using @cmd{CLOSE FILE HANDLE}. @xref{CLOSE FILE HANDLE}, for more information. @node BNF @section Backus-Naur Form @cindex BNF @cindex Backus-Naur Form @cindex command syntax, description of @cindex description of command syntax The syntax of some parts of the @pspp{} language is presented in this manual using the formalism known as @dfn{Backus-Naur Form}, or BNF. The following table describes BNF: @itemize @bullet @cindex keywords @cindex terminals @item Words in all-uppercase are @pspp{} keyword tokens. In BNF, these are often called @dfn{terminals}. There are some special terminals, which are written in lowercase for clarity: @table @asis @cindex @code{number} @item @code{number} A real number. @cindex @code{integer} @item @code{integer} An integer number. @cindex @code{string} @item @code{string} A string. @cindex @code{var-name} @item @code{var-name} A single variable name. @cindex operators @cindex punctuators @item @code{=}, @code{/}, @code{+}, @code{-}, etc. Operators and punctuators. @cindex @code{.} @item @code{.} The end of the command. This is not necessarily an actual dot in the syntax file: @xref{Commands}, for more details. @end table @item @cindex productions @cindex nonterminals Other words in all lowercase refer to BNF definitions, called @dfn{productions}. These productions are also known as @dfn{nonterminals}. Some nonterminals are very common, so they are defined here in English for clarity: @table @code @cindex @code{var-list} @item var-list A list of one or more variable names or the keyword @code{ALL}. @cindex @code{expression} @item expression An expression. @xref{Expressions}, for details. @end table @item @cindex ``is defined as'' @cindex productions @samp{::=} means ``is defined as''. The left side of @samp{::=} gives the name of the nonterminal being defined. The right side of @samp{::=} gives the definition of that nonterminal. If the right side is empty, then one possible expansion of that nonterminal is nothing. A BNF definition is called a @dfn{production}. @item @cindex terminals and nonterminals, differences So, the key difference between a terminal and a nonterminal is that a terminal cannot be broken into smaller parts---in fact, every terminal is a single token (@pxref{Tokens}). On the other hand, nonterminals are composed of a (possibly empty) sequence of terminals and nonterminals. Thus, terminals indicate the deepest level of syntax description. (In parsing theory, terminals are the leaves of the parse tree; nonterminals form the branches.) @item @cindex start symbol @cindex symbol, start The first nonterminal defined in a set of productions is called the @dfn{start symbol}. The start symbol defines the entire syntax for that command. @end itemize pspp-master/doc/license.texi000066400000000000000000000042631177044323000164210ustar00rootroot00000000000000@node License @chapter Your rights and obligations @cindex license @cindex licence @cindex your rights and obligations @cindex rights, your @cindex copyright @cindex obligations, your @pspp{} is not in the public domain. It is copyrighted and there are restrictions on its distribution, but these restrictions are designed to permit everything that a good cooperating citizen would want to do. What is not allowed is to try to prevent others from further sharing any version of this program that they might get from you. Specifically, we want to make sure that you have the right to give away copies of @pspp{}, that you receive source code or else can get it if you want it, that you can change these programs or use pieces of them in new free programs, and that you know you can do these things. To make sure that everyone has such rights, we have to forbid you to deprive anyone else of these rights. For example, if you distribute copies of @pspp{}, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. Also, for our own protection, we must make certain that everyone finds out that there is no warranty for @pspp{}. If these programs are modified by someone else and passed on, we want their recipients to know that what they have is not what we distributed, so that any problems introduced by others will not reflect on our reputation. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise conditions of the license for @pspp{} are found in the GNU General Public License. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. This manual specifically is covered by the GNU Free Documentation License (@pxref{GNU Free Documentation License}). pspp-master/doc/not-implemented.texi000066400000000000000000000003221177044323000200700ustar00rootroot00000000000000@node Not Implemented @chapter Not Implemented This chapter lists parts of the @pspp{} language that are not yet implemented. @cindex unimplemented commands @cindex commands, unimplemented @include ni.texi pspp-master/doc/pspp-dev.texinfo000066400000000000000000000051471177044323000172420ustar00rootroot00000000000000\input texinfo @c -*- texinfo -*- @c %**start of header @setfilename pspp-dev.info @settitle PSPP @c For double-sided printing, uncomment: @c @setchapternewpage odd @c %**end of header @include version-dev.texi @macro cmd{CMDNAME} \CMDNAME\ @end macro @macro struct{TAG} @code{struct \TAG\} @end macro @macro union{TAG} @code{union \TAG\} @end macro @macro enum{TAG} @code{enum \TAG\} @end macro @macro func{NAME} @code{\NAME\} @end macro @iftex @finalout @end iftex @dircategory Math @direntry * PSPP Developers Guide: (pspp-dev). Tutorial and reference for PSPP developers. @end direntry @copying This manual is for GNU PSPP version @value{VERSION}, software for statistical analysis. Copyright @copyright{} 1997, 1998, 2004, 2005, 2007, 2010 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". @end quotation @end copying @titlepage @title PSPP Developers Guide @subtitle GNU PSPP Statistical Analysis Software @subtitle Release @value{VERSION} @author @page @vskip 0pt plus 1filll @insertcopying @end titlepage @contents @ifnottex @node Top @top GNU PSPP Developers Guide @insertcopying @end ifnottex @menu * Introduction:: Introduction to PSPP development. * Basic Concepts:: Data structures and concepts. * Parsing Command Syntax:: How to parse command syntax. * Processing Data:: Data input, output, and processing. * Presenting Output:: Producing machine- and human-readable output. * Internationalisation:: Dealing with locale issues. * Function Index:: Index of PSPP functions. * Concept Index:: Index of concepts. * Portable File Format:: Format of PSPP portable files. * System File Format:: Format of PSPP system files. * q2c Input Format:: Format of syntax accepted by q2c. * GNU Free Documentation License:: License for copying this manual. @end menu @include dev/intro.texi @include dev/concepts.texi @include dev/syntax.texi @include dev/data.texi @include dev/output.texi @include dev/i18n.texi @include function-index.texi @include concept-index.texi @include dev/portable-file-format.texi @include dev/system-file-format.texi @include dev/q2c.texi @include fdl.texi @bye @c Local Variables: @c compile-command: "makeinfo pspp-dev.texinfo" @c End: pspp-master/doc/pspp.man000066400000000000000000000033161177044323000155610ustar00rootroot00000000000000.\" PSPP - computes sample statistics. .\" Copyright (C) 1997, 1998 Free Software Foundation, Inc. .\" .\" 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 . .\" .TH pspp 1 "4 Jul 1997" "manpage v1.0" "PSPP manual" .SH NAME pspp \- a system for statistical analysis .SH SYNOPSIS .B pspp \&.\|.\|. .SH DESCRIPTION .B pspp starts up the PSPP program. PSPP performs statistical analysis on sampled data. Please see Info document `pspp' for more details on using PSPP. For other miscellaneous information about PSPP, see the PSPP FAQ, which should be installed in /usr/doc/pspp. These documents and others are available in various formats. On Debian GNU/Linux systems, full documentation is available in directory `/usr/doc/pspp', in HTML and ASCII formats, and in `/usr/info', in Info format. TeX can be used to convert the Texinfo documentation in the source distribution to nice-looking output for printing. Documentation is also at http://www.gnu.org/software/pspp. .SH BUGS Probably a lot. Known bugs are listed in the documentation files BUGS, LANGUAGE, and TODO, depending on type. Please see those files for more details. pspp-master/doc/pspp.texinfo000066400000000000000000000103171177044323000164610ustar00rootroot00000000000000\input texinfo @c -*- texinfo -*- @c %**start of header @setfilename pspp.info @settitle PSPP @c For double-sided printing, uncomment: @c @setchapternewpage odd @c %**end of header @macro note{param1} @quotation @strong{Please note:} \param1\ @end quotation @end macro @include version.texi @c This macro should be used for marking command names. For the purposes of markup, @c no distinction is made between ``commands'' and ``procedures''. @macro cmd{CMDNAME} @code{\CMDNAME\} @end macro @c This macro is used for fragments of command syntax that are not in themselves command names. @c It does not necessarily have to be a subcommand. @macro subcmd{CMDNAME} @code{\CMDNAME\} @end macro @c Use this macro to refer to PSPP itself . Not when giving a shell command line example. @macro pspp @sc{pspp} @end macro @ifset MISSING_CLICKSEQUENCE @alias clicksequence = asis @macro click {} -> @end macro @end ifset @iftex @finalout @end iftex @dircategory Math @direntry * PSPP: (pspp). Statistical analysis package. * PSPPIRE: (pspp). Graphical user interface to @pspp{}. @end direntry @copying This manual is for GNU PSPP version @value{VERSION}, software for statistical analysis. Copyright @copyright{} 1997, 1998, 2004, 2005, 2009, 2012 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". @end quotation @end copying @titlepage @title PSPP Users Guide @subtitle GNU PSPP Statistical Analysis Software @subtitle Release @value{VERSION} @page @vskip 0pt plus 1filll @insertcopying @end titlepage @c @chapheading Acknowledgements The authors wish to thank Network Theory Ltd @url{http://www.network-theory.co.uk} for their financial support in the production of this manual. @contents @ifnottex @node Top @top GNU PSPP @insertcopying @end ifnottex @menu * Introduction:: Description of the package. * License:: Your rights and obligations. * Invoking PSPP:: Starting the PSPP text-based interface. * Invoking PSPPIRE:: Starting the PSPP graphical user interface. * Using PSPP:: How to use PSPP --- A brief tutorial. * Language:: Basics of the PSPP command language. * Expressions:: Numeric and string expression syntax. * Data Input and Output:: Reading data from user files. * System and Portable File IO:: Reading and writing system & portable files. * Combining Data Files:: Combining data from multiple files. * Variable Attributes:: Adjusting and examining variables. * Data Manipulation:: Simple operations on data. * Data Selection:: Select certain cases for analysis. * Conditionals and Looping:: Doing things many times or not at all. * Statistics:: Basic statistical procedures. * Utilities:: Other commands. * Not Implemented:: What's not here yet * Bugs:: Known problems; submitting bug reports. * Function Index:: Index of PSPP functions for expressions. * Command Index:: Index of PSPP procedures. * Concept Index:: Index of concepts. * GNU Free Documentation License:: License for copying this manual. @end menu @include introduction.texi @include license.texi @include invoking.texi @include tutorial.texi @include language.texi @include expressions.texi @include data-io.texi @include files.texi @include combining.texi @include variables.texi @include transformation.texi @include data-selection.texi @include flow-control.texi @include statistics.texi @include utilities.texi @include not-implemented.texi @include bugs.texi @include function-index.texi @include command-index.texi @include concept-index.texi @include fdl.texi @bye @c Local Variables: @c use (texinfo-multiple-files-update "pspp.texinfo") in emacs to keep these files consistent @c compile-command: "makeinfo pspp.texinfo" @c End: pspp-master/doc/regression.texi000066400000000000000000000075321177044323000171610ustar00rootroot00000000000000@node REGRESSION @section REGRESSION @cindex regression @cindex linear regression The @cmd{REGRESSION} procedure fits linear models to data via least-squares estimation. The procedure is appropriate for data which satisfy those assumptions typical in linear regression: @itemize @bullet @item The data set contains @math{n} observations of a dependent variable, say @math{Y_1,@dots{},Y_n}, and @math{n} observations of one or more explanatory variables. Let @math{X_{11}, X_{12}}, @dots{}, @math{X_{1n}} denote the @math{n} observations of the first explanatory variable; @math{X_{21}},@dots{},@math{X_{2n}} denote the @math{n} observations of the second explanatory variable; @math{X_{k1}},@dots{},@math{X_{kn}} denote the @math{n} observations of the @math{k}th explanatory variable. @item The dependent variable @math{Y} has the following relationship to the explanatory variables: @math{Y_i = b_0 + b_1 X_{1i} + ... + b_k X_{ki} + Z_i} where @math{b_0, b_1, @dots{}, b_k} are unknown coefficients, and @math{Z_1,@dots{},Z_n} are independent, normally distributed @dfn{noise} terms with mean zero and common variance. The noise, or @dfn{error} terms are unobserved. This relationship is called the @dfn{linear model}. @end itemize The @cmd{REGRESSION} procedure estimates the coefficients @math{b_0,@dots{},b_k} and produces output relevant to inferences for the linear model. @menu * Syntax:: Syntax definition. * Examples:: Using the REGRESSION procedure. @end menu @node Syntax @subsection Syntax @vindex REGRESSION @display REGRESSION /VARIABLES=@var{var_list} /DEPENDENT=@var{var_list} /STATISTICS=@{ALL, DEFAULTS, R, COEFF, ANOVA, BCOV@} /SAVE=@{PRED, RESID@} @end display The @cmd{REGRESSION} procedure reads the active dataset and outputs statistics relevant to the linear model specified by the user. The @subcmd{VARIABLES} subcommand, which is required, specifies the list of variables to be analyzed. Keyword @subcmd{VARIABLES} is required. The @subcmd{DEPENDENT} subcommand specifies the dependent variable of the linear model. The @subcmd{DEPENDENT} subcommand is required. All variables listed in the @subcmd{VARIABLES} subcommand, but not listed in the @subcmd{DEPENDENT} subcommand, are treated as explanatory variables in the linear model. All other subcommands are optional: The @subcmd{STATISTICS} subcommand specifies the statistics to be displayed: @table @subcmd @item ALL All of the statistics below. @item R The ratio of the sums of squares due to the model to the total sums of squares for the dependent variable. @item COEFF A table containing the estimated model coefficients and their standard errors. @item ANOVA Analysis of variance table for the model. @item BCOV The covariance matrix for the estimated model coefficients. @end table The @subcmd{SAVE} subcommand causes @pspp{} to save the residuals or predicted values from the fitted model to the active dataset. @pspp{} will store the residuals in a variable called @samp{RES1} if no such variable exists, @samp{RES2} if @samp{RES1} already exists, @samp{RES3} if @samp{RES1} and @samp{RES2} already exist, etc. It will choose the name of the variable for the predicted values similarly, but with @samp{PRED} as a prefix. @node Examples @subsection Examples The following @pspp{} syntax will generate the default output and save the predicted values and residuals to the active dataset. @example title 'Demonstrate REGRESSION procedure'. data list / v0 1-2 (A) v1 v2 3-22 (10). begin data. b 7.735648 -23.97588 b 6.142625 -19.63854 a 7.651430 -25.26557 c 6.125125 -16.57090 a 8.245789 -25.80001 c 6.031540 -17.56743 a 9.832291 -28.35977 c 5.343832 -16.79548 a 8.838262 -29.25689 b 6.200189 -18.58219 end data. list. regression /variables=v0 v1 v2 /statistics defaults /dependent=v2 /save pred resid /method=enter. @end example pspp-master/doc/statistics.texi000066400000000000000000002003541177044323000171700ustar00rootroot00000000000000@node Statistics @chapter Statistics This chapter documents the statistical procedures that @pspp{} supports so far. @menu * DESCRIPTIVES:: Descriptive statistics. * FREQUENCIES:: Frequency tables. * EXAMINE:: Testing data for normality. * CORRELATIONS:: Correlation tables. * CROSSTABS:: Crosstabulation tables. * FACTOR:: Factor analysis and Principal Components analysis * MEANS:: Average values and other statistics. * NPAR TESTS:: Nonparametric tests. * T-TEST:: Test hypotheses about means. * ONEWAY:: One way analysis of variance. * QUICK CLUSTER:: K-Means clustering. * RANK:: Compute rank scores. * REGRESSION:: Linear regression. * RELIABILITY:: Reliability analysis. * ROC:: Receiver Operating Characteristic. @end menu @node DESCRIPTIVES @section DESCRIPTIVES @vindex DESCRIPTIVES @display DESCRIPTIVES /VARIABLES=@var{var_list} /MISSING=@{VARIABLE,LISTWISE@} @{INCLUDE,NOINCLUDE@} /FORMAT=@{LABELS,NOLABELS@} @{NOINDEX,INDEX@} @{LINE,SERIAL@} /SAVE /STATISTICS=@{ALL,MEAN,SEMEAN,STDDEV,VARIANCE,KURTOSIS, SKEWNESS,RANGE,MINIMUM,MAXIMUM,SUM,DEFAULT, SESKEWNESS,SEKURTOSIS@} /SORT=@{NONE,MEAN,SEMEAN,STDDEV,VARIANCE,KURTOSIS,SKEWNESS, RANGE,MINIMUM,MAXIMUM,SUM,SESKEWNESS,SEKURTOSIS,NAME@} @{A,D@} @end display The @cmd{DESCRIPTIVES} procedure reads the active dataset and outputs descriptive statistics requested by the user. In addition, it can optionally compute Z-scores. The @subcmd{VARIABLES} subcommand, which is required, specifies the list of variables to be analyzed. Keyword @subcmd{VARIABLES} is optional. All other subcommands are optional: The @subcmd{MISSING} subcommand determines the handling of missing variables. If @subcmd{INCLUDE} is set, then user-missing values are included in the calculations. If @subcmd{NOINCLUDE} is set, which is the default, user-missing values are excluded. If @subcmd{VARIABLE} is set, then missing values are excluded on a variable by variable basis; if @subcmd{LISTWISE} is set, then the entire case is excluded whenever any value in that case has a system-missing or, if @subcmd{INCLUDE} is set, user-missing value. The @subcmd{FORMAT} subcommand affects the output format. Currently the @subcmd{LABELS/NOLABELS} and @subcmd{NOINDEX/INDEX} settings are not used. When @subcmd{SERIAL} is set, both valid and missing number of cases are listed in the output; when @subcmd{NOSERIAL} is set, only valid cases are listed. The @subcmd{SAVE} subcommand causes @cmd{DESCRIPTIVES} to calculate Z scores for all the specified variables. The Z scores are saved to new variables. Variable names are generated by trying first the original variable name with Z prepended and truncated to a maximum of 8 characters, then the names ZSC000 through ZSC999, STDZ00 through STDZ09, ZZZZ00 through ZZZZ09, ZQZQ00 through ZQZQ09, in that sequence. In addition, Z score variable names can be specified explicitly on @subcmd{VARIABLES} in the variable list by enclosing them in parentheses after each variable. The @subcmd{STATISTICS} subcommand specifies the statistics to be displayed: @table @code @item @subcmd{ALL} All of the statistics below. @item @subcmd{MEAN} Arithmetic mean. @item @subcmd{SEMEAN} Standard error of the mean. @item @subcmd{STDDEV} Standard deviation. @item @subcmd{VARIANCE} Variance. @item @subcmd{KURTOSIS} Kurtosis and standard error of the kurtosis. @item @subcmd{SKEWNESS} Skewness and standard error of the skewness. @item @subcmd{RANGE} Range. @item MINIMUM Minimum value. @item MAXIMUM Maximum value. @item SUM Sum. @item DEFAULT Mean, standard deviation of the mean, minimum, maximum. @item SEKURTOSIS Standard error of the kurtosis. @item SESKEWNESS Standard error of the skewness. @end table The @subcmd{SORT} subcommand specifies how the statistics should be sorted. Most of the possible values should be self-explanatory. @subcmd{NAME} causes the statistics to be sorted by name. By default, the statistics are listed in the order that they are specified on the @subcmd{VARIABLES} subcommand. The @subcmd{A} and @subcmd{D} settings request an ascending or descending sort order, respectively. @node FREQUENCIES @section FREQUENCIES @vindex FREQUENCIES @display FREQUENCIES /VARIABLES=@var{var_list} /FORMAT=@{TABLE,NOTABLE,LIMIT(@var{limit})@} @{AVALUE,DVALUE,AFREQ,DFREQ@} /MISSING=@{EXCLUDE,INCLUDE@} /STATISTICS=@{DEFAULT,MEAN,SEMEAN,MEDIAN,MODE,STDDEV,VARIANCE, KURTOSIS,SKEWNESS,RANGE,MINIMUM,MAXIMUM,SUM, SESKEWNESS,SEKURTOSIS,ALL,NONE@} /NTILES=@var{ntiles} /PERCENTILES=percent@dots{} /HISTOGRAM=[MINIMUM(@var{x_min})] [MAXIMUM(@var{x_max})] [@{FREQ[(@var{y_max})],PERCENT[(@var{y_max})]@}] [@{NONORMAL,NORMAL@}] /PIECHART=[MINIMUM(@var{x_min})] [MAXIMUM(@var{x_max})] [@{FREQ,PERCENT@}] [@{NOMISSING,MISSING@}] (These options are not currently implemented.) /BARCHART=@dots{} /HBAR=@dots{} /GROUPED=@dots{} @end display The @cmd{FREQUENCIES} procedure outputs frequency tables for specified variables. @cmd{FREQUENCIES} can also calculate and display descriptive statistics (including median and mode) and percentiles, @cmd{FREQUENCIES} can also output histograms and pie charts. The @subcmd{VARIABLES} subcommand is the only required subcommand. Specify the variables to be analyzed. The @subcmd{FORMAT} subcommand controls the output format. It has several possible settings: @itemize @subcmd{} @item @subcmd{TABLE}, the default, causes a frequency table to be output for every variable specified. @subcmd{NOTABLE} prevents them from being output. @subcmd{LIMIT} with a numeric argument causes them to be output except when there are more than the specified number of values in the table. @item Normally frequency tables are sorted in ascending order by value. This is @subcmd{AVALUE}. @subcmd{DVALUE} tables are sorted in descending order by value. @subcmd{AFREQ} and @subcmd{DFREQ} tables are sorted in ascending and descending order, respectively, by frequency count. @end itemize The @subcmd{MISSING} subcommand controls the handling of user-missing values. When @subcmd{EXCLUDE}, the default, is set, user-missing values are not included in frequency tables or statistics. When @subcmd{INCLUDE} is set, user-missing are included. System-missing values are never included in statistics, but are listed in frequency tables. The available @subcmd{STATISTICS} are the same as available in @cmd{DESCRIPTIVES} (@pxref{DESCRIPTIVES}), with the addition of @subcmd{MEDIAN}, the data's median value, and MODE, the mode. (If there are multiple modes, the smallest value is reported.) By default, the mean, standard deviation of the mean, minimum, and maximum are reported for each variable. @cindex percentiles @subcmd{PERCENTILES} causes the specified percentiles to be reported. The percentiles should be presented at a list of numbers between 0 and 100 inclusive. The @subcmd{NTILES} subcommand causes the percentiles to be reported at the boundaries of the data set divided into the specified number of ranges. For instance, @subcmd{/NTILES=4} would cause quartiles to be reported. @cindex histogram The @subcmd{HISTOGRAM} subcommand causes the output to include a histogram for each specified numeric variable. The X axis by default ranges from the minimum to the maximum value observed in the data, but the @subcmd{MINIMUM} and @subcmd{MAXIMUM} keywords can set an explicit range. Specify @subcmd{NORMAL} to superimpose a normal curve on the histogram. Histograms are not created for string variables. @cindex piechart The @subcmd{PIECHART} subcommand adds a pie chart for each variable to the data. Each slice represents one value, with the size of the slice proportional to the value's frequency. By default, all non-missing values are given slices. The @subcmd{MINIMUM} and @subcmd{MAXIMUM} keywords can be used to limit the displayed slices to a given range of values. The @subcmd{MISSING} keyword adds slices for missing values. The @subcmd{FREQ} and @subcmd{PERCENT} options on @subcmd{HISTOGRAM} and @subcmd{PIECHART} are accepted but not currently honoured. @node EXAMINE @section EXAMINE @vindex EXAMINE @cindex Exploratory data analysis @cindex Normality, testing for @display EXAMINE VARIABLES= @var{var1} [@var{var2}] @dots{} [@var{varN}] [BY @var{factor1} [BY @var{subfactor1}] [ @var{factor2} [BY @var{subfactor2}]] @dots{} [ @var{factor3} [BY @var{subfactor3}]] ] /STATISTICS=@{DESCRIPTIVES, EXTREME[(@var{n})], ALL, NONE@} /PLOT=@{BOXPLOT, NPPLOT, HISTOGRAM, SPREADLEVEL[(@var{t})], ALL, NONE@} /CINTERVAL @var{p} /COMPARE=@{GROUPS,VARIABLES@} /ID=@var{identity_variable} /@{TOTAL,NOTOTAL@} /PERCENTILE=[@var{percentiles}]=@{HAVERAGE, WAVERAGE, ROUND, AEMPIRICAL, EMPIRICAL @} /MISSING=@{LISTWISE, PAIRWISE@} [@{EXCLUDE, INCLUDE@}] [@{NOREPORT,REPORT@}] @end display The @cmd{EXAMINE} command is used to perform exploratory data analysis. In particular, it is useful for testing how closely a distribution follows a normal distribution, and for finding outliers and extreme values. The @subcmd{VARIABLES} subcommand is mandatory. It specifies the dependent variables and optionally variables to use as factors for the analysis. Variables listed before the first @subcmd{BY} keyword (if any) are the dependent variables. The dependent variables may optionally be followed by a list of factors which tell @pspp{} how to break down the analysis for each dependent variable. Following the dependent variables, factors may be specified. The factors (if desired) should be preceeded by a single @subcmd{BY} keyword. The format for each factor is @display @var{factorvar} [BY @var{subfactorvar}]. @end display Each unique combination of the values of @var{factorvar} and @var{subfactorvar} divide the dataset into @dfn{cells}. Statistics will be calculated for each cell and for the entire dataset (unless @subcmd{NOTOTAL} is given). The @subcmd{STATISTICS} subcommand specifies which statistics to show. @subcmd{DESCRIPTIVES} will produce a table showing some parametric and non-parametrics statistics. @subcmd{EXTREME} produces a table showing the extremities of each cell. A number in parentheses, @var{n} determines how many upper and lower extremities to show. The default number is 5. The subcommands @subcmd{TOTAL} and @subcmd{NOTOTAL} are mutually exclusive. If @subcmd{TOTAL} appears, then statistics will be produced for the entire dataset as well as for each cell. If @subcmd{NOTOTAL} appears, then statistics will be produced only for the cells (unless no factor variables have been given). These subcommands have no effect if there have been no factor variables specified. @cindex boxplot @cindex histogram @cindex npplot @cindex spreadlevel plot The @subcmd{PLOT} subcommand specifies which plots are to be produced if any. Available plots are @subcmd{HISTOGRAM}, @subcmd{NPPLOT}, @subcmd{BOXPLOT} and @subcmd{SPREADLEVEL}. The first three can be used to visualise how closely each cell conforms to a normal distribution, whilst the spread vs.@: level plot can be useful to visualise how the variance of differs between factors. Boxplots will also show you the outliers and extreme values. The @subcmd{SPREADLEVEL} plot displays the interquartile range versus the median. It takes an optional parameter @var{t}, which specifies how the data should be transformed prior to plotting. The given value @var{t} is a power to which the data is raised. For example, if @var{t} is given as 2, then the data will be squared. Zero, however is a special value. If @var{t} is 0 or is omitted, then data will be transformed by taking its natural logarithm instead of raising to the power of @var{t}. The @subcmd{COMPARE} subcommand is only relevant if producing boxplots, and it is only useful there is more than one dependent variable and at least one factor. If @subcmd{/COMPARE=GROUPS} is specified, then one plot per dependent variable is produced, each of which contain boxplots for all the cells. If @subcmd{/COMPARE=VARIABLES} is specified, then one plot per cell is produced, each containing one boxplot per dependent variable. If the @subcmd{/COMPARE} subcommand is omitted, then @pspp{} behaves as if @subcmd{/COMPARE=GROUPS} were given. The @subcmd{ID} subcommand is relevant only if @subcmd{/PLOT=BOXPLOT} or @subcmd{/STATISTICS=EXTREME} has been given. If given, it shoule provide the name of a variable which is to be used to labels extreme values and outliers. Numeric or string variables are permissible. If the @subcmd{ID} subcommand is not given, then the casenumber will be used for labelling. The @subcmd{CINTERVAL} subcommand specifies the confidence interval to use in calculation of the descriptives command. The default is 95%. @cindex percentiles The @subcmd{PERCENTILES} subcommand specifies which percentiles are to be calculated, and which algorithm to use for calculating them. The default is to calculate the 5, 10, 25, 50, 75, 90, 95 percentiles using the @subcmd{HAVERAGE} algorithm. The @subcmd{TOTAL} and @subcmd{NOTOTAL} subcommands are mutually exclusive. If @subcmd{NOTOTAL} is given and factors have been specified in the @subcmd{VARIABLES} subcommand, then then statistics for the unfactored dependent variables are produced in addition to the factored variables. If there are no factors specified then @subcmd{TOTAL} and @subcmd{NOTOTAL} have no effect. The following example will generate descriptive statistics and histograms for two variables @var{score1} and @var{score2}. Two factors are given, @i{viz}: @var{gender} and @var{gender} BY @var{culture}. Therefore, the descriptives and histograms will be generated for each distinct value of @var{gender} @emph{and} for each distinct combination of the values of @var{gender} and @var{race}. Since the @subcmd{NOTOTAL} keyword is given, statistics and histograms for @var{score1} and @var{score2} covering the whole dataset are not produced. @example EXAMINE @var{score1} @var{score2} BY @var{gender} @var{gender} BY @var{culture} /STATISTICS = DESCRIPTIVES /PLOT = HISTOGRAM /NOTOTAL. @end example Here is a second example showing how the @cmd{examine} command can be used to find extremities. @example EXAMINE @var{height} @var{weight} BY @var{gender} /STATISTICS = EXTREME (3) /PLOT = BOXPLOT /COMPARE = GROUPS /ID = @var{name}. @end example In this example, we look at the height and weight of a sample of individuals and how they differ between male and female. A table showing the 3 largest and the 3 smallest values of @var{height} and @var{weight} for each gender, and for the whole dataset will be shown. Boxplots will also be produced. Because @subcmd{/COMPARE = GROUPS} was given, boxplots for male and female will be shown in the same graphic, allowing us to easily see the difference between the genders. Since the variable @var{name} was specified on the @subcmd{ID} subcommand, this will be used to label the extreme values. @strong{Warning!} If many dependent variables are specified, or if factor variables are specified for which there are many distinct values, then @cmd{EXAMINE} will produce a very large quantity of output. @node CORRELATIONS @section CORRELATIONS @vindex CORRELATIONS @display CORRELATIONS /VARIABLES = @var{var_list} [ WITH @var{var_list} ] [ . . . /VARIABLES = @var{var_list} [ WITH @var{var_list} ] /VARIABLES = @var{var_list} [ WITH @var{var_list} ] ] [ /PRINT=@{TWOTAIL, ONETAIL@} @{SIG, NOSIG@} ] [ /STATISTICS=DESCRIPTIVES XPROD ALL] [ /MISSING=@{PAIRWISE, LISTWISE@} @{INCLUDE, EXCLUDE@} ] @end display @cindex correlation The @cmd{CORRELATIONS} procedure produces tables of the Pearson correlation coefficient for a set of variables. The significance of the coefficients are also given. At least one @subcmd{VARIABLES} subcommand is required. If the @subcmd{WITH} keyword is used, then a non-square correlation table will be produced. The variables preceding @subcmd{WITH}, will be used as the rows of the table, and the variables following will be the columns of the table. If no @subcmd{WITH} subcommand is given, then a square, symmetrical table using all variables is produced. The @cmd{MISSING} subcommand determines the handling of missing variables. If @subcmd{INCLUDE} is set, then user-missing values are included in the calculations, but system-missing values are not. If @subcmd{EXCLUDE} is set, which is the default, user-missing values are excluded as well as system-missing values. If @subcmd{LISTWISE} is set, then the entire case is excluded from analysis whenever any variable specified in any @cmd{/VARIABLES} subcommand contains a missing value. If @subcmd{PAIRWISE} is set, then a case is considered missing only if either of the values for the particular coefficient are missing. The default is @subcmd{PAIRWISE}. The @subcmd{PRINT} subcommand is used to control how the reported significance values are printed. If the @subcmd{TWOTAIL} option is used, then a two-tailed test of significance is printed. If the @subcmd{ONETAIL} option is given, then a one-tailed test is used. The default is @subcmd{TWOTAIL}. If the @subcmd{NOSIG} option is specified, then correlation coefficients with significance less than 0.05 are highlighted. If @subcmd{SIG} is specified, then no highlighting is performed. This is the default. @cindex covariance The @subcmd{STATISTICS} subcommand requests additional statistics to be displayed. The keyword @subcmd{DESCRIPTIVES} requests that the mean, number of non-missing cases, and the non-biased estimator of the standard deviation are displayed. These statistics will be displayed in a separated table, for all the variables listed in any @subcmd{/VARIABLES} subcommand. The @subcmd{XPROD} keyword requests cross-product deviations and covariance estimators to be displayed for each pair of variables. The keyword @subcmd{ALL} is the union of @subcmd{DESCRIPTIVES} and @subcmd{XPROD}. @node CROSSTABS @section CROSSTABS @vindex CROSSTABS @display CROSSTABS /TABLES=@var{var_list} BY @var{var_list} [BY @var{var_list}]@dots{} /MISSING=@{TABLE,INCLUDE,REPORT@} /WRITE=@{NONE,CELLS,ALL@} /FORMAT=@{TABLES,NOTABLES@} @{PIVOT,NOPIVOT@} @{AVALUE,DVALUE@} @{NOINDEX,INDEX@} @{BOX,NOBOX@} /CELLS=@{COUNT,ROW,COLUMN,TOTAL,EXPECTED,RESIDUAL,SRESIDUAL, ASRESIDUAL,ALL,NONE@} /STATISTICS=@{CHISQ,PHI,CC,LAMBDA,UC,BTAU,CTAU,RISK,GAMMA,D, KAPPA,ETA,CORR,ALL,NONE@} (Integer mode.) /VARIABLES=@var{var_list} (@var{low},@var{high})@dots{} @end display The @cmd{CROSSTABS} procedure displays crosstabulation tables requested by the user. It can calculate several statistics for each cell in the crosstabulation tables. In addition, a number of statistics can be calculated for each table itself. The @subcmd{TABLES} subcommand is used to specify the tables to be reported. Any number of dimensions is permitted, and any number of variables per dimension is allowed. The @subcmd{TABLES} subcommand may be repeated as many times as needed. This is the only required subcommand in @dfn{general mode}. Occasionally, one may want to invoke a special mode called @dfn{integer mode}. Normally, in general mode, @pspp{} automatically determines what values occur in the data. In integer mode, the user specifies the range of values that the data assumes. To invoke this mode, specify the @subcmd{VARIABLES} subcommand, giving a range of data values in parentheses for each variable to be used on the @subcmd{TABLES} subcommand. Data values inside the range are truncated to the nearest integer, then assigned to that value. If values occur outside this range, they are discarded. When it is present, the @subcmd{VARIABLES} subcommand must precede the @subcmd{TABLES} subcommand. In general mode, numeric and string variables may be specified on TABLES. In integer mode, only numeric variables are allowed. The @subcmd{MISSING} subcommand determines the handling of user-missing values. When set to @subcmd{TABLE}, the default, missing values are dropped on a table by table basis. When set to @subcmd{INCLUDE}, user-missing values are included in tables and statistics. When set to @subcmd{REPORT}, which is allowed only in integer mode, user-missing values are included in tables but marked with an @samp{M} (for ``missing'') and excluded from statistical calculations. Currently the @subcmd{WRITE} subcommand is ignored. The @subcmd{FORMAT} subcommand controls the characteristics of the crosstabulation tables to be displayed. It has a number of possible settings: @itemize @asis @item @subcmd{TABLES}, the default, causes crosstabulation tables to be output. @subcmd{NOTABLES} suppresses them. @item @subcmd{PIVOT}, the default, causes each @subcmd{TABLES} subcommand to be displayed in a pivot table format. @subcmd{NOPIVOT} causes the old-style crosstabulation format to be used. @item @subcmd{AVALUE}, the default, causes values to be sorted in ascending order. @subcmd{DVALUE} asserts a descending sort order. @item @subcmd{INDEX} and @subcmd{NOINDEX} are currently ignored. @item @subcmd{BOX} and @subcmd{NOBOX} is currently ignored. @end itemize The @subcmd{CELLS} subcommand controls the contents of each cell in the displayed crosstabulation table. The possible settings are: @table @asis @item COUNT Frequency count. @item ROW Row percent. @item COLUMN Column percent. @item TOTAL Table percent. @item EXPECTED Expected value. @item RESIDUAL Residual. @item SRESIDUAL Standardized residual. @item ASRESIDUAL Adjusted standardized residual. @item ALL All of the above. @item NONE Suppress cells entirely. @end table @samp{/CELLS} without any settings specified requests @subcmd{COUNT}, @subcmd{ROW}, @subcmd{COLUMN}, and @subcmd{TOTAL}. If @subcmd{CELLS} is not specified at all then only @subcmd{COUNT} will be selected. The @subcmd{STATISTICS} subcommand selects statistics for computation: @table @asis @item CHISQ @cindex chisquare @cindex chi-square Pearson chi-square, likelihood ratio, Fisher's exact test, continuity correction, linear-by-linear association. @item PHI Phi. @item CC Contingency coefficient. @item LAMBDA Lambda. @item UC Uncertainty coefficient. @item BTAU Tau-b. @item CTAU Tau-c. @item RISK Risk estimate. @item GAMMA Gamma. @item D Somers' D. @item KAPPA Cohen's Kappa. @item ETA Eta. @item CORR Spearman correlation, Pearson's r. @item ALL All of the above. @item NONE No statistics. @end table Selected statistics are only calculated when appropriate for the statistic. Certain statistics require tables of a particular size, and some statistics are calculated only in integer mode. @samp{/STATISTICS} without any settings selects CHISQ. If the @subcmd{STATISTICS} subcommand is not given, no statistics are calculated. @strong{Please note:} Currently the implementation of @cmd{CROSSTABS} has the followings bugs: @itemize @bullet @item Pearson's R (but not Spearman) is off a little. @item T values for Spearman's R and Pearson's R are wrong. @item Significance of symmetric and directional measures is not calculated. @item Asymmetric ASEs and T values for lambda are wrong. @item ASE of Goodman and Kruskal's tau is not calculated. @item ASE of symmetric somers' d is wrong. @item Approximate T of uncertainty coefficient is wrong. @end itemize Fixes for any of these deficiencies would be welcomed. @node FACTOR @section FACTOR @vindex FACTOR @cindex factor analysis @cindex principal components analysis @cindex principal axis factoring @cindex data reduction @display FACTOR VARIABLES=@var{var_list} [ /METHOD = @{CORRELATION, COVARIANCE@} ] [ /EXTRACTION=@{PC, PAF@}] [ /ROTATION=@{VARIMAX, EQUAMAX, QUARTIMAX, NOROTATE@}] [ /PRINT=[INITIAL] [EXTRACTION] [ROTATION] [UNIVARIATE] [CORRELATION] [COVARIANCE] [DET] [KMO] [SIG] [ALL] [DEFAULT] ] [ /PLOT=[EIGEN] ] [ /FORMAT=[SORT] [BLANK(@var{n})] [DEFAULT] ] [ /CRITERIA=[FACTORS(@var{n})] [MINEIGEN(@var{l})] [ITERATE(@var{m})] [ECONVERGE (@var{delta})] [DEFAULT] ] [ /MISSING=[@{LISTWISE, PAIRWISE@}] [@{INCLUDE, EXCLUDE@}] ] @end display The @cmd{FACTOR} command performs Factor Analysis or Principal Axis Factoring on a dataset. It may be used to find common factors in the data or for data reduction purposes. The @subcmd{VARIABLES} subcommand is required. It lists the variables which are to partake in the analysis. The @subcmd{/EXTRACTION} subcommand is used to specify the way in which factors (components) are extracted from the data. If @subcmd{PC} is specified, then Principal Components Analysis is used. If @subcmd{PAF} is specified, then Principal Axis Factoring is used. By default Principal Components Analysis will be used. The @subcmd{/ROTATION} subcommand is used to specify the method by which the extracted solution will be rotated. Three methods are available: @subcmd{VARIMAX} (which is the default), @subcmd{EQUAMAX}, and @subcmd{QUARTIMAX}. If don't want any rotation to be performed, the word @subcmd{NOROTATE} will prevent the command from performing any rotation on the data. Oblique rotations are not supported. The @subcmd{/METHOD} subcommand should be used to determine whether the covariance matrix or the correlation matrix of the data is to be analysed. By default, the correlation matrix is analysed. The @subcmd{/PRINT} subcommand may be used to select which features of the analysis are reported: @itemize @item @subcmd{UNIVARIATE} A table of mean values, standard deviations and total weights are printed. @item @subcmd{INITIAL} Initial communalities and eigenvalues are printed. @item @subcmd{EXTRACTION} Extracted communalities and eigenvalues are printed. @item @subcmd{ROTATION} Rotated communalities and eigenvalues are printed. @item @subcmd{CORRELATION} The correlation matrix is printed. @item @subcmd{COVARIANCE} The covariance matrix is printed. @item @subcmd{DET} The determinant of the correlation or covariance matrix is printed. @item @subcmd{KMO} The Kaiser-Meyer-Olkin measure of sampling adequacy and the Bartlett test of sphericity is printed. @item @subcmd{SIG} The significance of the elements of correlation matrix is printed. @item @subcmd{ALL} All of the above are printed. @item @subcmd{DEFAULT} Identical to @subcmd{INITIAL} and @subcmd{EXTRACTION}. @end itemize If @subcmd{/PLOT=EIGEN} is given, then a ``Scree'' plot of the eigenvalues will be printed. This can be useful for visualizing which factors (components) should be retained. The @subcmd{/FORMAT} subcommand determined how data are to be displayed in loading matrices. If @subcmd{SORT} is specified, then the variables are sorted in descending order of significance. If @subcmd{BLANK(@var{n})} is specified, then coefficients whose absolute value is less than @var{n} will not be printed. If the keyword @subcmd{DEFAULT} is given, or if no @subcmd{/FORMAT} subcommand is given, then no sorting is performed, and all coefficients will be printed. The @subcmd{/CRITERIA} subcommand is used to specify how the number of extracted factors (components) are chosen. If @subcmd{FACTORS(@var{n})} is specified, where @var{n} is an integer, then @var{n} factors will be extracted. Otherwise, the @subcmd{MINEIGEN} setting will be used. @subcmd{MINEIGEN(@var{l})} requests that all factors whose eigenvalues are greater than or equal to @var{l} are extracted. The default value of @var{l} is 1. The @subcmd{ECONVERGE} and @subcmd{ITERATE} settings have effect only when iterative algorithms for factor extraction (such as Principal Axis Factoring) are used. @subcmd{ECONVERGE(@var{delta})} specifies that iteration should cease when the maximum absolute value of the communality estimate between one iteration and the previous is less than @var{delta}. The default value of @var{delta} is 0.001. The @subcmd{ITERATE(@var{m})} setting sets the maximum number of iterations to @var{m}. The default value of @var{m} is 25. The @cmd{MISSING} subcommand determines the handling of missing variables. If @subcmd{INCLUDE} is set, then user-missing values are included in the calculations, but system-missing values are not. If @subcmd{EXCLUDE} is set, which is the default, user-missing values are excluded as well as system-missing values. This is the default. If @subcmd{LISTWISE} is set, then the entire case is excluded from analysis whenever any variable specified in the @cmd{VARIABLES} subcommand contains a missing value. If @subcmd{PAIRWISE} is set, then a case is considered missing only if either of the values for the particular coefficient are missing. The default is @subcmd{LISTWISE}. @node MEANS @section MEANS @vindex MEANS @cindex means @display MEANS [TABLES =] @{@var{var_list}@} [ BY @{@var{var_list}@} [BY @{@var{var_list}@} [BY @{@var{var_list}@} @dots{} ]]] [ /@{@var{var_list}@} [ BY @{@var{var_list}@} [BY @{@var{var_list}@} [BY @{@var{var_list}@} @dots{} ]]] ] [/CELLS = [MEAN] [COUNT] [STDDEV] [SEMEAN] [SUM] [MIN] [MAX] [RANGE] [VARIANCE] [KURT] [SEKURT] [SKEW] [SESKEW] [FIRST] [LAST] [HARMONIC] [GEOMETRIC] [DEFAULT] [ALL] [NONE] ] [/MISSING = [TABLE] [INCLUDE] [DEPENDENT]] @end display You can use the @cmd{MEANS} command to calculate the arithmetic mean and similar statistics, either for the dataset as a whole or for categories of data. The simplest form of the command is @example MEANS @var{v}. @end example @noindent which calculates the mean, count and standard deviation for @var{v}. If you specify a grouping variable, for example @example MEANS @var{v} BY @var{g}. @end example @noindent then the means, counts and standard deviations for @var{v} after having been grouped by @var{g} will be calculated. Instead of the mean, count and standard deviation, you could specify the statistics in which you are interested: @example MEANS @var{x} @var{y} BY @var{g} /CELLS = HARMONIC SUM MIN. @end example This example calculates the harmonic mean, the sum and the minimum values of @var{x} and @var{y} grouped by @var{g}. The @subcmd{CELLS} subcommand specifies which statistics to calculate. The available statistics are: @itemize @item @subcmd{MEAN} @cindex arithmetic mean The arithmetic mean. @item @subcmd{COUNT} The count of the values. @item @subcmd{STDDEV} The standard deviation. @item @subcmd{SEMEAN} The standard error of the mean. @item @subcmd{SUM} The sum of the values. @item @subcmd{MIN} The minimum value. @item @subcmd{MAX} The maximum value. @item @subcmd{RANGE} The difference between the maximum and minimum values. @item @subcmd{VARIANCE} The variance. @item @subcmd{FIRST} The first value in the category. @item @subcmd{LAST} The last value in the category. @item @subcmd{SKEW} The skewness. @item @subcmd{SESKEW} The standard error of the skewness. @item @subcmd{KURT} The kurtosis @item @subcmd{SEKURT} The standard error of the kurtosis. @item @subcmd{HARMONIC} @cindex harmonic mean The harmonic mean. @item @subcmd{GEOMETRIC} @cindex geometric mean The geometric mean. @end itemize In addition, three special keywords are recognized: @itemize @item @subcmd{DEFAULT} This is the same as @subcmd{MEAN} @subcmd{COUNT} @subcmd{STDDEV}. @item @subcmd{ALL} All of the above statistics will be calculated. @item @subcmd{NONE} No statistics will be calculated (only a summary will be shown). @end itemize More than one @dfn{table} can be specified in a single command. Each table is separated by a @samp{/}. For example @example MEANS TABLES = @var{c} @var{d} @var{e} BY @var{x} /@var{a} @var{b} BY @var{x} @var{y} /@var{f} BY @var{y} BY @var{z}. @end example has three tables (the @samp{TABLE =} is optional). The first table has three dependent variables @var{c}, @var{d} and @var{e} and a single categorical variable @var{x}. The second table has two dependent variables @var{a} and @var{b}, and two categorical variables @var{x} and @var{y}. The third table has a single dependent variables @var{f} and a categorical variable formed by the combination of @var{y} and @var{z}. By default values are omitted from the analysis only if missing values (either system missing or user missing) for any of the variables directly involved in their calculation are encountered. This behaviour can be modified with the @subcmd{/MISSING} subcommand. Three options are possible: @subcmd{TABLE}, @subcmd{INCLUDE} and @subcmd{DEPENDENT}. @subcmd{/MISSING = TABLE} causes cases to be dropped if any variable is missing in the table specification currently being processed, regardless of whether it is needed to calculate the statistic. @subcmd{/MISSING = INCLUDE} says that user missing values, either in the dependent variables or in the categorical variables should be taken at their face value, and not excluded. @subcmd{/MISSING = DEPENDENT} says that user missing values, in the dependent variables should be taken at their face value, however cases which have user missing values for the categorical variables should be omitted from the calculation. @node NPAR TESTS @section NPAR TESTS @vindex NPAR TESTS @cindex nonparametric tests @display NPAR TESTS nonparametric test subcommands . . . [ /STATISTICS=@{DESCRIPTIVES@} ] [ /MISSING=@{ANALYSIS, LISTWISE@} @{INCLUDE, EXCLUDE@} ] [ /METHOD=EXACT [ TIMER [(@var{n})] ] ] @end display @cmd{NPAR TESTS} performs nonparametric tests. Non parametric tests make very few assumptions about the distribution of the data. One or more tests may be specified by using the corresponding subcommand. If the @subcmd{/STATISTICS} subcommand is also specified, then summary statistics are produces for each variable that is the subject of any test. Certain tests may take a long time to execute, if an exact figure is required. Therefore, by default asymptotic approximations are used unless the subcommand @subcmd{/METHOD=EXACT} is specified. Exact tests give more accurate results, but may take an unacceptably long time to perform. If the @subcmd{TIMER} keyword is used, it sets a maximum time, after which the test will be abandoned, and a warning message printed. The time, in minutes, should be specified in parentheses after the @subcmd{TIMER} keyword. If the @subcmd{TIMER} keyword is given without this figure, then a default value of 5 minutes is used. @menu * BINOMIAL:: Binomial Test * CHISQUARE:: Chisquare Test * COCHRAN:: Cochran Q Test * FRIEDMAN:: Friedman Test * KENDALL:: Kendall's W Test * KOLMOGOROV-SMIRNOV:: Kolmogorov Smirnov Test * KRUSKAL-WALLIS:: Kruskal-Wallis Test * MANN-WHITNEY:: Mann Whitney U Test * MCNEMAR:: McNemar Test * MEDIAN:: Median Test * RUNS:: Runs Test * SIGN:: The Sign Test * WILCOXON:: Wilcoxon Signed Ranks Test @end menu @node BINOMIAL @subsection Binomial test @vindex BINOMIAL @cindex binomial test @display [ /BINOMIAL[(@var{p})]=@var{var_list}[(@var{value1}[, @var{value2})] ] ] @end display The @subcmd{/BINOMIAL} subcommand compares the observed distribution of a dichotomous variable with that of a binomial distribution. The variable @var{p} specifies the test proportion of the binomial distribution. The default value of 0.5 is assumed if @var{p} is omitted. If a single value appears after the variable list, then that value is used as the threshold to partition the observed values. Values less than or equal to the threshold value form the first category. Values greater than the threshold form the second category. If two values appear after the variable list, then they will be used as the values which a variable must take to be in the respective category. Cases for which a variable takes a value equal to neither of the specified values, take no part in the test for that variable. If no values appear, then the variable must assume dichotomous values. If more than two distinct, non-missing values for a variable under test are encountered then an error occurs. If the test proportion is equal to 0.5, then a two tailed test is reported. For any other test proportion, a one tailed test is reported. For one tailed tests, if the test proportion is less than or equal to the observed proportion, then the significance of observing the observed proportion or more is reported. If the test proportion is more than the observed proportion, then the significance of observing the observed proportion or less is reported. That is to say, the test is always performed in the observed direction. @pspp{} uses a very precise approximation to the gamma function to compute the binomial significance. Thus, exact results are reported even for very large sample sizes. @node CHISQUARE @subsection Chisquare Test @vindex CHISQUARE @cindex chisquare test @display [ /CHISQUARE=@var{var_list}[(@var{lo},@var{hi})] [/EXPECTED=@{EQUAL|@var{f1}, @var{f2} @dots{} @var{fn}@}] ] @end display The @subcmd{/CHISQUARE} subcommand produces a chi-square statistic for the differences between the expected and observed frequencies of the categories of a variable. Optionally, a range of values may appear after the variable list. If a range is given, then non integer values are truncated, and values outside the specified range are excluded from the analysis. The @subcmd{/EXPECTED} subcommand specifies the expected values of each category. There must be exactly one non-zero expected value, for each observed category, or the @subcmd{EQUAL} keywork must be specified. You may use the notation @subcmd{@var{n}*@var{f}} to specify @var{n} consecutive expected categories all taking a frequency of @var{f}. The frequencies given are proportions, not absolute frequencies. The sum of the frequencies need not be 1. If no @subcmd{/EXPECTED} subcommand is given, then then equal frequencies are expected. @node COCHRAN @subsection Cochran Q Test @vindex Cochran @cindex Cochran Q test @cindex Q, Cochran Q @display [ /COCHRAN = @var{var_list} ] @end display The Cochran Q test is used to test for differences between three or more groups. The data for @var{var_list} in all cases must assume exactly two distinct values (other than missing values). The value of Q will be displayed and its Asymptotic significance based on a chi-square distribution. @node FRIEDMAN @subsection Friedman Test @vindex FRIEDMAN @cindex Friedman test @display [ /FRIEDMAN = @var{var_list} ] @end display The Friedman test is used to test for differences between repeated measures when there is no indication that the distributions are normally distributed. A list of variables which contain the measured data must be given. The procedure prints the sum of ranks for each variable, the test statistic and its significance. @node KENDALL @subsection Kendall's W Test @vindex KENDALL @cindex Kendall's W test @cindex coefficient of concordance @display [ /KENDALL = @var{var_list} ] @end display The Kendall test investigates whether an arbitrary number of related samples come from the same population. It is identical to the Friedman test except that the additional statistic W, Kendall's Coefficient of Concordance is printed. It has the range [0,1] --- a value of zero indicates no agreement between the samples whereas a value of unity indicates complete agreement. @node KOLMOGOROV-SMIRNOV @subsection Kolmogorov-Smirnov Test @vindex KOLMOGOROV-SMIRNOV @vindex K-S @cindex Kolmogorov-Smirnov test @display [ /KOLMOGOROV-SMIRNOV (@{NORMAL [@var{mu}, @var{sigma}], UNIFORM [@var{min}, @var{max}], POISSON [@var{lambda}], EXPONENTIAL [@var{scale}] @}) = @var{var_list} ] @end display The one sample Kolmogorov-Smirnov subcommand is used to test whether or not a dataset is drawn from a particular distribution. Four distributions are supported, @i{viz:} Normal, Uniform, Poisson and Exponential. Ideally you should provide the parameters of the distribution against which you wish to test the data. For example, with the normal distribution the mean (@var{mu})and standard deviation (@var{sigma}) should be given; with the uniform distribution, the minimum (@var{min})and maximum (@var{max}) value should be provided. However, if the parameters are omitted they will be imputed from the data. Imputing the parameters reduces the power of the test so should be avoided if possible. In the following example, two variables @var{score} and @var{age} are tested to see if they follow a normal distribution with a mean of 3.5 and a standard deviation of 2.0. @example NPAR TESTS /KOLMOGOROV-SMIRNOV (normal 3.5 2.0) = @var{score} @var{age}. @end example If the variables need to be tested against different distributions, then a separate subcommand must be used. For example the following syntax tests @var{score} against a normal distribution with mean of 3.5 and standard deviation of 2.0 whilst @var{age} is tested against a normal distribution of mean 40 and standard deviation 1.5. @example NPAR TESTS /KOLMOGOROV-SMIRNOV (normal 3.5 2.0) = @var{score} /KOLMOGOROV-SMIRNOV (normal 40 1.5) = @var{age}. @end example The abbreviated subcommand @subcmd{K-S} may be used in place of @subcmd{KOLMOGOROV-SMIRNOV}. @node KRUSKAL-WALLIS @subsection Kruskal-Wallis Test @vindex KRUSKAL-WALLIS @vindex K-W @cindex Kruskal-Wallis test @display [ /KRUSKAL-WALLIS = @var{var_list} BY var (@var{lower}, @var{upper}) ] @end display The Kruskal-Wallis test is used to compare data from an arbitrary number of populations. It does not assume normality. The data to be compared are specified by @var{var_list}. The categorical variable determining the groups to which the data belongs is given by @var{var}. The limits @var{lower} and @var{upper} specify the valid range of @var{var}. Any cases for which @var{var} falls outside [@var{lower}, @var{upper}] will be ignored. The mean rank of each group as well as the chi-squared value and significance of the test will be printed. The abbreviated subcommand @subcmd{K-W} may be used in place of @subcmd{KRUSKAL-WALLIS}. @node MANN-WHITNEY @subsection Mann-Whitney U Test @vindex MANN-WHITNEY @vindex M-W @cindex Mann-Whitney U test @cindex U, Mann-Whitney U @display [ /MANN-WHITNEY = @var{var_list} BY var (@var{group1}, @var{group2}) ] @end display The Mann-Whitney subcommand is used to test whether two groups of data come from different populations. The variables to be tested should be specified in @var{var_list} and the grouping variable, that determines to which group the test variables belong, in @var{var}. @var{Var} may be either a string or an alpha variable. @var{Group1} and @var{group2} specify the two values of @var{var} which determine the groups of the test data. Cases for which the @var{var} value is neither @var{group1} or @var{group2} will be ignored. The value of the Mann-Whitney U statistic, the Wilcoxon W, and the significance will be printed. The abbreviated subcommand @subcmd{M-W} may be used in place of @subcmd{MANN-WHITNEY}. @node MCNEMAR @subsection McNemar Test @vindex MCNEMAR @cindex McNemar test @display [ /MCNEMAR @var{var_list} [ WITH @var{var_list} [ (PAIRED) ]]] @end display Use McNemar's test to analyse the significance of the difference between pairs of correlated proportions. If the @code{WITH} keyword is omitted, then tests for all combinations of the listed variables are performed. If the @code{WITH} keyword is given, and the @code{(PAIRED)} keyword is also given, then the number of variables preceding @code{WITH} must be the same as the number following it. In this case, tests for each respective pair of variables are performed. If the @code{WITH} keyword is given, but the @code{(PAIRED)} keyword is omitted, then tests for each combination of variable preceding @code{WITH} against variable following @code{WITH} are performed. The data in each variable must be dichotomous. If there are more than two distinct variables an error will occur and the test will not be run. @node MEDIAN @subsection Median Test @vindex MEDIAN @cindex Median test @display [ /MEDIAN [(@var{value})] = @var{var_list} BY @var{variable} (@var{value1}, @var{value2}) ] @end display The median test is used to test whether independent samples come from populations with a common median. The median of the populations against which the samples are to be tested may be given in parentheses immediately after the @subcmd{/MEDIAN} subcommand. If it is not given, the median will be imputed from the union of all the samples. The variables of the samples to be tested should immediately follow the @samp{=} sign. The keyword @code{BY} must come next, and then the grouping variable. Two values in parentheses should follow. If the first value is greater than the second, then a 2 sample test is performed using these two values to determine the groups. If however, the first variable is less than the second, then a @i{k} sample test is conducted and the group values used are all values encountered which lie in the range [@var{value1},@var{value2}]. @node RUNS @subsection Runs Test @vindex RUNS @cindex runs test @display [ /RUNS (@{MEAN, MEDIAN, MODE, @var{value}@}) = @var{var_list} ] @end display The @subcmd{/RUNS} subcommand tests whether a data sequence is randomly ordered. It works by examining the number of times a variable's value crosses a given threshold. The desired threshold must be specified within parentheses. It may either be specified as a number or as one of @subcmd{MEAN}, @subcmd{MEDIAN} or @subcmd{MODE}. Following the threshold specification comes the list of variables whose values are to be tested. The subcommand shows the number of runs, the asymptotic significance based on the length of the data. @node SIGN @subsection Sign Test @vindex SIGN @cindex sign test @display [ /SIGN @var{var_list} [ WITH @var{var_list} [ (PAIRED) ]]] @end display The @subcmd{/SIGN} subcommand tests for differences between medians of the variables listed. The test does not make any assumptions about the distribution of the data. If the @code{WITH} keyword is omitted, then tests for all combinations of the listed variables are performed. If the @code{WITH} keyword is given, and the @code{(PAIRED)} keyword is also given, then the number of variables preceding @code{WITH} must be the same as the number following it. In this case, tests for each respective pair of variables are performed. If the @code{WITH} keyword is given, but the @code{(PAIRED)} keyword is omitted, then tests for each combination of variable preceding @code{WITH} against variable following @code{WITH} are performed. @node WILCOXON @subsection Wilcoxon Matched Pairs Signed Ranks Test @vindex WILCOXON @cindex wilcoxon matched pairs signed ranks test @display [ /WILCOXON @var{var_list} [ WITH @var{var_list} [ (PAIRED) ]]] @end display The @subcmd{/WILCOXON} subcommand tests for differences between medians of the variables listed. The test does not make any assumptions about the variances of the samples. It does however assume that the distribution is symetrical. If the @subcmd{WITH} keyword is omitted, then tests for all combinations of the listed variables are performed. If the @subcmd{WITH} keyword is given, and the @subcmd{(PAIRED)} keyword is also given, then the number of variables preceding @subcmd{WITH} must be the same as the number following it. In this case, tests for each respective pair of variables are performed. If the @subcmd{WITH} keyword is given, but the @subcmd{(PAIRED)} keyword is omitted, then tests for each combination of variable preceding @subcmd{WITH} against variable following @subcmd{WITH} are performed. @node T-TEST @section T-TEST @vindex T-TEST @display T-TEST /MISSING=@{ANALYSIS,LISTWISE@} @{EXCLUDE,INCLUDE@} /CRITERIA=CIN(@var{confidence}) (One Sample mode.) TESTVAL=@var{test_value} /VARIABLES=@var{var_list} (Independent Samples mode.) GROUPS=var(@var{value1} [, @var{value2}]) /VARIABLES=@var{var_list} (Paired Samples mode.) PAIRS=@var{var_list} [WITH @var{var_list} [(PAIRED)] ] @end display The @cmd{T-TEST} procedure outputs tables used in testing hypotheses about means. It operates in one of three modes: @itemize @item One Sample mode. @item Independent Groups mode. @item Paired mode. @end itemize @noindent Each of these modes are described in more detail below. There are two optional subcommands which are common to all modes. The @cmd{/CRITERIA} subcommand tells @pspp{} the confidence interval used in the tests. The default value is 0.95. The @cmd{MISSING} subcommand determines the handling of missing variables. If @subcmd{INCLUDE} is set, then user-missing values are included in the calculations, but system-missing values are not. If @subcmd{EXCLUDE} is set, which is the default, user-missing values are excluded as well as system-missing values. This is the default. If @subcmd{LISTWISE} is set, then the entire case is excluded from analysis whenever any variable specified in the @subcmd{/VARIABLES}, @subcmd{/PAIRS} or @subcmd{/GROUPS} subcommands contains a missing value. If @subcmd{ANALYSIS} is set, then missing values are excluded only in the analysis for which they would be needed. This is the default. @menu * One Sample Mode:: Testing against a hypothesized mean * Independent Samples Mode:: Testing two independent groups for equal mean * Paired Samples Mode:: Testing two interdependent groups for equal mean @end menu @node One Sample Mode @subsection One Sample Mode The @subcmd{TESTVAL} subcommand invokes the One Sample mode. This mode is used to test a population mean against a hypothesized mean. The value given to the @subcmd{TESTVAL} subcommand is the value against which you wish to test. In this mode, you must also use the @subcmd{/VARIABLES} subcommand to tell @pspp{} which variables you wish to test. @node Independent Samples Mode @subsection Independent Samples Mode The @subcmd{GROUPS} subcommand invokes Independent Samples mode or `Groups' mode. This mode is used to test whether two groups of values have the same population mean. In this mode, you must also use the @subcmd{/VARIABLES} subcommand to tell @pspp{} the dependent variables you wish to test. The variable given in the @subcmd{GROUPS} subcommand is the independent variable which determines to which group the samples belong. The values in parentheses are the specific values of the independent variable for each group. If the parentheses are omitted and no values are given, the default values of 1.0 and 2.0 are assumed. If the independent variable is numeric, it is acceptable to specify only one value inside the parentheses. If you do this, cases where the independent variable is greater than or equal to this value belong to the first group, and cases less than this value belong to the second group. When using this form of the @subcmd{GROUPS} subcommand, missing values in the independent variable are excluded on a listwise basis, regardless of whether @subcmd{/MISSING=LISTWISE} was specified. @node Paired Samples Mode @subsection Paired Samples Mode The @cmd{PAIRS} subcommand introduces Paired Samples mode. Use this mode when repeated measures have been taken from the same samples. If the @subcmd{WITH} keyword is omitted, then tables for all combinations of variables given in the @cmd{PAIRS} subcommand are generated. If the @subcmd{WITH} keyword is given, and the @subcmd{(PAIRED)} keyword is also given, then the number of variables preceding @subcmd{WITH} must be the same as the number following it. In this case, tables for each respective pair of variables are generated. In the event that the @subcmd{WITH} keyword is given, but the @subcmd{(PAIRED)} keyword is omitted, then tables for each combination of variable preceding @subcmd{WITH} against variable following @subcmd{WITH} are generated. @node ONEWAY @section ONEWAY @vindex ONEWAY @cindex analysis of variance @cindex ANOVA @display ONEWAY [/VARIABLES = ] @var{var_list} BY @var{var} /MISSING=@{ANALYSIS,LISTWISE@} @{EXCLUDE,INCLUDE@} /CONTRAST= @var{value1} [, @var{value2}] ... [,@var{valueN}] /STATISTICS=@{DESCRIPTIVES,HOMOGENEITY@} /POSTHOC=@{BONFERRONI, GH, LSD, SCHEFFE, SIDAK, TUKEY, ALPHA ([@var{value}])@} @end display The @cmd{ONEWAY} procedure performs a one-way analysis of variance of variables factored by a single independent variable. It is used to compare the means of a population divided into more than two groups. The dependent variables to be analysed should be given in the @subcmd{VARIABLES} subcommand. The list of variables must be followed by the @subcmd{BY} keyword and the name of the independent (or factor) variable. You can use the @subcmd{STATISTICS} subcommand to tell @pspp{} to display ancilliary information. The options accepted are: @itemize @item DESCRIPTIVES Displays descriptive statistics about the groups factored by the independent variable. @item HOMOGENEITY Displays the Levene test of Homogeneity of Variance for the variables and their groups. @end itemize The @subcmd{CONTRAST} subcommand is used when you anticipate certain differences between the groups. The subcommand must be followed by a list of numerals which are the coefficients of the groups to be tested. The number of coefficients must correspond to the number of distinct groups (or values of the independent variable). If the total sum of the coefficients are not zero, then @pspp{} will display a warning, but will proceed with the analysis. The @subcmd{CONTRAST} subcommand may be given up to 10 times in order to specify different contrast tests. The @subcmd{MISSING} subcommand defines how missing values are handled. If @subcmd{LISTWISE} is specified then cases which have missing values for the independent variable or any dependent variable will be ignored. If @subcmd{ANALYSIS} is specified, then cases will be ignored if the independent variable is missing or if the dependent variable currently being analysed is missing. The default is @subcmd{ANALYSIS}. A setting of @subcmd{EXCLUDE} means that variables whose values are user-missing are to be excluded from the analysis. A setting of @subcmd{INCLUDE} means they are to be included. The default is @subcmd{EXCLUDE}. Using the @code{POSTHOC} subcommand you can perform multiple pairwise comparisons on the data. The following comparison methods are available: @itemize @item @subcmd{LSD} Least Significant Difference. @item @subcmd{TUKEY} Tukey Honestly Significant Difference. @item @subcmd{BONFERRONI} Bonferroni test. @item @subcmd{SCHEFFE} Scheff@'e's test. @item @subcmd{SIDAK} Sidak test. @item @subcmd{GH} The Games-Howell test. @end itemize @noindent The optional syntax @code{ALPHA(@var{value})} is used to indicate that @var{value} should be used as the confidence level for which the posthoc tests will be performed. The default is 0.05. @node QUICK CLUSTER @section QUICK CLUSTER @vindex QUICK CLUSTER @cindex K-means clustering @cindex clustering @display QUICK CLUSTER @var{var_list} [/CRITERIA=CLUSTERS(@var{k}) [MXITER(@var{max_iter})]] [/MISSING=@{EXCLUDE,INCLUDE@} @{LISTWISE, PAIRWISE@}] @end display The @cmd{QUICK CLUSTER} command performs k-means clustering on the dataset. This is useful when you wish to allocate cases into clusters of similar values and you already know the number of clusters. The minimum specification is @samp{QUICK CLUSTER} followed by the names of the variables which contain the cluster data. Normally you will also want to specify @subcmd{/CRITERIA=CLUSTERS(@var{k})} where @var{k} is the number of clusters. If this is not given, then @var{k} defaults to 2. The command uses an iterative algorithm to determine the clusters for each case. It will continue iterating until convergence, or until @var{max_iter} iterations have been done. The default value of @var{max_iter} is 2. The @subcmd{MISSING} subcommand determines the handling of missing variables. If @subcmd{INCLUDE} is set, then user-missing values are considered at their face value and not as missing values. If @subcmd{EXCLUDE} is set, which is the default, user-missing values are excluded as well as system-missing values. If @subcmd{LISTWISE} is set, then the entire case is excluded from the analysis whenever any of the clustering variables contains a missing value. If @subcmd{PAIRWISE} is set, then a case is considered missing only if all the clustering variables contain missing values. Otherwise it is clustered on the basis of the non-missing values. The default is @subcmd{LISTWISE}. @node RANK @section RANK @vindex RANK @display RANK [VARIABLES=] @var{var_list} [@{A,D@}] [BY @var{var_list}] /TIES=@{MEAN,LOW,HIGH,CONDENSE@} /FRACTION=@{BLOM,TUKEY,VW,RANKIT@} /PRINT[=@{YES,NO@} /MISSING=@{EXCLUDE,INCLUDE@} /RANK [INTO @var{var_list}] /NTILES(k) [INTO @var{var_list}] /NORMAL [INTO @var{var_list}] /PERCENT [INTO @var{var_list}] /RFRACTION [INTO @var{var_list}] /PROPORTION [INTO @var{var_list}] /N [INTO @var{var_list}] /SAVAGE [INTO @var{var_list}] @end display The @cmd{RANK} command ranks variables and stores the results into new variables. The @subcmd{VARIABLES} subcommand, which is mandatory, specifies one or more variables whose values are to be ranked. After each variable, @samp{A} or @samp{D} may appear, indicating that the variable is to be ranked in ascending or descending order. Ascending is the default. If a @subcmd{BY} keyword appears, it should be followed by a list of variables which are to serve as group variables. In this case, the cases are gathered into groups, and ranks calculated for each group. The @subcmd{TIES} subcommand specifies how tied values are to be treated. The default is to take the mean value of all the tied cases. The @subcmd{FRACTION} subcommand specifies how proportional ranks are to be calculated. This only has any effect if @subcmd{NORMAL} or @subcmd{PROPORTIONAL} rank functions are requested. The @subcmd{PRINT} subcommand may be used to specify that a summary of the rank variables created should appear in the output. The function subcommands are @subcmd{RANK}, @subcmd{NTILES}, @subcmd{NORMAL}, @subcmd{PERCENT}, @subcmd{RFRACTION}, @subcmd{PROPORTION} and @subcmd{SAVAGE}. Any number of function subcommands may appear. If none are given, then the default is RANK. The @subcmd{NTILES} subcommand must take an integer specifying the number of partitions into which values should be ranked. Each subcommand may be followed by the @subcmd{INTO} keyword and a list of variables which are the variables to be created and receive the rank scores. There may be as many variables specified as there are variables named on the @subcmd{VARIABLES} subcommand. If fewer are specified, then the variable names are automatically created. The @subcmd{MISSING} subcommand determines how user missing values are to be treated. A setting of @subcmd{EXCLUDE} means that variables whose values are user-missing are to be excluded from the rank scores. A setting of @subcmd{INCLUDE} means they are to be included. The default is @subcmd{EXCLUDE}. @include regression.texi @node RELIABILITY @section RELIABILITY @vindex RELIABILITY @display RELIABILITY /VARIABLES=@var{var_list} /SCALE (@var{name}) = @{@var{var_list}, ALL@} /MODEL=@{ALPHA, SPLIT[(@var{n})]@} /SUMMARY=@{TOTAL,ALL@} /MISSING=@{EXCLUDE,INCLUDE@} @end display @cindex Cronbach's Alpha The @cmd{RELIABILTY} command performs reliability analysis on the data. The @subcmd{VARIABLES} subcommand is required. It determines the set of variables upon which analysis is to be performed. The @subcmd{SCALE} subcommand determines which variables reliability is to be calculated for. If it is omitted, then analysis for all variables named in the @subcmd{VARIABLES} subcommand will be used. Optionally, the @var{name} parameter may be specified to set a string name for the scale. The @subcmd{MODEL} subcommand determines the type of analysis. If @subcmd{ALPHA} is specified, then Cronbach's Alpha is calculated for the scale. If the model is @subcmd{SPLIT}, then the variables are divided into 2 subsets. An optional parameter @var{n} may be given, to specify how many variables to be in the first subset. If @var{n} is omitted, then it defaults to one half of the variables in the scale, or one half minus one if there are an odd number of variables. The default model is @subcmd{ALPHA}. By default, any cases with user missing, or system missing values for any variables given in the @subcmd{VARIABLES} subcommand will be omitted from analysis. The @subcmd{MISSING} subcommand determines whether user missing values are to be included or excluded in the analysis. The @subcmd{SUMMARY} subcommand determines the type of summary analysis to be performed. Currently there is only one type: @subcmd{SUMMARY=TOTAL}, which displays per-item analysis tested against the totals. @node ROC @section ROC @vindex ROC @cindex Receiver Operating Characteristic @cindex Area under curve @display ROC @var{var_list} BY @var{state_var} (@var{state_value}) /PLOT = @{ CURVE [(REFERENCE)], NONE @} /PRINT = [ SE ] [ COORDINATES ] /CRITERIA = [ CUTOFF(@{INCLUDE,EXCLUDE@}) ] [ TESTPOS (@{LARGE,SMALL@}) ] [ CI (@var{confidence}) ] [ DISTRIBUTION (@{FREE, NEGEXPO @}) ] /MISSING=@{EXCLUDE,INCLUDE@} @end display The @cmd{ROC} command is used to plot the receiver operating characteristic curve of a dataset, and to estimate the area under the curve. This is useful for analysing the efficacy of a variable as a predictor of a state of nature. The mandatory @var{var_list} is the list of predictor variables. The variable @var{state_var} is the variable whose values represent the actual states, and @var{state_value} is the value of this variable which represents the positive state. The optional subcommand @subcmd{PLOT} is used to determine if and how the @subcmd{ROC} curve is drawn. The keyword @subcmd{CURVE} means that the @subcmd{ROC} curve should be drawn, and the optional keyword @subcmd{REFERENCE}, which should be enclosed in parentheses, says that the diagonal reference line should be drawn. If the keyword @subcmd{NONE} is given, then no @subcmd{ROC} curve is drawn. By default, the curve is drawn with no reference line. The optional subcommand @subcmd{PRINT} determines which additional tables should be printed. Two additional tables are available. The @subcmd{SE} keyword says that standard error of the area under the curve should be printed as well as the area itself. In addition, a p-value under the null hypothesis that the area under the curve equals 0.5 will be printed. The @subcmd{COORDINATES} keyword says that a table of coordinates of the @subcmd{ROC} curve should be printed. The @subcmd{CRITERIA} subcommand has four optional parameters: @itemize @bullet @item The @subcmd{TESTPOS} parameter may be @subcmd{LARGE} or @subcmd{SMALL}. @subcmd{LARGE} is the default, and says that larger values in the predictor variables are to be considered positive. @subcmd{SMALL} indicates that smaller values should be considered positive. @item The @subcmd{CI} parameter specifies the confidence interval that should be printed. It has no effect if the @subcmd{SE} keyword in the @subcmd{PRINT} subcommand has not been given. @item The @subcmd{DISTRIBUTION} parameter determines the method to be used when estimating the area under the curve. There are two possibilities, @i{viz}: @subcmd{FREE} and @subcmd{NEGEXPO}. The @subcmd{FREE} method uses a non-parametric estimate, and the @subcmd{NEGEXPO} method a bi-negative exponential distribution estimate. The @subcmd{NEGEXPO} method should only be used when the number of positive actual states is equal to the number of negative actual states. The default is @subcmd{FREE}. @item The @subcmd{CUTOFF} parameter is for compatibility and is ignored. @end itemize The @subcmd{MISSING} subcommand determines whether user missing values are to be included or excluded in the analysis. The default behaviour is to exclude them. Cases are excluded on a listwise basis; if any of the variables in @var{var_list} or if the variable @var{state_var} is missing, then the entire case will be excluded. pspp-master/doc/transformation.texi000066400000000000000000000675711177044323000200600ustar00rootroot00000000000000@node Data Manipulation @chapter Data transformations @cindex transformations The @pspp{} procedures examined in this chapter manipulate data and prepare the active dataset for later analyses. They do not produce output, as a rule. @menu * AGGREGATE:: Summarize multiple cases into a single case. * AUTORECODE:: Automatic recoding of variables. * COMPUTE:: Assigning a variable a calculated value. * COUNT:: Counting variables with particular values. * FLIP:: Exchange variables with cases. * IF:: Conditionally assigning a calculated value. * RECODE:: Mapping values from one set to another. * SORT CASES:: Sort the active dataset. @end menu @node AGGREGATE @section AGGREGATE @vindex AGGREGATE @display AGGREGATE OUTFILE=@{*,'@var{file_name}',@var{file_handle}@} [MODE=@{REPLACE, ADDVARIABLES@}] /PRESORTED /DOCUMENT /MISSING=COLUMNWISE /BREAK=@var{var_list} /@var{dest_var}['@var{label}']@dots{}=@var{agr_func}(@var{src_vars}, @var{args}@dots{})@dots{} @end display @cmd{AGGREGATE} summarizes groups of cases into single cases. Cases are divided into groups that have the same values for one or more variables called @dfn{break variables}. Several functions are available for summarizing case contents. The @subcmd{OUTFILE} subcommand is required and must appear first. Specify a system file or portable file by file name or file handle (@pxref{File Handles}), or a dataset by its name (@pxref{Datasets}). The aggregated cases are written to this file. If @samp{*} is specified, then the aggregated cases replace the active dataset's data. Use of @subcmd{OUTFILE} to write a portable file is a @pspp{} extension. If @subcmd{OUTFILE=*} is given, then the subcommand @subcmd{MODE} may also be specified. The mode subcommand has two possible values: @subcmd{ADDVARIABLES} or @subcmd{REPLACE}. In @subcmd{REPLACE} mode, the entire active dataset is replaced by a new dataset which contains just the break variables and the destination varibles. In this mode, the new file will contain as many cases as there are unique combinations of the break variables. In @subcmd{ADDVARIABLES} mode, the destination variables will be appended to the existing active dataset. Cases which have identical combinations of values in their break variables, will receive identical values for the destination variables. The number of cases in the active dataset will remain unchanged. Note that if @subcmd{ADDVARIABLES} is specified, then the data @emph{must} be sorted on the break variables. By default, the active dataset will be sorted based on the break variables before aggregation takes place. If the active dataset is already sorted or otherwise grouped in terms of the break variables, specify @subcmd{PRESORTED} to save time. @subcmd{PRESORTED} is assumed if @subcmd{MODE=ADDVARIABLES} is used. Specify @subcmd{DOCUMENT} to copy the documents from the active dataset into the aggregate file (@pxref{DOCUMENT}). Otherwise, the aggregate file will not contain any documents, even if the aggregate file replaces the active dataset. Normally, only a single case (for @subcmd{SD} and @subcmd{SD}., two cases) need be non-missing in each group for the aggregate variable to be non-missing. Specifying @subcmd{/MISSING=COLUMNWISE} inverts this behavior, so that the aggregate variable becomes missing if any aggregated value is missing. If @subcmd{PRESORTED}, @subcmd{DOCUMENT}, or @subcmd{MISSING} are specified, they must appear between @subcmd{OUTFILE} and @subcmd{BREAK}. At least one break variable must be specified on @subcmd{BREAK}, a required subcommand. The values of these variables are used to divide the active dataset into groups to be summarized. In addition, at least one @var{dest_var} must be specified. One or more sets of aggregation variables must be specified. Each set comprises a list of aggregation variables, an equals sign (@samp{=}), the name of an aggregation function (see the list below), and a list of source variables in parentheses. Some aggregation functions expect additional arguments following the source variable names. Aggregation variables typically are created with no variable label, value labels, or missing values. Their default print and write formats depend on the aggregation function used, with details given in the table below. A variable label for an aggregation variable may be specified just after the variable's name in the aggregation variable list. Each set must have exactly as many source variables as aggregation variables. Each aggregation variable receives the results of applying the specified aggregation function to the corresponding source variable. The @subcmd{MEAN}, @subcmd{MEDIAN}, @subcmd{SD}, and @subcmd{SUM} aggregation functions may only be applied to numeric variables. All the rest may be applied to numeric and string variables. The available aggregation functions are as follows: @table @asis @item @subcmd{FGT(@var{var_name}, @var{value})} Fraction of values greater than the specified constant. The default format is F5.3. @item @subcmd{FIN(@var{var_name}, @var{low}, @var{high})} Fraction of values within the specified inclusive range of constants. The default format is F5.3. @item @subcmd{FLT(@var{var_name}, @var{value})} Fraction of values less than the specified constant. The default format is F5.3. @item @subcmd{FIRST(@var{var_name})} First non-missing value in break group. The aggregation variable receives the complete dictionary information from the source variable. The sort performed by @cmd{AGGREGATE} (and by @cmd{SORT CASES}) is stable, so that the first case with particular values for the break variables before sorting will also be the first case in that break group after sorting. @item @subcmd{FOUT(@var{var_name}, @var{low}, @var{high})} Fraction of values strictly outside the specified range of constants. The default format is F5.3. @item @subcmd{LAST(@var{var_name})} Last non-missing value in break group. The aggregation variable receives the complete dictionary information from the source variable. The sort performed by @cmd{AGGREGATE} (and by @cmd{SORT CASES}) is stable, so that the last case with particular values for the break variables before sorting will also be the last case in that break group after sorting. @item @subcmd{MAX(@var{var_name})} Maximum value. The aggregation variable receives the complete dictionary information from the source variable. @item @subcmd{MEAN(@var{var_name})} Arithmetic mean. Limited to numeric values. The default format is F8.2. @item @subcmd{MEDIAN(@var{var_name})} The median value. Limited to numeric values. The default format is F8.2. @item @subcmd{MIN(@var{var_name})} Minimum value. The aggregation variable receives the complete dictionary information from the source variable. @item @subcmd{N(@var{var_name})} Number of non-missing values. The default format is F7.0 if weighting is not enabled, F8.2 if it is (@pxref{WEIGHT}). @item @subcmd{N} Number of cases aggregated to form this group. The default format is F7.0 if weighting is not enabled, F8.2 if it is (@pxref{WEIGHT}). @item @subcmd{NMISS(@var{var_name})} Number of missing values. The default format is F7.0 if weighting is not enabled, F8.2 if it is (@pxref{WEIGHT}). @item @subcmd{NU(@var{var_name})} Number of non-missing values. Each case is considered to have a weight of 1, regardless of the current weighting variable (@pxref{WEIGHT}). The default format is F7.0. @item @subcmd{NU} Number of cases aggregated to form this group. Each case is considered to have a weight of 1, regardless of the current weighting variable. The default format is F7.0. @item @subcmd{NUMISS(@var{var_name})} Number of missing values. Each case is considered to have a weight of 1, regardless of the current weighting variable. The default format is F7.0. @item @subcmd{PGT(@var{var_name}, @var{value})} Percentage between 0 and 100 of values greater than the specified constant. The default format is F5.1. @item @subcmd{PIN(@var{var_name}, @var{low}, @var{high})} Percentage of values within the specified inclusive range of constants. The default format is F5.1. @item @subcmd{PLT(@var{var_name}, @var{value})} Percentage of values less than the specified constant. The default format is F5.1. @item @subcmd{POUT(@var{var_name}, @var{low}, @var{high})} Percentage of values strictly outside the specified range of constants. The default format is F5.1. @item @subcmd{SD(@var{var_name})} Standard deviation of the mean. Limited to numeric values. The default format is F8.2. @item @subcmd{SUM(@var{var_name})} Sum. Limited to numeric values. The default format is F8.2. @end table Aggregation functions compare string values in terms of internal character codes. On most modern computers, this is @acronym{ASCII} or a superset thereof. The aggregation functions listed above exclude all user-missing values from calculations. To include user-missing values, insert a period (@samp{.}) at the end of the function name. (e.g.@: @samp{SUM.}). (Be aware that specifying such a function as the last token on a line will cause the period to be interpreted as the end of the command.) @cmd{AGGREGATE} both ignores and cancels the current @cmd{SPLIT FILE} settings (@pxref{SPLIT FILE}). @node AUTORECODE @section AUTORECODE @vindex AUTORECODE @display AUTORECODE VARIABLES=@var{src_vars} INTO @var{dest_vars} [ /DESCENDING ] [ /PRINT ] [ /GROUP ] [ /BLANK = @{VALID, MISSING@} ] @end display The @cmd{AUTORECODE} procedure considers the @var{n} values that a variable takes on and maps them onto values 1@dots{}@var{n} on a new numeric variable. Subcommand @subcmd{VARIABLES} is the only required subcommand and must come first. Specify @subcmd{VARIABLES}, an equals sign (@samp{=}), a list of source variables, @subcmd{INTO}, and a list of target variables. There must the same number of source and target variables. The target variables must not already exist. By default, increasing values of a source variable (for a string, this is based on character code comparisons) are recoded to increasing values of its target variable. To cause increasing values of a source variable to be recoded to decreasing values of its target variable (@var{n} down to 1), specify @subcmd{DESCENDING}. @subcmd{PRINT} is currently ignored. The @subcmd{GROUP} subcommand is relevant only if more than one variable is to be recoded. It causes a single mapping between source and target values to be used, instead of one map per variable. If @subcmd{/BLANK=MISSING} is given, then string variables which contain only whitespace are recoded as SYSMIS. If @subcmd{/BLANK=VALID} is given then they will be allocated a value like any other. @subcmd{/BLANK} is not relevant to numeric values. @subcmd{/BLANK=VALID} is the default. @cmd{AUTORECODE} is a procedure. It causes the data to be read. @node COMPUTE @section COMPUTE @vindex COMPUTE @display COMPUTE @var{variable} = @var{expression}. @end display or @display COMPUTE vector(@var{index}) = @var{expression}. @end display @cmd{COMPUTE} assigns the value of an expression to a target variable. For each case, the expression is evaluated and its value assigned to the target variable. Numeric and string variables may be assigned. When a string expression's width differs from the target variable's width, the string result of the expression is truncated or padded with spaces on the right as necessary. The expression and variable types must match. For numeric variables only, the target variable need not already exist. Numeric variables created by @cmd{COMPUTE} are assigned an @code{F8.2} output format. String variables must be declared before they can be used as targets for @cmd{COMPUTE}. The target variable may be specified as an element of a vector (@pxref{VECTOR}). In this case, an expression @var{index} must be specified in parentheses following the vector name. The expression @var{index} must evaluate to a numeric value that, after rounding down to the nearest integer, is a valid index for the named vector. Using @cmd{COMPUTE} to assign to a variable specified on @cmd{LEAVE} (@pxref{LEAVE}) resets the variable's left state. Therefore, @code{LEAVE} should be specified following @cmd{COMPUTE}, not before. @cmd{COMPUTE} is a transformation. It does not cause the active dataset to be read. When @cmd{COMPUTE} is specified following @cmd{TEMPORARY} (@pxref{TEMPORARY}), the @cmd{LAG} function may not be used (@pxref{LAG}). @node COUNT @section COUNT @vindex COUNT @display COUNT @var{var_name} = @var{var}@dots{} (@var{value}@dots{}). Each @var{value} takes one of the following forms: @var{number} @var{string} @var{num1} THRU @var{num2} MISSING SYSMIS where @var{num1} is a numeric expression or the words @subcmd{LO} or @subcmd{LOWEST} and @var{num2} is a numeric expression or @subcmd{HI} or @subcmd{HIGHEST}. @end display @cmd{COUNT} creates or replaces a numeric @dfn{target} variable that counts the occurrence of a @dfn{criterion} value or set of values over one or more @dfn{test} variables for each case. The target variable values are always nonnegative integers. They are never missing. The target variable is assigned an F8.2 output format. @xref{Input and Output Formats}. Any variables, including string variables, may be test variables. User-missing values of test variables are treated just like any other values. They are @strong{not} treated as system-missing values. User-missing values that are criterion values or inside ranges of criterion values are counted as any other values. However (for numeric variables), keyword @subcmd{MISSING} may be used to refer to all system- and user-missing values. @cmd{COUNT} target variables are assigned values in the order specified. In the command @subcmd{COUNT @var{A}=@var{A} @var{B}(1) /@var{B}=@var{A} @var{B}(2).}, the following actions occur: @itemize @minus @item The number of occurrences of 1 between @var{A} and @var{B} is counted. @item @var{A} is assigned this value. @item The number of occurrences of 1 between @var{B} and the @strong{new} value of @var{A} is counted. @item @var{B} is assigned this value. @end itemize Despite this ordering, all @cmd{COUNT} criterion variables must exist before the procedure is executed---they may not be created as target variables earlier in the command! Break such a command into two separate commands. The examples below may help to clarify. @enumerate A @item Assuming @code{Q0}, @code{Q2}, @dots{}, @code{Q9} are numeric variables, the following commands: @enumerate @item Count the number of times the value 1 occurs through these variables for each case and assigns the count to variable @code{QCOUNT}. @item Print out the total number of times the value 1 occurs throughout @emph{all} cases using @cmd{DESCRIPTIVES}. @xref{DESCRIPTIVES}, for details. @end enumerate @example COUNT QCOUNT=Q0 TO Q9(1). DESCRIPTIVES QCOUNT /STATISTICS=SUM. @end example @item Given these same variables, the following commands: @enumerate @item Count the number of valid values of these variables for each case and assigns the count to variable @code{QVALID}. @item Multiplies each value of @code{QVALID} by 10 to obtain a percentage of valid values, using @cmd{COMPUTE}. @xref{COMPUTE}, for details. @item Print out the percentage of valid values across all cases, using @cmd{DESCRIPTIVES}. @xref{DESCRIPTIVES}, for details. @end enumerate @example COUNT QVALID=Q0 TO Q9 (LO THRU HI). COMPUTE QVALID=QVALID*10. DESCRIPTIVES QVALID /STATISTICS=MEAN. @end example @end enumerate @node FLIP @section FLIP @vindex FLIP @display FLIP /VARIABLES=@var{var_list} /NEWNAMES=@var{var_name}. @end display @cmd{FLIP} transposes rows and columns in the active dataset. It causes cases to be swapped with variables, and vice versa. All variables in the transposed active dataset are numeric. String variables take on the system-missing value in the transposed file. @subcmd{N} subcommands are required. If specified, the @subcmd{VARIABLES} subcommand selects variables to be transformed into cases, and variables not specified are discarded. If the @subcmd{VARIABLES} subcommand is omitted, all variables are selected for transposition. The variables specified by @subcmd{NEWNAMES}, which must be a string variable, is used to give names to the variables created by @cmd{FLIP}. Only the first 8 characters of the variable are used. If @subcmd{NEWNAMES} is not specified then the default is a variable named CASE_LBL, if it exists. If it does not then the variables created by @cmd{FLIP} are named VAR000 through VAR999, then VAR1000, VAR1001, and so on. When a @subcmd{NEWNAMES} variable is available, the names must be canonicalized before becoming variable names. Invalid characters are replaced by letter @samp{V} in the first position, or by @samp{_} in subsequent positions. If the name thus generated is not unique, then numeric extensions are added, starting with 1, until a unique name is found or there are no remaining possibilities. If the latter occurs then the @cmd{FLIP} operation aborts. The resultant dictionary contains a CASE_LBL variable, a string variable of width 8, which stores the names of the variables in the dictionary before the transposition. Variables names longer than 8 characters are truncated. If the active dataset is subsequently transposed using @cmd{FLIP}, this variable can be used to recreate the original variable names. @cmd{FLIP} honors @cmd{N OF CASES} (@pxref{N OF CASES}). It ignores @cmd{TEMPORARY} (@pxref{TEMPORARY}), so that ``temporary'' transformations become permanent. @node IF @section IF @vindex IF @display IF @var{condition} @var{variable}=@var{expression}. @end display or @display IF @var{condition} vector(@var{index})=@var{expression}. @end display The @cmd{IF} transformation conditionally assigns the value of a target expression to a target variable, based on the truth of a test expression. Specify a boolean-valued expression (@pxref{Expressions}) to be tested following the @cmd{IF} keyword. This expression is evaluated for each case. If the value is true, then the value of the expression is computed and assigned to the specified variable. If the value is false or missing, nothing is done. Numeric and string variables may be assigned. When a string expression's width differs from the target variable's width, the string result of the expression is truncated or padded with spaces on the right as necessary. The expression and variable types must match. The target variable may be specified as an element of a vector (@pxref{VECTOR}). In this case, a vector index expression must be specified in parentheses following the vector name. The index expression must evaluate to a numeric value that, after rounding down to the nearest integer, is a valid index for the named vector. Using @cmd{IF} to assign to a variable specified on @cmd{LEAVE} (@pxref{LEAVE}) resets the variable's left state. Therefore, @code{LEAVE} should be specified following @cmd{IF}, not before. When @cmd{IF} is specified following @cmd{TEMPORARY} (@pxref{TEMPORARY}), the @cmd{LAG} function may not be used (@pxref{LAG}). @node RECODE @section RECODE @vindex RECODE The @cmd{RECODE} command is used to transform existing values into other, user specified values. The general form is: @display RECODE @var{src_vars} (@var{src_value} @var{src_value} @dots{} = @var{dest_value}) (@var{src_value} @var{src_value} @dots{} = @var{dest_value}) (@var{src_value} @var{src_value} @dots{} = @var{dest_value}) @dots{} [INTO @var{dest_vars}]. @end display Following the @cmd{RECODE} keyword itself comes @var{src_vars} which is a list of variables whose values are to be transformed. These variables may be string variables or they may be numeric. However the list must be homogeneous; you may not mix string variables and numeric variables in the same recoding. After the list of source variables, there should be one or more @dfn{mappings}. Each mapping is enclosed in parentheses, and contains the source values and a destination value separated by a single @samp{=}. The source values are used to specify the values in the dataset which need to change, and the destination value specifies the new value to which they should be changed. Each @var{src_value} may take one of the following forms: @itemize @bullet @item @var{number} If the source variables are numeric then @var{src_value} may be a literal number. @item @var{string} If the source variables are string variables then @var{src_value} may be a literal string (like all strings, enclosed in single or double quotes). @item @var{num1} THRU @var{num2} This form is valid only when the source variables are numeric. It specifies all values in the range [@var{num1}, @var{num2}]. Normally you would ensure that @var{num2} is greater than or equal to @var{num1}. If @var{num1} however is greater than @var{num2}, then the range [@var{num2},@var{num1}] will be used instead. Open-ended ranges may be specified using @samp{LO} or @samp{LOWEST} for @var{num1} or @samp{HI} or @samp{HIGHEST} for @var{num2}. @item @samp{MISSING} The literal keyword @samp{MISSING} matches both system missing and user missing values. It is valid for both numeric and string variables. @item @samp{SYSMIS} The literal keyword @samp{SYSMIS} matches system missing values. It is valid for both numeric variables only. @item @samp{ELSE} The @samp{ELSE} keyword may be used to match any values which are not matched by any other @var{src_value} appearing in the command. If this keyword appears, it should be used in the last mapping of the command. @end itemize After the source variables comes an @samp{=} and then the @var{dest_value}. The @var{dest_value} may take any of the following forms: @itemize @bullet @item @var{number} A literal numeric value to which the source values should be changed. This implies the destination variable must be numeric. @item @var{string} A literal string value (enclosed in quotation marks) to which the source values should be changed. This implies the destination variable must be a string variable. @item @samp{SYSMIS} The keyword @samp{SYSMIS} changes the value to the system missing value. This implies the destination variable must be numeric. @item @samp{COPY} The special keyword @samp{COPY} means that the source value should not be modified, but copied directly to the destination value. This is meaningful only if @samp{INTO @var{dest_vars}} is specified. @end itemize Mappings are considered from left to right. Therefore, if a value is matched by a @var{src_value} from more than one mapping, the first (leftmost) mapping which matches will be considered. Any subsequent matches will be ignored. The clause @samp{INTO @var{dest_vars}} is optional. The behaviour of the command is slightly different depending on whether it appears or not. If @samp{INTO @var{dest_vars}} does not appear, then values will be recoded ``in place´´. This means that the recoded values are written back to the source variables from whence the original values came. In this case, the @var{dest_value} for every mapping must imply a value which has the same type as the @var{src_value}. For example, if the source value is a string value, it is not permissible for @var{dest_value} to be @samp{SYSMIS} or another forms which implies a numeric result. The following example two numeric variables @var{x} and @var{y} are recoded in place. Zero is recoded to 99, the values 1 to 10 inclusive are unchanged, values 1000 and higher are recoded to the system-missing value and all other values are changed to 999: @example recode @var{x} @var{y} (0 = 99) (1 THRU 10 = COPY) (1000 THRU HIGHEST = SYSMIS) (ELSE = 999). @end example If @samp{INTO @var{dest_vars}} is given, then recoded values are written into the variables specified in @var{dest_vars}, which must therefore contain a list of valid variable names. The number of variables in @var{dest_vars} must be the same as the number of variables in @var{src_vars} and the respective order of the variables in @var{dest_vars} corresponds to the order of @var{src_vars}. That is to say, recoded values whose original value came from the @var{n}th variable in @var{src_vars} will be placed into the @var{n}th variable in @var{dest_vars}. The source variables will be unchanged. If any mapping implies a string as its destination value, then the respective destination variable must already exist, or have been declared using @cmd{STRING} or another transformation. Numeric variables however will be automatically created if they don't already exist. The following example deals with two source variables, @var{a} and @var{b} which contain string values. Hence there are two destination variables @var{v1} and @var{v2}. Any cases where @var{a} or @var{b} contain the values @samp{apple}, @samp{pear} or @samp{pomegranate} will result in @var{v1} or @var{v2} being filled with the string @samp{fruit} whilst cases with @samp{tomato}, @samp{lettuce} or @samp{carrot} will result in @samp{vegetable}. Any other values will produce the result @samp{unknown}: @example string @var{v1} (a20). string @var{v2} (a20). recode @var{a} @var{b} ("apple" "pear" "pomegranate" = "fruit") ("tomato" "lettuce" "carrot" = "vegetable") (ELSE = "unknown") into @var{v1} @var{v2}. @end example There is one very special mapping, not mentioned above. If the source variable is a string variable then a mapping may be specified as @samp{(CONVERT)}. This mapping, if it appears must be the last mapping given and the @samp{INTO @var{dest_vars}} clause must also be given and must not refer to a string variable. @samp{CONVERT} causes a number specified as a string to be converted to a numeric value. For example it will convert the string @samp{"3"} into the numeric value 3 (note that it will not convert @samp{three} into 3). If the string cannot be parsed as a number, then the system-missing value is assigned instead. In the following example, cases where the value of @var{x} (a string variable) is the empty string, are recoded to 999 and all others are converted to the numeric equivalent of the input value. The results are placed into the numeric variable @var{y}: @example recode @var{x} ("" = 999) (convert) into @var{y}. @end example It is possible to specify multiple recodings on a single command. Introduce additional recodings with a slash (@samp{/}) to separate them from the previous recodings: @example recode @var{a} (2 = 22) (else = 99) /@var{b} (1 = 3) into @var{z} . @end example @noindent Here we have two recodings. The first affects the source variable @var{a} and recodes in-place the value 2 into 22 and all other values to 99. The second recoding copies the values of @var{b} into the the variable @var{z}, changing any instances of 1 into 3. @node SORT CASES @section SORT CASES @vindex SORT CASES @display SORT CASES BY @var{var_list}[(@{D|A@}] [ @var{var_list}[(@{D|A@}] ] ... @end display @cmd{SORT CASES} sorts the active dataset by the values of one or more variables. Specify @subcmd{BY} and a list of variables to sort by. By default, variables are sorted in ascending order. To override sort order, specify @subcmd{(D)} or @subcmd{(DOWN)} after a list of variables to get descending order, or @subcmd{(A)} or @subcmd{(UP)} for ascending order. These apply to all the listed variables up until the preceding @subcmd{(A)}, @subcmd{(D)}, @subcmd{(UP)} or @subcmd{(DOWN)}. The sort algorithms used by @cmd{SORT CASES} are stable. That is, records that have equal values of the sort variables will have the same relative order before and after sorting. As a special case, re-sorting an already sorted file will not affect the ordering of cases. @cmd{SORT CASES} is a procedure. It causes the data to be read. @cmd{SORT CASES} attempts to sort the entire active dataset in main memory. If workspace is exhausted, it falls back to a merge sort algorithm that involves creates numerous temporary files. @cmd{SORT CASES} may not be specified following @cmd{TEMPORARY}. pspp-master/doc/tutorial.texi000066400000000000000000001032531177044323000166410ustar00rootroot00000000000000@alias prompt = sansserif @include tut.texi @node Using PSPP @chapter Using @pspp{} @pspp{} is a tool for the statistical analysis of sampled data. You can use it to discover patterns in the data, to explain differences in one subset of data in terms of another subset and to find out whether certain beliefs about the data are justified. This chapter does not attempt to introduce the theory behind the statistical analysis, but it shows how such analysis can be performed using @pspp{}. For the purposes of this tutorial, it is assumed that you are using @pspp{} in its interactive mode from the command line. However, the example commands can also be typed into a file and executed in a post-hoc mode by typing @samp{pspp @var{filename}} at a shell prompt, where @var{filename} is the name of the file containing the commands. Alternatively, from the graphical interface, you can select @clicksequence{File @click{} New @click{} Syntax} to open a new syntax window and use the @clicksequence{Run} menu when a syntax fragment is ready to be executed. Whichever method you choose, the syntax is identical. When using the interactive method, @pspp{} tells you that it's waiting for your data with a string like @prompt{PSPP>} or @prompt{data>}. In the examples of this chapter, whenever you see text like this, it indicates the prompt displayed by @pspp{}, @emph{not} something that you should type. Throughout this chapter reference is made to a number of sample data files. So that you can try the examples for yourself, you should have received these files along with your copy of @pspp{}.@c @footnote{These files contain purely fictitious data. They should not be used for research purposes.} @note{Normally these files are installed in the directory @file{@value{example-dir}}. If however your system administrator or operating system vendor has chosen to install them in a different location, you will have to adjust the examples accordingly.} @menu * Preparation of Data Files:: * Data Screening and Transformation:: * Hypothesis Testing:: @end menu @node Preparation of Data Files @section Preparation of Data Files Before analysis can commence, the data must be loaded into @pspp{} and arranged such that both @pspp{} and humans can understand what the data represents. There are two aspects of data: @itemize @bullet @item The variables --- these are the parameters of a quantity which has been measured or estimated in some way. For example height, weight and geographic location are all variables. @item The observations (also called `cases') of the variables --- each observation represents an instance when the variables were measured or observed. @end itemize @noindent For example, a data set which has the variables @var{height}, @var{weight}, and @var{name}, might have the observations: @example 1881 89.2 Ahmed 1192 107.01 Frank 1230 67 Julie @end example @noindent The following sections explain how to define a dataset. @menu * Defining Variables:: * Listing the data:: * Reading data from a text file:: * Reading data from a pre-prepared PSPP file:: * Saving data to a PSPP file.:: * Reading data from other sources:: @end menu @node Defining Variables @subsection Defining Variables @cindex variables Variables come in two basic types, @i{viz}: @dfn{numeric} and @dfn{string}. Variables such as age, height and satisfaction are numeric, whereas name is a string variable. String variables are best reserved for commentary data to assist the human observer. However they can also be used for nominal or categorical data. @ref{data-list} defines two variables @var{forename} and @var{height}, and reads data into them by manual input. @float Example, data-list @cartouche @example @prompt{PSPP>} data list list /forename (A12) height. @prompt{PSPP>} begin data. @prompt{data>} Ahmed 188 @prompt{data>} Bertram 167 @prompt{data>} Catherine 134.231 @prompt{data>} David 109.1 @prompt{data>} end data @prompt{PSPP>} @end example @end cartouche @caption{Manual entry of data using the @cmd{DATA LIST} command. Two variables @var{forename} and @var{height} are defined and subsequently filled with manually entered data.} @end float There are several things to note about this example. @itemize @bullet @item The words @samp{data list list} are an example of the @cmd{DATA LIST} command. @xref{DATA LIST}. It tells @pspp{} to prepare for reading data. The word @samp{list} intentionally appears twice. The first occurrence is part of the @cmd{DATA LIST} call, whilst the second tells @pspp{} that the data is to be read as free format data with one record per line. @item The @samp{/} character is important. It marks the start of the list of variables which you wish to define. @item The text @samp{forename} is the name of the first variable, and @samp{(A12)} says that the variable @var{forename} is a string variable and that its maximum length is 12 bytes. The second variable's name is specified by the text @samp{height}. Since no format is given, this variable has the default format. For more information on data formats, @pxref{Input and Output Formats}. @item Normally, @pspp{} displays the prompt @prompt{PSPP>} whenever it's expecting a command. However, when it's expecting data, the prompt changes to @prompt{data>} so that you know to enter data and not a command. @item At the end of every command there is a terminating @samp{.} which tells @pspp{} that the end of a command has been encountered. You should not enter @samp{.} when data is expected (@i{ie.} when the @prompt{data>} prompt is current) since it is appropriate only for terminating commands. @end itemize @node Listing the data @subsection Listing the data @vindex LIST Once the data has been entered, you could type @example @prompt{PSPP>} list /format=numbered. @end example @noindent to list the data. The optional text @samp{/format=numbered} requests the case numbers to be shown along with the data. It should show the following output: @example @group Case# forename height ----- ------------ -------- 1 Ahmed 188.00 2 Bertram 167.00 3 Catherine 134.23 4 David 109.10 @end group @end example @noindent Note that the numeric variable @var{height} is displayed to 2 decimal places, because the format for that variable is @samp{F8.2}. For a complete description of the @cmd{LIST} command, @pxref{LIST}. @node Reading data from a text file @subsection Reading data from a text file @cindex reading data The previous example showed how to define a set of variables and to manually enter the data for those variables. Manual entering of data is tedious work, and often a file containing the data will be have been previously prepared. Let us assume that you have a file called @file{mydata.dat} containing the ascii encoded data: @example Ahmed 188.00 Bertram 167.00 Catherine 134.23 David 109.10 @ . @ . @ . Zachariah 113.02 @end example @noindent You can can tell the @cmd{DATA LIST} command to read the data directly from this file instead of by manual entry, with a command like: @example @prompt{PSPP>} data list file='mydata.dat' list /forename (A12) height. @end example @noindent Notice however, that it is still necessary to specify the names of the variables and their formats, since this information is not contained in the file. It is also possible to specify the file's character encoding and other parameters. For full details refer to @pxref{DATA LIST}. @node Reading data from a pre-prepared PSPP file @subsection Reading data from a pre-prepared @pspp{} file @cindex system files @vindex GET When working with other @pspp{} users, or users of other software which uses the @pspp{} data format, you may be given the data in a pre-prepared @pspp{} file. Such files contain not only the data, but the variable definitions, along with their formats, labels and other meta-data. Conventionally, these files (sometimes called ``system'' files) have the suffix @file{.sav}, but that is not mandatory. The following syntax loads a file called @file{my-file.sav}. @example @prompt{PSPP>} get file='my-file.sav'. @end example @noindent You will encounter several instances of this in future examples. @node Saving data to a PSPP file. @subsection Saving data to a @pspp{} file. @cindex saving @vindex SAVE If you want to save your data, along with the variable definitions so that you or other @pspp{} users can use it later, you can do this with the @cmd{SAVE} command. The following syntax will save the existing data and variables to a file called @file{my-new-file.sav}. @example @prompt{PSPP>} save outfile='my-new-file.sav'. @end example @noindent If @file{my-new-file.sav} already exists, then it will be overwritten. Otherwise it will be created. @node Reading data from other sources @subsection Reading data from other sources @cindex comma separated values @cindex spreadsheets @cindex databases Sometimes it's useful to be able to read data from comma separated text, from spreadsheets, databases or other sources. In these instances you should use the @cmd{GET DATA} command (@pxref{GET DATA}). @node Data Screening and Transformation @section Data Screening and Transformation @cindex screening @cindex transformation Once data has been entered, it is often desirable, or even necessary, to transform it in some way before performing analysis upon it. At the very least, it's good practice to check for errors. @menu * Identifying incorrect data:: * Dealing with suspicious data:: * Inverting negatively coded variables:: * Testing data consistency:: * Testing for normality :: @end menu @node Identifying incorrect data @subsection Identifying incorrect data @cindex erroneous data @cindex errors, in data Data from real sources is rarely error free. @pspp{} has a number of procedures which can be used to help identify data which might be incorrect. The @cmd{DESCRIPTIVES} command (@pxref{DESCRIPTIVES}) is used to generate simple linear statistics for a dataset. It is also useful for identifying potential problems in the data. The example file @file{physiology.sav} contains a number of physiological measurements of a sample of healthy adults selected at random. However, the data entry clerk made a number of mistakes when entering the data. @ref{descriptives} illustrates the use of @cmd{DESCRIPTIVES} to screen this data and identify the erroneous values. @float Example, descriptives @cartouche @example @prompt{PSPP>} get file='@value{example-dir}/physiology.sav'. @prompt{PSPP>} descriptives sex, weight, height. @end example Output: @example DESCRIPTIVES. Valid cases = 40; cases with missing value(s) = 0. +--------#--+-------+-------+-------+-------+ |Variable# N| Mean |Std Dev|Minimum|Maximum| #========#==#=======#=======#=======#=======# |sex #40| .45| .50| .00| 1.00| |height #40|1677.12| 262.87| 179.00|1903.00| |weight #40| 72.12| 26.70| -55.60| 92.07| +--------#--+-------+-------+-------+-------+ @end example @end cartouche @caption{Using the @cmd{DESCRIPTIVES} command to display simple summary information about the data. In this case, the results show unexpectedly low values in the Minimum column, suggesting incorrect data entry.} @end float In the output of @ref{descriptives}, the most interesting column is the minimum value. The @var{weight} variable has a minimum value of less than zero, which is clearly erroneous. Similarly, the @var{height} variable's minimum value seems to be very low. In fact, it is more than 5 standard deviations from the mean, and is a seemingly bizarre height for an adult person. We can examine the data in more detail with the @cmd{EXAMINE} command (@pxref{EXAMINE}): In @ref{examine} you can see that the lowest value of @var{height} is 179 (which we suspect to be erroneous), but the second lowest is 1598 which we know from the @cmd{DESCRIPTIVES} command is within 1 standard deviation from the mean. Similarly the @var{weight} variable has a lowest value which is negative but a plausible value for the second lowest value. This suggests that the two extreme values are outliers and probably represent data entry errors. @float Example, examine @cartouche [@dots{} continue from @ref{descriptives}] @example @prompt{PSPP>} examine height, weight /statistics=extreme(3). @end example Output: @example #===============================#===========#=======# # #Case Number| Value # #===============================#===========#=======# #Height in millimetres Highest 1# 14|1903.00# # 2# 15|1884.00# # 3# 12|1801.65# # ----------#-----------+-------# # Lowest 1# 30| 179.00# # 2# 31|1598.00# # 3# 28|1601.00# # ----------#-----------+-------# #Weight in kilograms Highest 1# 13| 92.07# # 2# 5| 92.07# # 3# 17| 91.74# # ----------#-----------+-------# # Lowest 1# 38| -55.60# # 2# 39| 54.48# # 3# 33| 55.45# #===============================#===========#=======# @end example @end cartouche @caption{Using the @cmd{EXAMINE} command to see the extremities of the data for different variables. Cases 30 and 38 seem to contain values very much lower than the rest of the data. They are possibly erroneous.} @end float @node Dealing with suspicious data @subsection Dealing with suspicious data @cindex SYSMIS @cindex recoding data If possible, suspect data should be checked and re-measured. However, this may not always be feasible, in which case the researcher may decide to disregard these values. @pspp{} has a feature whereby data can assume the special value `SYSMIS', and will be disregarded in future analysis. @xref{Missing Observations}. You can set the two suspect values to the `SYSMIS' value using the @cmd{RECODE} command. @example @pspp{}> recode height (179 = SYSMIS). @pspp{}> recode weight (LOWEST THRU 0 = SYSMIS). @end example @noindent The first command says that for any observation which has a @var{height} value of 179, that value should be changed to the SYSMIS value. The second command says that any @var{weight} values of zero or less should be changed to SYSMIS. From now on, they will be ignored in analysis. For detailed information about the @cmd{RECODE} command @pxref{RECODE}. If you now re-run the @cmd{DESCRIPTIVES} or @cmd{EXAMINE} commands in @ref{descriptives} and @ref{examine} you will see a data summary with more plausible parameters. You will also notice that the data summaries indicate the two missing values. @node Inverting negatively coded variables @subsection Inverting negatively coded variables @cindex Likert scale @cindex Inverting data Data entry errors are not the only reason for wanting to recode data. The sample file @file{hotel.sav} comprises data gathered from a customer satisfaction survey of clients at a particular hotel. In @ref{reliability}, this file is loaded for analysis. The line @code{display dictionary.} tells @pspp{} to display the variables and associated data. The output from this command has been omitted from the example for the sake of clarity, but you will notice that each of the variables @var{v1}, @var{v2} @dots{} @var{v5} are measured on a 5 point Likert scale, with 1 meaning ``Strongly disagree'' and 5 meaning ``Strongly agree''. Whilst variables @var{v1}, @var{v2} and @var{v4} record responses to a positively posed question, variables @var{v3} and @var{v5} are responses to negatively worded questions. In order to perform meaningful analysis, we need to recode the variables so that they all measure in the same direction. We could use the @cmd{RECODE} command, with syntax such as: @example recode v3 (1 = 5) (2 = 4) (4 = 2) (5 = 1). @end example @noindent However an easier and more elegant way uses the @cmd{COMPUTE} command (@pxref{COMPUTE}). Since the variables are Likert variables in the range (1 @dots{} 5), subtracting their value from 6 has the effect of inverting them: @example compute @var{var} = 6 - @var{var}. @end example @noindent @ref{reliability} uses this technique to recode the variables @var{v3} and @var{v5}. After applying @cmd{COMPUTE} for both variables, all subsequent commands will use the inverted values. @node Testing data consistency @subsection Testing data consistency @cindex reliability @cindex consistency A sensible check to perform on survey data is the calculation of reliability. This gives the statistician some confidence that the questionnaires have been completed thoughtfully. If you examine the labels of variables @var{v1}, @var{v3} and @var{v5}, you will notice that they ask very similar questions. One would therefore expect the values of these variables (after recoding) to closely follow one another, and we can test that with the @cmd{RELIABILITY} command (@pxref{RELIABILITY}). @ref{reliability} shows a @pspp{} session where the user (after recoding negatively scaled variables) requests reliability statistics for @var{v1}, @var{v3} and @var{v5}. @float Example, reliability @cartouche @example @prompt{PSPP>} get file='@value{example-dir}/hotel.sav'. @prompt{PSPP>} display dictionary. @prompt{PSPP>} * recode negatively worded questions. @prompt{PSPP>} compute v3 = 6 - v3. @prompt{PSPP>} compute v5 = 6 - v5. @prompt{PSPP>} reliability v1, v3, v5. @end example Output (dictionary information omitted for clarity): @example 1.1 RELIABILITY. Case Processing Summary #==============#==#======# # # N| % # #==============#==#======# #Cases Valid #17|100.00# # Excluded# 0| .00# # Total #17|100.00# #==============#==#======# 1.2 RELIABILITY. Reliability Statistics #================#==========# #Cronbach's Alpha#N of Items# #================#==========# # .86# 3# #================#==========# @end example @end cartouche @caption{Recoding negatively scaled variables, and testing for reliability with the @cmd{RELIABILITY} command. The Cronbach Alpha coefficient suggests a high degree of reliability among variables @var{v1}, @var{v2} and @var{v5}.} @end float As a rule of thumb, many statisticians consider a value of Cronbach's Alpha of 0.7 or higher to indicate reliable data. Here, the value is 0.86 so the data and the recoding that we performed are vindicated. @node Testing for normality @subsection Testing for normality @cindex normality, testing Many statistical tests rely upon certain properties of the data. One common property, upon which many linear tests depend, is that of normality --- the data must have been drawn from a normal distribution. It is necessary then to ensure normality before deciding upon the test procedure to use. One way to do this uses the @cmd{EXAMINE} command. In @ref{normality}, a researcher was examining the failure rates of equipment produced by an engineering company. The file @file{repairs.sav} contains the mean time between failures (@var{mtbf}) of some items of equipment subject to the study. Before performing linear analysis on the data, the researcher wanted to ascertain that the data is normally distributed. A normal distribution has a skewness and kurtosis of zero. Looking at the skewness of @var{mtbf} in @ref{normality} it is clear that the mtbf figures have a lot of positive skew and are therefore not drawn from a normally distributed variable. Positive skew can often be compensated for by applying a logarithmic transformation. This is done with the @cmd{COMPUTE} command in the line @example compute mtbf_ln = ln (mtbf). @end example @noindent Rather than redefining the existing variable, this use of @cmd{COMPUTE} defines a new variable @var{mtbf_ln} which is the natural logarithm of @var{mtbf}. The final command in this example calls @cmd{EXAMINE} on this new variable, and it can be seen from the results that both the skewness and kurtosis for @var{mtbf_ln} are very close to zero. This provides some confidence that the @var{mtbf_ln} variable is normally distributed and thus safe for linear analysis. In the event that no suitable transformation can be found, then it would be worth considering an appropriate non-parametric test instead of a linear one. @xref{NPAR TESTS}, for information about non-parametric tests. @float Example, normality @cartouche @example @prompt{PSPP>} get file='@value{example-dir}/repairs.sav'. @prompt{PSPP>} examine mtbf /statistics=descriptives. @prompt{PSPP>} compute mtbf_ln = ln (mtbf). @prompt{PSPP>} examine mtbf_ln /statistics=descriptives. @end example Output: @example 1.2 EXAMINE. Descriptives #====================================================#=========#==========# # #Statistic|Std. Error# #====================================================#=========#==========# #mtbf Mean # 8.32 | 1.62 # # 95% Confidence Interval for Mean Lower Bound# 4.85 | # # Upper Bound# 11.79 | # # 5% Trimmed Mean # 7.69 | # # Median # 8.12 | # # Variance # 39.21 | # # Std. Deviation # 6.26 | # # Minimum # 1.63 | # # Maximum # 26.47 | # # Range # 24.84 | # # Interquartile Range # 5.83 | # # Skewness # 1.85 | .58 # # Kurtosis # 4.49 | 1.12 # #====================================================#=========#==========# 2.2 EXAMINE. Descriptives #====================================================#=========#==========# # #Statistic|Std. Error# #====================================================#=========#==========# #mtbf_ln Mean # 1.88 | .19 # # 95% Confidence Interval for Mean Lower Bound# 1.47 | # # Upper Bound# 2.29 | # # 5% Trimmed Mean # 1.88 | # # Median # 2.09 | # # Variance # .54 | # # Std. Deviation # .74 | # # Minimum # .49 | # # Maximum # 3.28 | # # Range # 2.79 | # # Interquartile Range # .92 | # # Skewness # -.16 | .58 # # Kurtosis # -.09 | 1.12 # #====================================================#=========#==========# @end example @end cartouche @caption{Testing for normality using the @cmd{EXAMINE} command and applying a logarithmic transformation. The @var{mtbf} variable has a large positive skew and is therefore unsuitable for linear statistical analysis. However the transformed variable (@var{mtbf_ln}) is close to normal and would appear to be more suitable.} @end float @node Hypothesis Testing @section Hypothesis Testing @cindex Hypothesis testing @cindex p-value @cindex null hypothesis One of the most fundamental purposes of statistical analysis is hypothesis testing. Researchers commonly need to test hypotheses about a set of data. For example, she might want to test whether one set of data comes from the same distribution as another, or whether the mean of a dataset significantly differs from a particular value. This section presents just some of the possible tests that @pspp{} offers. The researcher starts by making a @dfn{null hypothesis}. Often this is a hypothesis which he suspects to be false. For example, if he suspects that @var{A} is greater than @var{B} he will state the null hypothesis as @math{ @var{A} = @var{B}}.@c @footnote{This example assumes that it is already proven that @var{B} is not greater than @var{A}.} The @dfn{p-value} is a recurring concept in hypothesis testing. It is the highest acceptable probability that the evidence implying a null hypothesis is false, could have been obtained when the null hypothesis is in fact true. Note that this is not the same as ``the probability of making an error'' nor is it the same as ``the probability of rejecting a hypothesis when it is true''. @menu * Testing for differences of means:: * Linear Regression:: @end menu @node Testing for differences of means @subsection Testing for differences of means @cindex T-test @vindex T-TEST A common statistical test involves hypotheses about means. The @cmd{T-TEST} command is used to find out whether or not two separate subsets have the same mean. @ref{t-test} uses the file @file{physiology.sav} previously encountered. A researcher suspected that the heights and core body temperature of persons might be different depending upon their sex. To investigate this, he posed two null hypotheses: @itemize @bullet @item The mean heights of males and females in the population are equal. @item The mean body temperature of males and females in the population are equal. @end itemize @noindent For the purposes of the investigation the researcher decided to use a p-value of 0.05. In addition to the T-test, the @cmd{T-TEST} command also performs the Levene test for equal variances. If the variances are equal, then a more powerful form of the T-test can be used. However if it is unsafe to assume equal variances, then an alternative calculation is necessary. @pspp{} performs both calculations. For the @var{height} variable, the output shows the significance of the Levene test to be 0.33 which means there is a 33% probability that the Levene test produces this outcome when the variances are unequal. Such a probability is too high to assume that the variances are equal so the row for unequal variances should be used. Examining this row, the two tailed significance for the @var{height} t-test is less than 0.05, so it is safe to reject the null hypothesis and conclude that the mean heights of males and females are unequal. For the @var{temperature} variable, the significance of the Levene test is 0.58 so again, it is unsafe to use the row for equal variances. The unequal variances row indicates that the two tailed significance for @var{temperature} is 0.19. Since this is greater than 0.05 we must reject the null hypothesis and conclude that there is insufficient evidence to suggest that the body temperature of male and female persons are different. @float Example, t-test @cartouche @example @prompt{PSPP>} get file='@value{example-dir}/physiology.sav'. @prompt{PSPP>} recode height (179 = SYSMIS). @prompt{PSPP>} t-test group=sex(0,1) /variables = height temperature. @end example Output: @example 1.1 T-TEST. Group Statistics #==================#==#=======#==============#========# # sex | N| Mean |Std. Deviation|SE. Mean# #==================#==#=======#==============#========# #height Male |22|1796.49| 49.71| 10.60# # Female|17|1610.77| 25.43| 6.17# #temperature Male |22| 36.68| 1.95| .42# # Female|18| 37.43| 1.61| .38# #==================#==#=======#==============#========# 1.2 T-TEST. Independent Samples Test #===========================#=========#=============================== =# # # Levene's| t-test for Equality of Means # # #----+----+------+-----+------+---------+- -# # # | | | | | | # # # | | | |Sig. 2| | # # # F |Sig.| t | df |tailed|Mean Diff| # #===========================#====#====#======#=====#======#=========#= =# #height Equal variances# .97| .33| 14.02|37.00| .00| 185.72| ... # # Unequal variances# | | 15.15|32.71| .00| 185.72| ... # #temperature Equal variances# .31| .58| -1.31|38.00| .20| -.75| ... # # Unequal variances# | | -1.33|37.99| .19| -.75| ... # #===========================#====#====#======#=====#======#=========#= =# @end example @end cartouche @caption{The @cmd{T-TEST} command tests for differences of means. Here, the @var{height} variable's two tailed significance is less than 0.05, so the null hypothesis can be rejected. Thus, the evidence suggests there is a difference between the heights of male and female persons. However the significance of the test for the @var{temperature} variable is greater than 0.05 so the null hypothesis cannot be rejected, and there is insufficient evidence to suggest a difference in body temperature.} @end float @node Linear Regression @subsection Linear Regression @cindex linear regression @vindex REGRESSION Linear regression is a technique used to investigate if and how a variable is linearly related to others. If a variable is found to be linearly related, then this can be used to predict future values of that variable. In example @ref{regression}, the service department of the company wanted to be able to predict the time to repair equipment, in order to improve the accuracy of their quotations. It was suggested that the time to repair might be related to the time between failures and the duty cycle of the equipment. The p-value of 0.1 was chosen for this investigation. In order to investigate this hypothesis, the @cmd{REGRESSION} command was used. This command not only tests if the variables are related, but also identifies the potential linear relationship. @xref{REGRESSION}. @float Example, regression @cartouche @example @prompt{PSPP>} get file='@value{example-dir}/repairs.sav'. @prompt{PSPP>} regression /variables = mtbf duty_cycle /dependent = mttr. @prompt{PSPP>} regression /variables = mtbf /dependent = mttr. @end example Output: @example 1.3(1) REGRESSION. Coefficients #=============================================#====#==========#====#=====# # # B |Std. Error|Beta| t # #========#====================================#====#==========#====#=====# # |(Constant) #9.81| 1.50| .00| 6.54# # |Mean time between failures (months) #3.10| .10| .99|32.43# # |Ratio of working to non-working time#1.09| 1.78| .02| .61# # | # | | | # #========#====================================#====#==========#====#=====# 1.3(2) REGRESSION. Coefficients #=============================================#============# # #Significance# #========#====================================#============# # |(Constant) # .10# # |Mean time between failures (months) # .00# # |Ratio of working to non-working time# .55# # | # # #========#====================================#============# 2.3(1) REGRESSION. Coefficients #============================================#=====#==========#====#=====# # # B |Std. Error|Beta| t # #========#===================================#=====#==========#====#=====# # |(Constant) #10.50| .96| .00|10.96# # |Mean time between failures (months)# 3.11| .09| .99|33.39# # | # | | | # #========#===================================#=====#==========#====#=====# 2.3(2) REGRESSION. Coefficients #============================================#============# # #Significance# #========#===================================#============# # |(Constant) # .06# # |Mean time between failures (months)# .00# # | # # #========#===================================#============# @end example @end cartouche @caption{Linear regression analysis to find a predictor for @var{mttr}. The first attempt, including @var{duty_cycle}, produces some unacceptable high significance values. However the second attempt, which excludes @var{duty_cycle}, produces significance values no higher than 0.06. This suggests that @var{mtbf} alone may be a suitable predictor for @var{mttr}.} @end float The coefficients in the first table suggest that the formula @math{@var{mttr} = 9.81 + 3.1 \times @var{mtbf} + 1.09 \times @var{duty_cycle}} can be used to predict the time to repair. However, the significance value for the @var{duty_cycle} coefficient is very high, which would make this an unsafe predictor. For this reason, the test was repeated, but omitting the @var{duty_cycle} variable. This time, the significance of all coefficients no higher than 0.06, suggesting that at the 0.06 level, the formula @math{@var{mttr} = 10.5 + 3.11 \times @var{mtbf}} is a reliable predictor of the time to repair. @c LocalWords: PSPP dir itemize noindent var cindex dfn cartouche samp xref @c LocalWords: pxref ie sav Std Dev kilograms SYSMIS sansserif pre pspp emph @c LocalWords: Likert Cronbach's Cronbach mtbf npplot ln myfile cmd NPAR Sig @c LocalWords: vindex Levene Levene's df Diff clicksequence mydata dat ascii @c LocalWords: mttr outfile pspp-master/doc/utilities.texi000066400000000000000000000676531177044323000170260ustar00rootroot00000000000000@node Utilities @chapter Utilities Commands that don't fit any other category are placed here. Most of these commands are not affected by commands like @cmd{IF} and @cmd{LOOP}: they take effect only once, unconditionally, at the time that they are encountered in the input. @menu * ADD DOCUMENT:: Add documentary text to the active dataset. * CACHE:: Ignored for compatibility. * CD:: Change the current directory. * COMMENT:: Document your syntax file. * DOCUMENT:: Document the active dataset. * DISPLAY DOCUMENTS:: Display active dataset documents. * DISPLAY FILE LABEL:: Display the active dataset label. * DROP DOCUMENTS:: Remove documents from the active dataset. * ECHO:: Write a string to the output stream. * ERASE:: Erase a file. * EXECUTE:: Execute pending transformations. * FILE LABEL:: Set the active dataset's label. * FINISH:: Terminate the @pspp{} session. * HOST:: Temporarily return to the operating system. * INCLUDE:: Include a file within the current one. * INSERT:: Insert a file within the current one. * PERMISSIONS:: Change permissions on a file. * PRESERVE and RESTORE:: Saving settings and restoring them later. * SET:: Adjust @pspp{} runtime parameters. * SHOW:: Display runtime parameters. * SUBTITLE:: Provide a document subtitle. * TITLE:: Provide a document title. @end menu @node ADD DOCUMENT @section ADD DOCUMENT @vindex ADD DOCUMENT @display ADD DOCUMENT 'line one' 'line two' @dots{} 'last line' . @end display @cmd{ADD DOCUMENT} adds one or more lines of descriptive commentary to the active dataset. Documents added in this way are saved to system files. They can be viewed using @cmd{SYSFILE INFO} or @cmd{DISPLAY DOCUMENTS}. They can be removed from the active dataset with @cmd{DROP DOCUMENTS}. Each line of documentary text must be enclosed in quotation marks, and may not be more than 80 bytes long. @xref{DOCUMENT}. @node CACHE @section CACHE @vindex CACHE @display CACHE. @end display This command is accepted, for compatibility, but it has no effect. @node CD @section CD @vindex CD @cindex directory @cindex changing directory @display CD 'new directory' . @end display @cmd{CD} changes the current directory. The new directory will become that specified by the command. @node COMMENT @section COMMENT @vindex COMMENT @vindex * @display Two possibles syntaxes: COMMENT comment text @dots{} . *comment text @dots{} . @end display @cmd{COMMENT} is ignored. It is used to provide information to the author and other readers of the @pspp{} syntax file. @cmd{COMMENT} can extend over any number of lines. Don't forget to terminate it with a dot or a blank line. @node DOCUMENT @section DOCUMENT @vindex DOCUMENT @display DOCUMENT @var{documentary_text}. @end display @cmd{DOCUMENT} adds one or more lines of descriptive commentary to the active dataset. Documents added in this way are saved to system files. They can be viewed using @cmd{SYSFILE INFO} or @cmd{DISPLAY DOCUMENTS}. They can be removed from the active dataset with @cmd{DROP DOCUMENTS}. Specify the @var{documentary text} following the @subcmd{DOCUMENT} keyword. It is interpreted literally --- any quotes or other punctuation marks will be included in the file. You can extend the documentary text over as many lines as necessary. Lines are truncated at 80 bytes. Don't forget to terminate the command with a dot or a blank line. @xref{ADD DOCUMENT}. @node DISPLAY DOCUMENTS @section DISPLAY DOCUMENTS @vindex DISPLAY DOCUMENTS @display DISPLAY DOCUMENTS. @end display @cmd{DISPLAY DOCUMENTS} displays the documents in the active dataset. Each document is preceded by a line giving the time and date that it was added. @xref{DOCUMENT}. @node DISPLAY FILE LABEL @section DISPLAY FILE LABEL @vindex DISPLAY FILE LABEL @display DISPLAY FILE LABEL. @end display @cmd{DISPLAY FILE LABEL} displays the file label contained in the active dataset, if any. @xref{FILE LABEL}. This command is a @pspp{} extension. @node DROP DOCUMENTS @section DROP DOCUMENTS @vindex DROP DOCUMENTS @display DROP DOCUMENTS. @end display @cmd{DROP DOCUMENTS} removes all documents from the active dataset. New documents can be added with @cmd{DOCUMENT} (@pxref{DOCUMENT}). @cmd{DROP DOCUMENTS} changes only the active dataset. It does not modify any system files stored on disk. @node ECHO @section ECHO @vindex ECHO @display ECHO 'arbitrary text' . @end display Use @cmd{ECHO} to write arbitrary text to the output stream. The text should be enclosed in quotation marks following the normal rules for string tokens (@pxref{Tokens}). @node ERASE @section ERASE @vindex ERASE @display ERASE FILE @var{file_name}. @end display @cmd{ERASE FILE} deletes a file from the local filesystem. @var{file_name} must be quoted. This command cannot be used if the SAFER (@pxref{SET}) setting is active. @node EXECUTE @section EXECUTE @vindex EXECUTE @display EXECUTE. @end display @cmd{EXECUTE} causes the active dataset to be read and all pending transformations to be executed. @node FILE LABEL @section FILE LABEL @vindex FILE LABEL @display FILE LABEL @var{file_label}. @end display @cmd{FILE LABEL} provides a title for the active dataset. This title will be saved into system files and portable files that are created during this @pspp{} run. @var{file_label} should not be quoted. If quotes are included, they are literally interpreted and become part of the file label. @node FINISH @section FINISH @vindex FINISH @display FINISH. @end display @cmd{FINISH} terminates the current @pspp{} session and returns control to the operating system. @node HOST @section HOST @vindex HOST @display HOST. HOST COMMAND=['@var{command}'...]. @end display @cmd{HOST} suspends the current @pspp{} session and temporarily returns control to the operating system. This command cannot be used if the SAFER (@pxref{SET}) setting is active. If the @subcmd{COMMAND} subcommand is specified, as a sequence of shell commands as quoted strings within square brackets, then @pspp{} executes them together in a single subshell. If no subcommands are specified, then @pspp{} invokes an interactive subshell. @node INCLUDE @section INCLUDE @vindex INCLUDE @display INCLUDE [FILE=]'@var{file_name}' [ENCODING='@var{encoding}']. @end display @cmd{INCLUDE} causes the @pspp{} command processor to read an additional command file as if it were included bodily in the current command file. If errors are encountered in the included file, then command processing will stop and no more commands will be processed. Include files may be nested to any depth, up to the limit of available memory. The @cmd{INSERT} command (@pxref{INSERT}) is a more flexible alternative to @cmd{INCLUDE}. An @cmd{INCLUDE} command acts the same as @cmd{INSERT} with @subcmd{ERROR=STOP CD=NO SYNTAX=BATCH} specified. The optional @subcmd{ENCODING} subcommand has the same meaning as with @cmd{INSERT}. @node INSERT @section INSERT @vindex INSERT @display INSERT [FILE=]'@var{file_name}' [CD=@{NO,YES@}] [ERROR=@{CONTINUE,STOP@}] [SYNTAX=@{BATCH,INTERACTIVE@}] [ENCODING=@{LOCALE, '@var{charset_name}'@}]. @end display @cmd{INSERT} is similar to @cmd{INCLUDE} (@pxref{INCLUDE}) but somewhat more flexible. It causes the command processor to read a file as if it were embedded in the current command file. If @subcmd{CD=YES} is specified, then before including the file, the current directory will be changed to the directory of the included file. The default setting is @samp{CD=NO}. Note that this directory will remain current until it is changed explicitly (with the @cmd{CD} command, or a subsequent @cmd{INSERT} command with the @samp{CD=YES} option). It will not revert to its original setting even after the included file is finished processing. If @subcmd{ERROR=STOP} is specified, errors encountered in the inserted file will cause processing to immediately cease. Otherwise processing will continue at the next command. The default setting is @subcmd{ERROR=CONTINUE}. If @subcmd{SYNTAX=INTERACTIVE} is specified then the syntax contained in the included file must conform to interactive syntax conventions. @xref{Syntax Variants}. The default setting is @subcmd{SYNTAX=BATCH}. @subcmd{ENCODING} optionally specifies the character set used by the included file. Its argument, which is not case-sensitive, must be in one of the following forms: @table @asis @item @subcmd{LOCALE} The encoding used by the system locale, or as overridden by the @cmd{SET} command (@pxref{SET}). On GNU/Linux and other Unix-like systems, environment variables, e.g.@: @env{LANG} or @env{LC_ALL}, determine the system locale. @item @var{charset_name} One of the character set names listed by @acronym{IANA} at @uref{http://www.iana.org/assignments/character-sets}. Some examples are @code{ASCII} (United States), @code{ISO-8859-1} (western Europe), @code{EUC-JP} (Japan), and @code{windows-1252} (Windows). Not all systems support all character sets. @item @code{Auto,@var{encoding}} Automatically detects whether a syntax file is encoded in an Unicode encoding such as UTF-8, UTF-16, or UTF-32. If it is not, then @pspp{} generally assumes that the file is encoded in @var{encoding} (an @acronym{IANA} character set name). However, if @var{encoding} is UTF-8, and the syntax file is not valid UTF-8, @pspp{} instead assumes that the file is encoded in @code{windows-1252}. For best results, @var{encoding} should be an @acronym{ASCII}-compatible encoding (the most common locale encodings are all @acronym{ASCII}-compatible), because encodings that are not @acronym{ASCII} compatible cannot be automatically distinguished from UTF-8. @item @code{Auto} @item @code{Auto,Locale} Automatic detection, as above, with the default encoding taken from the system locale or the setting on @subcmd{SET LOCALE}. @end table When ENCODING is not specified, the default is taken from the @option{--syntax-encoding} command option, if it was specified, and otherwise it is @code{Auto}. @node PERMISSIONS @section PERMISSIONS @vindex PERMISSIONS @cindex mode @cindex file mode @cindex changing file permissions @display PERMISSIONS FILE='@var{file_name}' /PERMISSIONS = @{READONLY,WRITEABLE@}. @end display @cmd{PERMISSIONS} changes the permissions of a file. There is one mandatory subcommand which specifies the permissions to which the file should be changed. If you set a file's permission to @subcmd{READONLY}, then the file will become unwritable either by you or anyone else on the system. If you set the permission to @subcmd{WRITEABLE}, then the file will become writeable by you; the permissions afforded to others will be unchanged. This command cannot be used if the @subcmd{SAFER} (@pxref{SET}) setting is active. @node PRESERVE and RESTORE @section PRESERVE and RESTORE @vindex PRESERVE @vindex RESTORE @display PRESERVE. @dots{} RESTORE. @end display @cmd{PRESERVE} saves all of the settings that @cmd{SET} (@pxref{SET}) can adjust. A later @cmd{RESTORE} command restores those settings. @cmd{PRESERVE} can be nested up to five levels deep. @node SET @section SET @vindex SET @display SET (data input) /BLANKS=@{SYSMIS,'.',number@} /DECIMAL=@{DOT,COMMA@} /FORMAT=@var{fmt_spec} /EPOCH=@{AUTOMATIC,@var{year}@} /RIB=@{NATIVE,MSBFIRST,LSBFIRST,VAX@} /RRB=@{NATIVE,ISL,ISB,IDL,IDB,VF,VD,VG,ZS,ZL@} (interaction) /MXERRS=@var{max_errs} /MXWARNS=@var{max_warnings} /WORKSPACE=@var{workspace_size} (syntax execution) /LOCALE='@var{locale}' /MEXPAND=@{ON,OFF@} /MITERATE=@var{max_iterations} /MNEST=@var{max_nest} /MPRINT=@{ON,OFF@} /MXLOOPS=@var{max_loops} /SEED=@{RANDOM,@var{seed_value}@} /UNDEFINED=@{WARN,NOWARN@} (data output) /CC@{A,B,C,D,E@}=@{'@var{npre},@var{pre},@var{suf},@var{nsuf}','@var{npre}.@var{pre}.@var{suf}.@var{nsuf}'@} /DECIMAL=@{DOT,COMMA@} /FORMAT=@var{fmt_spec} /WIB=@{NATIVE,MSBFIRST,LSBFIRST,VAX@} /WRB=@{NATIVE,ISL,ISB,IDL,IDB,VF,VD,VG,ZS,ZL@} (output routing) /ERRORS=@{ON,OFF,TERMINAL,LISTING,BOTH,NONE@} /MESSAGES=@{ON,OFF,TERMINAL,LISTING,BOTH,NONE@} /PRINTBACK=@{ON,OFF,TERMINAL,LISTING,BOTH,NONE@} /RESULTS=@{ON,OFF,TERMINAL,LISTING,BOTH,NONE@} (output driver options) /HEADERS=@{NO,YES,BLANK@} /LENGTH=@{NONE,@var{n_lines}@} /MORE=@{ON,OFF@} /WIDTH=@{NARROW,WIDTH,@var{n_characters}@} /TNUMBERS=@{VALUES,LABELS,BOTH@} /TVARS=@{NAMES,LABELS,BOTH@} (logging) /JOURNAL=@{ON,OFF@} ['@var{file_name}'] (system files) /COMPRESSION=@{ON,OFF@} /SCOMPRESSION=@{ON,OFF@} (miscellaneous) /SAFER=ON /LOCALE='@var{string}' (obsolete settings accepted for compatibility, but ignored) /BOXSTRING=@{'@var{xxx}','@var{xxxxxxxxxxx}'@} /CASE=@{UPPER,UPLOW@} /CPI=cpi_value /HIGHRES=@{ON,OFF@} /HISTOGRAM='@var{c}' /LOWRES=@{AUTO,ON,OFF@} /LPI=@var{lpi_value} /MENUS=@{STANDARD,EXTENDED@} /MXMEMORY=@var{max_memory} /SCRIPTTAB='c' /TB1=@{'@var{xxx}','@var{xxxxxxxxxxx}'@} /TBFONTS='@var{string}' /XSORT=@{YES,NO@} @end display @cmd{SET} allows the user to adjust several parameters relating to @pspp{}'s execution. Since there are many subcommands to this command, its subcommands will be examined in groups. For subcommands that take boolean values, @subcmd{ON} and @subcmd{YES} are synonymous, as are @subcmd{OFF} and @subcmd{NO}, when used as subcommand values. The data input subcommands affect the way that data is read from data files. The data input subcommands are @table @asis @item BLANKS @anchor{SET BLANKS} This is the value assigned to an item data item that is empty or contains only white space. An argument of SYSMIS or '.' will cause the system-missing value to be assigned to null items. This is the default. Any real value may be assigned. @item DECIMAL @anchor{SET DECIMAL} This value may be set to @subcmd{DOT} or @subcmd{COMMA}. Setting it to @subcmd{DOT} causes the decimal point character to be @samp{.} and the grouping character to be @samp{,}. Setting it to @subcmd{COMMA} causes the decimal point character to be @samp{,} and the grouping character to be @samp{.}. The default value is determined from the system locale. @item FORMAT Allows the default numeric input/output format to be specified. The default is F8.2. @xref{Input and Output Formats}. @item EPOCH @anchor{SET EPOCH} Specifies the range of years used when a 2-digit year is read from a data file or used in a date construction expression (@pxref{Date Construction}). If a 4-digit year is specified for the epoch, then 2-digit years are interpreted starting from that year, known as the epoch. If @subcmd{AUTOMATIC} (the default) is specified, then the epoch begins 69 years before the current date. @item RIB @anchor{SET RIB} @pspp{} extension to set the byte ordering (endianness) used for reading data in IB or PIB format (@pxref{Binary and Hexadecimal Numeric Formats}). In @subcmd{MSBFIRST} ordering, the most-significant byte appears at the left end of a IB or PIB field. In @subcmd{LSBFIRST} ordering, the least-significant byte appears at the left end. @subcmd{VAX} ordering is like @subcmd{MSBFIRST}, except that each pair of bytes is in reverse order. @subcmd{NATIVE}, the default, is equivalent to @subcmd{MSBFIRST} or @subcmd{LSBFIRST} depending on the native format of the machine running @pspp{}. @item RRB @anchor{SET RRB} @pspp{} extension to set the floating-point format used for reading data in RB format (@pxref{Binary and Hexadecimal Numeric Formats}). The possibilities are: @table @asis @item NATIVE The native format of the machine running @pspp{}. Equivalent to either IDL or IDB. @item ISL 32-bit IEEE 754 single-precision floating point, in little-endian byte order. @item ISB 32-bit IEEE 754 single-precision floating point, in big-endian byte order. @item IDL 64-bit IEEE 754 double-precision floating point, in little-endian byte order. @item IDB 64-bit IEEE 754 double-precision floating point, in big-endian byte order. @item VF 32-bit VAX F format, in VAX-endian byte order. @item VD 64-bit VAX D format, in VAX-endian byte order. @item VG 64-bit VAX G format, in VAX-endian byte order. @item ZS 32-bit IBM Z architecture short format hexadecimal floating point, in big-endian byte order. @item ZL 64-bit IBM Z architecture long format hexadecimal floating point, in big-endian byte order. Z architecture also supports IEEE 754 floating point. The ZS and ZL formats are only for use with very old input files. @end table The default is NATIVE. @end table Interaction subcommands affect the way that @pspp{} interacts with an online user. The interaction subcommands are @table @asis @item MXERRS The maximum number of errors before @pspp{} halts processing of the current command file. The default is 50. @item MXWARNS The maximum number of warnings + errors before @pspp{} halts processing the current command file. The special value of zero means that all warning situations should be ignored. No warnings will be issued, except a single initial warning advising the user that warnings will not be given. The default value is 100. @end table Syntax execution subcommands control the way that @pspp{} commands execute. The syntax execution subcommands are @table @asis @item LOCALE Overrides the system locale for the purpose of reading and writing syntax and data files. The argument should be a locale name in the general form @code{@var{language}_@var{country}.@var{encoding}}, where @var{language} and @var{country} are 2-character language and country abbreviations, respectively, and @var{encoding} is an @acronym{IANA} character set name. Example locales are @code{en_US.UTF-8} (UTF-8 encoded English as spoken in the United States) and @code{ja_JP.EUC-JP} (EUC-JP encoded Japanese as spoken in Japan). @item MEXPAND @itemx MITERATE @itemx MNEST @itemx MPRINT Currently not used. @item MXLOOPS The maximum number of iterations for an uncontrolled loop (@pxref{LOOP}). The default @var{max_loops} is 40. @item SEED The initial pseudo-random number seed. Set to a real number or to RANDOM, which will obtain an initial seed from the current time of day. @item UNDEFINED Currently not used. @item WORKSPACE The maximum amount of memory that @pspp{} will use to store data being processed. If memory in excess of the workspace size is required, then @pspp{} will start to use temporary files to store the data. Setting a higher value will, in general, mean procedures will run faster, but may cause other applications to run slower. On platforms without virtual memory management, setting a very large workspace may cause @pspp{} to abort. @cindex workspace @cindex memory, amount used to store cases @end table Data output subcommands affect the format of output data. These subcommands are @table @asis @item CCA @itemx CCB @itemx CCC @itemx CCD @itemx CCE @anchor{CCx Settings} Set up custom currency formats. @xref{Custom Currency Formats}, for details. @item DECIMAL The default @subcmd{DOT} setting causes the decimal point character to be @samp{.}. A setting of @subcmd{COMMA} causes the decimal point character to be @samp{,}. @item FORMAT Allows the default numeric input/output format to be specified. The default is F8.2. @xref{Input and Output Formats}. @item WIB @anchor{SET WIB} @pspp{} extension to set the byte ordering (endianness) used for writing data in IB or PIB format (@pxref{Binary and Hexadecimal Numeric Formats}). In @subcmd{MSBFIRST} ordering, the most-significant byte appears at the left end of a IB or PIB field. In @subcmd{LSBFIRST} ordering, the least-significant byte appears at the left end. @subcmd{VAX} ordering is like @subcmd{MSBFIRST}, except that each pair of bytes is in reverse order. @subcmd{NATIVE}, the default, is equivalent to @subcmd{MSBFIRST} or @subcmd{LSBFIRST} depending on the native format of the machine running @pspp{}. @item WRB @anchor{SET WRB} @pspp{} extension to set the floating-point format used for writing data in RB format (@pxref{Binary and Hexadecimal Numeric Formats}). The choices are the same as @subcmd{SET RIB}. The default is @subcmd{NATIVE}. @end table In the @pspp{} text-based interface, the output routing subcommands affect where output is sent. The following values are allowed for each of these subcommands: @table @asis @item OFF @item NONE Discard this kind of output. @item TERMINAL Write this output to the terminal, but not to listing files and other output devices. @item LISTING Write this output to listing files and other output devices, but not to the terminal. @item ON @itemx BOTH Write this type of output to all output devices. @end table These output routing subcommands are: @table @asis @item ERRORS Applies to error and warning messages. The default is @subcmd{BOTH}. @item MESSAGES Applies to notes. The default is @subcmd{BOTH}. @item PRINTBACK Determines whether the syntax used for input is printed back as part of the output. The default is @subcmd{NONE}. @item RESULTS Applies to everything not in one of the above categories, such as the results of statistical procedures. The default is @subcmd{BOTH}. @end table These subcommands have no effect on output in the @pspp{} GUI environment. Output driver option subcommands affect output drivers' settings. These subcommands are @table @asis @item HEADERS @itemx LENGTH @itemx MORE @itemx WIDTH @itemx TNUMBERS The @subcmd{TNUMBERS} option sets the way in which values are displayed in output tables. The valid settings are @subcmd{VALUES}, @subcmd{LABELS} and @subcmd{BOTH}. If @subcmd{TNUMBERS} is set to @subcmd{VALUES}, then all values are displayed with their literal value (which for a numeric value is a number and for a string value an alphanumeric string). If @subcmd{TNUMBERS} is set to @subcmd{LABELS}, then values are displayed using their assigned labels if any. (@xref{VALUE LABELS}.) If the a value has no label, then it will be displayed using its literal value. If @subcmd{TNUMBERS} is set to @subcmd{BOTH}, then values will be displayed with both their label (if any) and their literal value in parentheses. @itemx TVARS The @subcmd{TVARS} option sets the way in which variables are displayed in output tables. The valid settings are @subcmd{NAMES}, @subcmd{LABELS} and @subcmd{BOTH}. If @subcmd{TVARS} is set to @subcmd{NAMES}, then all variables are displayed using their names. If @subcmd{TVARS} is set to @subcmd{LABELS}, then variables are displayed using their label if one has been set. If no label has been set, then the name will be used. (@xref{VARIABLE LABELS}.) If @subcmd{TVARS} is set to @subcmd{BOTH}, then variables will be displayed with both their label (if any) and their name in parentheses. @end table @cindex headers @cindex length @cindex more @cindex pager @cindex width @cindex tnumbers Logging subcommands affect logging of commands executed to external files. These subcommands are @table @asis @item JOURNAL @itemx LOG These subcommands, which are synonyms, control the journal. The default is @subcmd{ON}, which causes commands entered interactively to be written to the journal file. Commands included from syntax files that are included interactively and error messages printed by @pspp{} are also written to the journal file, prefixed by @samp{>}. @subcmd{OFF} disables use of the journal. The journal is named @file{pspp.jnl} by default. A different name may be specified. @end table System file subcommands affect the default format of system files produced by @pspp{}. These subcommands are @table @asis @item COMPRESSION Not currently used. @item SCOMPRESSION Whether system files created by @cmd{SAVE} or @cmd{XSAVE} are compressed by default. The default is @subcmd{ON}. @end table Security subcommands affect the operations that commands are allowed to perform. The security subcommands are @table @asis @item SAFER Setting this option disables the following operations: @itemize @bullet @item The @cmd{ERASE} command. @item The @cmd{HOST} command. @item The @cmd{PERMISSIONS} command. @item Pipes (file names beginning or ending with @samp{|}). @end itemize Be aware that this setting does not guarantee safety (commands can still overwrite files, for instance) but it is an improvement. When set, this setting cannot be reset during the same session, for obvious security reasons. @item LOCALE @cindex locale @cindex encoding, characters This item is used to set the default character encoding. The encoding may be specified either as an encoding name or alias (see @url{http://www.iana.org/assignments/character-sets}), or as a locale name. If given as a locale name, only the character encoding of the locale is relevant. System files written by @pspp{} will use this encoding. System files read by @pspp{}, for which the encoding is unknown, will be interpreted using this encoding. The full list of valid encodings and locale names/alias are operating system dependent. The following are all examples of acceptable syntax on common GNU/Linux systems. @example SET LOCALE='iso-8859-1'. SET LOCALE='ru_RU.cp1251'. SET LOCALE='japanese'. @end example Contrary to the intuition, this command does not affect any aspect of the system's locale. @end table @node SHOW @section SHOW @vindex SHOW @display SHOW [ALL] [BLANKS] [CC] [CCA] [CCB] [CCC] [CCD] [CCE] [COPYING] [DECIMALS] [DIRECTORY] [ENVIRONMENT] [FORMAT] [LENGTH] [MXERRS] [MXLOOPS] [MXWARNS] [N] [SCOMPRESSION] [TEMPDIR] [UNDEFINED] [VERSION] [WARRANTY] [WEIGHT] [WIDTH] @end display @cmd{SHOW} can be used to display the current state of @pspp{}'s execution parameters. Parameters that can be changed using @cmd{SET} (@pxref{SET}), can be examined using @cmd{SHOW} using the subcommand with the same name. @cmd{SHOW} supports the following additional subcommands: @table @bullet @item @subcmd{ALL} Show all settings. @item @subcmd{CC} Show all custom currency settings (@subcmd{CCA} through @subcmd{CCE}). @item @subcmd{DIRECTORY} Shows the current working directory. @item @subcmd{ENVIRONMENT} Shows the operating system details. @item @subcmd{N} Reports the number of cases in the active dataset. The reported number is not weighted. If no dataset is defined, then @samp{Unknown} will be reported. @item @subcmd{TEMPDIR} Shows the path of the directory where temporary files will be stored. @item @subcmd{VERSION} Shows the version of this installation of @pspp{}. @item @subcmd{WARRANTY} Show details of the lack of warranty for @pspp{}. @item @subcmd{COPYING} / @subcmd{LICENSE} Display the terms of @pspp{}'s copyright licence (@pxref{License}). @end table Specifying @cmd{SHOW} without any subcommands is equivalent to @subcmd{SHOW ALL}. @node SUBTITLE @section SUBTITLE @vindex SUBTITLE @display SUBTITLE '@var{subtitle_string}'. or SUBTITLE @var{subtitle_string}. @end display @cmd{SUBTITLE} provides a subtitle to a particular @pspp{} run. This subtitle appears at the top of each output page below the title, if headers are enabled on the output device. Specify a subtitle as a string in quotes. The alternate syntax that did not require quotes is now obsolete. If it is used then the subtitle is converted to all uppercase. @node TITLE @section TITLE @vindex TITLE @display TITLE '@var{title_string}'. or TITLE @var{title_string}. @end display @cmd{TITLE} provides a title to a particular @pspp{} run. This title appears at the top of each output page, if headers are enabled on the output device. Specify a title as a string in quotes. The alternate syntax that did not require quotes is now obsolete. If it is used then the title is converted to all uppercase. pspp-master/doc/variables.texi000066400000000000000000000571751177044323000167610ustar00rootroot00000000000000@node Variable Attributes @chapter Manipulating variables The variables in the active dataset dictionary are important. There are several utility functions for examining and adjusting them. @menu * ADD VALUE LABELS:: Add value labels to variables. * DELETE VARIABLES:: Delete variables. * DISPLAY:: Display information about the active dataset. * FORMATS:: Set print and write formats. * LEAVE:: Don't clear variables between cases. * MISSING VALUES:: Set missing values for variables. * MODIFY VARS:: Rename, reorder, and drop variables. * MRSETS:: Add, modify, and list multiple response sets. * NUMERIC:: Create new numeric variables. * PRINT FORMATS:: Set variable print formats. * RENAME VARIABLES:: Rename variables. * VALUE LABELS:: Set value labels for variables. * STRING:: Create new string variables. * VARIABLE ATTRIBUTE:: Set custom attributes on variables. * VARIABLE LABELS:: Set variable labels for variables. * VARIABLE ALIGNMENT:: Set the alignment for display. * VARIABLE WIDTH:: Set the display width. * VARIABLE LEVEL:: Set the measurement level. * VECTOR:: Declare an array of variables. * WRITE FORMATS:: Set variable write formats. @end menu @node ADD VALUE LABELS @section ADD VALUE LABELS @vindex ADD VALUE LABELS @display ADD VALUE LABELS /@var{var_list} @var{value} '@var{label}' [@var{value} '@var{label}']@dots{} @end display @cmd{ADD VALUE LABELS} has the same syntax and purpose as @cmd{VALUE LABELS} (@pxref{VALUE LABELS}), but it does not clear value labels from the variables before adding the ones specified. @node DELETE VARIABLES @section DELETE VARIABLES @vindex DELETE VARIABLES @display DELETE VARIABLES @var{var_list}. @end display @cmd{DELETE VARIABLES} deletes the specified variables from the dictionary. It may not be used to delete all variables from the dictionary; use @cmd{NEW FILE} to do that (@pxref{NEW FILE}). @cmd{DELETE VARIABLES} should not be used after defining transformations but before executing a procedure. If it is used in such a context, it causes the data to be read. If it is used while @cmd{TEMPORARY} is in effect, it causes the temporary transformations to become permanent. @node DISPLAY @section DISPLAY @vindex DISPLAY @display DISPLAY [SORTED] NAMES [[/VARIABLES=]@var{var_list}]. DISPLAY [SORTED] INDEX [[/VARIABLES=]@var{var_list}]. DISPLAY [SORTED] LABELS [[/VARIABLES=]@var{var_list}]. DISPLAY [SORTED] VARIABLES [[/VARIABLES=]@var{var_list}]. DISPLAY [SORTED] DICTIONARY [[/VARIABLES=]@var{var_list}]. DISPLAY [SORTED] SCRATCH [[/VARIABLES=]@var{var_list}]. DISPLAY [SORTED] ATTRIBUTES [[/VARIABLES=]@var{var_list}]. DISPLAY [SORTED] @@ATTRIBUTES [[/VARIABLES=]@var{var_list}]. DISPLAY [SORTED] VECTORS. @end display @cmd{DISPLAY} displays information about the active dataset. A variety of different forms of information can be requested. The following keywords primarily cause information about variables to be displayed. With these keywords, by default information is displayed about all variable in the active dataset, in the order that variables occur in the active dataset dictionary. The @subcmd{SORTED} keyword causes output to be sorted alphabetically by variable name. The @subcmd{VARIABLES} subcommand limits output to the specified variables. @table @asis @item NAMES The variables' names are displayed. @item INDEX The variables' names are displayed along with a value describing their position within the active dataset dictionary. @item LABELS Variable names, positions, and variable labels are displayed. @item VARIABLES Variable names, positions, print and write formats, and missing values are displayed. @item DICTIONARY Variable names, positions, print and write formats, missing values, variable labels, and value labels are displayed. @item SCRATCH Variable names are displayed, for scratch variables only (@pxref{Scratch Variables}). @item ATTRIBUTES @itemx @@ATTRIBUTES Datafile and variable attributes are displayed. The first form of the command omits those attributes whose names begin with @code{@@} or @code{$@@}. In the second for, all datafile and variable attributes are displayed. @end table With the @code{VECTOR} keyword, @cmd{DISPLAY} lists all the currently declared vectors. If the @subcmd{SORTED} keyword is given, the vectors are listed in alphabetical order; otherwise, they are listed in textual order of definition within the @pspp{} syntax file. For related commands, see @ref{DISPLAY DOCUMENTS} and @ref{DISPLAY FILE LABEL}. @node FORMATS @section FORMATS @vindex FORMATS @display FORMATS @var{var_list} (@var{fmt_spec}) [@var{var_list} (@var{fmt_spec})]@dots{}. @end display @cmd{FORMATS} set both print and write formats for the specified variables to the specified format specification. @xref{Input and Output Formats}. Specify a list of variables followed by a format specification in parentheses. The print and write formats of the specified variables will be changed. All of the variables listed together must have the same type and, for string variables, the same width. Additional lists of variables and formats may be included following the first one. @cmd{FORMATS} takes effect immediately. It is not affected by conditional and looping structures such as @cmd{DO IF} or @cmd{LOOP}. @node LEAVE @section LEAVE @vindex LEAVE @display LEAVE @var{var_list}. @end display @cmd{LEAVE} prevents the specified variables from being reinitialized whenever a new case is processed. Normally, when a data file is processed, every variable in the active dataset is initialized to the system-missing value or spaces at the beginning of processing for each case. When a variable has been specified on @cmd{LEAVE}, this is not the case. Instead, that variable is initialized to 0 (not system-missing) or spaces for the first case. After that, it retains its value between cases. This becomes useful for counters. For instance, in the example below the variable @code{SUM} maintains a running total of the values in the @code{ITEM} variable. @example DATA LIST /ITEM 1-3. COMPUTE SUM=SUM+ITEM. PRINT /ITEM SUM. LEAVE SUM BEGIN DATA. 123 404 555 999 END DATA. @end example @noindent Partial output from this example: @example 123 123.00 404 527.00 555 1082.00 999 2081.00 @end example It is best to use @cmd{LEAVE} command immediately before invoking a procedure command, because the left status of variables is reset by certain transformations---for instance, @cmd{COMPUTE} and @cmd{IF}. Left status is also reset by all procedure invocations. @node MISSING VALUES @section MISSING VALUES @vindex MISSING VALUES @display MISSING VALUES @var{var_list} (@var{missing_values}). where @var{missing_values} takes one of the following forms: @var{num1} @var{num1}, @var{num2} @var{num1}, @var{num2}, @var{num3} @var{num1} THRU @var{num2} @var{num1} THRU @var{num2}, @var{num3} @var{string1} @var{string1}, @var{string2} @var{string1}, @var{string2}, @var{string3} As part of a range, @subcmd{LO} or @subcmd{LOWEST} may take the place of @var{num1}; @subcmd{HI} or @subcmd{HIGHEST} may take the place of @var{num2}. @end display @cmd{MISSING VALUES} sets user-missing values for numeric and string variables. Long string variables may have missing values, but characters after the first 8 bytes of the missing value must be spaces. Specify a list of variables, followed by a list of their user-missing values in parentheses. Up to three discrete values may be given, or, for numeric variables only, a range of values optionally accompanied by a single discrete value. Ranges may be open-ended on one end, indicated through the use of the keyword @subcmd{LO} or @subcmd{LOWEST} or @subcmd{HI} or @subcmd{HIGHEST}. The @cmd{MISSING VALUES} command takes effect immediately. It is not affected by conditional and looping constructs such as @cmd{DO IF} or @cmd{LOOP}. @node MODIFY VARS @section MODIFY VARS @vindex MODIFY VARS @display MODIFY VARS /REORDER=@{FORWARD,BACKWARD@} @{POSITIONAL,ALPHA@} (@var{var_list})@dots{} /RENAME=(@var{old_names}=@var{new_names})@dots{} /@{DROP,KEEP@}=@var{var_list} /MAP @end display @cmd{MODIFY VARS} reorders, renames, and deletes variables in the active dataset. At least one subcommand must be specified, and no subcommand may be specified more than once. @subcmd{DROP} and @subcmd{KEEP} may not both be specified. The @subcmd{REORDER} subcommand changes the order of variables in the active dataset. Specify one or more lists of variable names in parentheses. By default, each list of variables is rearranged into the specified order. To put the variables into the reverse of the specified order, put keyword @subcmd{BACKWARD} before the parentheses. To put them into alphabetical order in the dictionary, specify keyword @subcmd{ALPHA} before the parentheses. @subcmd{BACKWARD} and @subcmd{ALPHA} may also be combined. To rename variables in the active dataset, specify @subcmd{RENAME}, an equals sign (@samp{=}), and lists of the old variable names and new variable names separated by another equals sign within parentheses. There must be the same number of old and new variable names. Each old variable is renamed to the corresponding new variable name. Multiple parenthesized groups of variables may be specified. The @subcmd{DROP} subcommand deletes a specified list of variables from the active dataset. The @subcmd{KEEP} subcommand keeps the specified list of variables in the active dataset. Any unlisted variables are deleted from the active dataset. @subcmd{MAP} is currently ignored. If either @subcmd{DROP} or @subcmd{KEEP} is specified, the data is read; otherwise it is not. @cmd{MODIFY VARS} may not be specified following @cmd{TEMPORARY} (@pxref{TEMPORARY}). @node MRSETS @section MRSETS @vindex MRSETS @display MRSETS /MDGROUP NAME=@var{name} VARIABLES=@var{var_list} VALUE=@var{value} [CATEGORYLABELS=@{VARLABELS,COUNTEDVALUES@}] [@{LABEL='@var{label}',LABELSOURCE=VARLABEL@}] /MCGROUP NAME=@var{name} VARIABLES=@var{var_list} [LABEL='@var{label}'] /DELETE NAME=@{[@var{names}],ALL@} /DISPLAY NAME=@{[@var{names}],ALL@} @end display @cmd{MRSETS} creates, modifies, deletes, and displays multiple response sets. A multiple response set is a set of variables that represent multiple responses to a single survey question in one of the two following ways: @itemize @bullet @item A @dfn{multiple dichotomy set} is analogous to a survey question with a set of checkboxes. Each variable in the set is treated in a Boolean fashion: one value (the "counted value") means that the box was checked, and any other value means that it was not. @item A @dfn{multiple category set} represents a survey question where the respondent is instructed to list up to @var{n} choices. Each variable represents one of the responses. @end itemize Any number of subcommands may be specified in any order. The @subcmd{MDGROUP} subcommand creates a new multiple dichotomy set or replaces an existing multiple response set. The @subcmd{NAME}, @subcmd{VARIABLES}, and @subcmd{VALUE} specifications are required. The others are optional: @itemize @bullet @item @var{NAME} specifies the name used in syntax for the new multiple dichotomy set. The name must begin with @samp{$}; it must otherwise follow the rules for identifiers (@pxref{Tokens}). @item @subcmd{VARIABLES} specifies the variables that belong to the set. At least two variables must be specified. The variables must be all string or all numeric. @item @subcmd{VALUE} specifies the counted value. If the variables are numeric, the value must be an integer. If the variables are strings, then the value must be a string that is no longer than the shortest of the variables in the set (ignoring trailing spaces). @item @subcmd{CATEGORYLABELS} optionally specifies the source of the labels for each category in the set: @itemize @minus @item @subcmd{VARLABELS}, the default, uses variable labels or, for variables without variable labels, variable names. @pspp{} warns if two variables have the same variable label, since these categories cannot be distinguished in output. @item @subcmd{COUNTEDVALUES} instead uses each variable's value label for the counted value. @pspp{} warns if two variables have the same value label for the counted value or if one of the variables lacks a value label, since such categories cannot be distinguished in output. @end itemize @item @subcmd{LABEL} optionally specifies a label for the multiple response set. If neither @subcmd{LABEL} nor @subcmd{LABELSOURCE=VARLABEL} is specified, the set is unlabeled. @item @subcmd{LABELSOURCE=VARLABEL} draws the multiple response set's label from the first variable label among the variables in the set; if none of the variables has a label, the name of the first variable is used. @subcmd{LABELSOURCE=VARLABEL} must be used with @subcmd{CATEGORYLABELS=COUNTEDVALUES}. It is mutually exclusive with @subcmd{LABEL}. @end itemize The @subcmd{MCGROUP} subcommand creates a new multiple category set or replaces an existing multiple response set. The @subcmd{NAME} and @subcmd{VARIABLES} specifications are required, and @subcmd{LABEL} is optional. Their meanings are as described above in @subcmd{MDGROUP}. @pspp{} warns if two variables in the set have different value labels for a single value, since each of the variables in the set should have the same possible categories. The @subcmd{DELETE} subcommand deletes multiple response groups. A list of groups may be named within a set of required square brackets, or ALL may be used to delete all groups. The @subcmd{DISPLAY} subcommand displays information about defined multiple response sets. Its syntax is the same as the @subcmd{DELETE} subcommand. Multiple response sets are saved to and read from system files by, e.g., the @cmd{SAVE} and @cmd{GET} command. Otherwise, multiple response sets are currently used only by third party software. @node NUMERIC @section NUMERIC @vindex NUMERIC @display NUMERIC /@var{var_list} [(@var{fmt_spec})]. @end display @cmd{NUMERIC} explicitly declares new numeric variables, optionally setting their output formats. Specify a slash (@samp{/}), followed by the names of the new numeric variables. If you wish to set their output formats, follow their names by an output format specification in parentheses (@pxref{Input and Output Formats}); otherwise, the default is F8.2. Variables created with @cmd{NUMERIC} are initialized to the system-missing value. @node PRINT FORMATS @section PRINT FORMATS @vindex PRINT FORMATS @display PRINT FORMATS @var{var_list} (@var{fmt_spec}) [@var{var_list} (@var{fmt_spec})]@dots{}. @end display @cmd{PRINT FORMATS} sets the print formats for the specified variables to the specified format specification. Its syntax is identical to that of @cmd{FORMATS} (@pxref{FORMATS}), but @cmd{PRINT FORMATS} sets only print formats, not write formats. @node RENAME VARIABLES @section RENAME VARIABLES @vindex RENAME VARIABLES @display RENAME VARIABLES (@var{old_names}=@var{new_names})@dots{} . @end display @cmd{RENAME VARIABLES} changes the names of variables in the active dataset. Specify lists of the old variable names and new variable names, separated by an equals sign (@samp{=}), within parentheses. There must be the same number of old and new variable names. Each old variable is renamed to the corresponding new variable name. Multiple parenthesized groups of variables may be specified. @cmd{RENAME VARIABLES} takes effect immediately. It does not cause the data to be read. @cmd{RENAME VARIABLES} may not be specified following @cmd{TEMPORARY} (@pxref{TEMPORARY}). @node VALUE LABELS @section VALUE LABELS @vindex VALUE LABELS @display VALUE LABELS /@var{var_list} @var{value} '@var{label}' [@var{value} '@var{label}']@dots{} @end display @cmd{VALUE LABELS} allows values of numeric and short string variables to be associated with labels. In this way, a short value can stand for a long value. To set up value labels for a set of variables, specify the variable names after a slash (@samp{/}), followed by a list of values and their associated labels, separated by spaces. Value labels in output are normally broken into lines automatically. Put @samp{\n} in a label string to force a line break at that point. The label may still be broken into lines at additional points. Before @cmd{VALUE LABELS} is executed, any existing value labels are cleared from the variables specified. Use @cmd{ADD VALUE LABELS} (@pxref{ADD VALUE LABELS}) to add value labels without clearing those already present. @node STRING @section STRING @vindex STRING @display STRING /@var{var_list} (@var{fmt_spec}). @end display @cmd{STRING} creates new string variables for use in transformations. Specify a slash (@samp{/}), followed by the names of the string variables to create and the desired output format specification in parentheses (@pxref{Input and Output Formats}). Variable widths are implicitly derived from the specified output formats. Created variables are initialized to spaces. @node VARIABLE ATTRIBUTE @section VARIABLE ATTRIBUTE @vindex VARIABLE ATTRIBUTE @display VARIABLE ATTRIBUTE VARIABLES=@var{var_list} ATTRIBUTE=@var{name}('@var{value}') [@var{name}('@var{value}')]@dots{} ATTRIBUTE=@var{name}@b{[}@var{index}@b{]}('@var{value}') [@var{name}@b{[}@var{index}@b{]}('@var{value}')]@dots{} DELETE=@var{name} [@var{name}]@dots{} DELETE=@var{name}@b{[}@var{index}@b{]} [@var{name}@b{[}@var{index}@b{]}]@dots{} @end display @cmd{VARIABLE ATTRIBUTE} adds, modifies, or removes user-defined attributes associated with variables in the active dataset. Custom variable attributes are not interpreted by @pspp{}, but they are saved as part of system files and may be used by other software that reads them. The required @subcmd{VARIABLES} subcommand must come first. Specify the variables to which the following @subcmd{ATTRIBUTE} or @subcmd{DELETE} subcommand should apply. Use the @subcmd{ATTRIBUTE} subcommand to add or modify custom variable attributes. Specify the name of the attribute as an identifier (@pxref{Tokens}), followed by the desired value, in parentheses, as a quoted string. The specified attributes are then added or modified in the variables specified on @subcmd{VARIABLES}. Attribute names that begin with @code{$} are reserved for @pspp{}'s internal use, and attribute names that begin with @code{@@} or @code{$@@} are not displayed by most @pspp{} commands that display other attributes. Other attribute names are not treated specially. Attributes may also be organized into arrays. To assign to an array element, add an integer array index enclosed in square brackets (@code{[} and @code{]}) between the attribute name and value. Array indexes start at 1, not 0. An attribute array that has a single element (number 1) is not distinguished from a non-array attribute. Use the @subcmd{DELETE} subcommand to delete an attribute from the variable specified on @subcmd{VARIABLES}. Specify an attribute name by itself to delete an entire attribute, including all array elements for attribute arrays. Specify an attribute name followed by an array index in square brackets to delete a single element of an attribute array. In the latter case, all the array elements numbered higher than the deleted element are shifted down, filling the vacated position. To associate custom attributes with the entire active dataset, instead of with particular variables, use @cmd{DATAFILE ATTRIBUTE} (@pxref{DATAFILE ATTRIBUTE}) instead. @cmd{VARIABLE ATTRIBUTE} takes effect immediately. It is not affected by conditional and looping structures such as @cmd{DO IF} or @cmd{LOOP}. @node VARIABLE LABELS @section VARIABLE LABELS @vindex VARIABLE LABELS @display VARIABLE LABELS @var{var_list} '@var{var_label}' [ /@var{var_list} '@var{var_label}'] . . . [ /@var{var_list} '@var{var_label}'] @end display @cmd{VARIABLE LABELS} associates explanatory names with variables. This name, called a @dfn{variable label}, is displayed by statistical procedures. To assign a variable label to a group of variables, specify a list of variable names and the variable label as a string. To assign different labels to different variables in the same command, precede the subsequent variable list with a slash (@samp{/}). @node VARIABLE ALIGNMENT @section VARIABLE ALIGNMENT @vindex VARIABLE ALIGNMENT @display VARIABLE ALIGNMENT @var{var_list} ( LEFT | RIGHT | CENTER ) [ /@var{var_list} ( LEFT | RIGHT | CENTER ) ] . . . [ /@var{var_list} ( LEFT | RIGHT | CENTER ) ] @end display @cmd{VARIABLE ALIGNMENT} sets the alignment of variables for display editing purposes. This only has effect for third party software. It does not affect the display of variables in the @pspp{} output. @node VARIABLE WIDTH @section VARIABLE WIDTH @vindex VARIABLE WIDTH @display VARIABLE WIDTH @var{var_list} (width) [ /@var{var_list} (width) ] . . . [ /@var{var_list} (width) ] @end display @cmd{VARIABLE WIDTH} sets the column width of variables for display editing purposes. This only affects third party software. It does not affect the display of variables in the @pspp{} output. @node VARIABLE LEVEL @section VARIABLE LEVEL @vindex VARIABLE LEVEL @display VARIABLE LEVEL @var{var_list} ( SCALE | NOMINAL | ORDINAL ) [ /@var{var_list} ( SCALE | NOMINAL | ORDINAL ) ] . . . [ /@var{var_list} ( SCALE | NOMINAL | ORDINAL ) ] @end display @cmd{VARIABLE LEVEL} sets the measurement level of variables. Currently, this has no effect except for certain third party software. @node VECTOR @section VECTOR @vindex VECTOR @display Two possible syntaxes: VECTOR @var{vec_name}=@var{var_list}. VECTOR @var{vec_name_list}(@var{count} [@var{format}]). @end display @cmd{VECTOR} allows a group of variables to be accessed as if they were consecutive members of an array with a vector(index) notation. To make a vector out of a set of existing variables, specify a name for the vector followed by an equals sign (@samp{=}) and the variables to put in the vector. All the variables in the vector must be the same type. String variables in a vector must all have the same width. To make a vector and create variables at the same time, specify one or more vector names followed by a count in parentheses. This will cause variables named @code{@var{vec}1} through @code{@var{vec}@var{count}} to be created as numeric variables. By default, the new variables have print and write format F8.2, but an alternate format may be specified inside the parentheses before or after the count and separated from it by white space or a comma. Variable names including numeric suffixes may not exceed 64 characters in length, and none of the variables may exist prior to @cmd{VECTOR}. Vectors created with @cmd{VECTOR} disappear after any procedure or procedure-like command is executed. The variables contained in the vectors remain, unless they are scratch variables (@pxref{Scratch Variables}). Variables within a vector may be referenced in expressions using @code{vector(index)} syntax. @node WRITE FORMATS @section WRITE FORMATS @vindex WRITE FORMATS @display WRITE FORMATS @var{var_list} (@var{fmt_spec}) [@var{var_list} (@var{fmt_spec})]@dots{}. @end display @cmd{WRITE FORMATS} sets the write formats for the specified variables to the specified format specification. Its syntax is identical to that of @cmd{FORMATS} (@pxref{FORMATS}), but @cmd{WRITE FORMATS} sets only write formats, not print formats. pspp-master/examples/000077500000000000000000000000001177044323000151505ustar00rootroot00000000000000pspp-master/examples/.gitignore000066400000000000000000000000251177044323000171350ustar00rootroot00000000000000Makefile Makefile.in pspp-master/examples/OChangeLog000066400000000000000000000006611177044323000170440ustar00rootroot00000000000000Tue Apr 4 20:19:48 2006 Ben Pfaff * automake.mk: Add missing \ to definition. Sun Aug 9 11:16:13 1998 Ben Pfaff * descriptives.stat: Renamed descript.stat. Sat Aug 8 00:28:24 1998 Ben Pfaff * New directory. * descriptives.stat: New file. ---------------------------------------------------------------------- Local Variables: mode: change-log version-control: never End: pspp-master/examples/automake.mk000066400000000000000000000005261177044323000173120ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in -*- makefile -*- examplesdir = $(pkgdatadir)/examples examples_DATA = \ examples/descript.sps \ examples/hotel.sav \ examples/physiology.sav \ examples/repairs.sav \ examples/regress.sps \ examples/regress_categorical.sps EXTRA_DIST += examples/OChangeLog $(examples_DATA) pspp-master/examples/descript.sps000066400000000000000000000005761177044323000175240ustar00rootroot00000000000000title 'Demonstrate DESCRIPTIVES procedure'. * Sample syntax file for PSPP. * Run this syntax file with the command: * pspp example.stat * Output is written to the file "pspp.list". data list / v0 to v2 1-9. begin data. 12 12 89 34 12 80 56 12 77 78 12 73 90 91 37 97 85 52 82 12 79 26 78 76 29 13 71 end data. descript all/stat=all/format=serial. pspp-master/examples/grid.sps000066400000000000000000000006561177044323000166330ustar00rootroot00000000000000COMMENT -*-pspp-*- . COMMENT This program is useful for testing the behaviour of the Data and Variable Sheets. input program. vector var(500 F8.3). loop #c = 1 to 1000. loop #v = 1 to 500. compute var(#v) = #v + #c / 1000. end loop. end case. end loop. end file. end input program. variable label var1 'First variable' var2 'Second variable' var3 'Third variable'. save outfile='grid.sav'. execute. pspp-master/examples/hotel.sav000066400000000000000000000030521177044323000167760ustar00rootroot00000000000000$FL2@(#) SPSS DATA FILE GNU pspp 0.7.2 - i686-pc-linux-gnu Y@27 Apr 0917:20:57 V1 (I am satisfied with the level of serviceV2 The value for money was goodV3 $The staff were slow in responding V4 4My concerns were dealt with in an efficient manner V5 (There was too much noise in the rooms ð?Strongly Disagree@Disagree@ No Opinion@Agree@Strongly Agreeð?Strongly Disagree@Disagree@ No Opinion@Agree@Strongly Agreeð?Strongly Disagree@Disagree@ No Opinion@Agree@Strongly Agreeð?Strongly Disagree@Disagree@ No Opinion@Agree@Strongly Agreeð?Strongly Disagree@Disagree@ No Opinion@Agree@Strongly Agreeÿÿÿÿÿÿÿÿÿÿïÿÿÿÿÿÿÿïþÿÿÿÿÿïÿ  V1=v1 V2=v2 V3=v3 V4=v4 V5=v5UTF-8çhfgheeegeeiffghgegefigeigefihfgfhgeehifegfgeffihfehffgifeheeefiiffgggeheeegeeieffiiffpspp-master/examples/physiology.sav000066400000000000000000000034711177044323000200760ustar00rootroot00000000000000$FL2@(#) SPSS DATA FILE GNU pspp 0.7.2 - i686-pc-linux-gnu (Y@04 May 0911:00:35 SEX Sex of subject HEIGHT Height in millimeters WEIGHT Weight in kilograms TEMPERAT,Internal body temperature in degrees CelciusMaleð?Femaleÿÿÿÿÿÿÿÿÿÿïÿÿÿÿÿÿÿïþÿÿÿÿÿïÿ   8SEX=sex HEIGHT=height WEIGHT=weight TEMPERAT=temperatureUTF-8çdýýýdýýýÙD·O˜œ@MLz Á¸V@­¯ŒàJÄB@9i\]œ@Aé+ã˜V@ûnzŽªB@dýýýdýýýûÍ4T)!œ@MUk87V@qH½ ƒB@¯CC8mœ@I™ñ±Í–V@rX™m×B@dýýýdýýý´™@FÖ+W@x†ëU™VB@š@½p‡"œ@1zzÌm8V@>ãÓC€B@dýýýdýýý&3¤õ% œ@UÆü ´`V@)¦Ýn B@I,Ó}Øœ@r6õ"ë“V@Fª/(FK@@dýýýdýýý²¾E¶@œ@c?9ÂV@T¿!8)ÌB@:¥ºÛœ@§‡b5ç@V@¹“¿€›Í@@dýýýdýýýø§ém"œ@|»ü ežV@Zéè~è5A@IœÎ}œ&œ@8Oh¹éU@ó¸b:ƒA@dýýýdýýýqÙøÐ$œ@#¤«=‘W@j§”WýA@¼@ß4½áV@òKþ+ÂB@dýýýdýýýp@•ù)vå&V@+{&ŠûC@2WÔaþ#œ@éü,|»V@ïev[ƒC@dýýýdýýý 3brì$œ@°ð_#ïV@d¿žs}C@¬Ø% œ@! UYhV@Àš‡0.‚B@dýýýdýýýÔ{:Píœ@Uë¹­(QV@5½Zé âC@ˆš@ ð ?‚ŠV@3ØUxB@dýýýdýýýœ@x¼:õƒV@Áç+}ŽA@eÚúóœ@ET“ÑL©V@(€³A@eýýýeýýý(Ýc™@v8º§+L@Ò#´ B@]úW5ü™@h]¸‡$L@o×’pB@eýýýeýýýIIÙ™@ð¹ 5ðóK@ÏõÖ ìB@n Ö5Ô™@d–ŸŸRL@‡Ý©œŒgB@eýýýeýýý™@õ¶^?1L@Bz›W¹GA@™@0BgÜçôK@1ž|™òC@eýýýeýýý,¦Âm˜™@æ"j[oèL@kaêɨB@`f@ûåë(%L@QBEÍÃ’A@eýýýeýýýø˜@.¾ÅÊK@޶K¢/¯B@/7Z.“™@j.) M@O†bü’lC@eýýýeýýý$™@ '4«X¹K@8wá–0»A@¾ ²™@ü›ÿµûK@vžy«›HB@eýýýeýýý´š@ÌÕQÌK@"M×#;¹C@Š7õ\V™@!F5ëL@œÃÀÈ’B@eýýýeýýýýö`¥¯™@á8ZaøÓL@<âÿ@q}C@+š 0Ι@ÍÌÌÌÌÌKÀY¹†ÜC@eýýýeýýý„}¶y¡™@†‰Z_=K@ÓÁºŽ¥îB@ ™@ÚsÐCKL@G{Ó¼fC@pspp-master/examples/regress.sps000066400000000000000000000013151177044323000173510ustar00rootroot00000000000000set decimal=dot. title 'Demonstrate REGRESSION procedure'. /* run this syntax file with the command: /* pspp example.stat /* /* Output is written to the file "pspp.list". /* /* (This comment will not appear in the output.) data list / v0 to v2 1-33 (10). begin data. 0.65377128 7.735648 -23.97588 -0.13087553 6.142625 -19.63854 0.34880368 7.651430 -25.26557 0.69249021 6.125125 -16.57090 -0.07368178 8.245789 -25.80001 -0.34404919 6.031540 -17.56743 0.75981559 9.832291 -28.35977 -0.46958313 5.343832 -16.79548 -0.06108490 8.838262 -29.25689 0.56154863 6.200189 -18.58219 end data. list. regression /variables=v0 v1 v2 /statistics defaults /dependent=v2 /method=enter. pspp-master/examples/regress_categorical.sps000066400000000000000000000012151177044323000217050ustar00rootroot00000000000000set decimal=dot. title 'Demonstrate REGRESSION procedure'. /* run this syntax file with the command: /* pspp example.stat /* /* Output is written to the file "pspp.list". /* /* (This comment will not appear in the output.) data list / v0 1-2 (A) v1 v2 3-22 (10). begin data. b 7.735648 -23.97588 b 6.142625 -19.63854 a 7.651430 -25.26557 c 6.125125 -16.57090 a 8.245789 -25.80001 c 6.031540 -17.56743 a 9.832291 -28.35977 c 5.343832 -16.79548 a 8.838262 -29.25689 b 6.200189 -18.58219 end data. list. freq /variables=v0 v1 v2. regression /variables= v1 v2 /statistics defaults /dependent=v2 /method=enter. pspp-master/examples/repairs.sav000066400000000000000000000021131177044323000173250ustar00rootroot00000000000000$FL2@(#) SPSS DATA FILE GNU pspp 0.7.2 - i686-pc-linux-gnu Y@05 May 0910:26:10 MTBF $Mean time between failures (months) MTTR Mean time to repair (hours) DUTY_CYC$Ratio of working to non-working timeFACTORY Manufacturing facility ÿÿÿÿÿÿÿÿÿÿïÿÿÿÿÿÿÿïþÿÿÿÿÿïÿ   7MTBF=mtbf MTTR=mttr DUTY_CYC=duty_cycle FACTORY=factoryçýýýdýýýdÆ Œ½@Ì!†43@>»&­‚vï?’n{cš@õ“Í"13@q= ×£pÍ?ýýýeýýýeÙYTÊð@ªòCùÊ2@kNCžù¬å?yá%úðÉ@Ü,+ §ˆA@ÍÌÌÌÌÌì?ýýýdýýýd€ŒFþ}“ @†‡K¬À+B@–>¼ì?ùYEÌÁ@:PÊV©«=@øART~Ð?ýýýeýýýeùƒÈò¿´)@s©šY‘I@jÆDW¨•à?Ù]S.šx:@Ûvÿ¨V@uìk¯hPï?ýýýdýýýd‹|™|V#@ŠhÜC$ØD@Ãõ(\Âí?¾B~;zŸ @¨‹dtËŽA@ÿ-<סÄ?ýýýeýýýdñI…³@%’MØ7@q= ×£pí?@¬wú> @Fn‘fJ©A@®Gáz®ï?ýýýeýýýe€¾•#3 ú?ŒÏ©Õ ,@\Âõ(\ï?~ˆ8#®-@7ô¶çhN@^«ðkT²â?ýýýd¨Ž'𻚠@Ž)LÓêA@š™™™™™¹?pspp-master/glade/000077500000000000000000000000001177044323000144065ustar00rootroot00000000000000pspp-master/glade/OChangeLog000066400000000000000000000014341177044323000163010ustar00rootroot000000000000002007-11-21 John Darrington * icons/22x22/psppire-acr.png icons/16x16/psppire-acr.png: New files. * automake.mk: Install the new icons. 2007-10-19 John Darrington * acr.c (new file) * psppire.xml: Added entry for PsppireAcr widget 2007-09-26 Ben Pfaff * automake.mk (libglade_psppire_la_CFLAGS): Enable VPATH build by using $(top_srcdir) in -I directive. 4/4/2007 John Darrington * Seperated psppire-buttonbox into psppire-vbuttonbox and psppire-buttonbox Sat Mar 31 07:09:33 WST 2007 John Darrington * Added icons directory and its contents. * Re-wrote psppire.xml to work with glade 3.2.0, and to know about the keypad widget. pspp-master/glade/acr.c000066400000000000000000000027161177044323000153250ustar00rootroot00000000000000#include #include #include "psppire-acr.h" #include void glade_psppire_acr_post_create (GladeWidgetAdaptor *adaptor, GObject *object, GladeCreateReason reason) { GladeWidget *widget ; PsppireAcr *acr = PSPPIRE_ACR (object); g_return_if_fail (PSPPIRE_IS_ACR (acr)); widget = glade_widget_get_from_gobject (GTK_WIDGET (acr)); if (!widget) return; if (reason == GLADE_CREATE_USER) { /* HIG complient border-width defaults on acrs */ glade_widget_property_set (widget, "border-width", 5); } } GtkWidget * glade_psppire_acr_get_internal_child (GladeWidgetAdaptor *adaptor, PsppireAcr *acr, const gchar *name) { #if DEBUGGING g_print ("%s\n", __FUNCTION__); #endif return GTK_WIDGET (acr); } void glade_psppire_acr_set_property (GladeWidgetAdaptor *adaptor, GObject *object, const gchar *id, const GValue *value) { #if DEBUGGING g_print ("%s(%p) Type=\"%s\" Id=\"%s\"\n", __FUNCTION__, object, G_OBJECT_TYPE_NAME( object ), id); #endif GWA_GET_CLASS (GTK_TYPE_WINDOW)->set_property (adaptor, object, id, value); } GList * glade_psppire_acr_get_children (GladeWidgetAdaptor *adaptor, PsppireAcr *acr) { GList *list = NULL; g_return_val_if_fail (PSPPIRE_IS_ACR (acr), NULL); list = glade_util_container_get_all_children (GTK_CONTAINER (acr)); return list; } pspp-master/glade/automake.mk000066400000000000000000000032301177044323000165430ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in -*- makefile -*- module_LTLIBRARIES = libglade-psppire.la moduledir = `pkg-config --variable=moduledir gladeui-1.0` catalogdir = `pkg-config --variable=catalogdir gladeui-1.0` pixmapdir = `pkg-config --variable=pixmapdir gladeui-1.0` small_pixmapdir = $(pixmapdir)/16x16 large_pixmapdir = $(pixmapdir)/22x22 libglade_psppire_la_SOURCES = \ glade/dialog.c \ glade/bbox.c \ glade/selector.c \ glade/acr.c \ glade/dictview.c \ glade/var-view.c \ src/ui/gui/helper.c \ src/ui/gui/psppire-conf.c \ src/ui/gui/psppire-acr.c \ src/ui/gui/psppire-buttonbox.c \ src/ui/gui/psppire-hbuttonbox.c \ src/ui/gui/psppire-vbuttonbox.c \ src/ui/gui/psppire-dialog.c \ src/ui/gui/psppire-keypad.c \ src/ui/gui/psppire-dictview.c \ src/ui/gui/psppire-selector.c \ src/ui/gui/psppire-select-dest.c \ src/ui/gui/psppire-var-view.c dist_catalog_DATA = \ glade/psppire.xml dist_small_pixmap_DATA = \ glade/icons/16x16/psppire-acr.png \ glade/icons/16x16/psppire-hbuttonbox.png \ glade/icons/16x16/psppire-vbuttonbox.png \ glade/icons/16x16/psppire-dialog.png \ glade/icons/16x16/psppire-keypad.png \ glade/icons/16x16/psppire-selector.png dist_large_pixmap_DATA = \ glade/icons/22x22/psppire-acr.png \ glade/icons/22x22/psppire-hbuttonbox.png \ glade/icons/22x22/psppire-vbuttonbox.png \ glade/icons/22x22/psppire-dialog.png \ glade/icons/22x22/psppire-keypad.png \ glade/icons/22x22/psppire-selector.png libglade_psppire_la_CFLAGS = $(GLADE_UI_CFLAGS) $(GLADE_CFLAGS) \ $(GTKSOURCEVIEW_CFLAGS) -I $(top_srcdir)/src/ui/gui -DDEBUGGING libglade_psppire_la_LIBADD = gl/libgl.la EXTRA_DIST += glade/OChangeLog pspp-master/glade/bbox.c000066400000000000000000000030601177044323000155030ustar00rootroot00000000000000#include #include #include "psppire-buttonbox.h" void glade_psppire_button_box_post_create (GladeWidgetAdaptor *adaptor, GObject *object, GladeCreateReason reason) { GladeWidget *box_widget; PsppireButtonBox *bbox = PSPPIRE_BUTTONBOX (object); g_return_if_fail (PSPPIRE_IS_BUTTONBOX (bbox)); box_widget = glade_widget_get_from_gobject (GTK_WIDGET (bbox)); if (!box_widget) return; if (reason == GLADE_CREATE_USER) { /* HIG complient border-width defaults on dialogs */ glade_widget_property_set (box_widget, "border-width", 5); } } GtkWidget * glade_psppire_button_box_get_internal_child (GladeWidgetAdaptor *adaptor, PsppireButtonBox *bbox, const gchar *name) { #if DEBUGGING g_print ("%s\n", __FUNCTION__); #endif return GTK_WIDGET (bbox); } void glade_psppire_button_box_set_property (GladeWidgetAdaptor *adaptor, GObject *object, const gchar *id, const GValue *value) { #if DEBUGGING g_print ("%s(%p) Type=\"%s\" Id=\"%s\"\n", __FUNCTION__, object, G_OBJECT_TYPE_NAME( object ), id); #endif GWA_GET_CLASS (GTK_TYPE_WINDOW)->set_property (adaptor, object, id, value); } GList * glade_psppire_button_box_get_children (GladeWidgetAdaptor *adaptor, PsppireButtonBox *bbox) { GList *list = NULL; g_return_val_if_fail (PSPPIRE_IS_BUTTONBOX (bbox), NULL); list = glade_util_container_get_all_children (GTK_CONTAINER (bbox)); return list; } pspp-master/glade/dialog.c000066400000000000000000000044621177044323000160170ustar00rootroot00000000000000#include #include #include "psppire-dialog.h" #include #include #include void glade_psppire_dialog_post_create (GladeWidgetAdaptor *adaptor, GObject *object, GladeCreateReason reason) { GladeWidget *widget ; GladeWidget *box_widget; PsppireDialog *dialog = PSPPIRE_DIALOG (object); g_return_if_fail (PSPPIRE_IS_DIALOG (dialog)); widget = glade_widget_get_from_gobject (GTK_WIDGET (dialog)); if (!widget) return; if (reason == GLADE_CREATE_USER) { /* HIG compliant border-width defaults on dialogs */ glade_widget_property_set (widget, "border-width", 5); } box_widget = glade_widget_adaptor_create_internal (widget, G_OBJECT(dialog->box), "hbox", "dialog", FALSE, reason); /* These properties are controlled by the GtkDialog style properties: * "content-area-border", "button-spacing" and "action-area-border", * so we must disable their use. */ glade_widget_remove_property (box_widget, "border-width"); /* Only set these on the original create. */ if (reason == GLADE_CREATE_USER) { /* HIG compliant spacing defaults on dialogs */ glade_widget_property_set (box_widget, "spacing", 2); glade_widget_property_set (box_widget, "size", 2); } } GtkWidget * glade_psppire_dialog_get_internal_child (GladeWidgetAdaptor *adaptor, PsppireDialog *dialog, const gchar *name) { #if DEBUGGING g_print ("%s\n", __FUNCTION__); #endif g_assert (0 == strcmp (name, "hbox")); return dialog->box; } void glade_psppire_dialog_set_property (GladeWidgetAdaptor *adaptor, GObject *object, const gchar *id, const GValue *value) { #if DEBUGGING g_print ("%s(%p) Type=\"%s\" Id=\"%s\"\n", __FUNCTION__, object, G_OBJECT_TYPE_NAME( object ), id); #endif assert ( GWA_GET_CLASS (GTK_TYPE_WINDOW)->set_property ); GWA_GET_CLASS (GTK_TYPE_WINDOW)->set_property (adaptor, object, id, value); } GList * glade_psppire_dialog_get_children (GladeWidgetAdaptor *adaptor, PsppireDialog *dialog) { GList *list = NULL; g_return_val_if_fail (PSPPIRE_IS_DIALOG (dialog), NULL); list = glade_util_container_get_all_children (GTK_CONTAINER (dialog)); return list; } pspp-master/glade/dictview.c000066400000000000000000000031601177044323000163700ustar00rootroot00000000000000#include #include #include #include "psppire-dictview.h" #include GType psppire_dict_get_type () { return 0; } void glade_psppire_dictview_post_create (GladeWidgetAdaptor *adaptor, GObject *object, GladeCreateReason reason) { GladeWidget *widget ; PsppireDictView *dictview = PSPPIRE_DICT_VIEW (object); g_return_if_fail (PSPPIRE_IS_DICT_VIEW (dictview)); widget = glade_widget_get_from_gobject (GTK_WIDGET (dictview)); if (!widget) return; if (reason == GLADE_CREATE_USER) { /* HIG complient border-width defaults on dictviews */ glade_widget_property_set (widget, "border-width", 5); } } GtkWidget * glade_psppire_dictview_get_internal_child (GladeWidgetAdaptor *adaptor, PsppireDictView *dictview, const gchar *name) { #if DEBUGGING g_print ("%s\n", __FUNCTION__); #endif return GTK_WIDGET (dictview); } void glade_psppire_dictview_set_property (GladeWidgetAdaptor *adaptor, GObject *object, const gchar *id, const GValue *value) { #if DEBUGGING g_print ("%s(%p) Type=\"%s\" Id=\"%s\"\n", __FUNCTION__, object, G_OBJECT_TYPE_NAME( object ), id); #endif GWA_GET_CLASS (GTK_TYPE_WINDOW)->set_property (adaptor, object, id, value); } GList * glade_psppire_dictview_get_children (GladeWidgetAdaptor *adaptor, PsppireDictView *dv) { GList *list = NULL; g_return_val_if_fail (PSPPIRE_IS_DICT_VIEW (dv), NULL); list = glade_util_container_get_all_children (GTK_CONTAINER (dv)); return list; } pspp-master/glade/icons/000077500000000000000000000000001177044323000155215ustar00rootroot00000000000000pspp-master/glade/icons/16x16/000077500000000000000000000000001177044323000163065ustar00rootroot00000000000000pspp-master/glade/icons/16x16/psppire-acr.png000066400000000000000000000006361177044323000212460ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIME× ;¶¬yy+IDAT8Ë¥S»Šƒ@=n¦!"Å€Œ aŠü„M V’ÞÆO³Ùm ¤™Fÿa@Áb1E U`« ¾– É)ÏÜÇœsï5’$ù¶m;ĸ\.?Ķíp·ÛAJ9 ð}BˆÙdÎ9N§SH@J‰ÍfJ©ÈóJ)”e‰8ŽÉmÛê†äIRJá8ŽZ­VÓ4üUU ¤i ˲úúÀç=,úyjUJMº¸®;¦c‚€÷ûËåR?Ôu þ„–°ßïZ³,{i”_øúÇãq"aÆÄùs&n·Û9ñ§‰×ëu2ÆÃáðº„(ŠÞ2‘ô׳ÛíÆº®CÓ4“UàœCJ©× ÃÀz½†çy(Šbö˜Îç3ŒOÏù×Ùq ‰{CPIEND®B`‚pspp-master/glade/icons/16x16/psppire-dialog.png000066400000000000000000000003241177044323000217320ustar00rootroot00000000000000‰PNG  IHDRóÿa›IDAT8ËÝ“Á à —ÈÍ™–/zEð§ ÓÓ¹ˆÍò9RÌÏ÷A§Ñ.w¬Ë‘|ÈõycŒ—ÔµÖìHjd… J)—Ä)¥Í¤ÿqΣ)ÜÀàxÄÖ–e9€÷ó<Ÿ2ïýÖÔº®")I23™™HÊ̾ØÞïçôîBènÙã=cÝ ÝXõ‹ ¦Ñð Ò[4ÂïM¿IEND®B`‚pspp-master/glade/icons/16x16/psppire-hbuttonbox.png000066400000000000000000000002001177044323000226600ustar00rootroot00000000000000‰PNG  IHDRóÿaGIDAT8Ëíϱ €0 Á±ã{2là)CC”6ˆ"M®ó– Ë|›z×;—̼F;jmÔÚ6öýï P"¢ŸÔ}íË4æ"7ÀJš("IEND®B`‚pspp-master/glade/icons/16x16/psppire-keypad.png000066400000000000000000000001601177044323000217460ustar00rootroot00000000000000‰PNG  IHDRóÿa7IDAT8Ëc Oc``˜É@HgÿHcb  ¼Œáááÿ)2a4G‘ZHQvej°•1K-IEND®B`‚pspp-master/glade/icons/16x16/psppire-selector.png000066400000000000000000000001741177044323000223160ustar00rootroot00000000000000‰PNG  IHDRóÿaCIDAT8Ëc` <<üxxøbÕ3b3™¿råJFŠ d‰^«'Û(h@`!V'./°«‘ „4Ž3HN:IEND®B`‚pspp-master/glade/icons/16x16/psppire-vbuttonbox.png000066400000000000000000000001741177044323000227100ustar00rootroot00000000000000‰PNG  IHDRóÿaCIDAT8ËcdÀÂÃÃÓfB¹é+W®œÅ@ ÿáááÿq©cb °à‘Kˆˆ€{aÐÆÑX…A äœ:c]mIEND®B`‚pspp-master/glade/icons/22x22/000077500000000000000000000000001177044323000163005ustar00rootroot00000000000000pspp-master/glade/icons/22x22/psppire-acr.png000066400000000000000000000003731177044323000212360ustar00rootroot00000000000000‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs  šœtIME×  íUˆIDAT8ËíUA € c£'Ž/¨7õ¿ØÉ. !š«$E4ÇaÇÝ5$g+îÅ’þnôž°Ö^FpÎ5A’"cœ sšX7 ºKî+ x&â6c* hfwÀ$¸©˜XÓŠæQhZñøò¾]·6ãÚ­«ÿº½§Ú±Tµ¢f¦×1ÝýA~×]zƒIEND®B`‚pspp-master/glade/icons/22x22/psppire-dialog.png000066400000000000000000000004331177044323000217250ustar00rootroot00000000000000‰PNG  IHDRÄ´l;âIDAT8ËíUA ƒ0œ„œüRüE)IK±õn^ã,AB>âƒô JÓCQc­ Ý[–ÙÙìì& D2r‡3!IŸxœ3yž½mUU†À0 èû>i’$o)„.†Æ ʲ Jª”5â&f»Þ?!^¿snx-hoÂ1I|)œshšÖÚHJ Î9|…YhllZ/Ð,˦ k-´Ö1Þæu]çm!dòµm;;oNÅY^P…·Ì‘DJ ¥”³JÌ9Ÿ•ã³4M71ãjºR°{àÕt‹5mxª'S›Ú‰@‘IEND®B`‚pspp-master/glade/icons/22x22/psppire-hbuttonbox.png000066400000000000000000000002101177044323000226530ustar00rootroot00000000000000‰PNG  IHDRÄ´l;OIDAT8ËíÐÁ €@ DѯØã¤·&í U®'AâmEA˜w ™Ã€Ùg&I+°•}ËÌ`4GR¯$õób4Ÿßªâ EĽüËü07³êjŠO¬GÆIEND®B`‚pspp-master/glade/icons/22x22/psppire-keypad.png000066400000000000000000000001701177044323000217410ustar00rootroot00000000000000‰PNG  IHDRÄ´l;?IDAT8Ëc Oc``˜É@]Îþ DމF`Ô`ÚÌþŸ&&&·QƒG“ÛhªèäF“Ê%ÜøYj8aIEND®B`‚pspp-master/glade/icons/22x22/psppire-selector.png000066400000000000000000000002061177044323000223040ustar00rootroot00000000000000‰PNG  IHDRÄ´l;MIDAT8Ëí’¹ 0CÄŽž‘)I›&át\Gᳬ5 n(Íæé'¾g¡q´ ,ö¤ÅVÁî:>gƒÖ*¸ZGß«…ÃðæéV£VIEND®B`‚pspp-master/glade/icons/22x22/psppire-vbuttonbox.png000066400000000000000000000002061177044323000226760ustar00rootroot00000000000000‰PNG  IHDRÄ´l;MIDAT8Ëcd ÂÃÃÓf¢ §¯\¹r% <<ü?:ÿOHÀÐ3˜…5é‘Ç0ìãh:MÇ£éx4Ët ¯oRW')+ˆIEND®B`‚pspp-master/glade/psppire.xml000066400000000000000000000225671177044323000166260ustar00rootroot00000000000000 glade_psppire_dialog_post_create glade_psppire_dialog_get_internal_child glade_psppire_dialog_get_children glade_psppire_button_box_post_create glade_psppire_button_box_get_children glade_psppire_button_box_get_internal_child glade_psppire_button_box_post_create glade_psppire_button_box_get_children glade_psppire_button_box_get_internal_child glade_psppire_selector_post_create glade_psppire_selector_get_children glade_psppire_selector_get_internal_child glade_psppire_acr_post_create glade_psppire_acr_get_children glade_psppire_acr_get_internal_child glade_psppire_dictview_post_create glade_psppire_dictview_get_children glade_psppire_dictview_get_internal_child glade_psppire_var_view_post_create glade_psppire_var_view_get_children glade_psppire_var_view_get_internal_child pspp-master/glade/selector.c000066400000000000000000000030621177044323000163730ustar00rootroot00000000000000#include #include #include "psppire-selector.h" #include void glade_psppire_selector_post_create (GladeWidgetAdaptor *adaptor, GObject *object, GladeCreateReason reason) { GladeWidget *widget ; PsppireSelector *selector = PSPPIRE_SELECTOR (object); g_return_if_fail (PSPPIRE_IS_SELECTOR (selector)); widget = glade_widget_get_from_gobject (GTK_WIDGET (selector)); if (!widget) return; if (reason == GLADE_CREATE_USER) { /* HIG complient border-width defaults on selectors */ glade_widget_property_set (widget, "border-width", 5); } } GtkWidget * glade_psppire_selector_get_internal_child (GladeWidgetAdaptor *adaptor, PsppireSelector *selector, const gchar *name) { #if DEBUGGING g_print ("%s\n", __FUNCTION__); #endif return GTK_WIDGET (selector); } void glade_psppire_selector_set_property (GladeWidgetAdaptor *adaptor, GObject *object, const gchar *id, const GValue *value) { #if DEBUGGING g_print ("%s(%p) Type=\"%s\" Id=\"%s\"\n", __FUNCTION__, object, G_OBJECT_TYPE_NAME( object ), id); #endif GWA_GET_CLASS (GTK_TYPE_WINDOW)->set_property (adaptor, object, id, value); } GList * glade_psppire_selector_get_children (GladeWidgetAdaptor *adaptor, PsppireSelector *selector) { GList *list = NULL; g_return_val_if_fail (PSPPIRE_IS_SELECTOR (selector), NULL); list = glade_util_container_get_all_children (GTK_CONTAINER (selector)); return list; } pspp-master/glade/var-view.c000066400000000000000000000033271177044323000163170ustar00rootroot00000000000000#include #include #include #include "psppire-var-view.h" #include /* Dummy function to keep the linker happy. Glade never actually needs to use this return value. */ GType psppire_var_ptr_get_type (void) { return 0; } void glade_psppire_var_view_post_create (GladeWidgetAdaptor *adaptor, GObject *object, GladeCreateReason reason) { GladeWidget *widget ; PsppireVarView *var_view = PSPPIRE_VAR_VIEW (object); g_return_if_fail (PSPPIRE_IS_VAR_VIEW (var_view)); widget = glade_widget_get_from_gobject (GTK_WIDGET (var_view)); if (!widget) return; if (reason == GLADE_CREATE_USER) { /* HIG complient border-width defaults on var_views */ glade_widget_property_set (widget, "border-width", 5); } } GtkWidget * glade_psppire_var_view_get_internal_child (GladeWidgetAdaptor *adaptor, PsppireVarView *var_view, const gchar *name) { #if DEBUGGING g_print ("%s\n", __FUNCTION__); #endif return GTK_WIDGET (var_view); } void glade_psppire_var_view_set_property (GladeWidgetAdaptor *adaptor, GObject *object, const gchar *id, const GValue *value) { #if DEBUGGING g_print ("%s(%p) Type=\"%s\" Id=\"%s\"\n", __FUNCTION__, object, G_OBJECT_TYPE_NAME( object ), id); #endif GWA_GET_CLASS (GTK_TYPE_WINDOW)->set_property (adaptor, object, id, value); } GList * glade_psppire_var_view_get_children (GladeWidgetAdaptor *adaptor, PsppireVarView *dv) { GList *list = NULL; g_return_val_if_fail (PSPPIRE_IS_VAR_VIEW (dv), NULL); list = glade_util_container_get_all_children (GTK_CONTAINER (dv)); return list; } pspp-master/lib/000077500000000000000000000000001177044323000141005ustar00rootroot00000000000000pspp-master/lib/.gitignore000066400000000000000000000000251177044323000160650ustar00rootroot00000000000000Makefile Makefile.in pspp-master/lib/OChangeLog000066400000000000000000000023771177044323000160020ustar00rootroot000000000000002008/07/20 John Darrington * Removed gsl-extras. Functionality now available in gsl. Sun Jul 31 11:29:04 2005 Ben Pfaff * misc/: Removed in favor of gnulib. * Makefile.am: (SUBDIRS) Removed misc. Wed Mar 9 09:53:50 2005 Ben Pfaff * gsl-extras/: New directory. * Makefile.am: (SUBDIRS) Add gsl-extras. Mon Feb 28 23:20:05 2005 Ben Pfaff * julcal/: Removed directory. * Makefile.am: (SUBDIRS) Removed julcal. (DIST_SUBDIRS) Removed. Sun Jan 2 21:31:48 2000 Ben Pfaff * Makefile.am: (SUBDIRS) Only include gmp if libgmp not installed on this system already. Sun May 31 00:55:51 1998 Ben Pfaff * Makefile.am: (SUBDIRS) Add gmp. * gmp/: New subdirectory, containing a subset of GNU libgmp2 just big enough to support mpf_init_set_d(), mpf_get_str(), and mpf_clear(). Fri Apr 24 12:52:07 1998 Ben Pfaff * Makefile.am: (SUBDIRS) Remove avllib. * avllib/: Removed. Wed Dec 24 22:36:50 1997 Ben Pfaff * Makefile.am: (SUBDIRS) Add dcdflib. * dcdflib: New subdirectory. ---------------------------------------------------------------------- Local Variables: mode: change-log version-control: never End: pspp-master/lib/automake.mk000066400000000000000000000004111177044323000162330ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in -*- makefile -*- include $(top_srcdir)/lib/linreg/automake.mk include $(top_srcdir)/lib/tukey/automake.mk if HAVE_GUI include $(top_srcdir)/lib/gtk-contrib/automake.mk endif EXTRA_DIST += lib/OChangeLog pspp-master/lib/gtk-contrib/000077500000000000000000000000001177044323000163235ustar00rootroot00000000000000pspp-master/lib/gtk-contrib/COPYING.LESSER000066400000000000000000000635001177044323000203560ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! pspp-master/lib/gtk-contrib/OChangeLog000066400000000000000000000130501177044323000202130ustar00rootroot000000000000002008-05-08 Ben Pfaff Patch #6506. Reviewed by John Darrington. * gtksheet.c (gtk_sheet_unrealize): Don't call gtk_widget_unparent on sheet->button if it's null. 2008-05-06 Ben Pfaff * gtksheet.c (gtk_sheet_dispose): Set the sheet's entry_container and button members to NULL after unref'ing them, so that a later call to gtk_sheet_for_all will not try to dereference a dangling pointer. 2008-03-06 John Darrington * gsheet-row-iface.c gsheet-row-iface.h: Delete unused, unneccesary gpointer variable from the interface. * gtksheet.c: Update to match new gsheet-row-iface 2008-02-27 John Darrington * gtksheet.c gtksheet.h: Corrected some leaks and other problems related to de-allocating the sheet. 2008-02-27 John Darrington * gtksheet.c: (gtk_sheet_expose) Don't queue a redraw on the entry widget. Fixes bug #21073 2008-02-20 John Darrington * gtksheet.c gtksheet.h: Removed some unused signals. Made the models properties of the widget. 2008-02-08 John Darrington * gtksheet.c: Removed the sheet_locked feature, which we never used, and interfered with the editability of the entry widget. * gtksheet.c: Add one to the row to which we scroll. Seems like the best way to cope with granularity problems. 21 Septempber 2007 John Darrington * gtksheet.c (range_update_callback): Scroll to cell 0,0 if the current position is outside the model's range. 24 July 2007 John Darrington * gtksheet.c gtksheet.h: Removed the `clip' feature, which IMO is a croc, and we're unlikely to use. In its place, added a primary selection which supports text and html targets. 16 July 2007 John Darrington * gtksheet.c gtksheet.h: Removed some legacy functions called from gtk_sheet_finalize which caused unnecessary delays when shutting down. 12 July 2007 John Darrington * gtksheet.c gtksheet.h: Removed view member and replaced with function call. Removed hadjustment_changed and vadjustment_changed functions which did nothing. Added some whitespace arount != operators. 09 July 2007 John Darrington * gtksheet.c gtksheet.h (gtk_sheet_get_active_cell): Allowed row, column to be NULL. 07 July 2007 John Darrington * gsheet-column-iface.c gsheet-column-iface.h gsheet-row-iface.c gsheet-row-iface.h gtksheet.c gtksheet.h: Added a "subtitle" feature on row/column titles, which shows tooltip-like popups. 03 July 2007 John Darrington * gtksheet.c gtksheet.h: Removed the autoscroll-on-select feature that was causing us grief. 28 June 2007 John Darrington * gtksheet.c: Removed some features that we dont use, to get better speed. Sat Feb 17 17:36:56 2007 Ben Pfaff * gsheet-column-iface.c gsheet-hetero-column.c gsheet-row-iface.c gsheet-uniform-column.c gsheet-uniform-row.c gsheetmodel.c gtkextra-marshal.c gtkextra.c gtkiconlist.c gtkitementry.c gtksheet.c: Add "#include ". Mon Jun 19 18:03:21 WST 2006 John Darrington * gsheet-column-iface.c gsheet-column-iface.h gsheet-hetero-column.c gsheet-row-iface.c gsheet-row-iface.h gsheet-uniform-column.c gsheet-uniform-row.c gtksheet.c gtksheet.h: Fixed some warnings. Corrected errors updating row/column titles Di Mai 30 19:51:19 WST 2006 John Darrington * gtksheet.c gtksheet.h: constness. Removed dependence on glib2.10 Sat May 27 16:29:36 WST 2006 John Darrington * gtksheet.c: Removed call to gtk_entry_set_text, which caused warnings and was unnecessary. Thu May 25 17:58:51 WST 2006 John Darrington * gsheet-column-iface.c gsheet-column-iface.h gsheet-hetero-column.c gsheet-row-iface.c gsheet-row-iface.h gsheet-uniform-row.c gtksheet-extra.h gtksheet.c: Plugged memory leaks. Rationalised the way that GtkSheetButtons are created. Sat May 20 21:02:03 WST 2006 John Darrington * gsheetmodel.c gsheetmodel.h: Added columns-inserted and columns-deleted signals. Added g_sheet_get_{row,column}_count functions. * gtksheet.c gtksheet.h: Allowed -1 to be passed to gtk_sheet_set_active_cell to indicate no active cell. Mon May 15 16:10:49 WST 2006 John Darrington * gtksheet.c: Removed code which rendered the title buttons a second time. Cut and Paste error ? Sat May 13 07:58:32 WST 2006 John Darrington * gsheetmodel.c gsheetmodel.h gtksheet.c gtksheeet.h: Added free_strings flag to tell the sheet whether to free the string data passed from the model. Thu May 11 22:20:04 WST 2006 John Darrington * gtksheet.c, gtksheet.h: Fixed broken deallocation of sheet->pixmap. Thu May 4 17:55:48 WST 2006 John Darrington * gtksheet.c: Added callback on inserted rows. Sat Jan 28 08:48:08 2006 UTC John Darrington * Separated the data out of the GtkSheet. The gtksheet should now be regarded as a way of looking into the data. The data is represented by a GSheetModel and the rows and columns by GSheetRow and GSheetColumn. pspp-master/lib/gtk-contrib/README000066400000000000000000000007141177044323000172050ustar00rootroot00000000000000This is not part of the GNU PSPP program, but is used with GNU PSPP. This directory contains a version of the GtkXPaned widget. It includes minor modifications. GtkXPaned is licensed under the GNU Lesser General Public License. See COPYING.LESSER. This directory also contains the PsppireSheet widget which is a very heavily modified version of GtkSheet widget. This modified version if licensed under the GNU General Public License version 3 or later. pspp-master/lib/gtk-contrib/automake.mk000066400000000000000000000010661177044323000204650ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in -*- makefile -*- noinst_LIBRARIES += lib/gtk-contrib/libgtksheet.a lib_gtk_contrib_libgtksheet_a_CPPFLAGS = $(AM_CPPFLAGS) -Isrc/ui/gui/include lib_gtk_contrib_libgtksheet_a_CFLAGS = $(GTK_CFLAGS) -Wall -DGDK_MULTIHEAD_SAFE=1 lib_gtk_contrib_libgtksheet_a_SOURCES = \ lib/gtk-contrib/gtkextra-sheet.h \ lib/gtk-contrib/psppire-sheet.c \ lib/gtk-contrib/psppire-sheet.h \ lib/gtk-contrib/gtkxpaned.c \ lib/gtk-contrib/gtkxpaned.h EXTRA_DIST += lib/gtk-contrib/OChangeLog \ lib/gtk-contrib/README pspp-master/lib/gtk-contrib/gtkextra-sheet.h000066400000000000000000000032401177044323000214320ustar00rootroot00000000000000/* This version of GtkSheet has been heavily modified, for the specific * requirements of PSPPIRE. * * GtkSheet widget for Gtk+. * Copyright (C) 1999-2001 Adrian E. Feiguin * * Based on GtkClist widget by Jay Painter, but major changes. * Memory allocation routines inspired on SC (Spreadsheet Calculator) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PSPPIRE_EXTRA_SHEET_H__ #define PSPPIRE_EXTRA_SHEET_H__ struct _PsppireSheet ; typedef struct _PsppireSheet PsppireSheet; struct _PsppireSheetButton { GtkStateType state; gchar *label; gboolean label_visible; GtkJustification justification; gboolean overstruck; }; struct _PsppireSheetCell { gint row; gint col; }; typedef struct _PsppireSheetButton PsppireSheetButton; typedef struct _PsppireSheetCell PsppireSheetCell; PsppireSheetButton * psppire_sheet_button_new (void); void psppire_sheet_button_free (PsppireSheetButton *button); #endif /* PSPPIRE_EXTRA_SHEET_H__ */ pspp-master/lib/gtk-contrib/gtkxpaned.c000066400000000000000000003041211177044323000204550ustar00rootroot00000000000000/******************************************************************************* **3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ** 10 20 30 40 50 60 70 80 ** ** library for GtkXPaned-widget, a 2x2 grid-like variation of GtkPaned of gtk+ ** Copyright (C) 2005-2006 Mirco "MacSlow" Müller ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** GtkXPaned is based on GtkPaned which was done by... ** ** "Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald" ** ** and later modified by... ** ** "the GTK+ Team and others 1997-2000" ** *******************************************************************************/ #include #include "gtkxpaned.h" #include #include #include enum WidgetProperties { PROP_0, PROP_X_POSITION, PROP_Y_POSITION, PROP_POSITION_SET, PROP_MIN_X_POSITION, PROP_MIN_Y_POSITION, PROP_MAX_X_POSITION, PROP_MAX_Y_POSITION }; enum ChildProperties { CHILD_PROP_0, CHILD_PROP_RESIZE, CHILD_PROP_SHRINK }; enum WidgetSignals { CYCLE_CHILD_FOCUS, TOGGLE_HANDLE_FOCUS, MOVE_HANDLE, CYCLE_HANDLE_FOCUS, ACCEPT_POSITION, CANCEL_POSITION, LAST_SIGNAL }; static void gtk_xpaned_class_init (GtkXPanedClass* klass); static void gtk_xpaned_init (GtkXPaned* xpaned); static void gtk_xpaned_size_request (GtkWidget* widget, GtkRequisition* requisition); static void gtk_xpaned_size_allocate (GtkWidget* widget, GtkAllocation* allocation); static void gtk_xpaned_set_property (GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec); static void gtk_xpaned_get_property (GObject* object, guint prop_id, GValue* value, GParamSpec* pspec); static void gtk_xpaned_set_child_property (GtkContainer* container, GtkWidget* child, guint property_id, const GValue* value, GParamSpec* pspec); static void gtk_xpaned_get_child_property (GtkContainer* container, GtkWidget* child, guint property_id, GValue* value, GParamSpec* pspec); static void gtk_xpaned_finalize (GObject* object); static void gtk_xpaned_realize (GtkWidget* widget); static void gtk_xpaned_unrealize (GtkWidget* widget); static void gtk_xpaned_map (GtkWidget* widget); static void gtk_xpaned_unmap (GtkWidget* widget); static gboolean gtk_xpaned_expose (GtkWidget* widget, GdkEventExpose* event); static gboolean gtk_xpaned_enter (GtkWidget* widget, GdkEventCrossing* event); static gboolean gtk_xpaned_leave (GtkWidget* widget, GdkEventCrossing* event); static gboolean gtk_xpaned_button_press (GtkWidget* widget, GdkEventButton* event); static gboolean gtk_xpaned_button_release (GtkWidget* widget, GdkEventButton* event); static gboolean gtk_xpaned_motion (GtkWidget* widget, GdkEventMotion* event); static gboolean gtk_xpaned_focus (GtkWidget* widget, GtkDirectionType direction); static void gtk_xpaned_add (GtkContainer* container, GtkWidget* widget); static void gtk_xpaned_remove (GtkContainer* container, GtkWidget* widget); static void gtk_xpaned_forall (GtkContainer* container, gboolean include_internals, GtkCallback callback, gpointer callback_data); static void gtk_xpaned_set_focus_child (GtkContainer* container, GtkWidget* child); static void gtk_xpaned_set_saved_focus (GtkXPaned* xpaned, GtkWidget* widget); static void gtk_xpaned_set_first_xpaned (GtkXPaned* xpaned, GtkXPaned* first_xpaned); static void gtk_xpaned_set_last_top_left_child_focus (GtkXPaned* xpaned, GtkWidget* widget); static void gtk_xpaned_set_last_top_right_child_focus (GtkXPaned* xpaned, GtkWidget* widget); static void gtk_xpaned_set_last_bottom_left_child_focus (GtkXPaned* xpaned, GtkWidget* widget); static void gtk_xpaned_set_last_bottom_right_child_focus (GtkXPaned* xpaned, GtkWidget* widget); static gboolean gtk_xpaned_cycle_child_focus (GtkXPaned* xpaned, gboolean reverse); static gboolean gtk_xpaned_cycle_handle_focus (GtkXPaned* xpaned, gboolean reverse); static gboolean gtk_xpaned_move_handle (GtkXPaned* xpaned, GtkScrollType scroll); static gboolean gtk_xpaned_accept_position (GtkXPaned* xpaned); static gboolean gtk_xpaned_cancel_position (GtkXPaned* xpaned); static gboolean gtk_xpaned_toggle_handle_focus (GtkXPaned* xpaned); static GType gtk_xpaned_child_type (GtkContainer* container); static GtkContainerClass* parent_class = NULL; struct _GtkXPanedPrivate { GtkWidget *saved_focus; GtkXPaned *first_xpaned; }; GType gtk_xpaned_get_type (void) { static GType xpaned_type = 0; if (!xpaned_type) { static const GTypeInfo xpaned_info = { sizeof (GtkXPanedClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) gtk_xpaned_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GtkXPaned), 0, /* n_preallocs */ (GInstanceInitFunc) gtk_xpaned_init }; xpaned_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkXPaned", &xpaned_info, 0); } return xpaned_type; } GtkWidget* gtk_xpaned_new (void) { GtkXPaned* xpaned; xpaned = g_object_new (GTK_TYPE_XPANED, NULL); return GTK_WIDGET (xpaned); } static guint signals[LAST_SIGNAL] = { 0 }; static void add_tab_bindings (GtkBindingSet* binding_set, GdkModifierType modifiers) { gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers, "toggle_handle_focus", 0); gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers, "toggle_handle_focus", 0); } static void add_move_binding (GtkBindingSet* binding_set, guint keyval, GdkModifierType mask, GtkScrollType scroll) { gtk_binding_entry_add_signal (binding_set, keyval, mask, "move_handle", 1, GTK_TYPE_SCROLL_TYPE, scroll); } static void gtk_xpaned_class_init (GtkXPanedClass* class) { GObjectClass* object_class; GtkWidgetClass* widget_class; GtkContainerClass* container_class; GtkXPanedClass* xpaned_class; GtkBindingSet* binding_set; object_class = (GObjectClass *) class; widget_class = (GtkWidgetClass *) class; container_class = (GtkContainerClass *) class; xpaned_class = (GtkXPanedClass *) class; parent_class = g_type_class_peek_parent (class); object_class->set_property = gtk_xpaned_set_property; object_class->get_property = gtk_xpaned_get_property; object_class->finalize = gtk_xpaned_finalize; widget_class->realize = gtk_xpaned_realize; widget_class->unrealize = gtk_xpaned_unrealize; widget_class->map = gtk_xpaned_map; widget_class->unmap = gtk_xpaned_unmap; widget_class->expose_event = gtk_xpaned_expose; widget_class->focus = gtk_xpaned_focus; widget_class->enter_notify_event = gtk_xpaned_enter; widget_class->leave_notify_event = gtk_xpaned_leave; widget_class->button_press_event = gtk_xpaned_button_press; widget_class->button_release_event = gtk_xpaned_button_release; widget_class->motion_notify_event = gtk_xpaned_motion; widget_class->size_request = gtk_xpaned_size_request; widget_class->size_allocate = gtk_xpaned_size_allocate; container_class->add = gtk_xpaned_add; container_class->remove = gtk_xpaned_remove; container_class->forall = gtk_xpaned_forall; container_class->child_type = gtk_xpaned_child_type; container_class->set_focus_child = gtk_xpaned_set_focus_child; container_class->set_child_property = gtk_xpaned_set_child_property; container_class->get_child_property = gtk_xpaned_get_child_property; xpaned_class->cycle_child_focus = gtk_xpaned_cycle_child_focus; xpaned_class->toggle_handle_focus = gtk_xpaned_toggle_handle_focus; xpaned_class->move_handle = gtk_xpaned_move_handle; xpaned_class->cycle_handle_focus = gtk_xpaned_cycle_handle_focus; xpaned_class->accept_position = gtk_xpaned_accept_position; xpaned_class->cancel_position = gtk_xpaned_cancel_position; g_object_class_install_property (object_class, PROP_X_POSITION, g_param_spec_int ("x-position", ("x-Position"), ("x-Position of paned separator in pixels (0 means all the way to the left)"), 0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_Y_POSITION, g_param_spec_int ("y-position", "y-Position", "y-Position of paned separator in pixels (0 means all the way to the top)", 0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_WRITABLE)); g_object_class_install_property (object_class, PROP_POSITION_SET, g_param_spec_boolean ("position-set", "Position Set", "TRUE if the Position property should be used", FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE)); gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("handle-size", "Handle Size", "Width of handle", 0, G_MAXINT, 3, G_PARAM_READABLE)); /** * GtkXPaned:min-x-position: * * The smallest possible value for the x-position property. This property is derived from the * size and shrinkability of the widget's children. * * Since: 2.4 */ g_object_class_install_property (object_class, PROP_MIN_X_POSITION, g_param_spec_int ("min-x-position", "Minimal x-Position", "Smallest possible value for the \"x-position\" property", 0, G_MAXINT, 0, G_PARAM_READABLE)); /** * GtkXPaned:min-y-position: * * The smallest possible value for the y-position property. This property is derived from the * size and shrinkability of the widget's children. * * Since: 2.4 */ g_object_class_install_property (object_class, PROP_MIN_Y_POSITION, g_param_spec_int ("min-y-position", "Minimal y-Position", "Smallest possible value for the \"y-position\" property", 0, G_MAXINT, 0, G_PARAM_READABLE)); /** * GtkPaned:max-x-position: * * The largest possible value for the x-position property. This property is derived from the * size and shrinkability of the widget's children. * * Since: 2.4 */ g_object_class_install_property (object_class, PROP_MAX_X_POSITION, g_param_spec_int ("max-x-position", "Maximal x-Position", "Largest possible value for the \"x-position\" property", 0, G_MAXINT, G_MAXINT, G_PARAM_READABLE)); /** * GtkPaned:max-y-position: * * The largest possible value for the y-position property. This property is derived from the * size and shrinkability of the widget's children. * * Since: 2.4 */ g_object_class_install_property (object_class, PROP_MAX_Y_POSITION, g_param_spec_int ("max-y-position", "Maximal y-Position", "Largest possible value for the \"y-position\" property", 0, G_MAXINT, G_MAXINT, G_PARAM_READABLE)); /** * GtkPaned:resize: * * The "resize" child property determines whether the child expands and * shrinks along with the paned widget. * * Since: 2.4 */ gtk_container_class_install_child_property (container_class, CHILD_PROP_RESIZE, g_param_spec_boolean ("resize", "Resize", "If TRUE, the child expands and shrinks along with the paned widget", TRUE, G_PARAM_READWRITE)); /** * GtkPaned:shrink: * * The "shrink" child property determines whether the child can be made * smaller than its requisition. * * Since: 2.4 */ gtk_container_class_install_child_property (container_class, CHILD_PROP_SHRINK, g_param_spec_boolean ("shrink", "Shrink", "If TRUE, the child can be made smaller than its requisition", TRUE, G_PARAM_READWRITE)); signals [CYCLE_CHILD_FOCUS] = g_signal_new ("cycle-child-focus", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkXPanedClass, cycle_child_focus), NULL, NULL, psppire_marshal_BOOLEAN__BOOLEAN, G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN); signals [TOGGLE_HANDLE_FOCUS] = g_signal_new ("toggle-handle-focus", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkXPanedClass, toggle_handle_focus), NULL, NULL, psppire_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN, 0); signals[MOVE_HANDLE] = g_signal_new ("move-handle", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkXPanedClass, move_handle), NULL, NULL, psppire_marshal_BOOLEAN__ENUM, G_TYPE_BOOLEAN, 1, GTK_TYPE_SCROLL_TYPE); signals [CYCLE_HANDLE_FOCUS] = g_signal_new ("cycle-handle-focus", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkXPanedClass, cycle_handle_focus), NULL, NULL, psppire_marshal_BOOLEAN__BOOLEAN, G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN); signals [ACCEPT_POSITION] = g_signal_new ("accept-position", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkXPanedClass, accept_position), NULL, NULL, psppire_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN, 0); signals [CANCEL_POSITION] = g_signal_new ("cancel-position", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GtkXPanedClass, cancel_position), NULL, NULL, psppire_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN, 0); binding_set = gtk_binding_set_by_class (class); /* F6 and friends */ gtk_binding_entry_add_signal (binding_set, GDK_F6, 0, "cycle-child-focus", 1, G_TYPE_BOOLEAN, FALSE); gtk_binding_entry_add_signal (binding_set, GDK_F6, GDK_SHIFT_MASK, "cycle-child-focus", 1, G_TYPE_BOOLEAN, TRUE); /* F8 and friends */ gtk_binding_entry_add_signal (binding_set, GDK_F8, 0, "cycle-handle-focus", 1, G_TYPE_BOOLEAN, FALSE); gtk_binding_entry_add_signal (binding_set, GDK_F8, GDK_SHIFT_MASK, "cycle-handle-focus", 1, G_TYPE_BOOLEAN, TRUE); add_tab_bindings (binding_set, 0); add_tab_bindings (binding_set, GDK_CONTROL_MASK); add_tab_bindings (binding_set, GDK_SHIFT_MASK); add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK); /* accept and cancel positions */ gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, "cancel-position", 0); gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "accept-position", 0); gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "accept-position", 0); gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "accept-position", 0); gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0, "accept-position", 0); /* move handle */ add_move_binding (binding_set, GDK_Left, 0, GTK_SCROLL_STEP_LEFT); add_move_binding (binding_set, GDK_KP_Left, 0, GTK_SCROLL_STEP_LEFT); add_move_binding (binding_set, GDK_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT); add_move_binding (binding_set, GDK_KP_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT); add_move_binding (binding_set, GDK_Right, 0, GTK_SCROLL_STEP_RIGHT); add_move_binding (binding_set, GDK_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT); add_move_binding (binding_set, GDK_KP_Right, 0, GTK_SCROLL_STEP_RIGHT); add_move_binding (binding_set, GDK_KP_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT); add_move_binding (binding_set, GDK_Up, 0, GTK_SCROLL_STEP_UP); add_move_binding (binding_set, GDK_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP); add_move_binding (binding_set, GDK_KP_Up, 0, GTK_SCROLL_STEP_UP); add_move_binding (binding_set, GDK_KP_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP); add_move_binding (binding_set, GDK_Page_Up, 0, GTK_SCROLL_PAGE_UP); add_move_binding (binding_set, GDK_KP_Page_Up, 0, GTK_SCROLL_PAGE_UP); add_move_binding (binding_set, GDK_Down, 0, GTK_SCROLL_STEP_DOWN); add_move_binding (binding_set, GDK_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN); add_move_binding (binding_set, GDK_KP_Down, 0, GTK_SCROLL_STEP_DOWN); add_move_binding (binding_set, GDK_KP_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN); add_move_binding (binding_set, GDK_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT); add_move_binding (binding_set, GDK_KP_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT); add_move_binding (binding_set, GDK_Home, 0, GTK_SCROLL_START); add_move_binding (binding_set, GDK_KP_Home, 0, GTK_SCROLL_START); add_move_binding (binding_set, GDK_End, 0, GTK_SCROLL_END); add_move_binding (binding_set, GDK_KP_End, 0, GTK_SCROLL_END); } static GType gtk_xpaned_child_type (GtkContainer* container) { if (!GTK_XPANED (container)->top_left_child || !GTK_XPANED (container)->top_right_child || !GTK_XPANED (container)->bottom_left_child || !GTK_XPANED (container)->bottom_right_child) return GTK_TYPE_WIDGET; else return G_TYPE_NONE; } static void gtk_xpaned_init (GtkXPaned* xpaned) { GTK_WIDGET_SET_FLAGS (xpaned, GTK_NO_WINDOW | GTK_CAN_FOCUS); xpaned->top_left_child = NULL; xpaned->top_right_child = NULL; xpaned->bottom_left_child = NULL; xpaned->bottom_right_child = NULL; xpaned->handle_east = NULL; xpaned->handle_west = NULL; xpaned->handle_north = NULL; xpaned->handle_south = NULL; xpaned->handle_middle = NULL; xpaned->xor_gc = NULL; xpaned->cursor_type_east = GDK_SB_V_DOUBLE_ARROW; xpaned->cursor_type_west = GDK_SB_V_DOUBLE_ARROW; xpaned->cursor_type_north = GDK_SB_H_DOUBLE_ARROW; xpaned->cursor_type_south = GDK_SB_H_DOUBLE_ARROW; xpaned->cursor_type_middle = GDK_FLEUR; xpaned->handle_pos_east.width = 5; xpaned->handle_pos_east.height = 5; xpaned->handle_pos_west.width = 5; xpaned->handle_pos_west.height = 5; xpaned->handle_pos_north.width = 5; xpaned->handle_pos_north.height = 5; xpaned->handle_pos_south.width = 5; xpaned->handle_pos_south.height = 5; xpaned->handle_pos_middle.width = 5; xpaned->handle_pos_middle.height = 5; xpaned->position_set = FALSE; xpaned->last_allocation.width = -1; xpaned->last_allocation.height = -1; xpaned->in_drag_vert = FALSE; xpaned->in_drag_horiz = FALSE; xpaned->in_drag_vert_and_horiz = FALSE; xpaned->maximized[GTK_XPANED_TOP_LEFT] = FALSE; xpaned->maximized[GTK_XPANED_TOP_RIGHT] = FALSE; xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] = FALSE; xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT] = FALSE; xpaned->priv = g_new0 (GtkXPanedPrivate, 1); xpaned->last_top_left_child_focus = NULL; xpaned->last_top_right_child_focus = NULL; xpaned->last_bottom_left_child_focus = NULL; xpaned->last_bottom_right_child_focus = NULL; xpaned->in_recursion = FALSE; xpaned->handle_prelit = FALSE; xpaned->original_position.x = -1; xpaned->original_position.y = -1; xpaned->unmaximized_position.x = -1; xpaned->unmaximized_position.y = -1; xpaned->handle_pos_east.x = -1; xpaned->handle_pos_east.y = -1; xpaned->handle_pos_west.x = -1; xpaned->handle_pos_west.y = -1; xpaned->handle_pos_north.x = -1; xpaned->handle_pos_north.y = -1; xpaned->handle_pos_south.x = -1; xpaned->handle_pos_south.y = -1; xpaned->handle_pos_middle.x = -1; xpaned->handle_pos_middle.y = -1; xpaned->drag_pos.x = -1; xpaned->drag_pos.y = -1; } static void gtk_xpaned_size_request (GtkWidget* widget, GtkRequisition* requisition) { GtkXPaned* xpaned = GTK_XPANED (widget); GtkRequisition child_requisition; requisition->width = 0; requisition->height = 0; if (xpaned->top_left_child && gtk_widget_get_visible (xpaned->top_left_child)) { gtk_widget_size_request (xpaned->top_left_child, &child_requisition); requisition->width = child_requisition.width; requisition->height = child_requisition.height; } if (xpaned->top_right_child && gtk_widget_get_visible (xpaned->top_right_child)) { gtk_widget_size_request (xpaned->top_right_child, &child_requisition); requisition->width += child_requisition.width; requisition->height = MAX (requisition->height, child_requisition.height); } if (xpaned->bottom_left_child && gtk_widget_get_visible (xpaned->bottom_left_child)) { gtk_widget_size_request (xpaned->bottom_left_child, &child_requisition); requisition->width = MAX (requisition->width, child_requisition.width); requisition->height += child_requisition.height; } if (xpaned->bottom_right_child && gtk_widget_get_visible (xpaned->bottom_right_child)) { gtk_widget_size_request (xpaned->bottom_right_child, &child_requisition); requisition->width = MAX (requisition->width, child_requisition.width); requisition->height = MAX (requisition->height, child_requisition.height); } /* add 2 times the set border-width to the GtkXPaneds requisition */ requisition->width += GTK_CONTAINER (xpaned)->border_width * 2; requisition->height += GTK_CONTAINER (xpaned)->border_width * 2; /* also add the handle "thickness" to GtkXPaneds width- and height-requisitions */ if (xpaned->top_left_child && gtk_widget_get_visible (xpaned->top_left_child) && xpaned->top_right_child && gtk_widget_get_visible (xpaned->top_right_child) && xpaned->bottom_left_child && gtk_widget_get_visible (xpaned->bottom_left_child) && xpaned->bottom_right_child && gtk_widget_get_visible (xpaned->bottom_right_child)) { gint handle_size; gtk_widget_style_get (widget, "handle-size", &handle_size, NULL); requisition->width += handle_size; requisition->height += handle_size; } } void gtk_xpaned_compute_position (GtkXPaned* xpaned, const GtkAllocation* allocation, GtkRequisition* top_left_child_req, GtkRequisition* top_right_child_req, GtkRequisition* bottom_left_child_req, GtkRequisition* bottom_right_child_req); static void gtk_xpaned_size_allocate (GtkWidget* widget, GtkAllocation* allocation) { GtkXPaned* xpaned = GTK_XPANED (widget); gint border_width = GTK_CONTAINER (xpaned)->border_width; GtkAllocation top_left_child_allocation; GtkAllocation top_right_child_allocation; GtkAllocation bottom_left_child_allocation; GtkAllocation bottom_right_child_allocation; GtkRequisition top_left_child_requisition; GtkRequisition top_right_child_requisition; GtkRequisition bottom_left_child_requisition; GtkRequisition bottom_right_child_requisition; gint handle_size; /* determine size of handle(s) */ gtk_widget_style_get (widget, "handle-size", &handle_size, NULL); widget->allocation = *allocation; if (xpaned->top_left_child && gtk_widget_get_visible (xpaned->top_left_child) && xpaned->top_right_child && gtk_widget_get_visible (xpaned->top_right_child) && xpaned->bottom_left_child && gtk_widget_get_visible (xpaned->bottom_left_child) && xpaned->bottom_right_child && gtk_widget_get_visible (xpaned->bottom_right_child)) { /* what sizes do the children want to be at least at */ gtk_widget_get_child_requisition (xpaned->top_left_child, &top_left_child_requisition); gtk_widget_get_child_requisition (xpaned->top_right_child, &top_right_child_requisition); gtk_widget_get_child_requisition (xpaned->bottom_left_child, &bottom_left_child_requisition); gtk_widget_get_child_requisition (xpaned->bottom_right_child, &bottom_right_child_requisition); /* determine the total requisition-sum of all requisitions of borders, * handles, children etc. */ gtk_xpaned_compute_position (xpaned, allocation, &top_left_child_requisition, &top_right_child_requisition, &bottom_left_child_requisition, &bottom_right_child_requisition); /* calculate the current positions and sizes of the handles */ xpaned->handle_pos_east.x = widget->allocation.x + border_width + xpaned->top_left_child_size.width + handle_size; xpaned->handle_pos_east.y = widget->allocation.y + border_width + xpaned->top_left_child_size.height; xpaned->handle_pos_east.width = widget->allocation.width - xpaned->top_left_child_size.width - 2 * border_width - handle_size; xpaned->handle_pos_east.height = handle_size; xpaned->handle_pos_west.x = widget->allocation.x + border_width; xpaned->handle_pos_west.y = xpaned->handle_pos_east.y; xpaned->handle_pos_west.width = widget->allocation.width - xpaned->handle_pos_east.width - 2 * border_width - handle_size; xpaned->handle_pos_west.height = handle_size; xpaned->handle_pos_north.x = xpaned->handle_pos_east.x - handle_size; xpaned->handle_pos_north.y = widget->allocation.y + border_width; xpaned->handle_pos_north.width = handle_size; xpaned->handle_pos_north.height = xpaned->handle_pos_east.y - widget->allocation.y - border_width; xpaned->handle_pos_south.x = xpaned->handle_pos_north.x; xpaned->handle_pos_south.y = xpaned->handle_pos_east.y + handle_size; xpaned->handle_pos_south.width = handle_size; xpaned->handle_pos_south.height = widget->allocation.height - xpaned->handle_pos_north.height - 2 * border_width - handle_size; #define CENTRUM 20 xpaned->handle_pos_middle.x = xpaned->handle_pos_north.x ; xpaned->handle_pos_middle.y = xpaned->handle_pos_east.y ; xpaned->handle_pos_middle.width = handle_size + CENTRUM ; xpaned->handle_pos_middle.height = handle_size + CENTRUM; /* set allocation for top-left child */ top_left_child_allocation.x = widget->allocation.x + border_width; top_left_child_allocation.y = widget->allocation.y + border_width; top_left_child_allocation.width = xpaned->handle_pos_west.width; top_left_child_allocation.height = xpaned->handle_pos_north.height; /* set allocation for top-right child */ top_right_child_allocation.x = widget->allocation.x + border_width + handle_size + top_left_child_allocation.width; top_right_child_allocation.y = widget->allocation.y + border_width; top_right_child_allocation.width = xpaned->handle_pos_east.width; top_right_child_allocation.height = xpaned->handle_pos_north.height; /* set allocation for bottom-left child */ bottom_left_child_allocation.x = xpaned->handle_pos_west.x; bottom_left_child_allocation.y = xpaned->handle_pos_south.y; bottom_left_child_allocation.width = xpaned->handle_pos_west.width; bottom_left_child_allocation.height = xpaned->handle_pos_south.height; /* set allocation for bottom-right child */ bottom_right_child_allocation.x = top_right_child_allocation.x; bottom_right_child_allocation.y = bottom_left_child_allocation.y; bottom_right_child_allocation.width = xpaned->handle_pos_east.width; bottom_right_child_allocation.height = xpaned->handle_pos_south.height; if (gtk_widget_get_realized (widget)) { if (gtk_widget_get_mapped (widget)) { gdk_window_show (xpaned->handle_east); gdk_window_show (xpaned->handle_west); gdk_window_show (xpaned->handle_north); gdk_window_show (xpaned->handle_south); gdk_window_show (xpaned->handle_middle); } gdk_window_move_resize (xpaned->handle_east, xpaned->handle_pos_east.x, xpaned->handle_pos_east.y, xpaned->handle_pos_east.width, xpaned->handle_pos_east.height); gdk_window_move_resize (xpaned->handle_west, xpaned->handle_pos_west.x, xpaned->handle_pos_west.y, xpaned->handle_pos_west.width, xpaned->handle_pos_west.height); gdk_window_move_resize (xpaned->handle_north, xpaned->handle_pos_north.x, xpaned->handle_pos_north.y, xpaned->handle_pos_north.width, xpaned->handle_pos_north.height); gdk_window_move_resize (xpaned->handle_south, xpaned->handle_pos_south.x, xpaned->handle_pos_south.y, xpaned->handle_pos_south.width, xpaned->handle_pos_south.height); gdk_window_move_resize (xpaned->handle_middle, xpaned->handle_pos_middle.x, xpaned->handle_pos_middle.y, xpaned->handle_pos_middle.width, xpaned->handle_pos_middle.height); } /* Now allocate the childen, making sure, when resizing not to * overlap the windows */ if (gtk_widget_get_mapped (widget)) { gtk_widget_size_allocate (xpaned->top_right_child, &top_right_child_allocation); gtk_widget_size_allocate (xpaned->top_left_child, &top_left_child_allocation); gtk_widget_size_allocate (xpaned->bottom_left_child, &bottom_left_child_allocation); gtk_widget_size_allocate (xpaned->bottom_right_child, &bottom_right_child_allocation); } } } static void gtk_xpaned_set_property (GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { GtkXPaned* xpaned = GTK_XPANED (object); switch (prop_id) { case PROP_X_POSITION: gtk_xpaned_set_position_x (xpaned, g_value_get_int (value)); break; case PROP_Y_POSITION: gtk_xpaned_set_position_y (xpaned, g_value_get_int (value)); break; case PROP_POSITION_SET: xpaned->position_set = g_value_get_boolean (value); gtk_widget_queue_resize (GTK_WIDGET (xpaned)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gtk_xpaned_get_property (GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { GtkXPaned* xpaned = GTK_XPANED (object); switch (prop_id) { case PROP_X_POSITION: g_value_set_int (value, xpaned->top_left_child_size.width); break; case PROP_Y_POSITION: g_value_set_int (value, xpaned->top_left_child_size.height); break; case PROP_POSITION_SET: g_value_set_boolean (value, xpaned->position_set); break; case PROP_MIN_X_POSITION: g_value_set_int (value, xpaned->min_position.x); break; case PROP_MIN_Y_POSITION: g_value_set_int (value, xpaned->min_position.y); break; case PROP_MAX_X_POSITION: g_value_set_int (value, xpaned->max_position.x); break; case PROP_MAX_Y_POSITION: g_value_set_int (value, xpaned->max_position.y); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gtk_xpaned_set_child_property (GtkContainer* container, GtkWidget* child, guint property_id, const GValue* value, GParamSpec* pspec) { GtkXPaned* xpaned = GTK_XPANED (container); gboolean old_value = FALSE; gboolean new_value = FALSE; g_assert (child == xpaned->top_left_child || child == xpaned->top_right_child || child == xpaned->bottom_left_child || child == xpaned->bottom_right_child); new_value = g_value_get_boolean (value); switch (property_id) { case CHILD_PROP_RESIZE: if (child == xpaned->top_left_child) { old_value = xpaned->top_left_child_resize; xpaned->top_left_child_resize = new_value; } else if (child == xpaned->top_right_child) { old_value = xpaned->top_right_child_resize; xpaned->top_right_child_resize = new_value; } else if (child == xpaned->bottom_left_child) { old_value = xpaned->bottom_left_child_resize; xpaned->bottom_left_child_resize = new_value; } else if (child == xpaned->bottom_right_child) { old_value = xpaned->bottom_right_child_resize; xpaned->bottom_right_child_resize = new_value; } break; case CHILD_PROP_SHRINK : if (child == xpaned->top_left_child) { old_value = xpaned->top_left_child_shrink; xpaned->top_left_child_shrink = new_value; } else if (child == xpaned->top_right_child) { old_value = xpaned->top_right_child_shrink; xpaned->top_right_child_shrink = new_value; } else if (child == xpaned->bottom_left_child) { old_value = xpaned->bottom_left_child_shrink; xpaned->bottom_left_child_shrink = new_value; } else if (child == xpaned->bottom_right_child) { old_value = xpaned->bottom_right_child_shrink; xpaned->bottom_right_child_shrink = new_value; } break; default: GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec); old_value = -1; /* quiet gcc */ break; } if (old_value != new_value) gtk_widget_queue_resize (GTK_WIDGET (container)); } static void gtk_xpaned_get_child_property (GtkContainer* container, GtkWidget* child, guint property_id, GValue* value, GParamSpec* pspec) { GtkXPaned* xpaned = GTK_XPANED (container); g_assert (child == xpaned->top_left_child || child == xpaned->top_right_child || child == xpaned->bottom_left_child || child == xpaned->bottom_right_child); switch (property_id) { case CHILD_PROP_RESIZE : if (child == xpaned->top_left_child) g_value_set_boolean (value, xpaned->top_left_child_resize); else if (child == xpaned->top_right_child) g_value_set_boolean (value, xpaned->top_right_child_resize); else if (child == xpaned->bottom_left_child) g_value_set_boolean (value, xpaned->bottom_left_child_resize); else if (child == xpaned->bottom_right_child) g_value_set_boolean (value, xpaned->bottom_right_child_resize); break; case CHILD_PROP_SHRINK : if (child == xpaned->top_left_child) g_value_set_boolean (value, xpaned->top_left_child_shrink); else if (child == xpaned->top_right_child) g_value_set_boolean (value, xpaned->top_right_child_shrink); else if (child == xpaned->bottom_left_child) g_value_set_boolean (value, xpaned->bottom_left_child_shrink); else if (child == xpaned->bottom_right_child) g_value_set_boolean (value, xpaned->bottom_right_child_shrink); break; default: GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec); break; } } static void gtk_xpaned_finalize (GObject* object) { GtkXPaned* xpaned = GTK_XPANED (object); gtk_xpaned_set_saved_focus (xpaned, NULL); gtk_xpaned_set_first_xpaned (xpaned, NULL); g_free (xpaned->priv); G_OBJECT_CLASS (parent_class)->finalize (object); } static void gtk_xpaned_realize (GtkWidget* widget) { GtkXPaned* xpaned; GdkWindowAttr attributes_east; GdkWindowAttr attributes_west; GdkWindowAttr attributes_north; GdkWindowAttr attributes_south; GdkWindowAttr attributes_middle; gint attributes_mask_east; gint attributes_mask_west; gint attributes_mask_north; gint attributes_mask_south; gint attributes_mask_middle; GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); xpaned = GTK_XPANED (widget); widget->window = gtk_widget_get_parent_window (widget); g_object_ref (widget->window); attributes_east.window_type = GDK_WINDOW_CHILD; attributes_west.window_type = GDK_WINDOW_CHILD; attributes_north.window_type = GDK_WINDOW_CHILD; attributes_south.window_type = GDK_WINDOW_CHILD; attributes_middle.window_type = GDK_WINDOW_CHILD; attributes_east.wclass = GDK_INPUT_ONLY; attributes_west.wclass = GDK_INPUT_ONLY; attributes_north.wclass = GDK_INPUT_ONLY; attributes_south.wclass = GDK_INPUT_ONLY; attributes_middle.wclass = GDK_INPUT_ONLY; attributes_east.x = xpaned->handle_pos_east.x; attributes_east.y = xpaned->handle_pos_east.y; attributes_east.width = xpaned->handle_pos_east.width; attributes_east.height = xpaned->handle_pos_east.height; attributes_west.x = xpaned->handle_pos_west.x; attributes_west.y = xpaned->handle_pos_west.y; attributes_west.width = xpaned->handle_pos_west.width; attributes_west.height = xpaned->handle_pos_west.height; attributes_north.x = xpaned->handle_pos_north.x; attributes_north.y = xpaned->handle_pos_north.y; attributes_north.width = xpaned->handle_pos_north.width; attributes_north.height = xpaned->handle_pos_north.height; attributes_south.x = xpaned->handle_pos_south.x; attributes_south.y = xpaned->handle_pos_south.y; attributes_south.width = xpaned->handle_pos_south.width; attributes_south.height = xpaned->handle_pos_south.height; attributes_middle.x = xpaned->handle_pos_middle.x; attributes_middle.y = xpaned->handle_pos_middle.y; attributes_middle.width = xpaned->handle_pos_middle.width; attributes_middle.height = xpaned->handle_pos_middle.height; attributes_east.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), xpaned->cursor_type_east); attributes_west.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), xpaned->cursor_type_west); attributes_north.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), xpaned->cursor_type_north); attributes_south.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), xpaned->cursor_type_south); attributes_middle.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), xpaned->cursor_type_middle); attributes_east.event_mask = gtk_widget_get_events (widget); attributes_west.event_mask = gtk_widget_get_events (widget); attributes_north.event_mask = gtk_widget_get_events (widget); attributes_south.event_mask = gtk_widget_get_events (widget); attributes_middle.event_mask = gtk_widget_get_events (widget); attributes_east.event_mask |= (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); attributes_west.event_mask |= (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); attributes_north.event_mask |= (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); attributes_south.event_mask |= (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); attributes_middle.event_mask |= (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); attributes_mask_east = GDK_WA_X | GDK_WA_Y | GDK_WA_CURSOR; attributes_mask_west = GDK_WA_X | GDK_WA_Y | GDK_WA_CURSOR; attributes_mask_north = GDK_WA_X | GDK_WA_Y | GDK_WA_CURSOR; attributes_mask_south = GDK_WA_X | GDK_WA_Y | GDK_WA_CURSOR; attributes_mask_middle = GDK_WA_X | GDK_WA_Y | GDK_WA_CURSOR; xpaned->handle_east = gdk_window_new (widget->window, &attributes_east, attributes_mask_east); xpaned->handle_west = gdk_window_new (widget->window, &attributes_west, attributes_mask_west); xpaned->handle_north = gdk_window_new (widget->window, &attributes_north, attributes_mask_north); xpaned->handle_south = gdk_window_new (widget->window, &attributes_south, attributes_mask_south); xpaned->handle_middle = gdk_window_new (widget->window, &attributes_middle, attributes_mask_middle); gdk_window_set_user_data (xpaned->handle_east, xpaned); gdk_window_set_user_data (xpaned->handle_west, xpaned); gdk_window_set_user_data (xpaned->handle_north, xpaned); gdk_window_set_user_data (xpaned->handle_south, xpaned); gdk_window_set_user_data (xpaned->handle_middle, xpaned); gdk_cursor_unref (attributes_east.cursor); gdk_cursor_unref (attributes_west.cursor); gdk_cursor_unref (attributes_north.cursor); gdk_cursor_unref (attributes_south.cursor); gdk_cursor_unref (attributes_middle.cursor); widget->style = gtk_style_attach (widget->style, widget->window); if (xpaned->top_left_child && gtk_widget_get_visible (xpaned->top_left_child) && xpaned->top_right_child && gtk_widget_get_visible (xpaned->top_right_child) && xpaned->bottom_left_child && gtk_widget_get_visible (xpaned->bottom_left_child) && xpaned->bottom_right_child && gtk_widget_get_visible (xpaned->bottom_right_child)) { gdk_window_show (xpaned->handle_east); gdk_window_show (xpaned->handle_west); gdk_window_show (xpaned->handle_north); gdk_window_show (xpaned->handle_south); gdk_window_show (xpaned->handle_middle); } } static void gtk_xpaned_unrealize (GtkWidget *widget) { GtkXPaned* xpaned = GTK_XPANED (widget); if (xpaned->xor_gc) { g_object_unref (xpaned->xor_gc); xpaned->xor_gc = NULL; } if (xpaned->handle_east) { gdk_window_set_user_data (xpaned->handle_east, NULL); gdk_window_destroy (xpaned->handle_east); xpaned->handle_east = NULL; } if (xpaned->handle_west) { gdk_window_set_user_data (xpaned->handle_west, NULL); gdk_window_destroy (xpaned->handle_west); xpaned->handle_west = NULL; } if (xpaned->handle_north) { gdk_window_set_user_data (xpaned->handle_north, NULL); gdk_window_destroy (xpaned->handle_north); xpaned->handle_north = NULL; } if (xpaned->handle_south) { gdk_window_set_user_data (xpaned->handle_south, NULL); gdk_window_destroy (xpaned->handle_south); xpaned->handle_south = NULL; } if (xpaned->handle_middle) { gdk_window_set_user_data (xpaned->handle_middle, NULL); gdk_window_destroy (xpaned->handle_middle); xpaned->handle_middle = NULL; } gtk_xpaned_set_last_top_left_child_focus (xpaned, NULL); gtk_xpaned_set_last_top_right_child_focus (xpaned, NULL); gtk_xpaned_set_last_bottom_left_child_focus (xpaned, NULL); gtk_xpaned_set_last_bottom_right_child_focus (xpaned, NULL); gtk_xpaned_set_saved_focus (xpaned, NULL); gtk_xpaned_set_first_xpaned (xpaned, NULL); if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); } static void gtk_xpaned_map (GtkWidget* widget) { GtkXPaned* xpaned = GTK_XPANED (widget); gdk_window_show (xpaned->handle_east); gdk_window_show (xpaned->handle_west); gdk_window_show (xpaned->handle_north); gdk_window_show (xpaned->handle_south); gdk_window_show (xpaned->handle_middle); GTK_WIDGET_CLASS (parent_class)->map (widget); } static void gtk_xpaned_unmap (GtkWidget* widget) { GtkXPaned* xpaned = GTK_XPANED (widget); gdk_window_hide (xpaned->handle_east); gdk_window_hide (xpaned->handle_west); gdk_window_hide (xpaned->handle_north); gdk_window_hide (xpaned->handle_south); gdk_window_hide (xpaned->handle_middle); GTK_WIDGET_CLASS (parent_class)->unmap (widget); } static gboolean gtk_xpaned_expose (GtkWidget* widget, GdkEventExpose* event) { GtkXPaned* xpaned = GTK_XPANED (widget); gint handle_size; GdkRectangle horizontalClipArea; GdkRectangle verticalClipArea; /* determine size of handle(s) */ gtk_widget_style_get (widget, "handle-size", &handle_size, NULL); /* I want the handle-"thickness" to be at least 3 */ g_assert (handle_size >= 3); if (gtk_widget_get_visible (widget) && gtk_widget_get_mapped (widget) && xpaned->top_left_child && gtk_widget_get_visible (xpaned->top_left_child) && xpaned->top_right_child && gtk_widget_get_visible (xpaned->top_right_child) && xpaned->bottom_left_child && gtk_widget_get_visible (xpaned->bottom_left_child) && xpaned->bottom_right_child && gtk_widget_get_visible (xpaned->bottom_right_child)) { GtkStateType state; if (gtk_widget_is_focus (widget)) state = GTK_STATE_SELECTED; else if (xpaned->handle_prelit) state = GTK_STATE_PRELIGHT; else state = gtk_widget_get_state (widget); horizontalClipArea.x = xpaned->handle_pos_west.x; horizontalClipArea.y = xpaned->handle_pos_west.y; horizontalClipArea.width = xpaned->handle_pos_west.width + handle_size + xpaned->handle_pos_east.width; horizontalClipArea.height = handle_size; verticalClipArea.x = xpaned->handle_pos_north.x; verticalClipArea.y = xpaned->handle_pos_north.y; verticalClipArea.width = handle_size; verticalClipArea.height = xpaned->handle_pos_north.height + handle_size + xpaned->handle_pos_south.height; gtk_paint_handle (widget->style, widget->window, state, GTK_SHADOW_NONE, &horizontalClipArea, widget, "paned", xpaned->handle_pos_east.x - handle_size - 256 / 2, xpaned->handle_pos_west.y + 1, 256 + handle_size, handle_size - 2, /*xpaned->handle_pos_west.x, xpaned->handle_pos_west.y + 1, xpaned->handle_pos_west.width + handle_size + xpaned->handle_pos_east.width, handle_size - 2,*/ GTK_ORIENTATION_HORIZONTAL); gtk_paint_handle (widget->style, widget->window, state, GTK_SHADOW_NONE, &verticalClipArea, widget, "paned", xpaned->handle_pos_north.x + 1, xpaned->handle_pos_south.y - handle_size - 256 / 2, handle_size - 2, 256 + handle_size, /*xpaned->handle_pos_north.x + 1, xpaned->handle_pos_north.y, handle_size - 2, xpaned->handle_pos_north.height + handle_size + xpaned->handle_pos_south.height,*/ GTK_ORIENTATION_VERTICAL); } /* Chain up to draw children */ GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); return FALSE; } static gboolean is_rtl (GtkXPaned* xpaned) { if (gtk_widget_get_direction (GTK_WIDGET (xpaned)) == GTK_TEXT_DIR_RTL) return TRUE; return FALSE; } static void update_drag (GtkXPaned* xpaned) { GdkPoint pos; gint handle_size; GtkRequisition size; gtk_widget_get_pointer (GTK_WIDGET (xpaned), &pos.x, &pos.y); if (xpaned->in_drag_vert) { pos.y -= xpaned->drag_pos.y; if (is_rtl (xpaned)) { gtk_widget_style_get (GTK_WIDGET (xpaned), "handle-size", &handle_size, NULL); size.height = GTK_WIDGET (xpaned)->allocation.height - pos.y - handle_size; } else { size.height = pos.y; } size.height -= GTK_CONTAINER (xpaned)->border_width; size.height = CLAMP (size.height, xpaned->min_position.y, xpaned->max_position.y); if (size.height != xpaned->top_left_child_size.height) gtk_xpaned_set_position_y (xpaned, size.height); } if (xpaned->in_drag_horiz) { pos.x -= xpaned->drag_pos.x; if (is_rtl (xpaned)) { gtk_widget_style_get (GTK_WIDGET (xpaned), "handle-size", &handle_size, NULL); size.width = GTK_WIDGET (xpaned)->allocation.width - pos.x - handle_size; } else { size.width = pos.x; } size.width -= GTK_CONTAINER (xpaned)->border_width; size.width = CLAMP (size.width, xpaned->min_position.x, xpaned->max_position.x); if (size.width != xpaned->top_left_child_size.width) gtk_xpaned_set_position_x (xpaned, size.width); } if (xpaned->in_drag_vert_and_horiz) { pos.x -= xpaned->drag_pos.x; pos.y -= xpaned->drag_pos.y; if (is_rtl (xpaned)) { gtk_widget_style_get (GTK_WIDGET (xpaned), "handle-size", &handle_size, NULL); size.width = GTK_WIDGET (xpaned)->allocation.width - pos.x - handle_size; size.height = GTK_WIDGET (xpaned)->allocation.height - pos.y - handle_size; } else { size.width = pos.x; size.height = pos.y; } size.width -= GTK_CONTAINER (xpaned)->border_width; size.height -= GTK_CONTAINER (xpaned)->border_width; size.width = CLAMP (size.width, xpaned->min_position.x, xpaned->max_position.x); size.height = CLAMP (size.height, xpaned->min_position.y, xpaned->max_position.y); if (size.width != xpaned->top_left_child_size.width) gtk_xpaned_set_position_x (xpaned, size.width); if (size.height != xpaned->top_left_child_size.height) gtk_xpaned_set_position_y (xpaned, size.height); } } static gboolean gtk_xpaned_enter (GtkWidget* widget, GdkEventCrossing* event) { GtkXPaned* xpaned = GTK_XPANED (widget); if (xpaned->in_drag_vert || xpaned->in_drag_horiz || xpaned->in_drag_vert_and_horiz) update_drag (xpaned); else { xpaned->handle_prelit = TRUE; gtk_widget_queue_draw_area (widget, xpaned->handle_pos_east.x, xpaned->handle_pos_east.y, xpaned->handle_pos_east.width, xpaned->handle_pos_east.height); gtk_widget_queue_draw_area (widget, xpaned->handle_pos_west.x, xpaned->handle_pos_west.y, xpaned->handle_pos_west.width, xpaned->handle_pos_west.height); gtk_widget_queue_draw_area (widget, xpaned->handle_pos_north.x, xpaned->handle_pos_north.y, xpaned->handle_pos_north.width, xpaned->handle_pos_north.height); gtk_widget_queue_draw_area (widget, xpaned->handle_pos_south.x, xpaned->handle_pos_south.y, xpaned->handle_pos_south.width, xpaned->handle_pos_south.height); gtk_widget_queue_draw_area (widget, xpaned->handle_pos_middle.x, xpaned->handle_pos_middle.y, xpaned->handle_pos_middle.width, xpaned->handle_pos_middle.height); } return TRUE; } static gboolean gtk_xpaned_leave (GtkWidget* widget, GdkEventCrossing* event) { GtkXPaned* xpaned = GTK_XPANED (widget); if (xpaned->in_drag_vert || xpaned->in_drag_horiz || xpaned->in_drag_vert_and_horiz) update_drag (xpaned); else { xpaned->handle_prelit = FALSE; gtk_widget_queue_draw_area (widget, xpaned->handle_pos_east.x, xpaned->handle_pos_east.y, xpaned->handle_pos_east.width, xpaned->handle_pos_east.height); gtk_widget_queue_draw_area (widget, xpaned->handle_pos_west.x, xpaned->handle_pos_west.y, xpaned->handle_pos_west.width, xpaned->handle_pos_west.height); gtk_widget_queue_draw_area (widget, xpaned->handle_pos_north.x, xpaned->handle_pos_north.y, xpaned->handle_pos_north.width, xpaned->handle_pos_north.height); gtk_widget_queue_draw_area (widget, xpaned->handle_pos_south.x, xpaned->handle_pos_south.y, xpaned->handle_pos_south.width, xpaned->handle_pos_south.height); gtk_widget_queue_draw_area (widget, xpaned->handle_pos_middle.x, xpaned->handle_pos_middle.y, xpaned->handle_pos_middle.width, xpaned->handle_pos_middle.height); } return TRUE; } static gboolean gtk_xpaned_focus (GtkWidget* widget, GtkDirectionType direction) { gboolean retval; /* This is a hack, but how can this be done without * excessive cut-and-paste from gtkcontainer.c? */ GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS); retval = (* GTK_WIDGET_CLASS (parent_class)->focus) (widget, direction); GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); return retval; } static gboolean gtk_xpaned_button_press (GtkWidget* widget, GdkEventButton* event) { GtkXPaned* xpaned = GTK_XPANED (widget); /* if any child is currently maximized, jump right back */ if (xpaned->maximized[GTK_XPANED_TOP_LEFT] || xpaned->maximized[GTK_XPANED_TOP_RIGHT] || xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] || xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT]) return FALSE; /* if user is dragging the handles around */ if (!xpaned->in_drag_vert_and_horiz && event->window != xpaned->handle_east && event->window != xpaned->handle_west && event->window != xpaned->handle_north && event->window != xpaned->handle_south && event->window == xpaned->handle_middle && event->button == 1) { xpaned->in_drag_vert_and_horiz = TRUE; /* We need a server grab here, not gtk_grab_add(), since * we don't want to pass events on to the widget's children */ if (gdk_pointer_grab (xpaned->handle_middle, FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK, NULL, NULL, event->time) == GDK_GRAB_SUCCESS) { } xpaned->drag_pos.x = event->x; xpaned->drag_pos.y = event->y; return TRUE; } else if (!xpaned->in_drag_vert && event->window == xpaned->handle_east && event->window != xpaned->handle_west && event->window != xpaned->handle_north && event->window != xpaned->handle_south && event->window != xpaned->handle_middle && event->button == 1) { xpaned->in_drag_vert = TRUE; /* We need a server grab here, not gtk_grab_add(), since * we don't want to pass events on to the widget's children */ if (gdk_pointer_grab (xpaned->handle_east, FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK, NULL, NULL, event->time) == GDK_GRAB_SUCCESS) { } xpaned->drag_pos.y = event->y; return TRUE; } else if (!xpaned->in_drag_vert && event->window != xpaned->handle_east && event->window == xpaned->handle_west && event->window != xpaned->handle_north && event->window != xpaned->handle_south && event->window != xpaned->handle_middle && event->button == 1) { xpaned->in_drag_vert = TRUE; /* We need a server grab here, not gtk_grab_add(), since * we don't want to pass events on to the widget's children */ if (gdk_pointer_grab (xpaned->handle_west, FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK, NULL, NULL, event->time) == GDK_GRAB_SUCCESS) { } xpaned->drag_pos.y = event->y; return TRUE; } else if (!xpaned->in_drag_horiz && event->window != xpaned->handle_east && event->window != xpaned->handle_west && event->window == xpaned->handle_north && event->window != xpaned->handle_south && event->window != xpaned->handle_middle && event->button == 1) { xpaned->in_drag_horiz = TRUE; /* We need a server grab here, not gtk_grab_add(), since * we don't want to pass events on to the widget's children */ if (gdk_pointer_grab (xpaned->handle_north, FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK, NULL, NULL, event->time) == GDK_GRAB_SUCCESS) { } xpaned->drag_pos.x = event->x; return TRUE; } else if (!xpaned->in_drag_horiz && event->window != xpaned->handle_east && event->window != xpaned->handle_west && event->window != xpaned->handle_north && event->window == xpaned->handle_south && event->window != xpaned->handle_middle && event->button == 1) { xpaned->in_drag_horiz = TRUE; /* We need a server grab here, not gtk_grab_add(), since * we don't want to pass events on to the widget's children */ if (gdk_pointer_grab (xpaned->handle_south, FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK, NULL, NULL, event->time) == GDK_GRAB_SUCCESS) { } xpaned->drag_pos.x = event->x; return TRUE; } return FALSE; } static gboolean gtk_xpaned_button_release (GtkWidget* widget, GdkEventButton* event) { GtkXPaned* xpaned = GTK_XPANED (widget); if (xpaned->in_drag_vert && (event->button == 1)) { xpaned->in_drag_vert = FALSE; xpaned->drag_pos.y = -1; xpaned->position_set = TRUE; gdk_display_pointer_ungrab (gtk_widget_get_display (widget), event->time); return TRUE; } else if (xpaned->in_drag_horiz && (event->button == 1)) { xpaned->in_drag_horiz = FALSE; xpaned->drag_pos.x = -1; xpaned->position_set = TRUE; gdk_display_pointer_ungrab (gtk_widget_get_display (widget), event->time); return TRUE; } else if (xpaned->in_drag_vert_and_horiz && (event->button == 1)) { xpaned->in_drag_vert_and_horiz = FALSE; xpaned->drag_pos.x = -1; xpaned->drag_pos.y = -1; xpaned->position_set = TRUE; gdk_display_pointer_ungrab (gtk_widget_get_display (widget), event->time); return TRUE; } return FALSE; } static gboolean gtk_xpaned_motion (GtkWidget* widget, GdkEventMotion* event) { GtkXPaned* xpaned = GTK_XPANED (widget); if (xpaned->in_drag_vert || xpaned->in_drag_horiz || xpaned->in_drag_vert_and_horiz) { update_drag (xpaned); return TRUE; } return FALSE; } void gtk_xpaned_add_top_left (GtkXPaned* xpaned, GtkWidget *widget) { gtk_xpaned_pack_top_left (xpaned, widget, FALSE, TRUE); } void gtk_xpaned_add_top_right (GtkXPaned* xpaned, GtkWidget *widget) { gtk_xpaned_pack_top_right (xpaned, widget, FALSE, TRUE); } void gtk_xpaned_add_bottom_left (GtkXPaned* xpaned, GtkWidget *widget) { gtk_xpaned_pack_bottom_left (xpaned, widget, FALSE, TRUE); } void gtk_xpaned_add_bottom_right (GtkXPaned* xpaned, GtkWidget *widget) { gtk_xpaned_pack_bottom_right (xpaned, widget, FALSE, TRUE); } void gtk_xpaned_pack_top_left (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink) { g_return_if_fail (GTK_IS_XPANED (xpaned)); g_return_if_fail (GTK_IS_WIDGET (child)); if (!xpaned->top_left_child) { xpaned->top_left_child = child; xpaned->top_left_child_resize = resize; xpaned->top_left_child_shrink = shrink; gtk_widget_set_parent (child, GTK_WIDGET (xpaned)); } } void gtk_xpaned_pack_top_right (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink) { g_return_if_fail (GTK_IS_XPANED (xpaned)); g_return_if_fail (GTK_IS_WIDGET (child)); if (!xpaned->top_right_child) { xpaned->top_right_child = child; xpaned->top_right_child_resize = resize; xpaned->top_right_child_shrink = shrink; gtk_widget_set_parent (child, GTK_WIDGET (xpaned)); } } void gtk_xpaned_pack_bottom_left (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink) { g_return_if_fail (GTK_IS_XPANED (xpaned)); g_return_if_fail (GTK_IS_WIDGET (child)); if (!xpaned->bottom_left_child) { xpaned->bottom_left_child = child; xpaned->bottom_left_child_resize = resize; xpaned->bottom_left_child_shrink = shrink; gtk_widget_set_parent (child, GTK_WIDGET (xpaned)); } } void gtk_xpaned_pack_bottom_right (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink) { g_return_if_fail (GTK_IS_XPANED (xpaned)); g_return_if_fail (GTK_IS_WIDGET (child)); if (!xpaned->bottom_right_child) { xpaned->bottom_right_child = child; xpaned->bottom_right_child_resize = resize; xpaned->bottom_right_child_shrink = shrink; gtk_widget_set_parent (child, GTK_WIDGET (xpaned)); } } static void gtk_xpaned_add (GtkContainer* container, GtkWidget* widget) { GtkXPaned* xpaned; g_return_if_fail (GTK_IS_XPANED (container)); xpaned = GTK_XPANED (container); if (!xpaned->top_left_child) gtk_xpaned_add_top_left (xpaned, widget); else if (!xpaned->top_right_child) gtk_xpaned_add_top_right (xpaned, widget); else if (!xpaned->bottom_left_child) gtk_xpaned_add_bottom_left (xpaned, widget); else if (!xpaned->bottom_right_child) gtk_xpaned_add_bottom_right (xpaned, widget); else g_warning ("GtkXPaned cannot have more than 4 children\n"); } static void gtk_xpaned_remove (GtkContainer* container, GtkWidget* widget) { GtkXPaned* xpaned; gboolean was_visible; xpaned = GTK_XPANED (container); was_visible = gtk_widget_get_visible (widget); if (xpaned->top_left_child == widget) { gtk_widget_unparent (widget); xpaned->top_left_child = NULL; if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container))) gtk_widget_queue_resize (GTK_WIDGET (container)); } else if (xpaned->top_right_child == widget) { gtk_widget_unparent (widget); xpaned->top_right_child = NULL; if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container))) gtk_widget_queue_resize (GTK_WIDGET (container)); } else if (xpaned->bottom_left_child == widget) { gtk_widget_unparent (widget); xpaned->bottom_left_child = NULL; if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container))) gtk_widget_queue_resize (GTK_WIDGET (container)); } else if (xpaned->bottom_right_child == widget) { gtk_widget_unparent (widget); xpaned->bottom_right_child = NULL; if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container))) gtk_widget_queue_resize (GTK_WIDGET (container)); } else g_warning ("GtkXPaned has no more children attached\n"); } static void gtk_xpaned_forall (GtkContainer* container, gboolean include_internals, GtkCallback callback, gpointer callback_data) { GtkXPaned* xpaned; g_return_if_fail (callback != NULL); xpaned = GTK_XPANED (container); if (xpaned->top_left_child) (*callback) (xpaned->top_left_child, callback_data); if (xpaned->top_right_child) (*callback) (xpaned->top_right_child, callback_data); if (xpaned->bottom_left_child) (*callback) (xpaned->bottom_left_child, callback_data); if (xpaned->bottom_right_child) (*callback) (xpaned->bottom_right_child, callback_data); } /** * gtk_xpaned_get_position_x: * @paned: a #GtkXPaned widget * * Obtains the x-position of the divider. * * Return value: x-position of the divider **/ gint gtk_xpaned_get_position_x (GtkXPaned* xpaned) { g_return_val_if_fail (GTK_IS_XPANED (xpaned), 0); return xpaned->top_left_child_size.width; } /** * gtk_xpaned_get_position_y: * @paned: a #GtkXPaned widget * * Obtains the y-position of the divider. * * Return value: y-position of the divider **/ gint gtk_xpaned_get_position_y (GtkXPaned* xpaned) { g_return_val_if_fail (GTK_IS_XPANED (xpaned), 0); return xpaned->top_left_child_size.height; } /** * gtk_xpaned_set_position_x: * @paned: a #GtkXPaned widget * @xposition: pixel x-position of divider, a negative values * of a component mean that the position is unset. * * Sets the x-position of the divider between the four panes. **/ void gtk_xpaned_set_position_x (GtkXPaned* xpaned, gint xposition) { GObject* object; g_return_if_fail (GTK_IS_XPANED (xpaned)); /* if any child is currently maximized, jump right back */ if (xpaned->maximized[GTK_XPANED_TOP_LEFT] || xpaned->maximized[GTK_XPANED_TOP_RIGHT] || xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] || xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT]) return; object = G_OBJECT (xpaned); if (xposition >= 0) { /* We don't clamp here - the assumption is that * if the total allocation changes at the same time * as the position, the position set is with reference * to the new total size. If only the position changes, * then clamping will occur in gtk_paned_compute_position() */ xpaned->top_left_child_size.width = xposition; xpaned->position_set = TRUE; } else { xpaned->position_set = FALSE; } g_object_freeze_notify (object); g_object_notify (object, "x-position"); g_object_notify (object, "position-set"); g_object_thaw_notify (object); gtk_widget_queue_resize (GTK_WIDGET (xpaned)); } /** * gtk_xpaned_set_position_y: * @paned: a #GtkXPaned widget * @yposition: pixel y-position of divider, a negative values * of a component mean that the position is unset. * * Sets the y-position of the divider between the four panes. **/ void gtk_xpaned_set_position_y (GtkXPaned* xpaned, gint yposition) { GObject* object; g_return_if_fail (GTK_IS_XPANED (xpaned)); /* if any child is currently maximized, jump right back */ if (xpaned->maximized[GTK_XPANED_TOP_LEFT] || xpaned->maximized[GTK_XPANED_TOP_RIGHT] || xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] || xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT]) return; object = G_OBJECT (xpaned); if (yposition >= 0) { /* We don't clamp here - the assumption is that * if the total allocation changes at the same time * as the position, the position set is with reference * to the new total size. If only the position changes, * then clamping will occur in gtk_paned_compute_position() */ xpaned->top_left_child_size.height = yposition; xpaned->position_set = TRUE; } else { xpaned->position_set = FALSE; } g_object_freeze_notify (object); g_object_notify (object, "y-position"); g_object_notify (object, "position-set"); g_object_thaw_notify (object); gtk_widget_queue_resize (GTK_WIDGET (xpaned)); } /* this call is private and only intended for internal use! */ void gtk_xpaned_save_unmaximized_x (GtkXPaned* xpaned) { xpaned->unmaximized_position.x = gtk_xpaned_get_position_x (xpaned); } /* this call is private and only intended for internal use! */ void gtk_xpaned_save_unmaximized_y (GtkXPaned* xpaned) { xpaned->unmaximized_position.y = gtk_xpaned_get_position_y (xpaned); } /* this call is private and only intended for internal use! */ gint gtk_xpaned_fetch_unmaximized_x (GtkXPaned* xpaned) { return xpaned->unmaximized_position.x; } /* this call is private and only intended for internal use! */ gint gtk_xpaned_fetch_unmaximized_y (GtkXPaned* xpaned) { return xpaned->unmaximized_position.y; } /** * gtk_xpaned_get_top_left_child: * @xpaned: a #GtkXPaned widget * * Obtains the top-left child of the xpaned widget. * * Return value: top-left child, or %NULL if it is not set. * * Since: 2.4 **/ GtkWidget* gtk_xpaned_get_top_left_child (GtkXPaned* xpaned) { g_return_val_if_fail (GTK_IS_XPANED (xpaned), NULL); return xpaned->top_left_child; } /** * gtk_xpaned_get_top_right_child: * @xpaned: a #GtkXPaned widget * * Obtains the top-right child of the xpaned widget. * * Return value: top-right child, or %NULL if it is not set. * * Since: 2.4 **/ GtkWidget* gtk_xpaned_get_top_right_child (GtkXPaned* xpaned) { g_return_val_if_fail (GTK_IS_XPANED (xpaned), NULL); return xpaned->top_right_child; } /** * gtk_xpaned_get_bottom_left_child: * @xpaned: a #GtkXPaned widget * * Obtains the bottom-left child of the xpaned widget. * * Return value: bottom-left child, or %NULL if it is not set. * * Since: 2.4 **/ GtkWidget* gtk_xpaned_get_bottom_left_child (GtkXPaned* xpaned) { g_return_val_if_fail (GTK_IS_XPANED (xpaned), NULL); return xpaned->bottom_left_child; } /** * gtk_xpaned_get_bottom_right_child: * @xpaned: a #GtkXPaned widget * * Obtains the bottom-right child of the xpaned widget. * * Return value: bottom-right child, or %NULL if it is not set. * * Since: 2.4 **/ GtkWidget* gtk_xpaned_get_bottom_right_child (GtkXPaned* xpaned) { g_return_val_if_fail (GTK_IS_XPANED (xpaned), NULL); return xpaned->bottom_right_child; } gboolean gtk_xpaned_maximize_top_left (GtkXPaned* xpaned, gboolean maximize) { if (maximize) { /* see if any child is already maximized */ if (!xpaned->maximized[GTK_XPANED_TOP_LEFT] && !xpaned->maximized[GTK_XPANED_TOP_RIGHT] && !xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] && !xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT]) { /* save current position */ gtk_xpaned_save_unmaximized_x (xpaned); gtk_xpaned_save_unmaximized_y (xpaned); /* set new maximized position */ gtk_xpaned_set_position_x (xpaned, xpaned->max_position.x); gtk_xpaned_set_position_y (xpaned, xpaned->max_position.y); /* mark maximized flag for top-left child */ xpaned->maximized[GTK_XPANED_TOP_LEFT] = TRUE; return TRUE; } /* already one child maximized, report error */ else return FALSE; } else { /* verify that top-left child is really currently maximized */ if (xpaned->maximized[GTK_XPANED_TOP_LEFT]) { /* clear maximized flat for top-left child */ xpaned->maximized[GTK_XPANED_TOP_LEFT] = FALSE; /* restore unmaximized position */ gtk_xpaned_set_position_x (xpaned, gtk_xpaned_fetch_unmaximized_x (xpaned)); gtk_xpaned_set_position_y (xpaned, gtk_xpaned_fetch_unmaximized_y (xpaned)); return TRUE; } /* top-left child is currently not maximized, report error */ else return FALSE; } } gboolean gtk_xpaned_maximize_top_right (GtkXPaned* xpaned, gboolean maximize) { if (maximize) { /* see if any child is already maximized */ if (!xpaned->maximized[GTK_XPANED_TOP_LEFT] && !xpaned->maximized[GTK_XPANED_TOP_RIGHT] && !xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] && !xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT]) { /* save current position */ gtk_xpaned_save_unmaximized_x (xpaned); gtk_xpaned_save_unmaximized_y (xpaned); /* set new maximized position */ gtk_xpaned_set_position_x (xpaned, xpaned->min_position.x); gtk_xpaned_set_position_y (xpaned, xpaned->max_position.y); /* mark maximized flag for top-right child */ xpaned->maximized[GTK_XPANED_TOP_RIGHT] = TRUE; return TRUE; } /* already one child maximized, report error */ else return FALSE; } else { /* verify that top-right child is really currently maximized */ if (xpaned->maximized[GTK_XPANED_TOP_RIGHT]) { /* clear maximized flat for top-right child */ xpaned->maximized[GTK_XPANED_TOP_RIGHT] = FALSE; /* restore unmaximized position */ gtk_xpaned_set_position_x (xpaned, gtk_xpaned_fetch_unmaximized_x (xpaned)); gtk_xpaned_set_position_y (xpaned, gtk_xpaned_fetch_unmaximized_y (xpaned)); return TRUE; } /* top-right child is currently not maximized, report error */ else return FALSE; } } gboolean gtk_xpaned_maximize_bottom_left (GtkXPaned* xpaned, gboolean maximize) { if (maximize) { /* see if any child is already maximized */ if (!xpaned->maximized[GTK_XPANED_TOP_LEFT] && !xpaned->maximized[GTK_XPANED_TOP_RIGHT] && !xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] && !xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT]) { /* save current position */ gtk_xpaned_save_unmaximized_x (xpaned); gtk_xpaned_save_unmaximized_y (xpaned); /* set new maximized position */ gtk_xpaned_set_position_x (xpaned, xpaned->max_position.x); gtk_xpaned_set_position_y (xpaned, xpaned->min_position.y); /* mark maximized flag for bottom-left child */ xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] = TRUE; return TRUE; } /* already one child maximized, report error */ else return FALSE; } else { /* verify that bottom-left child is really currently maximized */ if (xpaned->maximized[GTK_XPANED_BOTTOM_LEFT]) { /* clear maximized flat for bottom-left child */ xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] = FALSE; /* restore unmaximized position */ gtk_xpaned_set_position_x (xpaned, gtk_xpaned_fetch_unmaximized_x (xpaned)); gtk_xpaned_set_position_y (xpaned, gtk_xpaned_fetch_unmaximized_y (xpaned)); return TRUE; } /* bottom-left child is currently not maximized, report error */ else return FALSE; } } gboolean gtk_xpaned_maximize_bottom_right (GtkXPaned* xpaned, gboolean maximize) { if (maximize) { /* see if any child is already maximized */ if (!xpaned->maximized[GTK_XPANED_TOP_LEFT] && !xpaned->maximized[GTK_XPANED_TOP_RIGHT] && !xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] && !xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT]) { /* save current position */ gtk_xpaned_save_unmaximized_x (xpaned); gtk_xpaned_save_unmaximized_y (xpaned); /* set new maximized position */ gtk_xpaned_set_position_x (xpaned, xpaned->min_position.x); gtk_xpaned_set_position_y (xpaned, xpaned->min_position.y); /* mark maximized flag for bottom-right child */ xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT] = TRUE; return TRUE; } /* already one child maximized, report error */ else return FALSE; } else { /* verify that bottom-right child is really currently maximized */ if (xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT]) { /* clear maximized flat for bottom-right child */ xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT] = FALSE; /* restore unmaximized position */ gtk_xpaned_set_position_x (xpaned, gtk_xpaned_fetch_unmaximized_x (xpaned)); gtk_xpaned_set_position_y (xpaned, gtk_xpaned_fetch_unmaximized_y (xpaned)); return TRUE; } /* bottom-right child is currently not maximized, report error */ else return FALSE; } } void gtk_xpaned_compute_position (GtkXPaned* xpaned, const GtkAllocation* allocation, GtkRequisition* top_left_child_req, GtkRequisition* top_right_child_req, GtkRequisition* bottom_left_child_req, GtkRequisition* bottom_right_child_req) { GdkPoint old_position; GdkPoint old_min_position; GdkPoint old_max_position; gint handle_size; gint border_width = GTK_CONTAINER (xpaned)->border_width; g_return_if_fail (GTK_IS_XPANED (xpaned)); old_position.x = xpaned->top_left_child_size.width; old_position.y = xpaned->top_left_child_size.height; old_min_position.x = xpaned->min_position.x; old_min_position.y = xpaned->min_position.y; old_max_position.x = xpaned->max_position.x; old_max_position.y = xpaned->max_position.y; xpaned->min_position.x = xpaned->top_left_child_shrink ? 0 : top_left_child_req->width; xpaned->min_position.y = xpaned->top_left_child_shrink ? 0 : top_left_child_req->height; gtk_widget_style_get (GTK_WIDGET (xpaned), "handle-size", &handle_size, NULL); xpaned->max_position.x = allocation->width - 2 * border_width - handle_size; xpaned->max_position.y = allocation->height - 2 * border_width - handle_size; if (!xpaned->top_left_child_shrink) xpaned->max_position.x = MAX (1, xpaned->max_position.x - top_left_child_req->width); xpaned->max_position.x = MAX (xpaned->min_position.x, xpaned->max_position.x); if (!xpaned->position_set) { if (xpaned->top_left_child_resize && !xpaned->top_right_child_resize) { xpaned->top_left_child_size.width = MAX (0, allocation->width - top_right_child_req->width); xpaned->top_left_child_size.height = MAX (0, allocation->height - top_right_child_req->height); } else if (!xpaned->top_left_child_resize && xpaned->top_right_child_resize) { xpaned->top_left_child_size.width = top_left_child_req->width; xpaned->top_left_child_size.height = top_left_child_req->height; } else if (top_left_child_req->width + top_right_child_req->width != 0) { xpaned->top_left_child_size.width = allocation->width * ((gdouble)top_left_child_req->width / (top_left_child_req->width + top_right_child_req->width)) + 0.5; } else if (top_left_child_req->height + top_right_child_req->height != 0) { xpaned->top_left_child_size.height = allocation->height * ((gdouble)top_left_child_req->height / (top_left_child_req->height + top_right_child_req->height)) + 0.5; } else { xpaned->top_left_child_size.width = allocation->width * 0.5 + 0.5; xpaned->top_left_child_size.height = allocation->height * 0.5 + 0.5; } } else { /* If the position was set before the initial allocation. ** (paned->last_allocation <= 0) just clamp it and leave it. */ if (xpaned->last_allocation.width > 0) { if (xpaned->top_left_child_resize && !xpaned->top_right_child_resize) { xpaned->top_left_child_size.width += allocation->width - xpaned->last_allocation.width; xpaned->top_left_child_size.height += allocation->height - xpaned->last_allocation.height; } else if (!(!xpaned->top_left_child_resize && xpaned->top_right_child_resize)) { xpaned->top_left_child_size.width = allocation->width * ((gdouble) xpaned->top_left_child_size.width / (xpaned->last_allocation.width)) + 0.5; xpaned->top_left_child_size.height = allocation->height * ((gdouble) xpaned->top_left_child_size.height / (xpaned->last_allocation.height)) + 0.5; } } if (xpaned->last_allocation.height > 0) { if (xpaned->top_left_child_resize && !xpaned->top_right_child_resize) { xpaned->top_left_child_size.width += allocation->width - xpaned->last_allocation.width; xpaned->top_left_child_size.height += allocation->height - xpaned->last_allocation.height; } else if (!(!xpaned->top_left_child_resize && xpaned->top_right_child_resize)) { xpaned->top_left_child_size.width = allocation->width * ((gdouble) xpaned->top_left_child_size.width / (xpaned->last_allocation.width)) + 0.5; xpaned->top_left_child_size.height = allocation->height * ((gdouble) xpaned->top_left_child_size.height / (xpaned->last_allocation.height)) + 0.5; } } } xpaned->top_left_child_size.width = CLAMP (xpaned->top_left_child_size.width, xpaned->min_position.x, xpaned->max_position.x); xpaned->top_left_child_size.height = CLAMP (xpaned->top_left_child_size.height, xpaned->min_position.y, xpaned->max_position.y); xpaned->top_right_child_size.width = CLAMP (xpaned->top_right_child_size.width, xpaned->min_position.x, xpaned->max_position.x); xpaned->top_right_child_size.height = CLAMP (xpaned->top_right_child_size.height, xpaned->min_position.y, xpaned->max_position.y); xpaned->bottom_left_child_size.width = CLAMP (xpaned->bottom_left_child_size.width, xpaned->min_position.x, xpaned->max_position.x); xpaned->bottom_left_child_size.height = CLAMP (xpaned->bottom_left_child_size.height, xpaned->min_position.y, xpaned->max_position.y); xpaned->bottom_right_child_size.width = CLAMP (xpaned->bottom_right_child_size.width, xpaned->min_position.x, xpaned->max_position.x); xpaned->bottom_right_child_size.height = CLAMP (xpaned->bottom_right_child_size.height, xpaned->min_position.y, xpaned->max_position.y); gtk_widget_set_child_visible (xpaned->top_left_child, TRUE); gtk_widget_set_child_visible (xpaned->top_right_child, TRUE); gtk_widget_set_child_visible (xpaned->bottom_left_child, TRUE); gtk_widget_set_child_visible (xpaned->bottom_right_child, TRUE); g_object_freeze_notify (G_OBJECT (xpaned)); if (xpaned->top_left_child_size.width != old_position.x) g_object_notify (G_OBJECT (xpaned), "x-position"); if (xpaned->top_left_child_size.height != old_position.y) g_object_notify (G_OBJECT (xpaned), "y-position"); if (xpaned->top_right_child_size.width != old_position.x) g_object_notify (G_OBJECT (xpaned), "x-position"); if (xpaned->top_right_child_size.height != old_position.y) g_object_notify (G_OBJECT (xpaned), "y-position"); if (xpaned->bottom_left_child_size.width != old_position.x) g_object_notify (G_OBJECT (xpaned), "x-position"); if (xpaned->bottom_left_child_size.height != old_position.y) g_object_notify (G_OBJECT (xpaned), "y-position"); if (xpaned->bottom_right_child_size.width != old_position.x) g_object_notify (G_OBJECT (xpaned), "x-position"); if (xpaned->bottom_right_child_size.height != old_position.y) g_object_notify (G_OBJECT (xpaned), "y-position"); if (xpaned->min_position.x != old_min_position.x) g_object_notify (G_OBJECT (xpaned), "min-x-position"); if (xpaned->min_position.y != old_min_position.y) g_object_notify (G_OBJECT (xpaned), "min-y-position"); if (xpaned->max_position.x != old_max_position.x) g_object_notify (G_OBJECT (xpaned), "max-y-position"); if (xpaned->max_position.y != old_max_position.y) g_object_notify (G_OBJECT (xpaned), "max-y-position"); g_object_thaw_notify (G_OBJECT (xpaned)); xpaned->last_allocation.width = allocation->width; xpaned->last_allocation.height = allocation->height; } static void gtk_xpaned_set_saved_focus (GtkXPaned* xpaned, GtkWidget* widget) { if (xpaned->priv->saved_focus) g_object_remove_weak_pointer (G_OBJECT (xpaned->priv->saved_focus), (gpointer *)&(xpaned->priv->saved_focus)); xpaned->priv->saved_focus = widget; if (xpaned->priv->saved_focus) g_object_add_weak_pointer (G_OBJECT (xpaned->priv->saved_focus), (gpointer *)&(xpaned->priv->saved_focus)); } static void gtk_xpaned_set_first_xpaned (GtkXPaned* xpaned, GtkXPaned* first_xpaned) { if (xpaned->priv->first_xpaned) g_object_remove_weak_pointer (G_OBJECT (xpaned->priv->first_xpaned), (gpointer *)&(xpaned->priv->first_xpaned)); xpaned->priv->first_xpaned = first_xpaned; if (xpaned->priv->first_xpaned) g_object_add_weak_pointer (G_OBJECT (xpaned->priv->first_xpaned), (gpointer *)&(xpaned->priv->first_xpaned)); } static void gtk_xpaned_set_last_top_left_child_focus (GtkXPaned* xpaned, GtkWidget* widget) { if (xpaned->last_top_left_child_focus) g_object_remove_weak_pointer (G_OBJECT (xpaned->last_top_left_child_focus), (gpointer *)&(xpaned->last_top_left_child_focus)); xpaned->last_top_left_child_focus = widget; if (xpaned->last_top_left_child_focus) g_object_add_weak_pointer (G_OBJECT (xpaned->last_top_left_child_focus), (gpointer *)&(xpaned->last_top_left_child_focus)); } static void gtk_xpaned_set_last_top_right_child_focus (GtkXPaned* xpaned, GtkWidget *widget) { if (xpaned->last_top_right_child_focus) g_object_remove_weak_pointer (G_OBJECT (xpaned->last_top_right_child_focus), (gpointer *)&(xpaned->last_top_right_child_focus)); xpaned->last_top_right_child_focus = widget; if (xpaned->last_top_right_child_focus) g_object_add_weak_pointer (G_OBJECT (xpaned->last_top_right_child_focus), (gpointer *)&(xpaned->last_top_right_child_focus)); } static void gtk_xpaned_set_last_bottom_left_child_focus (GtkXPaned* xpaned, GtkWidget *widget) { if (xpaned->last_bottom_left_child_focus) g_object_remove_weak_pointer (G_OBJECT (xpaned->last_bottom_left_child_focus), (gpointer *)&(xpaned->last_bottom_left_child_focus)); xpaned->last_bottom_left_child_focus = widget; if (xpaned->last_bottom_left_child_focus) g_object_add_weak_pointer (G_OBJECT (xpaned->last_bottom_left_child_focus), (gpointer *)&(xpaned->last_bottom_left_child_focus)); } static void gtk_xpaned_set_last_bottom_right_child_focus (GtkXPaned* xpaned, GtkWidget *widget) { if (xpaned->last_bottom_right_child_focus) g_object_remove_weak_pointer (G_OBJECT (xpaned->last_bottom_right_child_focus), (gpointer *)&(xpaned->last_bottom_right_child_focus)); xpaned->last_bottom_right_child_focus = widget; if (xpaned->last_bottom_right_child_focus) g_object_add_weak_pointer (G_OBJECT (xpaned->last_bottom_right_child_focus), (gpointer *)&(xpaned->last_bottom_right_child_focus)); } static GtkWidget* xpaned_get_focus_widget (GtkXPaned* xpaned) { GtkWidget* toplevel; toplevel = gtk_widget_get_toplevel (GTK_WIDGET (xpaned)); if (gtk_widget_is_toplevel (toplevel)) return GTK_WINDOW (toplevel)->focus_widget; return NULL; } static void gtk_xpaned_set_focus_child (GtkContainer* container, GtkWidget* focus_child) { GtkXPaned* xpaned; g_return_if_fail (GTK_IS_XPANED (container)); xpaned = GTK_XPANED (container); if (focus_child == NULL) { GtkWidget* last_focus; GtkWidget* w; last_focus = xpaned_get_focus_widget (xpaned); if (last_focus) { /* If there is one or more paned widgets between us and the * focus widget, we want the topmost of those as last_focus */ for (w = last_focus; w != GTK_WIDGET (xpaned); w = w->parent) if (GTK_IS_XPANED (w)) last_focus = w; if (container->focus_child == xpaned->top_left_child) gtk_xpaned_set_last_top_left_child_focus (xpaned, last_focus); else if (container->focus_child == xpaned->top_right_child) gtk_xpaned_set_last_top_right_child_focus (xpaned, last_focus); else if (container->focus_child == xpaned->bottom_left_child) gtk_xpaned_set_last_bottom_left_child_focus (xpaned, last_focus); else if (container->focus_child == xpaned->bottom_right_child) gtk_xpaned_set_last_bottom_right_child_focus (xpaned, last_focus); } } if (parent_class->set_focus_child) (* parent_class->set_focus_child) (container, focus_child); } static void gtk_xpaned_get_cycle_chain (GtkXPaned* xpaned, GtkDirectionType direction, GList** widgets) { GtkContainer* container = GTK_CONTAINER (xpaned); GtkWidget* ancestor = NULL; GList* temp_list = NULL; GList* list; if (xpaned->in_recursion) return; g_assert (widgets != NULL); if (xpaned->last_top_left_child_focus && !gtk_widget_is_ancestor (xpaned->last_top_left_child_focus, GTK_WIDGET (xpaned))) { gtk_xpaned_set_last_top_left_child_focus (xpaned, NULL); } if (xpaned->last_top_right_child_focus && !gtk_widget_is_ancestor (xpaned->last_top_right_child_focus, GTK_WIDGET (xpaned))) { gtk_xpaned_set_last_top_right_child_focus (xpaned, NULL); } if (xpaned->last_bottom_left_child_focus && !gtk_widget_is_ancestor (xpaned->last_bottom_left_child_focus, GTK_WIDGET (xpaned))) { gtk_xpaned_set_last_bottom_left_child_focus (xpaned, NULL); } if (xpaned->last_bottom_right_child_focus && !gtk_widget_is_ancestor (xpaned->last_bottom_right_child_focus, GTK_WIDGET (xpaned))) { gtk_xpaned_set_last_bottom_right_child_focus (xpaned, NULL); } if (GTK_WIDGET (xpaned)->parent) ancestor = gtk_widget_get_ancestor (GTK_WIDGET (xpaned)->parent, GTK_TYPE_XPANED); /* The idea here is that temp_list is a list of widgets we want to cycle * to. The list is prioritized so that the first element is our first * choice, the next our second, and so on. * * We can't just use g_list_reverse(), because we want to try * paned->last_child?_focus before paned->child?, both when we * are going forward and backward. */ if (direction == GTK_DIR_TAB_FORWARD) { if (container->focus_child == xpaned->top_left_child) { temp_list = g_list_append (temp_list, xpaned->last_top_right_child_focus); temp_list = g_list_append (temp_list, xpaned->top_right_child); temp_list = g_list_append (temp_list, ancestor); } else if (container->focus_child == xpaned->top_right_child) { temp_list = g_list_append (temp_list, ancestor); temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus); temp_list = g_list_append (temp_list, xpaned->bottom_left_child); } else if (container->focus_child == xpaned->bottom_left_child) { temp_list = g_list_append (temp_list, ancestor); temp_list = g_list_append (temp_list, xpaned->last_bottom_right_child_focus); temp_list = g_list_append (temp_list, xpaned->bottom_right_child); } else if (container->focus_child == xpaned->bottom_right_child) { temp_list = g_list_append (temp_list, ancestor); temp_list = g_list_append (temp_list, xpaned->last_top_left_child_focus); temp_list = g_list_append (temp_list, xpaned->top_left_child); } else { temp_list = g_list_append (temp_list, xpaned->last_top_left_child_focus); temp_list = g_list_append (temp_list, xpaned->top_left_child); temp_list = g_list_append (temp_list, xpaned->last_top_right_child_focus); temp_list = g_list_append (temp_list, xpaned->top_right_child); temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus); temp_list = g_list_append (temp_list, xpaned->bottom_left_child); temp_list = g_list_append (temp_list, xpaned->last_bottom_right_child_focus); temp_list = g_list_append (temp_list, xpaned->bottom_right_child); temp_list = g_list_append (temp_list, ancestor); } } else { if (container->focus_child == xpaned->top_left_child) { temp_list = g_list_append (temp_list, ancestor); temp_list = g_list_append (temp_list, xpaned->last_top_right_child_focus); temp_list = g_list_append (temp_list, xpaned->top_right_child); } else if (container->focus_child == xpaned->top_right_child) { temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus); temp_list = g_list_append (temp_list, xpaned->bottom_left_child); temp_list = g_list_append (temp_list, ancestor); } else if (container->focus_child == xpaned->bottom_right_child) { temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus); temp_list = g_list_append (temp_list, xpaned->bottom_left_child); temp_list = g_list_append (temp_list, ancestor); } else if (container->focus_child == xpaned->top_right_child) { temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus); temp_list = g_list_append (temp_list, xpaned->bottom_left_child); temp_list = g_list_append (temp_list, ancestor); } else { temp_list = g_list_append (temp_list, xpaned->last_bottom_right_child_focus); temp_list = g_list_append (temp_list, xpaned->bottom_right_child); temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus); temp_list = g_list_append (temp_list, xpaned->bottom_left_child); temp_list = g_list_append (temp_list, xpaned->last_top_right_child_focus); temp_list = g_list_append (temp_list, xpaned->top_right_child); temp_list = g_list_append (temp_list, xpaned->last_top_left_child_focus); temp_list = g_list_append (temp_list, xpaned->top_left_child); temp_list = g_list_append (temp_list, ancestor); } } /* Walk the list and expand all the paned widgets. */ for (list = temp_list; list != NULL; list = list->next) { GtkWidget *widget = list->data; if (widget) { if (GTK_IS_XPANED (widget)) { xpaned->in_recursion = TRUE; gtk_xpaned_get_cycle_chain (GTK_XPANED (widget), direction, widgets); xpaned->in_recursion = FALSE; } else { *widgets = g_list_append (*widgets, widget); } } } g_list_free (temp_list); } static gboolean gtk_xpaned_cycle_child_focus (GtkXPaned* xpaned, gboolean reversed) { GList* cycle_chain = NULL; GList* list; GtkDirectionType direction = reversed ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD; /* ignore f6 if the handle is focused */ if (gtk_widget_is_focus (GTK_WIDGET (xpaned))) return TRUE; /* we can't just let the event propagate up the hierarchy, * because the paned will want to cycle focus _unless_ an * ancestor paned handles the event */ gtk_xpaned_get_cycle_chain (xpaned, direction, &cycle_chain); for (list = cycle_chain; list != NULL; list = list->next) if (gtk_widget_child_focus (GTK_WIDGET (list->data), direction)) break; g_list_free (cycle_chain); return TRUE; } static void get_child_xpanes (GtkWidget* widget, GList** xpanes) { if (GTK_IS_XPANED (widget)) { GtkXPaned* xpaned = GTK_XPANED (widget); get_child_xpanes (xpaned->top_left_child, xpanes); *xpanes = g_list_prepend (*xpanes, widget); get_child_xpanes (xpaned->top_right_child, xpanes); *xpanes = g_list_prepend (*xpanes, widget); get_child_xpanes (xpaned->bottom_left_child, xpanes); *xpanes = g_list_prepend (*xpanes, widget); get_child_xpanes (xpaned->bottom_right_child, xpanes); } else if (GTK_IS_CONTAINER (widget)) { gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback)get_child_xpanes, xpanes); } } static GList* get_all_xpanes (GtkXPaned* xpaned) { GtkXPaned* topmost = NULL; GList* result = NULL; GtkWidget* w; for (w = GTK_WIDGET (xpaned); w != NULL; w = w->parent) { if (GTK_IS_XPANED (w)) topmost = GTK_XPANED (w); } g_assert (topmost); get_child_xpanes (GTK_WIDGET (topmost), &result); return g_list_reverse (result); } static void gtk_xpaned_find_neighbours (GtkXPaned* xpaned, GtkXPaned** next, GtkXPaned** prev) { GList* all_xpanes; GList* this_link; all_xpanes = get_all_xpanes (xpaned); g_assert (all_xpanes); this_link = g_list_find (all_xpanes, xpaned); g_assert (this_link); if (this_link->next) *next = this_link->next->data; else *next = all_xpanes->data; if (this_link->prev) *prev = this_link->prev->data; else *prev = g_list_last (all_xpanes)->data; g_list_free (all_xpanes); } static gboolean gtk_xpaned_move_handle (GtkXPaned* xpaned, GtkScrollType scroll) { if (gtk_widget_is_focus (GTK_WIDGET (xpaned))) { GdkPoint old_position; GdkPoint new_position; gint increment; enum { SINGLE_STEP_SIZE = 1, PAGE_STEP_SIZE = 75 }; new_position.x = old_position.x = gtk_xpaned_get_position_x (xpaned); new_position.y = old_position.y = gtk_xpaned_get_position_y (xpaned); increment = 0; switch (scroll) { case GTK_SCROLL_STEP_LEFT: case GTK_SCROLL_STEP_UP: case GTK_SCROLL_STEP_BACKWARD: increment = - SINGLE_STEP_SIZE; break; case GTK_SCROLL_STEP_RIGHT: case GTK_SCROLL_STEP_DOWN: case GTK_SCROLL_STEP_FORWARD: increment = SINGLE_STEP_SIZE; break; case GTK_SCROLL_PAGE_LEFT: case GTK_SCROLL_PAGE_UP: case GTK_SCROLL_PAGE_BACKWARD: increment = - PAGE_STEP_SIZE; break; case GTK_SCROLL_PAGE_RIGHT: case GTK_SCROLL_PAGE_DOWN: case GTK_SCROLL_PAGE_FORWARD: increment = PAGE_STEP_SIZE; break; case GTK_SCROLL_START: new_position.x = xpaned->min_position.x; new_position.y = xpaned->min_position.y; break; case GTK_SCROLL_END: new_position.x = xpaned->max_position.x; new_position.y = xpaned->max_position.y; break; default: break; } if (increment) { if (is_rtl (xpaned)) increment = -increment; new_position.x = old_position.x + increment; new_position.y = old_position.y + increment; } new_position.x = CLAMP (new_position.x, xpaned->min_position.x, xpaned->max_position.x); new_position.y = CLAMP (new_position.y, xpaned->min_position.y, xpaned->max_position.y); if (old_position.x != new_position.x) gtk_xpaned_set_position_x (xpaned, new_position.x); if (old_position.y != new_position.y) gtk_xpaned_set_position_y (xpaned, new_position.y); return TRUE; } return FALSE; } static void gtk_xpaned_restore_focus (GtkXPaned* xpaned) { if (gtk_widget_is_focus (GTK_WIDGET (xpaned))) { if (xpaned->priv->saved_focus && gtk_widget_get_sensitive (xpaned->priv->saved_focus)) { gtk_widget_grab_focus (xpaned->priv->saved_focus); } else { /* the saved focus is somehow not available for focusing, * try * 1) tabbing into the paned widget * if that didn't work, * 2) unset focus for the window if there is one */ if (!gtk_widget_child_focus (GTK_WIDGET (xpaned), GTK_DIR_TAB_FORWARD)) { GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (xpaned)); if (GTK_IS_WINDOW (toplevel)) gtk_window_set_focus (GTK_WINDOW (toplevel), NULL); } } gtk_xpaned_set_saved_focus (xpaned, NULL); gtk_xpaned_set_first_xpaned (xpaned, NULL); } } static gboolean gtk_xpaned_accept_position (GtkXPaned* xpaned) { if (gtk_widget_is_focus (GTK_WIDGET (xpaned))) { xpaned->original_position.x = -1; xpaned->original_position.y = -1; gtk_xpaned_restore_focus (xpaned); return TRUE; } return FALSE; } static gboolean gtk_xpaned_cancel_position (GtkXPaned* xpaned) { if (gtk_widget_is_focus (GTK_WIDGET (xpaned))) { if (xpaned->original_position.x != -1) { gtk_xpaned_set_position_x (xpaned, xpaned->original_position.x); xpaned->original_position.x = -1; } if (xpaned->original_position.y != -1) { gtk_xpaned_set_position_y (xpaned, xpaned->original_position.y); xpaned->original_position.y = -1; } gtk_xpaned_restore_focus (xpaned); return TRUE; } return FALSE; } static gboolean gtk_xpaned_cycle_handle_focus (GtkXPaned* xpaned, gboolean reversed) { GtkXPaned* next; GtkXPaned* prev; if (gtk_widget_is_focus (GTK_WIDGET (xpaned))) { GtkXPaned* focus = NULL; if (!xpaned->priv->first_xpaned) { /* The first_pane has disappeared. As an ad-hoc solution, * we make the currently focused paned the first_paned. To the * user this will seem like the paned cycling has been reset. */ gtk_xpaned_set_first_xpaned (xpaned, xpaned); } gtk_xpaned_find_neighbours (xpaned, &next, &prev); if (reversed && prev && prev != xpaned && xpaned != xpaned->priv->first_xpaned) { focus = prev; } else if (!reversed && next && next != xpaned && next != xpaned->priv->first_xpaned) { focus = next; } else { gtk_xpaned_accept_position (xpaned); return TRUE; } g_assert (focus); gtk_xpaned_set_saved_focus (focus, xpaned->priv->saved_focus); gtk_xpaned_set_first_xpaned (focus, xpaned->priv->first_xpaned); gtk_xpaned_set_saved_focus (xpaned, NULL); gtk_xpaned_set_first_xpaned (xpaned, NULL); gtk_widget_grab_focus (GTK_WIDGET (focus)); if (!gtk_widget_is_focus (GTK_WIDGET (xpaned))) { xpaned->original_position.x = -1; xpaned->original_position.y = -1; focus->original_position.x = gtk_xpaned_get_position_x (focus); focus->original_position.y = gtk_xpaned_get_position_y (focus); } } else { GtkContainer* container = GTK_CONTAINER (xpaned); GtkXPaned* focus; GtkXPaned* first; GtkXPaned* prev; GtkXPaned* next; GtkWidget* toplevel; gtk_xpaned_find_neighbours (xpaned, &next, &prev); if (container->focus_child == xpaned->top_left_child) { if (reversed) { focus = prev; first = xpaned; } else { focus = xpaned; first = xpaned; } } else if (container->focus_child == xpaned->top_right_child) { if (reversed) { focus = xpaned; first = next; } else { focus = next; first = next; } } else { /* Focus is not inside this xpaned, and we don't have focus. * Presumably this happened because the application wants us * to start keyboard navigating. */ focus = xpaned; if (reversed) first = xpaned; else first = next; } toplevel = gtk_widget_get_toplevel (GTK_WIDGET (xpaned)); if (GTK_IS_WINDOW (toplevel)) gtk_xpaned_set_saved_focus (focus, GTK_WINDOW (toplevel)->focus_widget); gtk_xpaned_set_first_xpaned (focus, first); focus->original_position.x = gtk_xpaned_get_position_x (focus); focus->original_position.y = gtk_xpaned_get_position_y (focus); gtk_widget_grab_focus (GTK_WIDGET (focus)); } return TRUE; } static gboolean gtk_xpaned_toggle_handle_focus (GtkXPaned* xpaned) { /* This function/signal has the wrong name. It is called when you * press Tab or Shift-Tab and what we do is act as if * the user pressed Return and then Tab or Shift-Tab */ if (gtk_widget_is_focus (GTK_WIDGET (xpaned))) gtk_xpaned_accept_position (xpaned); return FALSE; } /*#define __GTK_XPANED_C__*/ /*#include "gtkaliasdef.c"*/ pspp-master/lib/gtk-contrib/gtkxpaned.h000066400000000000000000000154371177044323000204730ustar00rootroot00000000000000/******************************************************************************* **3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 ** 10 20 30 40 50 60 70 80 ** ** library for GtkXPaned-widget, a 2x2 grid-like variation of GtkPaned of gtk+ ** Copyright (C) 2005-2006 Mirco "MacSlow" Müller ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** GtkXPaned is based on GtkPaned which was done by... ** ** "Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald" ** ** and later modified by... ** ** "the GTK+ Team and others 1997-2000" ** *******************************************************************************/ #ifndef GTK_XPANED_H #define GTK_XPANED_H #include G_BEGIN_DECLS #define GTK_TYPE_XPANED (gtk_xpaned_get_type ()) #define GTK_XPANED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_XPANED, GtkXPaned)) #define GTK_XPANED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_XPANED, GtkXPanedClass)) #define GTK_IS_XPANED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_XPANED)) #define GTK_IS_XPANED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_XPANED)) #define GTK_XPANED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_XPANED, GtkXPanedClass)) typedef struct _GtkXPaned GtkXPaned; typedef struct _GtkXPanedClass GtkXPanedClass; typedef struct _GtkXPanedPrivate GtkXPanedPrivate; typedef enum _GtkXPanedChild { GTK_XPANED_TOP_LEFT = 0, GTK_XPANED_TOP_RIGHT, GTK_XPANED_BOTTOM_LEFT, GTK_XPANED_BOTTOM_RIGHT } GtkXPanedChild; struct _GtkXPaned { GtkContainer container; GtkWidget* top_left_child; GtkWidget* top_right_child; GtkWidget* bottom_left_child; GtkWidget* bottom_right_child; GdkWindow* handle_east; GdkWindow* handle_west; GdkWindow* handle_north; GdkWindow* handle_south; GdkWindow* handle_middle; GdkGC* xor_gc; GdkCursorType cursor_type_east; GdkCursorType cursor_type_west; GdkCursorType cursor_type_north; GdkCursorType cursor_type_south; GdkCursorType cursor_type_middle; /*< private >*/ GdkRectangle handle_pos_east; GdkRectangle handle_pos_west; GdkRectangle handle_pos_north; GdkRectangle handle_pos_south; GdkRectangle handle_pos_middle; GtkRequisition top_left_child_size; GtkRequisition top_right_child_size; GtkRequisition bottom_left_child_size; GtkRequisition bottom_right_child_size; GtkRequisition last_allocation; GdkPoint min_position; GdkPoint max_position; gboolean maximized[4]; guint position_set : 1; guint in_drag_vert : 1; guint in_drag_horiz : 1; guint in_drag_vert_and_horiz : 1; guint top_left_child_shrink : 1; guint top_left_child_resize : 1; guint top_right_child_shrink : 1; guint top_right_child_resize : 1; guint bottom_left_child_shrink : 1; guint bottom_left_child_resize : 1; guint bottom_right_child_shrink : 1; guint bottom_right_child_resize : 1; guint in_recursion : 1; guint handle_prelit : 1; GtkWidget* last_top_left_child_focus; GtkWidget* last_top_right_child_focus; GtkWidget* last_bottom_left_child_focus; GtkWidget* last_bottom_right_child_focus; GtkXPanedPrivate* priv; GdkPoint drag_pos; GdkPoint original_position; GdkPoint unmaximized_position; }; struct _GtkXPanedClass { GtkContainerClass parent_class; gboolean (*cycle_child_focus) (GtkXPaned* xpaned, gboolean reverse); gboolean (*toggle_handle_focus) (GtkXPaned* xpaned); gboolean (*move_handle) (GtkXPaned* xpaned, GtkScrollType scroll); gboolean (*cycle_handle_focus) (GtkXPaned* xpaned, gboolean reverse); gboolean (*accept_position) (GtkXPaned* xpaned); gboolean (*cancel_position) (GtkXPaned* xpaned); }; GType gtk_xpaned_get_type (void) G_GNUC_CONST; GtkWidget* gtk_xpaned_new (void); void gtk_xpaned_add_top_left (GtkXPaned* xpaned, GtkWidget* child); void gtk_xpaned_add_top_right (GtkXPaned* xpaned, GtkWidget* child); void gtk_xpaned_add_bottom_left (GtkXPaned* xpaned, GtkWidget* child); void gtk_xpaned_add_bottom_right (GtkXPaned* xpaned, GtkWidget* child); void gtk_xpaned_pack_top_left (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink); void gtk_xpaned_pack_top_right (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink); void gtk_xpaned_pack_bottom_left (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink); void gtk_xpaned_pack_bottom_right (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink); gint gtk_xpaned_get_position_x (GtkXPaned* xpaned); gint gtk_xpaned_get_position_y (GtkXPaned* xpaned); void gtk_xpaned_set_position_x (GtkXPaned* xpaned, gint xposition); void gtk_xpaned_set_position_y (GtkXPaned* xpaned, gint yposition); void gtk_xpaned_save_unmaximized_x (GtkXPaned* xpaned); void gtk_xpaned_save_unmaximized_y (GtkXPaned* xpaned); gint gtk_xpaned_fetch_unmaximized_x (GtkXPaned* xpaned); gint gtk_xpaned_fetch_unmaximized_y (GtkXPaned* xpaned); GtkWidget* gtk_xpaned_get_top_left_child (GtkXPaned* xpaned); GtkWidget* gtk_xpaned_get_top_right_child (GtkXPaned* xpaned); GtkWidget* gtk_xpaned_get_bottom_right_child (GtkXPaned* xpaned); GtkWidget* gtk_xpaned_get_bottom_left_child (GtkXPaned* xpaned); gboolean gtk_xpaned_maximize_top_left (GtkXPaned* xpaned, gboolean maximize); gboolean gtk_xpaned_maximize_top_right (GtkXPaned* xpaned, gboolean maximize); gboolean gtk_xpaned_maximize_bottom_left (GtkXPaned* xpaned, gboolean maximize); gboolean gtk_xpaned_maximize_bottom_right (GtkXPaned* xpaned, gboolean maximize); /* Internal function */ #if !defined (GTK_DISABLE_DEPRECATED) || defined (GTK_COMPILATION) void gtk_xpaned_compute_position (GtkXPaned* xpaned, const GtkAllocation* allocation, GtkRequisition* top_left_child_req, GtkRequisition* top_right_child_req, GtkRequisition* bottom_left_child_req, GtkRequisition* bottom_right_child_req); #endif /* !GTK_DISABLE_DEPRECATED || GTK_COMPILATION */ #ifndef GTK_DISABLE_DEPRECATED #define gtk_xpaned_gutter_size(p,s) (void) 0 #define gtk_xpaned_set_gutter_size(p,s) (void) 0 #endif /* GTK_DISABLE_DEPRECATED */ G_END_DECLS #endif /* GTK_XPANED_H */ pspp-master/lib/gtk-contrib/psppire-sheet.c000066400000000000000000003633501177044323000212710ustar00rootroot00000000000000/* Copyright (C) 2006, 2008, 2009, 2011 Free Software Foundation 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 . This file is derived from the gtksheet.c and extensively modified for the requirements of PSPPIRE. The changes are copyright by the Free Software Foundation. The copyright notice for the original work is below. */ /* GtkSheet widget for Gtk+. * Copyright (C) 1999-2001 Adrian E. Feiguin * * Based on GtkClist widget by Jay Painter, but major changes. * Memory allocation routines inspired on SC (Spreadsheet Calculator) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION:psppiresheet * @short_description: spreadsheet widget for gtk2 * * PsppireSheet is a matrix widget for GTK+. It consists of an scrollable grid of * cells where you can allocate text. Cell contents can be edited interactively * through a specially designed entry, GtkItemEntry. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "psppire-sheet.h" #include #include #include #include /* sheet flags */ enum { PSPPIRE_SHEET_IN_XDRAG = 1 << 1, PSPPIRE_SHEET_IN_YDRAG = 1 << 2, PSPPIRE_SHEET_IN_DRAG = 1 << 3, /* This flag is set when the user is actually in the process of making a selection - ie while the mouse button is depressed. */ PSPPIRE_SHEET_IN_SELECTION = 1 << 4 }; #define PSPPIRE_SHEET_FLAGS(sheet) (PSPPIRE_SHEET (sheet)->flags) #define PSPPIRE_SHEET_SET_FLAGS(sheet,flag) (PSPPIRE_SHEET_FLAGS (sheet) |= (flag)) #define PSPPIRE_SHEET_UNSET_FLAGS(sheet,flag) (PSPPIRE_SHEET_FLAGS (sheet) &= ~ (flag)) #define PSPPIRE_SHEET_IN_XDRAG(sheet) (PSPPIRE_SHEET_FLAGS (sheet) & PSPPIRE_SHEET_IN_XDRAG) #define PSPPIRE_SHEET_IN_YDRAG(sheet) (PSPPIRE_SHEET_FLAGS (sheet) & PSPPIRE_SHEET_IN_YDRAG) #define PSPPIRE_SHEET_IN_DRAG(sheet) (PSPPIRE_SHEET_FLAGS (sheet) & PSPPIRE_SHEET_IN_DRAG) #define PSPPIRE_SHEET_IN_SELECTION(sheet) (PSPPIRE_SHEET_FLAGS (sheet) & PSPPIRE_SHEET_IN_SELECTION) #define CELL_SPACING 1 #define TIMEOUT_HOVER 300 #define COLUMN_MIN_WIDTH 10 #define COLUMN_TITLES_HEIGHT 4 #define DEFAULT_COLUMN_WIDTH 80 #define DEFAULT_ROW_HEIGHT 25 static void set_entry_widget_font (PsppireSheet *sheet); static void psppire_sheet_update_primary_selection (PsppireSheet *sheet); static void draw_column_title_buttons_range (PsppireSheet *sheet, gint first, gint n); static void draw_row_title_buttons_range (PsppireSheet *sheet, gint first, gint n); static void redraw_range (PsppireSheet *sheet, PsppireSheetRange *range); static void set_row_height (PsppireSheet *sheet, gint row, gint height); static void destroy_hover_window (PsppireSheetHoverTitle *); static PsppireSheetHoverTitle *create_hover_window (void); static inline void dispose_string (const PsppireSheet *sheet, gchar *text) { PsppireSheetModel *model = psppire_sheet_get_model (sheet); if ( ! model ) return; if (psppire_sheet_model_free_strings (model)) g_free (text); } /* FIXME: Why bother with these two ? */ /* returns the column index from a pixel location */ static inline gint column_from_xpixel (const PsppireSheet *sheet, gint pixel) { return psppire_axis_unit_at_pixel (sheet->haxis, pixel); } static inline gint row_from_ypixel (const PsppireSheet *sheet, gint pixel) { return psppire_axis_unit_at_pixel (sheet->vaxis, pixel); } /* Return the lowest row number which is wholly or partially on the visible range of the sheet */ static inline glong min_visible_row (const PsppireSheet *sheet) { return row_from_ypixel (sheet, sheet->vadjustment->value); } static inline glong min_fully_visible_row (const PsppireSheet *sheet) { glong row = min_visible_row (sheet); if ( psppire_axis_start_pixel (sheet->vaxis, row) < sheet->vadjustment->value) row++; return row; } static inline glong max_visible_row (const PsppireSheet *sheet) { return row_from_ypixel (sheet, sheet->vadjustment->value + sheet->vadjustment->page_size); } static inline glong max_fully_visible_row (const PsppireSheet *sheet) { glong row = max_visible_row (sheet); if ( psppire_axis_start_pixel (sheet->vaxis, row) + psppire_axis_unit_size (sheet->vaxis, row) > sheet->vadjustment->value) row--; return row; } /* Returns the lowest column number which is wholly or partially on the sheet */ static inline glong min_visible_column (const PsppireSheet *sheet) { return column_from_xpixel (sheet, sheet->hadjustment->value); } static inline glong min_fully_visible_column (const PsppireSheet *sheet) { glong col = min_visible_column (sheet); if ( psppire_axis_start_pixel (sheet->haxis, col) < sheet->hadjustment->value) col++; return col; } /* Returns the highest column number which is wholly or partially on the sheet */ static inline glong max_visible_column (const PsppireSheet *sheet) { return column_from_xpixel (sheet, sheet->hadjustment->value + sheet->hadjustment->page_size); } static inline glong max_fully_visible_column (const PsppireSheet *sheet) { glong col = max_visible_column (sheet); if ( psppire_axis_start_pixel (sheet->haxis, col) + psppire_axis_unit_size (sheet->haxis, col) > sheet->hadjustment->value) col--; return col; } /* The size of the region (in pixels) around the row/column boundaries where the height/width may be grabbed to change size */ #define DRAG_WIDTH 6 static gboolean on_column_boundary (const PsppireSheet *sheet, gint x, gint *column) { gint col; gint pixel; x += sheet->hadjustment->value; if ( x < 0) return FALSE; col = column_from_xpixel (sheet, x); pixel = x - DRAG_WIDTH / 2; if (pixel < 0) pixel = 0; if ( column_from_xpixel (sheet, pixel) < col ) { *column = col - 1; return TRUE; } if ( column_from_xpixel (sheet, x + DRAG_WIDTH / 2) > col ) { *column = col; return TRUE; } return FALSE; } static gboolean on_row_boundary (const PsppireSheet *sheet, gint y, gint *row) { gint r; gint pixel; y += sheet->vadjustment->value; if ( y < 0) return FALSE; r = row_from_ypixel (sheet, y); pixel = y - DRAG_WIDTH / 2; if (pixel < 0) pixel = 0; if ( row_from_ypixel (sheet, pixel) < r ) { *row = r - 1; return TRUE; } if ( row_from_ypixel (sheet, y + DRAG_WIDTH / 2) > r ) { *row = r; return TRUE; } return FALSE; } static inline gboolean POSSIBLE_DRAG (const PsppireSheet *sheet, gint x, gint y, gint *drag_row, gint *drag_column) { gint ydrag, xdrag; /* Can't drag if nothing is selected */ if ( sheet->range.row0 < 0 || sheet->range.rowi < 0 || sheet->range.col0 < 0 || sheet->range.coli < 0 ) return FALSE; *drag_column = column_from_xpixel (sheet, x); *drag_row = row_from_ypixel (sheet, y); if (x >= psppire_axis_start_pixel (sheet->haxis, sheet->range.col0) - DRAG_WIDTH / 2 && x <= psppire_axis_start_pixel (sheet->haxis, sheet->range.coli) + psppire_axis_unit_size (sheet->haxis, sheet->range.coli) + DRAG_WIDTH / 2) { ydrag = psppire_axis_start_pixel (sheet->vaxis, sheet->range.row0); if (y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2) { *drag_row = sheet->range.row0; return TRUE; } ydrag = psppire_axis_start_pixel (sheet->vaxis, sheet->range.rowi) + psppire_axis_unit_size (sheet->vaxis, sheet->range.rowi); if (y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2) { *drag_row = sheet->range.rowi; return TRUE; } } if (y >= psppire_axis_start_pixel (sheet->vaxis, sheet->range.row0) - DRAG_WIDTH / 2 && y <= psppire_axis_start_pixel (sheet->vaxis, sheet->range.rowi) + psppire_axis_unit_size (sheet->vaxis, sheet->range.rowi) + DRAG_WIDTH / 2) { xdrag = psppire_axis_start_pixel (sheet->haxis, sheet->range.col0); if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2) { *drag_column = sheet->range.col0; return TRUE; } xdrag = psppire_axis_start_pixel (sheet->haxis, sheet->range.coli) + psppire_axis_unit_size (sheet->haxis, sheet->range.coli); if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2) { *drag_column = sheet->range.coli; return TRUE; } } return FALSE; } static inline gboolean POSSIBLE_RESIZE (const PsppireSheet *sheet, gint x, gint y, gint *drag_row, gint *drag_column) { gint xdrag, ydrag; /* Can't drag if nothing is selected */ if ( sheet->range.row0 < 0 || sheet->range.rowi < 0 || sheet->range.col0 < 0 || sheet->range.coli < 0 ) return FALSE; xdrag = psppire_axis_start_pixel (sheet->haxis, sheet->range.coli)+ psppire_axis_unit_size (sheet->haxis, sheet->range.coli); ydrag = psppire_axis_start_pixel (sheet->vaxis, sheet->range.rowi) + psppire_axis_unit_size (sheet->vaxis, sheet->range.rowi); if (sheet->select_status == PSPPIRE_SHEET_COLUMN_SELECTED) ydrag = psppire_axis_start_pixel (sheet->vaxis, min_visible_row (sheet)); if (sheet->select_status == PSPPIRE_SHEET_ROW_SELECTED) xdrag = psppire_axis_start_pixel (sheet->haxis, min_visible_column (sheet)); *drag_column = column_from_xpixel (sheet, x); *drag_row = row_from_ypixel (sheet, y); if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2 && y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2) return TRUE; return FALSE; } static void rectangle_from_range (PsppireSheet *sheet, const PsppireSheetRange *range, GdkRectangle *r) { gint col0 = MIN (range->col0, range->coli); gint coli = MAX (range->col0, range->coli); gint row0 = MIN (range->row0, range->rowi); gint rowi = MAX (range->row0, range->rowi); if ( row0 == -1 ) row0 = min_visible_row (sheet); if ( rowi == -1 ) rowi = max_visible_row (sheet); if ( col0 == -1 ) col0 = min_visible_column (sheet); if ( coli == -1 ) coli = max_visible_column (sheet); r->x = psppire_axis_start_pixel (sheet->haxis, col0); r->x -= round (sheet->hadjustment->value); r->y = psppire_axis_start_pixel (sheet->vaxis, row0); r->y -= round (sheet->vadjustment->value); r->width = psppire_axis_start_pixel (sheet->haxis, coli) - psppire_axis_start_pixel (sheet->haxis, col0) + psppire_axis_unit_size (sheet->haxis, coli); r->height = psppire_axis_start_pixel (sheet->vaxis, rowi) - psppire_axis_start_pixel (sheet->vaxis, row0) + psppire_axis_unit_size (sheet->vaxis, rowi); if ( sheet->column_titles_visible) { r->y += sheet->column_title_area.height; } if ( sheet->row_titles_visible) { r->x += sheet->row_title_area.width; } } static void rectangle_from_cell (PsppireSheet *sheet, gint row, gint col, GdkRectangle *r) { PsppireSheetRange range; g_return_if_fail (row >= 0); g_return_if_fail (col >= 0); range.row0 = range.rowi = row; range.col0 = range.coli = col; rectangle_from_range (sheet, &range, r); } static void psppire_sheet_class_init (PsppireSheetClass *klass); static void psppire_sheet_init (PsppireSheet *sheet); static void psppire_sheet_dispose (GObject *object); static void psppire_sheet_finalize (GObject *object); static void psppire_sheet_style_set (GtkWidget *widget, GtkStyle *previous_style); static void psppire_sheet_realize (GtkWidget *widget); static void psppire_sheet_unrealize (GtkWidget *widget); static void psppire_sheet_map (GtkWidget *widget); static void psppire_sheet_unmap (GtkWidget *widget); static gint psppire_sheet_expose (GtkWidget *widget, GdkEventExpose *event); static void psppire_sheet_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); static gboolean psppire_sheet_set_scroll_adjustments (PsppireSheet *sheet, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment); static gint psppire_sheet_button_press (GtkWidget *widget, GdkEventButton *event); static gint psppire_sheet_button_release (GtkWidget *widget, GdkEventButton *event); static gint psppire_sheet_motion (GtkWidget *widget, GdkEventMotion *event); static gboolean psppire_sheet_crossing_notify (GtkWidget *widget, GdkEventCrossing *event); static gint psppire_sheet_entry_key_press (GtkWidget *widget, GdkEventKey *key); static gboolean psppire_sheet_key_press (GtkWidget *widget, GdkEventKey *key); static void psppire_sheet_size_request (GtkWidget *widget, GtkRequisition *requisition); static void psppire_sheet_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static gboolean psppire_sheet_focus_in (GtkWidget *widget, GdkEventFocus *event); /* Sheet queries */ static gboolean psppire_sheet_range_isvisible (const PsppireSheet *sheet, const PsppireSheetRange *range); static gboolean psppire_sheet_cell_isvisible (PsppireSheet *sheet, gint row, gint column); /* Drawing Routines */ /* draw cell */ static void psppire_sheet_cell_draw (PsppireSheet *sheet, gint row, gint column); /* draw visible part of range. */ static void draw_sheet_region (PsppireSheet *sheet, GdkRegion *region); /* Selection */ static void psppire_sheet_draw_border (PsppireSheet *sheet, PsppireSheetRange range); /* Active Cell handling */ static void psppire_sheet_hide_entry_widget (PsppireSheet *sheet); static void change_active_cell (PsppireSheet *sheet, gint row, gint col); static gboolean psppire_sheet_draw_active_cell (PsppireSheet *sheet); static void psppire_sheet_show_entry_widget (PsppireSheet *sheet); static gboolean psppire_sheet_click_cell (PsppireSheet *sheet, gint row, gint column); /* Scrollbars */ static void adjust_scrollbars (PsppireSheet *sheet); static void vadjustment_value_changed (GtkAdjustment *adjustment, gpointer data); static void hadjustment_value_changed (GtkAdjustment *adjustment, gpointer data); static void draw_xor_vline (PsppireSheet *sheet); static void draw_xor_hline (PsppireSheet *sheet); static void draw_xor_rectangle (PsppireSheet *sheet, PsppireSheetRange range); /* Sheet Button */ static void create_global_button (PsppireSheet *sheet); static void global_button_clicked (GtkWidget *widget, gpointer data); /* Sheet Entry */ static void create_sheet_entry (PsppireSheet *sheet); static void psppire_sheet_size_allocate_entry (PsppireSheet *sheet); /* Sheet button gadgets */ static void draw_column_title_buttons (PsppireSheet *sheet); static void draw_row_title_buttons (PsppireSheet *sheet); static void size_allocate_global_button (PsppireSheet *sheet); static void psppire_sheet_real_cell_clear (PsppireSheet *sheet, gint row, gint column); /* Signals */ enum { SELECT_ROW, SELECT_COLUMN, DOUBLE_CLICK_ROW, DOUBLE_CLICK_COLUMN, BUTTON_EVENT_ROW, BUTTON_EVENT_COLUMN, SELECT_RANGE, RESIZE_RANGE, MOVE_RANGE, TRAVERSE, ACTIVATE, LAST_SIGNAL }; static GtkContainerClass *parent_class = NULL; static guint sheet_signals[LAST_SIGNAL] = { 0 }; GType psppire_sheet_get_type () { static GType sheet_type = 0; if (!sheet_type) { static const GTypeInfo sheet_info = { sizeof (PsppireSheetClass), NULL, NULL, (GClassInitFunc) psppire_sheet_class_init, NULL, NULL, sizeof (PsppireSheet), 0, (GInstanceInitFunc) psppire_sheet_init, NULL, }; sheet_type = g_type_register_static (GTK_TYPE_BIN, "PsppireSheet", &sheet_info, 0); } return sheet_type; } static PsppireSheetRange* psppire_sheet_range_copy (const PsppireSheetRange *range) { PsppireSheetRange *new_range; g_return_val_if_fail (range != NULL, NULL); new_range = g_new (PsppireSheetRange, 1); *new_range = *range; return new_range; } static void psppire_sheet_range_free (PsppireSheetRange *range) { g_return_if_fail (range != NULL); g_free (range); } GType psppire_sheet_range_get_type (void) { static GType sheet_range_type = 0; if (!sheet_range_type) { sheet_range_type = g_boxed_type_register_static ("PsppireSheetRange", (GBoxedCopyFunc) psppire_sheet_range_copy, (GBoxedFreeFunc) psppire_sheet_range_free); } return sheet_range_type; } static PsppireSheetCell* psppire_sheet_cell_copy (const PsppireSheetCell *cell) { PsppireSheetCell *new_cell; g_return_val_if_fail (cell != NULL, NULL); new_cell = g_new (PsppireSheetCell, 1); *new_cell = *cell; return new_cell; } static void psppire_sheet_cell_free (PsppireSheetCell *cell) { g_return_if_fail (cell != NULL); g_free (cell); } GType psppire_sheet_cell_get_type (void) { static GType sheet_cell_type = 0; if (!sheet_cell_type) { sheet_cell_type = g_boxed_type_register_static ("PsppireSheetCell", (GBoxedCopyFunc) psppire_sheet_cell_copy, (GBoxedFreeFunc) psppire_sheet_cell_free); } return sheet_cell_type; } /* Properties */ enum { PROP_0, PROP_VAXIS, PROP_HAXIS, PROP_CELL_PADDING, PROP_MODEL }; static void resize_column (PsppireSheet *sheet, gint unit, glong size) { PsppireSheetRange range; range.col0 = unit; range.coli = max_visible_column (sheet); range.row0 = min_visible_row (sheet); range.rowi = max_visible_row (sheet); redraw_range (sheet, &range); draw_column_title_buttons_range (sheet, range.col0, range.coli); } static void psppire_sheet_set_horizontal_axis (PsppireSheet *sheet, PsppireAxis *a) { if ( sheet->haxis ) g_object_unref (sheet->haxis); sheet->haxis = a; g_signal_connect_swapped (a, "resize-unit", G_CALLBACK (resize_column), sheet); if ( sheet->haxis ) g_object_ref (sheet->haxis); } static void resize_row (PsppireSheet *sheet, gint unit, glong size) { PsppireSheetRange range; range.col0 = min_visible_column (sheet); range.coli = max_visible_column (sheet); range.row0 = unit; range.rowi = max_visible_row (sheet); redraw_range (sheet, &range); draw_row_title_buttons_range (sheet, range.row0, range.rowi); } static void psppire_sheet_set_vertical_axis (PsppireSheet *sheet, PsppireAxis *a) { if ( sheet->vaxis ) g_object_unref (sheet->vaxis); sheet->vaxis = a; g_signal_connect_swapped (a, "resize-unit", G_CALLBACK (resize_row), sheet); if ( sheet->vaxis ) g_object_ref (sheet->vaxis); } static const GtkBorder default_cell_padding = {3, 3, 3, 3}; static void psppire_sheet_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { PsppireSheet *sheet = PSPPIRE_SHEET (object); switch (prop_id) { case PROP_CELL_PADDING: if ( sheet->cell_padding) g_boxed_free (GTK_TYPE_BORDER, sheet->cell_padding); sheet->cell_padding = g_value_dup_boxed (value); if (NULL == sheet->cell_padding) sheet->cell_padding = g_boxed_copy (GTK_TYPE_BORDER, &default_cell_padding); if (sheet->vaxis) g_object_set (sheet->vaxis, "padding", sheet->cell_padding->top + sheet->cell_padding->bottom, NULL); if (sheet->haxis) g_object_set (sheet->haxis, "padding", sheet->cell_padding->left + sheet->cell_padding->right, NULL); break; case PROP_VAXIS: psppire_sheet_set_vertical_axis (sheet, g_value_get_pointer (value)); g_object_set (sheet->vaxis, "padding", sheet->cell_padding->top + sheet->cell_padding->bottom, NULL); break; case PROP_HAXIS: psppire_sheet_set_horizontal_axis (sheet, g_value_get_pointer (value)); g_object_set (sheet->haxis, "padding", sheet->cell_padding->left + sheet->cell_padding->right, NULL); break; case PROP_MODEL: psppire_sheet_set_model (sheet, g_value_get_pointer (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; }; } static void psppire_sheet_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { PsppireSheet *sheet = PSPPIRE_SHEET (object); switch (prop_id) { case PROP_CELL_PADDING: g_value_set_boxed (value, sheet->cell_padding); break; case PROP_VAXIS: g_value_set_pointer (value, sheet->vaxis); break; case PROP_HAXIS: g_value_set_pointer (value, sheet->haxis); break; case PROP_MODEL: g_value_set_pointer (value, sheet->model); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; }; } static void psppire_sheet_class_init (PsppireSheetClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GParamSpec *haxis_spec ; GParamSpec *vaxis_spec ; GParamSpec *model_spec ; GParamSpec *cell_padding_spec ; GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); parent_class = g_type_class_peek_parent (klass); /** * PsppireSheet::select-row * @sheet: the sheet widget that emitted the signal * @row: the newly selected row index, or -1 if no row is selected. * * A row has been selected. */ sheet_signals[SELECT_ROW] = g_signal_new ("select-row", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, offsetof (PsppireSheetClass, select_row), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); /** * PsppireSheet::select - column * @sheet: the sheet widget that emitted the signal * @column: the newly selected column index, or -1 if no column is selected. * * A column has been selected. */ sheet_signals[SELECT_COLUMN] = g_signal_new ("select-column", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, offsetof (PsppireSheetClass, select_column), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); /** * PsppireSheet::double-click-row * @sheet: the sheet widget that emitted the signal * @row: the row that was double clicked. * * A row's title button has been double clicked */ sheet_signals[DOUBLE_CLICK_ROW] = g_signal_new ("double-click-row", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); /** * PsppireSheet::double-click-column * @sheet: the sheet widget that emitted the signal * @column: the column that was double clicked. * * A column's title button has been double clicked */ sheet_signals[DOUBLE_CLICK_COLUMN] = g_signal_new ("double-click-column", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); /** * PsppireSheet::button-event-column * @sheet: the sheet widget that emitted the signal * @column: the column on which the event occured. * * A button event occured on a column title button */ sheet_signals[BUTTON_EVENT_COLUMN] = g_signal_new ("button-event-column", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, psppire_marshal_VOID__INT_POINTER, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER ); /** * PsppireSheet::button-event-row * @sheet: the sheet widget that emitted the signal * @column: the column on which the event occured. * * A button event occured on a row title button */ sheet_signals[BUTTON_EVENT_ROW] = g_signal_new ("button-event-row", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, psppire_marshal_VOID__INT_POINTER, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_POINTER ); sheet_signals[SELECT_RANGE] = g_signal_new ("select-range", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, offsetof (PsppireSheetClass, select_range), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, PSPPIRE_TYPE_SHEET_RANGE); sheet_signals[RESIZE_RANGE] = g_signal_new ("resize-range", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, offsetof (PsppireSheetClass, resize_range), NULL, NULL, psppire_marshal_VOID__BOXED_BOXED, G_TYPE_NONE, 2, PSPPIRE_TYPE_SHEET_RANGE, PSPPIRE_TYPE_SHEET_RANGE ); sheet_signals[MOVE_RANGE] = g_signal_new ("move-range", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, offsetof (PsppireSheetClass, move_range), NULL, NULL, psppire_marshal_VOID__BOXED_BOXED, G_TYPE_NONE, 2, PSPPIRE_TYPE_SHEET_RANGE, PSPPIRE_TYPE_SHEET_RANGE ); sheet_signals[TRAVERSE] = g_signal_new ("traverse", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, offsetof (PsppireSheetClass, traverse), NULL, NULL, psppire_marshal_BOOLEAN__BOXED_POINTER, G_TYPE_BOOLEAN, 2, PSPPIRE_TYPE_SHEET_CELL, G_TYPE_POINTER); sheet_signals[ACTIVATE] = g_signal_new ("activate", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, offsetof (PsppireSheetClass, activate), NULL, NULL, psppire_marshal_VOID__INT_INT_INT_INT, G_TYPE_NONE, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); widget_class->set_scroll_adjustments_signal = g_signal_new ("set-scroll-adjustments", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, offsetof (PsppireSheetClass, set_scroll_adjustments), NULL, NULL, psppire_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT); container_class->add = NULL; container_class->remove = NULL; container_class->forall = psppire_sheet_forall; container_class->set_focus_child = NULL; object_class->dispose = psppire_sheet_dispose; object_class->finalize = psppire_sheet_finalize; cell_padding_spec = g_param_spec_boxed ("cell-padding", "Cell Padding", "The space between a cell's contents and its border", GTK_TYPE_BORDER, G_PARAM_CONSTRUCT | G_PARAM_READABLE | G_PARAM_WRITABLE); vaxis_spec = g_param_spec_pointer ("vertical-axis", "Vertical Axis", "A pointer to the PsppireAxis object for the rows", G_PARAM_READABLE | G_PARAM_WRITABLE ); haxis_spec = g_param_spec_pointer ("horizontal-axis", "Horizontal Axis", "A pointer to the PsppireAxis object for the columns", G_PARAM_READABLE | G_PARAM_WRITABLE ); model_spec = g_param_spec_pointer ("model", "Model", "A pointer to the data model", G_PARAM_READABLE | G_PARAM_WRITABLE ); object_class->set_property = psppire_sheet_set_property; object_class->get_property = psppire_sheet_get_property; g_object_class_install_property (object_class, PROP_VAXIS, vaxis_spec); g_object_class_install_property (object_class, PROP_HAXIS, haxis_spec); g_object_class_install_property (object_class, PROP_CELL_PADDING, cell_padding_spec); g_object_class_install_property (object_class, PROP_MODEL, model_spec); widget_class->realize = psppire_sheet_realize; widget_class->unrealize = psppire_sheet_unrealize; widget_class->map = psppire_sheet_map; widget_class->unmap = psppire_sheet_unmap; widget_class->style_set = psppire_sheet_style_set; widget_class->button_press_event = psppire_sheet_button_press; widget_class->button_release_event = psppire_sheet_button_release; widget_class->motion_notify_event = psppire_sheet_motion; widget_class->enter_notify_event = psppire_sheet_crossing_notify; widget_class->leave_notify_event = psppire_sheet_crossing_notify; widget_class->key_press_event = psppire_sheet_key_press; widget_class->expose_event = psppire_sheet_expose; widget_class->size_request = psppire_sheet_size_request; widget_class->size_allocate = psppire_sheet_size_allocate; widget_class->focus_in_event = psppire_sheet_focus_in; widget_class->focus_out_event = NULL; klass->set_scroll_adjustments = psppire_sheet_set_scroll_adjustments; klass->select_row = NULL; klass->select_column = NULL; klass->select_range = NULL; klass->resize_range = NULL; klass->move_range = NULL; klass->traverse = NULL; klass->activate = NULL; klass->changed = NULL; } static void psppire_sheet_init (PsppireSheet *sheet) { sheet->model = NULL; sheet->haxis = NULL; sheet->vaxis = NULL; sheet->flags = 0; sheet->select_status = PSPPIRE_SHEET_NORMAL; GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW); GTK_WIDGET_SET_FLAGS (sheet, GTK_CAN_FOCUS); sheet->column_title_window = NULL; sheet->column_title_area.x = 0; sheet->column_title_area.y = 0; sheet->column_title_area.width = 0; sheet->column_title_area.height = DEFAULT_ROW_HEIGHT; sheet->row_title_window = NULL; sheet->row_title_area.x = 0; sheet->row_title_area.y = 0; sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH; sheet->row_title_area.height = 0; sheet->active_cell.row = 0; sheet->active_cell.col = 0; sheet->range.row0 = 0; sheet->range.rowi = 0; sheet->range.col0 = 0; sheet->range.coli = 0; sheet->sheet_window = NULL; sheet->entry_widget = NULL; sheet->button = NULL; sheet->hadjustment = NULL; sheet->vadjustment = NULL; sheet->cursor_drag = NULL; sheet->xor_gc = NULL; sheet->fg_gc = NULL; sheet->bg_gc = NULL; sheet->x_drag = 0; sheet->y_drag = 0; sheet->show_grid = TRUE; sheet->motion_timer = 0; sheet->row_titles_visible = TRUE; sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH; sheet->column_titles_visible = TRUE; /* create sheet entry */ sheet->entry_type = GTK_TYPE_ENTRY; create_sheet_entry (sheet); /* create global selection button */ create_global_button (sheet); } /* Cause RANGE to be redrawn. If RANGE is null, then the entire visible range will be redrawn. */ static void redraw_range (PsppireSheet *sheet, PsppireSheetRange *range) { GdkRectangle rect; if ( ! GTK_WIDGET_REALIZED (sheet)) return; if ( NULL != range ) rectangle_from_range (sheet, range, &rect); else { GdkRegion *r = gdk_drawable_get_visible_region (sheet->sheet_window); gdk_region_get_clipbox (r, &rect); if ( sheet->column_titles_visible) { rect.y += sheet->column_title_area.height; rect.height -= sheet->column_title_area.height; } if ( sheet->row_titles_visible) { rect.x += sheet->row_title_area.width; rect.width -= sheet->row_title_area.width; } } gdk_window_invalidate_rect (sheet->sheet_window, &rect, FALSE); } /* Callback which occurs whenever columns are inserted / deleted in the model */ static void columns_inserted_deleted_callback (PsppireSheetModel *model, gint first_column, gint n_columns, gpointer data) { PsppireSheet *sheet = PSPPIRE_SHEET (data); PsppireSheetRange range; gint model_columns = psppire_sheet_model_get_column_count (model); /* Need to update all the columns starting from the first column and onwards. * Previous column are unchanged, so don't need to be updated. */ range.col0 = first_column; range.row0 = 0; range.coli = psppire_axis_unit_count (sheet->haxis) - 1; range.rowi = psppire_axis_unit_count (sheet->vaxis) - 1; adjust_scrollbars (sheet); if (sheet->active_cell.col >= model_columns) change_active_cell (sheet, sheet->active_cell.row, model_columns - 1); draw_column_title_buttons_range (sheet, first_column, max_visible_column (sheet)); redraw_range (sheet, &range); } /* Callback which occurs whenever rows are inserted / deleted in the model */ static void rows_inserted_deleted_callback (PsppireSheetModel *model, gint first_row, gint n_rows, gpointer data) { PsppireSheet *sheet = PSPPIRE_SHEET (data); PsppireSheetRange range; gint model_rows = psppire_sheet_model_get_row_count (model); /* Need to update all the rows starting from the first row and onwards. * Previous rows are unchanged, so don't need to be updated. */ range.row0 = first_row; range.col0 = 0; range.rowi = psppire_axis_unit_count (sheet->vaxis) - 1; range.coli = psppire_axis_unit_count (sheet->haxis) - 1; adjust_scrollbars (sheet); if (sheet->active_cell.row >= model_rows) change_active_cell (sheet, model_rows - 1, sheet->active_cell.col); draw_row_title_buttons_range (sheet, first_row, max_visible_row (sheet)); redraw_range (sheet, &range); } /* If row0 or rowi are negative, then all rows will be updated. If col0 or coli are negative, then all columns will be updated. */ static void range_update_callback (PsppireSheetModel *m, gint row0, gint col0, gint rowi, gint coli, gpointer data) { PsppireSheet *sheet = PSPPIRE_SHEET (data); PsppireSheetRange range; range.row0 = row0; range.col0 = col0; range.rowi = rowi; range.coli = coli; if ( !GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return; if ( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) ) { redraw_range (sheet, NULL); adjust_scrollbars (sheet); draw_row_title_buttons_range (sheet, min_visible_row (sheet), max_visible_row (sheet)); draw_column_title_buttons_range (sheet, min_visible_column (sheet), max_visible_column (sheet)); return; } else if ( row0 < 0 || rowi < 0 ) { range.row0 = min_visible_row (sheet); range.rowi = max_visible_row (sheet); } else if ( col0 < 0 || coli < 0 ) { range.col0 = min_visible_column (sheet); range.coli = max_visible_column (sheet); } redraw_range (sheet, &range); } /** * psppire_sheet_new: * @rows: initial number of rows * @columns: initial number of columns * @title: sheet title * @model: the model to use for the sheet data * * Creates a new sheet widget with the given number of rows and columns. * * Returns: the new sheet widget */ GtkWidget * psppire_sheet_new (PsppireSheetModel *model) { GtkWidget *widget = g_object_new (PSPPIRE_TYPE_SHEET, "model", model, NULL); return widget; } /** * psppire_sheet_set_model * @sheet: the sheet to set the model for * @model: the model to use for the sheet data * * Sets the model for a PsppireSheet * */ void psppire_sheet_set_model (PsppireSheet *sheet, PsppireSheetModel *model) { g_return_if_fail (PSPPIRE_IS_SHEET (sheet)); if (sheet->model ) g_object_unref (sheet->model); sheet->model = model; if ( model) { g_object_ref (model); sheet->update_handler_id = g_signal_connect (model, "range_changed", G_CALLBACK (range_update_callback), sheet); g_signal_connect (model, "rows_inserted", G_CALLBACK (rows_inserted_deleted_callback), sheet); g_signal_connect (model, "rows_deleted", G_CALLBACK (rows_inserted_deleted_callback), sheet); g_signal_connect (model, "columns_inserted", G_CALLBACK (columns_inserted_deleted_callback), sheet); g_signal_connect (model, "columns_deleted", G_CALLBACK (columns_inserted_deleted_callback), sheet); } } void psppire_sheet_change_entry (PsppireSheet *sheet, GType entry_type) { g_return_if_fail (sheet != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (sheet)); if (sheet->select_status == PSPPIRE_SHEET_NORMAL) psppire_sheet_hide_entry_widget (sheet); sheet->entry_type = entry_type; create_sheet_entry (sheet); if (sheet->select_status == PSPPIRE_SHEET_NORMAL) psppire_sheet_show_entry_widget (sheet); } void psppire_sheet_show_grid (PsppireSheet *sheet, gboolean show) { g_return_if_fail (sheet != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (sheet)); if (show == sheet->show_grid) return; sheet->show_grid = show; redraw_range (sheet, NULL); } gboolean psppire_sheet_grid_visible (PsppireSheet *sheet) { g_return_val_if_fail (sheet != NULL, 0); g_return_val_if_fail (PSPPIRE_IS_SHEET (sheet), 0); return sheet->show_grid; } guint psppire_sheet_get_columns_count (PsppireSheet *sheet) { g_return_val_if_fail (sheet != NULL, 0); g_return_val_if_fail (PSPPIRE_IS_SHEET (sheet), 0); return psppire_axis_unit_count (sheet->haxis); } static void set_column_width (PsppireSheet *sheet, gint column, gint width); void psppire_sheet_show_column_titles (PsppireSheet *sheet) { if (sheet->column_titles_visible) return; sheet->column_titles_visible = TRUE; if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return; gdk_window_show (sheet->column_title_window); gdk_window_move_resize (sheet->column_title_window, sheet->column_title_area.x, sheet->column_title_area.y, sheet->column_title_area.width, sheet->column_title_area.height); adjust_scrollbars (sheet); if (sheet->vadjustment) g_signal_emit_by_name (sheet->vadjustment, "value_changed"); size_allocate_global_button (sheet); if ( sheet->row_titles_visible) gtk_widget_show (sheet->button); } void psppire_sheet_show_row_titles (PsppireSheet *sheet) { if (sheet->row_titles_visible) return; sheet->row_titles_visible = TRUE; if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) { gdk_window_show (sheet->row_title_window); gdk_window_move_resize (sheet->row_title_window, sheet->row_title_area.x, sheet->row_title_area.y, sheet->row_title_area.width, sheet->row_title_area.height); adjust_scrollbars (sheet); } if (sheet->hadjustment) g_signal_emit_by_name (sheet->hadjustment, "value_changed"); size_allocate_global_button (sheet); if ( sheet->column_titles_visible) gtk_widget_show (sheet->button); } void psppire_sheet_hide_column_titles (PsppireSheet *sheet) { if (!sheet->column_titles_visible) return; sheet->column_titles_visible = FALSE; if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) { if (sheet->column_title_window) gdk_window_hide (sheet->column_title_window); gtk_widget_hide (sheet->button); adjust_scrollbars (sheet); } if (sheet->vadjustment) g_signal_emit_by_name (sheet->vadjustment, "value_changed"); } void psppire_sheet_hide_row_titles (PsppireSheet *sheet) { if (!sheet->row_titles_visible) return; sheet->row_titles_visible = FALSE; if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) { if (sheet->row_title_window) gdk_window_hide (sheet->row_title_window); gtk_widget_hide (sheet->button); adjust_scrollbars (sheet); } if (sheet->hadjustment) g_signal_emit_by_name (sheet->hadjustment, "value_changed"); } /* Scroll the sheet so that the cell ROW, COLUMN is visible. If {ROW,COL}_ALIGN is zero, then the cell will be placed at the {top,left} of the sheet. If it's 1, then it'll be placed at the {bottom,right}. ROW or COL may be -1, in which case scrolling in that dimension does not occur. */ void psppire_sheet_moveto (PsppireSheet *sheet, gint row, gint col, gfloat row_align, gfloat col_align) { gint width, height; g_return_if_fail (row_align >= 0); g_return_if_fail (col_align >= 0); g_return_if_fail (row_align <= 1); g_return_if_fail (col_align <= 1); g_return_if_fail (col < psppire_axis_unit_count (sheet->haxis)); g_return_if_fail (row < psppire_axis_unit_count (sheet->vaxis)); gdk_drawable_get_size (sheet->sheet_window, &width, &height); if (row >= 0) { gint y = psppire_axis_start_pixel (sheet->vaxis, row); gtk_adjustment_set_value (sheet->vadjustment, y - height * row_align); } if (col >= 0) { gint x = psppire_axis_start_pixel (sheet->haxis, col); gtk_adjustment_set_value (sheet->hadjustment, x - width * col_align); } } static gboolean psppire_sheet_range_isvisible (const PsppireSheet *sheet, const PsppireSheetRange *range) { g_return_val_if_fail (sheet != NULL, FALSE); if (range->row0 < 0 || range->row0 >= psppire_axis_unit_count (sheet->vaxis)) return FALSE; if (range->rowi < 0 || range->rowi >= psppire_axis_unit_count (sheet->vaxis)) return FALSE; if (range->col0 < 0 || range->col0 >= psppire_axis_unit_count (sheet->haxis)) return FALSE; if (range->coli < 0 || range->coli >= psppire_axis_unit_count (sheet->haxis)) return FALSE; if (range->rowi < min_visible_row (sheet)) return FALSE; if (range->row0 > max_visible_row (sheet)) return FALSE; if (range->coli < min_visible_column (sheet)) return FALSE; if (range->col0 > max_visible_column (sheet)) return FALSE; return TRUE; } static gboolean psppire_sheet_cell_isvisible (PsppireSheet *sheet, gint row, gint column) { PsppireSheetRange range; range.row0 = row; range.col0 = column; range.rowi = row; range.coli = column; return psppire_sheet_range_isvisible (sheet, &range); } void psppire_sheet_get_visible_range (PsppireSheet *sheet, PsppireSheetRange *range) { g_return_if_fail (sheet != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (sheet)) ; g_return_if_fail (range != NULL); range->row0 = min_visible_row (sheet); range->col0 = min_visible_column (sheet); range->rowi = max_visible_row (sheet); range->coli = max_visible_column (sheet); } static gboolean psppire_sheet_set_scroll_adjustments (PsppireSheet *sheet, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment) { if ( sheet->vadjustment != vadjustment ) { if (sheet->vadjustment) g_object_unref (sheet->vadjustment); sheet->vadjustment = vadjustment; if ( vadjustment) { g_object_ref (vadjustment); g_signal_connect (sheet->vadjustment, "value_changed", G_CALLBACK (vadjustment_value_changed), sheet); } } if ( sheet->hadjustment != hadjustment ) { if (sheet->hadjustment) g_object_unref (sheet->hadjustment); sheet->hadjustment = hadjustment; if ( hadjustment) { g_object_ref (hadjustment); g_signal_connect (sheet->hadjustment, "value_changed", G_CALLBACK (hadjustment_value_changed), sheet); } } return TRUE; } static void psppire_sheet_finalize (GObject *object) { PsppireSheet *sheet; g_return_if_fail (object != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (object)); sheet = PSPPIRE_SHEET (object); if (G_OBJECT_CLASS (parent_class)->finalize) (*G_OBJECT_CLASS (parent_class)->finalize) (object); } static void psppire_sheet_dispose (GObject *object) { PsppireSheet *sheet = PSPPIRE_SHEET (object); g_return_if_fail (object != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (object)); if ( sheet->dispose_has_run ) return ; sheet->dispose_has_run = TRUE; if ( sheet->cell_padding) g_boxed_free (GTK_TYPE_BORDER, sheet->cell_padding); if (sheet->model) g_object_unref (sheet->model); if (sheet->vaxis) g_object_unref (sheet->vaxis); if (sheet->haxis) g_object_unref (sheet->haxis); g_object_unref (sheet->button); sheet->button = NULL; /* unref adjustments */ if (sheet->hadjustment) { g_signal_handlers_disconnect_matched (sheet->hadjustment, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, sheet); g_object_unref (sheet->hadjustment); sheet->hadjustment = NULL; } if (sheet->vadjustment) { g_signal_handlers_disconnect_matched (sheet->vadjustment, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, sheet); g_object_unref (sheet->vadjustment); sheet->vadjustment = NULL; } if (G_OBJECT_CLASS (parent_class)->dispose) (*G_OBJECT_CLASS (parent_class)->dispose) (object); } static void psppire_sheet_style_set (GtkWidget *widget, GtkStyle *previous_style) { PsppireSheet *sheet; g_return_if_fail (widget != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (widget)); if (GTK_WIDGET_CLASS (parent_class)->style_set) (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style); sheet = PSPPIRE_SHEET (widget); if (GTK_WIDGET_REALIZED (widget)) { gtk_style_set_background (widget->style, widget->window, widget->state); } set_entry_widget_font (sheet); } static void psppire_sheet_realize (GtkWidget *widget) { PsppireSheet *sheet; GdkWindowAttr attributes; const gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_CURSOR; GdkGCValues values; GdkColormap *colormap; GdkDisplay *display; g_return_if_fail (widget != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (widget)); sheet = PSPPIRE_SHEET (widget); colormap = gtk_widget_get_colormap (widget); display = gtk_widget_get_display (widget); attributes.window_type = GDK_WINDOW_CHILD; attributes.x = widget->allocation.x; attributes.y = widget->allocation.y; attributes.width = widget->allocation.width; attributes.height = widget->allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gtk_widget_get_visual (widget); attributes.colormap = colormap; attributes.event_mask = gtk_widget_get_events (widget); attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); attributes.cursor = gdk_cursor_new_for_display (display, GDK_TOP_LEFT_ARROW); /* main window */ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gdk_window_set_user_data (widget->window, sheet); widget->style = gtk_style_attach (widget->style, widget->window); gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); gdk_color_parse ("white", &sheet->color[BG_COLOR]); gdk_colormap_alloc_color (colormap, &sheet->color[BG_COLOR], FALSE, TRUE); gdk_color_parse ("gray", &sheet->color[GRID_COLOR]); gdk_colormap_alloc_color (colormap, &sheet->color[GRID_COLOR], FALSE, TRUE); attributes.x = 0; attributes.y = 0; attributes.width = sheet->column_title_area.width; attributes.height = sheet->column_title_area.height; /* column - title window */ sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask); gdk_window_set_user_data (sheet->column_title_window, sheet); gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL); attributes.x = 0; attributes.y = 0; attributes.width = sheet->row_title_area.width; attributes.height = sheet->row_title_area.height; /* row - title window */ sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask); gdk_window_set_user_data (sheet->row_title_window, sheet); gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL); /* sheet - window */ attributes.cursor = gdk_cursor_new_for_display (display, GDK_PLUS); attributes.x = 0; attributes.y = 0; sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask); gdk_window_set_user_data (sheet->sheet_window, sheet); gdk_cursor_unref (attributes.cursor); gdk_window_set_background (sheet->sheet_window, &widget->style->white); gdk_window_show (sheet->sheet_window); /* GCs */ sheet->fg_gc = gdk_gc_new (widget->window); sheet->bg_gc = gdk_gc_new (widget->window); values.foreground = widget->style->white; values.function = GDK_INVERT; values.subwindow_mode = GDK_INCLUDE_INFERIORS; values.line_width = MAX (sheet->cell_padding->left, MAX (sheet->cell_padding->right, MAX (sheet->cell_padding->top, sheet->cell_padding->bottom))); sheet->xor_gc = gdk_gc_new_with_values (widget->window, &values, GDK_GC_FOREGROUND | GDK_GC_FUNCTION | GDK_GC_SUBWINDOW | GDK_GC_LINE_WIDTH ); gtk_widget_set_parent_window (sheet->entry_widget, sheet->sheet_window); gtk_widget_set_parent (sheet->entry_widget, GTK_WIDGET (sheet)); gtk_widget_set_parent_window (sheet->button, sheet->sheet_window); gtk_widget_set_parent (sheet->button, GTK_WIDGET (sheet)); sheet->button->style = gtk_style_attach (sheet->button->style, sheet->sheet_window); sheet->cursor_drag = gdk_cursor_new_for_display (display, GDK_PLUS); if (sheet->column_titles_visible) gdk_window_show (sheet->column_title_window); if (sheet->row_titles_visible) gdk_window_show (sheet->row_title_window); sheet->hover_window = create_hover_window (); draw_row_title_buttons (sheet); draw_column_title_buttons (sheet); psppire_sheet_update_primary_selection (sheet); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); } static void create_global_button (PsppireSheet *sheet) { sheet->button = gtk_button_new_with_label (" "); GTK_WIDGET_UNSET_FLAGS(sheet->button, GTK_CAN_FOCUS); g_object_ref_sink (sheet->button); g_signal_connect (sheet->button, "pressed", G_CALLBACK (global_button_clicked), sheet); } static void size_allocate_global_button (PsppireSheet *sheet) { GtkAllocation allocation; if (!sheet->column_titles_visible) return; if (!sheet->row_titles_visible) return; gtk_widget_size_request (sheet->button, NULL); allocation.x = 0; allocation.y = 0; allocation.width = sheet->row_title_area.width; allocation.height = sheet->column_title_area.height; gtk_widget_size_allocate (sheet->button, &allocation); } static void global_button_clicked (GtkWidget *widget, gpointer data) { psppire_sheet_click_cell (PSPPIRE_SHEET (data), -1, -1); } static void psppire_sheet_unrealize (GtkWidget *widget) { PsppireSheet *sheet; g_return_if_fail (widget != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (widget)); sheet = PSPPIRE_SHEET (widget); gdk_cursor_unref (sheet->cursor_drag); sheet->cursor_drag = NULL; gdk_colormap_free_colors (gtk_widget_get_colormap (widget), sheet->color, n_COLORS); g_object_unref (sheet->xor_gc); g_object_unref (sheet->fg_gc); g_object_unref (sheet->bg_gc); destroy_hover_window (sheet->hover_window); gdk_window_destroy (sheet->sheet_window); gdk_window_destroy (sheet->column_title_window); gdk_window_destroy (sheet->row_title_window); gtk_widget_unparent (sheet->entry_widget); if (sheet->button != NULL) gtk_widget_unparent (sheet->button); if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); } static void psppire_sheet_map (GtkWidget *widget) { PsppireSheet *sheet = PSPPIRE_SHEET (widget); g_return_if_fail (widget != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (widget)); if (!GTK_WIDGET_MAPPED (widget)) { GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); gdk_window_show (widget->window); gdk_window_show (sheet->sheet_window); if (sheet->column_titles_visible) { draw_column_title_buttons (sheet); gdk_window_show (sheet->column_title_window); } if (sheet->row_titles_visible) { draw_row_title_buttons (sheet); gdk_window_show (sheet->row_title_window); } if (!GTK_WIDGET_MAPPED (sheet->entry_widget) && sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 ) { gtk_widget_show (sheet->entry_widget); gtk_widget_map (sheet->entry_widget); } if (!GTK_WIDGET_MAPPED (sheet->button)) { gtk_widget_show (sheet->button); gtk_widget_map (sheet->button); } redraw_range (sheet, NULL); change_active_cell (sheet, sheet->active_cell.row, sheet->active_cell.col); } } static void psppire_sheet_unmap (GtkWidget *widget) { PsppireSheet *sheet = PSPPIRE_SHEET (widget); if (!GTK_WIDGET_MAPPED (widget)) return; GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); gdk_window_hide (sheet->sheet_window); if (sheet->column_titles_visible) gdk_window_hide (sheet->column_title_window); if (sheet->row_titles_visible) gdk_window_hide (sheet->row_title_window); gdk_window_hide (widget->window); gtk_widget_unmap (sheet->entry_widget); gtk_widget_unmap (sheet->button); gtk_widget_unmap (sheet->hover_window->window); } /* get cell attributes of the given cell */ /* TRUE means that the cell is currently allocated */ static gboolean psppire_sheet_get_attributes (const PsppireSheet *sheet, gint row, gint col, PsppireSheetCellAttr *attributes); static void psppire_sheet_cell_draw (PsppireSheet *sheet, gint row, gint col) { PangoLayout *layout; PangoRectangle text; PangoFontDescription *font_desc = GTK_WIDGET (sheet)->style->font_desc; gint font_height; gchar *label; PsppireSheetCellAttr attributes; GdkRectangle area; g_return_if_fail (sheet != NULL); /* bail now if we aren't yet drawable */ if (!GTK_WIDGET_DRAWABLE (sheet)) return; if (row < 0 || row >= psppire_axis_unit_count (sheet->vaxis)) return; if (col < 0 || col >= psppire_axis_unit_count (sheet->haxis)) return; psppire_sheet_get_attributes (sheet, row, col, &attributes); /* select GC for background rectangle */ gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground); gdk_gc_set_foreground (sheet->bg_gc, &attributes.background); rectangle_from_cell (sheet, row, col, &area); gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0); if (sheet->show_grid) { gdk_gc_set_foreground (sheet->bg_gc, &sheet->color[GRID_COLOR]); gdk_draw_rectangle (sheet->sheet_window, sheet->bg_gc, FALSE, area.x, area.y, area.width, area.height); } label = psppire_sheet_cell_get_text (sheet, row, col); if (NULL == label) return; layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), label); dispose_string (sheet, label); pango_layout_set_font_description (layout, font_desc); pango_layout_get_pixel_extents (layout, NULL, &text); gdk_gc_set_clip_rectangle (sheet->fg_gc, &area); font_height = pango_font_description_get_size (font_desc); if ( !pango_font_description_get_size_is_absolute (font_desc)) font_height /= PANGO_SCALE; if ( sheet->cell_padding ) { area.x += sheet->cell_padding->left; area.width -= sheet->cell_padding->right + sheet->cell_padding->left; area.y += sheet->cell_padding->top; area.height -= sheet->cell_padding->bottom + sheet->cell_padding->top; } /* Centre the text vertically */ area.y += (area.height - font_height) / 2.0; switch (attributes.justification) { case GTK_JUSTIFY_RIGHT: area.x += area.width - text.width; break; case GTK_JUSTIFY_CENTER: area.x += (area.width - text.width) / 2.0; break; case GTK_JUSTIFY_LEFT: /* Do nothing */ break; default: g_critical ("Unhandled justification %d in column %d\n", attributes.justification, col); break; } gdk_draw_layout (sheet->sheet_window, sheet->fg_gc, area.x, area.y, layout); gdk_gc_set_clip_rectangle (sheet->fg_gc, NULL); g_object_unref (layout); } static void draw_sheet_region (PsppireSheet *sheet, GdkRegion *region) { PsppireSheetRange range; GdkRectangle area; gint y, x; gint i, j; PsppireSheetRange drawing_range; gdk_region_get_clipbox (region, &area); y = area.y + sheet->vadjustment->value; x = area.x + sheet->hadjustment->value; if ( sheet->column_titles_visible) y -= sheet->column_title_area.height; if ( sheet->row_titles_visible) x -= sheet->row_title_area.width; maximize_int (&x, 0); maximize_int (&y, 0); range.row0 = row_from_ypixel (sheet, y); range.rowi = row_from_ypixel (sheet, y + area.height); range.col0 = column_from_xpixel (sheet, x); range.coli = column_from_xpixel (sheet, x + area.width); g_return_if_fail (sheet != NULL); g_return_if_fail (PSPPIRE_SHEET (sheet)); if (!GTK_WIDGET_DRAWABLE (GTK_WIDGET (sheet))) return; if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return; if (!GTK_WIDGET_MAPPED (GTK_WIDGET (sheet))) return; drawing_range.row0 = MAX (range.row0, min_visible_row (sheet)); drawing_range.col0 = MAX (range.col0, min_visible_column (sheet)); drawing_range.rowi = MIN (range.rowi, max_visible_row (sheet)); drawing_range.coli = MIN (range.coli, max_visible_column (sheet)); g_return_if_fail (drawing_range.rowi >= drawing_range.row0); g_return_if_fail (drawing_range.coli >= drawing_range.col0); for (i = drawing_range.row0; i <= drawing_range.rowi; i++) { for (j = drawing_range.col0; j <= drawing_range.coli; j++) psppire_sheet_cell_draw (sheet, i, j); } if (sheet->select_status == PSPPIRE_SHEET_NORMAL && sheet->active_cell.row >= drawing_range.row0 && sheet->active_cell.row <= drawing_range.rowi && sheet->active_cell.col >= drawing_range.col0 && sheet->active_cell.col <= drawing_range.coli) psppire_sheet_show_entry_widget (sheet); } static void psppire_sheet_set_cell (PsppireSheet *sheet, gint row, gint col, GtkJustification justification, const gchar *text) { PsppireSheetModel *model ; gchar *old_text ; g_return_if_fail (sheet != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (sheet)); if (col >= psppire_axis_unit_count (sheet->haxis) || row >= psppire_axis_unit_count (sheet->vaxis)) return; if (col < 0 || row < 0) return; model = psppire_sheet_get_model (sheet); old_text = psppire_sheet_model_get_string (model, row, col); if (0 != g_strcmp0 (old_text, text)) { g_signal_handler_block (sheet->model, sheet->update_handler_id); psppire_sheet_model_set_string (model, text, row, col); g_signal_handler_unblock (sheet->model, sheet->update_handler_id); } if ( psppire_sheet_model_free_strings (model)) g_free (old_text); } void psppire_sheet_cell_clear (PsppireSheet *sheet, gint row, gint column) { PsppireSheetRange range; g_return_if_fail (sheet != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (sheet)); if (column >= psppire_axis_unit_count (sheet->haxis) || row >= psppire_axis_unit_count (sheet->vaxis)) return; if (column < 0 || row < 0) return; range.row0 = row; range.rowi = row; range.col0 = min_visible_column (sheet); range.coli = max_visible_column (sheet); psppire_sheet_real_cell_clear (sheet, row, column); redraw_range (sheet, &range); } static void psppire_sheet_real_cell_clear (PsppireSheet *sheet, gint row, gint column) { PsppireSheetModel *model = psppire_sheet_get_model (sheet); gchar *old_text = psppire_sheet_cell_get_text (sheet, row, column); if (old_text && strlen (old_text) > 0 ) { psppire_sheet_model_datum_clear (model, row, column); } dispose_string (sheet, old_text); } gchar * psppire_sheet_cell_get_text (const PsppireSheet *sheet, gint row, gint col) { PsppireSheetModel *model; g_return_val_if_fail (sheet != NULL, NULL); g_return_val_if_fail (PSPPIRE_IS_SHEET (sheet), NULL); if (col >= psppire_axis_unit_count (sheet->haxis) || row >= psppire_axis_unit_count (sheet->vaxis)) return NULL; if (col < 0 || row < 0) return NULL; model = psppire_sheet_get_model (sheet); if ( !model ) return NULL; return psppire_sheet_model_get_string (model, row, col); } /* Convert X, Y (in pixels) to *ROW, *COLUMN If the function returns FALSE, then the results will be unreliable. */ static gboolean psppire_sheet_get_pixel_info (PsppireSheet *sheet, gint x, gint y, gint *row, gint *column) { gint trow, tcol; *row = -G_MAXINT; *column = -G_MAXINT; g_return_val_if_fail (sheet != NULL, 0); g_return_val_if_fail (PSPPIRE_IS_SHEET (sheet), 0); /* bounds checking, return false if the user clicked on a blank area */ if (y < 0) return FALSE; if (x < 0) return FALSE; if ( sheet->column_titles_visible) y -= sheet->column_title_area.height; y += sheet->vadjustment->value; if ( y < 0 && sheet->column_titles_visible) { trow = -1; } else { trow = row_from_ypixel (sheet, y); if (trow > psppire_axis_unit_count (sheet->vaxis)) return FALSE; } *row = trow; if ( sheet->row_titles_visible) x -= sheet->row_title_area.width; x += sheet->hadjustment->value; if ( x < 0 && sheet->row_titles_visible) { tcol = -1; } else { tcol = column_from_xpixel (sheet, x); if (tcol > psppire_axis_unit_count (sheet->haxis)) return FALSE; } *column = tcol; return TRUE; } gboolean psppire_sheet_get_cell_area (PsppireSheet *sheet, gint row, gint column, GdkRectangle *area) { g_return_val_if_fail (sheet != NULL, 0); g_return_val_if_fail (PSPPIRE_IS_SHEET (sheet), 0); if (row >= psppire_axis_unit_count (sheet->vaxis) || column >= psppire_axis_unit_count (sheet->haxis)) return FALSE; area->x = (column == -1) ? 0 : psppire_axis_start_pixel (sheet->haxis, column); area->y = (row == -1) ? 0 : psppire_axis_start_pixel (sheet->vaxis, row); area->width= (column == -1) ? sheet->row_title_area.width : psppire_axis_unit_size (sheet->haxis, column); area->height= (row == -1) ? sheet->column_title_area.height : psppire_axis_unit_size (sheet->vaxis, row); return TRUE; } void psppire_sheet_set_active_cell (PsppireSheet *sheet, gint row, gint col) { g_return_if_fail (sheet != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (sheet)); if (row < -1 || col < -1) return; if (row >= psppire_axis_unit_count (sheet->vaxis) || col >= psppire_axis_unit_count (sheet->haxis)) return; if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return; if ( row == -1 || col == -1) { psppire_sheet_hide_entry_widget (sheet); return; } change_active_cell (sheet, row, col); } void psppire_sheet_get_active_cell (PsppireSheet *sheet, gint *row, gint *column) { g_return_if_fail (sheet != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (sheet)); if ( row ) *row = sheet->active_cell.row; if (column) *column = sheet->active_cell.col; } static void entry_load_text (PsppireSheet *sheet) { gint row, col; const char *text; GtkJustification justification; PsppireSheetCellAttr attributes; if (!GTK_WIDGET_VISIBLE (sheet->entry_widget)) return; if (sheet->select_status != PSPPIRE_SHEET_NORMAL) return; row = sheet->active_cell.row; col = sheet->active_cell.col; if (row < 0 || col < 0) return; text = gtk_entry_get_text (psppire_sheet_get_entry (sheet)); if (text && strlen (text) > 0) { psppire_sheet_get_attributes (sheet, row, col, &attributes); justification = attributes.justification; psppire_sheet_set_cell (sheet, row, col, justification, text); } } static void psppire_sheet_hide_entry_widget (PsppireSheet *sheet) { if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return; if (sheet->active_cell.row < 0 || sheet->active_cell.col < 0) return; gtk_widget_hide (sheet->entry_widget); gtk_widget_unmap (sheet->entry_widget); GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (sheet->entry_widget), GTK_VISIBLE); } static void change_active_cell (PsppireSheet *sheet, gint row, gint col) { gint old_row, old_col; g_return_if_fail (PSPPIRE_IS_SHEET (sheet)); if (row < 0 || col < 0) return; if ( row > psppire_axis_unit_count (sheet->vaxis) || col > psppire_axis_unit_count (sheet->haxis)) return; old_row = sheet->active_cell.row; old_col = sheet->active_cell.col; entry_load_text (sheet); /* Erase the old cell border */ psppire_sheet_draw_active_cell (sheet); sheet->active_cell.row = row; sheet->active_cell.col = col; PSPPIRE_SHEET_UNSET_FLAGS (sheet, PSPPIRE_SHEET_IN_SELECTION); GTK_WIDGET_UNSET_FLAGS (sheet->entry_widget, GTK_HAS_FOCUS); psppire_sheet_draw_active_cell (sheet); psppire_sheet_show_entry_widget (sheet); GTK_WIDGET_SET_FLAGS (sheet->entry_widget, GTK_HAS_FOCUS); g_signal_emit (sheet, sheet_signals [ACTIVATE], 0, row, col, old_row, old_col); } static void psppire_sheet_show_entry_widget (PsppireSheet *sheet) { GtkEntry *sheet_entry; PsppireSheetCellAttr attributes; gint row, col; g_return_if_fail (PSPPIRE_IS_SHEET (sheet)); row = sheet->active_cell.row; col = sheet->active_cell.col; /* Don't show the active cell, if there is no active cell: */ if (! (row >= 0 && col >= 0)) /* e.g row or coll == -1. */ return; if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return; if (sheet->select_status != PSPPIRE_SHEET_NORMAL) return; if (PSPPIRE_SHEET_IN_SELECTION (sheet)) return; GTK_WIDGET_SET_FLAGS (GTK_WIDGET (sheet->entry_widget), GTK_VISIBLE); sheet_entry = psppire_sheet_get_entry (sheet); psppire_sheet_get_attributes (sheet, row, col, &attributes); if (GTK_IS_ENTRY (sheet_entry)) { gchar *text = psppire_sheet_cell_get_text (sheet, row, col); const gchar *old_text = gtk_entry_get_text (GTK_ENTRY (sheet_entry)); if ( ! text ) text = g_strdup (""); if (strcmp (old_text, text) != 0) gtk_entry_set_text (sheet_entry, text); dispose_string (sheet, text); { switch (attributes.justification) { case GTK_JUSTIFY_RIGHT: gtk_entry_set_alignment (GTK_ENTRY (sheet_entry), 1.0); break; case GTK_JUSTIFY_CENTER: gtk_entry_set_alignment (GTK_ENTRY (sheet_entry), 0.5); break; case GTK_JUSTIFY_LEFT: default: gtk_entry_set_alignment (GTK_ENTRY (sheet_entry), 0.0); break; } } } psppire_sheet_size_allocate_entry (sheet); gtk_widget_set_sensitive (GTK_WIDGET (sheet_entry), psppire_sheet_model_is_editable (sheet->model, row, col)); gtk_widget_map (sheet->entry_widget); } static gboolean psppire_sheet_draw_active_cell (PsppireSheet *sheet) { gint row, col; PsppireSheetRange range; row = sheet->active_cell.row; col = sheet->active_cell.col; if (row < 0 || col < 0) return FALSE; if (!psppire_sheet_cell_isvisible (sheet, row, col)) return FALSE; range.col0 = range.coli = col; range.row0 = range.rowi = row; psppire_sheet_draw_border (sheet, range); return FALSE; } static void psppire_sheet_draw_border (PsppireSheet *sheet, PsppireSheetRange new_range) { GdkRectangle area; rectangle_from_range (sheet, &new_range, &area); area.width ++; area.height ++; gdk_gc_set_clip_rectangle (sheet->xor_gc, &area); area.x += sheet->cell_padding->left / 2; area.y += sheet->cell_padding->top / 2; area.width -= (sheet->cell_padding->left + sheet->cell_padding->right ) / 2; area.height -= (sheet->cell_padding->top + sheet->cell_padding->bottom ) / 2; gdk_draw_rectangle (sheet->sheet_window, sheet->xor_gc, FALSE, area.x, area.y, area.width, area.height); gdk_gc_set_clip_rectangle (sheet->xor_gc, NULL); } /* Selection related functions */ void psppire_sheet_select_row (PsppireSheet *sheet, gint row) { GdkRectangle area; sheet->select_status = PSPPIRE_SHEET_ROW_SELECTED; sheet->range.col0 = sheet->range.coli = -1; sheet->range.row0 = sheet->range.rowi = row; rectangle_from_range (sheet, &sheet->range, &area); area.x++; area.y++; gdk_window_invalidate_rect (sheet->sheet_window, &area, FALSE); g_signal_emit (sheet, sheet_signals [SELECT_ROW], 0, row); } void psppire_sheet_select_column (PsppireSheet *sheet, gint column) { GdkRectangle area; sheet->select_status = PSPPIRE_SHEET_COLUMN_SELECTED; sheet->range.col0 = sheet->range.coli = column; sheet->range.row0 = sheet->range.rowi = -1; rectangle_from_range (sheet, &sheet->range, &area); area.x++; area.y++; gdk_window_invalidate_rect (sheet->sheet_window, &area, FALSE); g_signal_emit (sheet, sheet_signals [SELECT_COLUMN], 0, column); } void psppire_sheet_select_range (PsppireSheet *sheet, const PsppireSheetRange *range) { GdkRectangle area; sheet->select_status = PSPPIRE_SHEET_RANGE_SELECTED; sheet->range = *range; rectangle_from_range (sheet, range, &area); area.x++; area.y++; gdk_window_invalidate_rect (sheet->sheet_window, &area, FALSE); } void psppire_sheet_unselect_range (PsppireSheet *sheet) { sheet->select_status = PSPPIRE_SHEET_NORMAL; if (sheet->sheet_window != NULL) { GdkRectangle area; rectangle_from_range (sheet, &sheet->range, &area); area.x++; area.y++; gdk_window_invalidate_rect (sheet->sheet_window, &area, FALSE); } g_signal_emit (sheet, sheet_signals [SELECT_COLUMN], 0, -1); g_signal_emit (sheet, sheet_signals [SELECT_ROW], 0, -1); } void psppire_sheet_get_selected_range (PsppireSheet *sheet, PsppireSheetRange *range) { g_return_if_fail (sheet != NULL); *range = sheet->range; } static gint psppire_sheet_expose (GtkWidget *widget, GdkEventExpose *event) { PsppireSheet *sheet = PSPPIRE_SHEET (widget); g_return_val_if_fail (event != NULL, FALSE); if (!GTK_WIDGET_DRAWABLE (widget)) return FALSE; /* exposure events on the sheet */ if (event->window == sheet->row_title_window && sheet->row_titles_visible) { draw_row_title_buttons_range (sheet, min_visible_row (sheet), max_visible_row (sheet)); } if (event->window == sheet->column_title_window && sheet->column_titles_visible) { draw_column_title_buttons_range (sheet, min_visible_column (sheet), max_visible_column (sheet)); } if (event->window == sheet->sheet_window) { draw_sheet_region (sheet, event->region); if (sheet->select_status != PSPPIRE_SHEET_NORMAL) { GdkRectangle area; rectangle_from_range (sheet, &sheet->range, &area); gdk_draw_rectangle (sheet->sheet_window, sheet->xor_gc, TRUE, area.x + 1, area.y + 1, area.width, area.height); } if ((!PSPPIRE_SHEET_IN_XDRAG (sheet)) && (!PSPPIRE_SHEET_IN_YDRAG (sheet))) { GdkRectangle rect; PsppireSheetRange range; range.row0 = range.rowi = sheet->active_cell.row; range.col0 = range.coli = sheet->active_cell.col; rectangle_from_range (sheet, &range, &rect); if (GDK_OVERLAP_RECTANGLE_OUT != gdk_region_rect_in (event->region, &rect)) { psppire_sheet_draw_active_cell (sheet); } } } (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event); return FALSE; } static gboolean psppire_sheet_button_press (GtkWidget *widget, GdkEventButton *event) { PsppireSheet *sheet; GdkModifierType mods; gint x, y; gint row, column; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (PSPPIRE_IS_SHEET (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); sheet = PSPPIRE_SHEET (widget); /* Cancel any pending tooltips */ if (sheet->motion_timer) { g_source_remove (sheet->motion_timer); sheet->motion_timer = 0; } gtk_widget_get_pointer (widget, &x, &y); psppire_sheet_get_pixel_info (sheet, x, y, &row, &column); if (event->window == sheet->column_title_window) { sheet->x_drag = event->x; g_signal_emit (sheet, sheet_signals[BUTTON_EVENT_COLUMN], 0, column, event); if (psppire_sheet_model_get_column_sensitivity (sheet->model, column)) { if ( event->type == GDK_2BUTTON_PRESS && event->button == 1) g_signal_emit (sheet, sheet_signals[DOUBLE_CLICK_COLUMN], 0, column); } } if (event->window == sheet->row_title_window) { g_signal_emit (sheet, sheet_signals[BUTTON_EVENT_ROW], 0, row, event); if (psppire_sheet_model_get_row_sensitivity (sheet->model, row)) { if ( event->type == GDK_2BUTTON_PRESS && event->button == 1) g_signal_emit (sheet, sheet_signals[DOUBLE_CLICK_ROW], 0, row); } } gdk_window_get_pointer (widget->window, NULL, NULL, &mods); if (! (mods & GDK_BUTTON1_MASK)) return TRUE; /* press on resize windows */ if (event->window == sheet->column_title_window) { sheet->x_drag = event->x; if (on_column_boundary (sheet, sheet->x_drag, &sheet->drag_cell.col)) { PSPPIRE_SHEET_SET_FLAGS (sheet, PSPPIRE_SHEET_IN_XDRAG); gdk_pointer_grab (sheet->column_title_window, FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, NULL, event->time); draw_xor_vline (sheet); return TRUE; } } if (event->window == sheet->row_title_window) { sheet->y_drag = event->y; if (on_row_boundary (sheet, sheet->y_drag, &sheet->drag_cell.row)) { PSPPIRE_SHEET_SET_FLAGS (sheet, PSPPIRE_SHEET_IN_YDRAG); gdk_pointer_grab (sheet->row_title_window, FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, NULL, event->time); draw_xor_hline (sheet); return TRUE; } } /* the sheet itself does not handle other than single click events */ if (event->type != GDK_BUTTON_PRESS) return FALSE; /* selections on the sheet */ if (event->window == sheet->sheet_window) { gtk_widget_get_pointer (widget, &x, &y); psppire_sheet_get_pixel_info (sheet, x, y, &row, &column); gdk_pointer_grab (sheet->sheet_window, FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, NULL, event->time); gtk_grab_add (GTK_WIDGET (sheet)); if ( sheet->select_status == PSPPIRE_SHEET_NORMAL) { sheet->range.row0 = row; sheet->range.col0 = column; } else { psppire_sheet_unselect_range (sheet); } psppire_sheet_click_cell (sheet, row, column); } if (event->window == sheet->column_title_window) { gtk_widget_get_pointer (widget, &x, &y); if ( sheet->row_titles_visible) x -= sheet->row_title_area.width; x += sheet->hadjustment->value; column = column_from_xpixel (sheet, x); if (psppire_sheet_model_get_column_sensitivity (sheet->model, column)) { gtk_grab_add (GTK_WIDGET (sheet)); PSPPIRE_SHEET_SET_FLAGS (sheet, PSPPIRE_SHEET_IN_SELECTION); } } if (event->window == sheet->row_title_window) { gtk_widget_get_pointer (widget, &x, &y); if ( sheet->column_titles_visible) y -= sheet->column_title_area.height; y += sheet->vadjustment->value; row = row_from_ypixel (sheet, y); if (psppire_sheet_model_get_row_sensitivity (sheet->model, row)) { gtk_grab_add (GTK_WIDGET (sheet)); PSPPIRE_SHEET_SET_FLAGS (sheet, PSPPIRE_SHEET_IN_SELECTION); } } return TRUE; } static gboolean psppire_sheet_click_cell (PsppireSheet *sheet, gint row, gint column) { PsppireSheetCell cell; gboolean forbid_move; cell.row = row; cell.col = column; if (row >= psppire_axis_unit_count (sheet->vaxis) || column >= psppire_axis_unit_count (sheet->haxis)) { return FALSE; } g_signal_emit (sheet, sheet_signals[TRAVERSE], 0, &sheet->active_cell, &cell, &forbid_move); if (forbid_move) { if (sheet->select_status == PSPPIRE_SHEET_NORMAL) return FALSE; row = sheet->active_cell.row; column = sheet->active_cell.col; change_active_cell (sheet, row, column); return FALSE; } if (row == -1 && column >= 0) { psppire_sheet_select_column (sheet, column); return TRUE; } if (column == -1 && row >= 0) { psppire_sheet_select_row (sheet, row); return TRUE; } if (row == -1 && column == -1) { sheet->range.row0 = 0; sheet->range.col0 = 0; sheet->range.rowi = psppire_axis_unit_count (sheet->vaxis) - 1; sheet->range.coli = psppire_axis_unit_count (sheet->haxis) - 1; return TRUE; } if (sheet->select_status == PSPPIRE_SHEET_NORMAL) change_active_cell (sheet, row, column); gtk_widget_grab_focus (GTK_WIDGET (sheet->entry_widget)); return TRUE; } static gint psppire_sheet_button_release (GtkWidget *widget, GdkEventButton *event) { GdkDisplay *display = gtk_widget_get_display (widget); PsppireSheet *sheet = PSPPIRE_SHEET (widget); /* release on resize windows */ if (PSPPIRE_SHEET_IN_XDRAG (sheet)) { gint width; PSPPIRE_SHEET_UNSET_FLAGS (sheet, PSPPIRE_SHEET_IN_XDRAG); PSPPIRE_SHEET_UNSET_FLAGS (sheet, PSPPIRE_SHEET_IN_SELECTION); gdk_display_pointer_ungrab (display, event->time); draw_xor_vline (sheet); width = event->x - psppire_axis_start_pixel (sheet->haxis, sheet->drag_cell.col) + sheet->hadjustment->value; set_column_width (sheet, sheet->drag_cell.col, width); return TRUE; } if (PSPPIRE_SHEET_IN_YDRAG (sheet)) { gint height; PSPPIRE_SHEET_UNSET_FLAGS (sheet, PSPPIRE_SHEET_IN_YDRAG); PSPPIRE_SHEET_UNSET_FLAGS (sheet, PSPPIRE_SHEET_IN_SELECTION); gdk_display_pointer_ungrab (display, event->time); draw_xor_hline (sheet); height = event->y - psppire_axis_start_pixel (sheet->vaxis, sheet->drag_cell.row) + sheet->vadjustment->value; set_row_height (sheet, sheet->drag_cell.row, height); return TRUE; } if (PSPPIRE_SHEET_IN_DRAG (sheet)) { PsppireSheetRange old_range; draw_xor_rectangle (sheet, sheet->drag_range); PSPPIRE_SHEET_UNSET_FLAGS (sheet, PSPPIRE_SHEET_IN_DRAG); gdk_display_pointer_ungrab (display, event->time); psppire_sheet_unselect_range (sheet); old_range = sheet->range; sheet->range = sheet->drag_range; sheet->drag_range = old_range; g_signal_emit (sheet, sheet_signals[MOVE_RANGE], 0, &sheet->drag_range, &sheet->range); psppire_sheet_select_range (sheet, &sheet->range); } if (PSPPIRE_SHEET_IN_SELECTION (sheet)) { PSPPIRE_SHEET_UNSET_FLAGS (sheet, PSPPIRE_SHEET_IN_SELECTION); sheet->select_status = PSPPIRE_SHEET_RANGE_SELECTED; change_active_cell (sheet, sheet->active_cell.row, sheet->active_cell.col); } gdk_display_pointer_ungrab (display, event->time); gtk_grab_remove (GTK_WIDGET (sheet)); PSPPIRE_SHEET_UNSET_FLAGS (sheet, PSPPIRE_SHEET_IN_SELECTION); return TRUE; } /* Shamelessly lifted from gtktooltips */ static gboolean psppire_sheet_subtitle_paint_window (GtkWidget *tip_window) { GtkRequisition req; gtk_widget_size_request (tip_window, &req); gtk_paint_flat_box (tip_window->style, tip_window->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, GTK_WIDGET(tip_window), "tooltip", 0, 0, req.width, req.height); return FALSE; } static void destroy_hover_window (PsppireSheetHoverTitle *h) { gtk_widget_destroy (h->window); g_free (h); } static PsppireSheetHoverTitle * create_hover_window (void) { PsppireSheetHoverTitle *hw = g_malloc (sizeof (*hw)); hw->window = gtk_window_new (GTK_WINDOW_POPUP); #if GTK_CHECK_VERSION (2, 9, 0) gtk_window_set_type_hint (GTK_WINDOW (hw->window), GDK_WINDOW_TYPE_HINT_TOOLTIP); #endif gtk_widget_set_app_paintable (hw->window, TRUE); gtk_window_set_resizable (GTK_WINDOW (hw->window), FALSE); gtk_widget_set_name (hw->window, "gtk-tooltips"); gtk_container_set_border_width (GTK_CONTAINER (hw->window), 4); g_signal_connect (hw->window, "expose_event", G_CALLBACK (psppire_sheet_subtitle_paint_window), NULL); hw->label = gtk_label_new (NULL); gtk_label_set_line_wrap (GTK_LABEL (hw->label), TRUE); gtk_misc_set_alignment (GTK_MISC (hw->label), 0.5, 0.5); gtk_container_add (GTK_CONTAINER (hw->window), hw->label); gtk_widget_show (hw->label); g_signal_connect (hw->window, "destroy", G_CALLBACK (gtk_widget_destroyed), &hw->window); return hw; } #define HOVER_WINDOW_Y_OFFSET 2 static void show_subtitle (PsppireSheet *sheet, gint row, gint column, const gchar *subtitle) { gint x, y; gint px, py; gint width; if ( ! subtitle ) return; gtk_label_set_text (GTK_LABEL (sheet->hover_window->label), subtitle); sheet->hover_window->row = row; sheet->hover_window->column = column; gdk_window_get_origin (GTK_WIDGET (sheet)->window, &x, &y); gtk_widget_get_pointer (GTK_WIDGET (sheet), &px, &py); gtk_widget_show (sheet->hover_window->window); width = GTK_WIDGET (sheet->hover_window->label)->allocation.width; if (row == -1 ) { x += px; x -= width / 2; y += sheet->column_title_area.y; y += sheet->column_title_area.height; y += HOVER_WINDOW_Y_OFFSET; } if ( column == -1 ) { y += py; x += sheet->row_title_area.x; x += sheet->row_title_area.width * 2 / 3.0; } gtk_window_move (GTK_WINDOW (sheet->hover_window->window), x, y); } static gboolean motion_timeout_callback (gpointer data) { PsppireSheet *sheet = PSPPIRE_SHEET (data); gint x, y; gint row, column; gdk_threads_enter (); gtk_widget_get_pointer (GTK_WIDGET (sheet), &x, &y); if ( psppire_sheet_get_pixel_info (sheet, x, y, &row, &column) ) { if (sheet->row_title_under && row >= 0) { gchar *text = psppire_sheet_model_get_row_subtitle (sheet->model, row); show_subtitle (sheet, row, -1, text); g_free (text); } if (sheet->column_title_under && column >= 0) { gchar *text = psppire_sheet_model_get_column_subtitle (sheet->model, column); show_subtitle (sheet, -1, column, text); g_free (text); } } gdk_threads_leave (); return FALSE; } static gboolean psppire_sheet_motion (GtkWidget *widget, GdkEventMotion *event) { PsppireSheet *sheet = PSPPIRE_SHEET (widget); GdkModifierType mods; GdkCursorType new_cursor; gint x, y; gint row, column; GdkDisplay *display; g_return_val_if_fail (event != NULL, FALSE); display = gtk_widget_get_display (widget); /* selections on the sheet */ x = event->x; y = event->y; if (!GTK_WIDGET_VISIBLE (sheet->hover_window->window)) { if ( sheet->motion_timer > 0 ) g_source_remove (sheet->motion_timer); sheet->motion_timer = g_timeout_add (TIMEOUT_HOVER, motion_timeout_callback, sheet); } else { gint row, column; gint wx, wy; gtk_widget_get_pointer (widget, &wx, &wy); if ( psppire_sheet_get_pixel_info (sheet, wx, wy, &row, &column) ) { if ( row != sheet->hover_window->row || column != sheet->hover_window->column) { gtk_widget_hide (sheet->hover_window->window); } } } if (event->window == sheet->column_title_window) { if (!PSPPIRE_SHEET_IN_SELECTION (sheet) && on_column_boundary (sheet, x, &column)) { new_cursor = GDK_SB_H_DOUBLE_ARROW; if (new_cursor != sheet->cursor_drag->type) { gdk_cursor_unref (sheet->cursor_drag); sheet->cursor_drag = gdk_cursor_new_for_display (display, new_cursor); gdk_window_set_cursor (sheet->column_title_window, sheet->cursor_drag); } } else { new_cursor = GDK_TOP_LEFT_ARROW; if (!PSPPIRE_SHEET_IN_XDRAG (sheet) && new_cursor != sheet->cursor_drag->type) { gdk_cursor_unref (sheet->cursor_drag); sheet->cursor_drag = gdk_cursor_new_for_display (display, new_cursor); gdk_window_set_cursor (sheet->column_title_window, sheet->cursor_drag); } } } else if (event->window == sheet->row_title_window) { if (!PSPPIRE_SHEET_IN_SELECTION (sheet) && on_row_boundary (sheet, y, &row)) { new_cursor = GDK_SB_V_DOUBLE_ARROW; if (new_cursor != sheet->cursor_drag->type) { gdk_cursor_unref (sheet->cursor_drag); sheet->cursor_drag = gdk_cursor_new_for_display (display, new_cursor); gdk_window_set_cursor (sheet->row_title_window, sheet->cursor_drag); } } else { new_cursor = GDK_TOP_LEFT_ARROW; if (!PSPPIRE_SHEET_IN_YDRAG (sheet) && new_cursor != sheet->cursor_drag->type) { gdk_cursor_unref (sheet->cursor_drag); sheet->cursor_drag = gdk_cursor_new_for_display (display, new_cursor); gdk_window_set_cursor (sheet->row_title_window, sheet->cursor_drag); } } } new_cursor = GDK_PLUS; if ( event->window == sheet->sheet_window && !POSSIBLE_DRAG (sheet, x, y, &row, &column) && !PSPPIRE_SHEET_IN_DRAG (sheet) && !POSSIBLE_RESIZE (sheet, x, y, &row, &column) && new_cursor != sheet->cursor_drag->type) { gdk_cursor_unref (sheet->cursor_drag); sheet->cursor_drag = gdk_cursor_new_for_display (display, GDK_PLUS); gdk_window_set_cursor (sheet->sheet_window, sheet->cursor_drag); } new_cursor = GDK_TOP_LEFT_ARROW; if ( event->window == sheet->sheet_window && ! (POSSIBLE_RESIZE (sheet, x, y, &row, &column) ) && (POSSIBLE_DRAG (sheet, x, y, &row, &column) || PSPPIRE_SHEET_IN_DRAG (sheet)) && new_cursor != sheet->cursor_drag->type) { gdk_cursor_unref (sheet->cursor_drag); sheet->cursor_drag = gdk_cursor_new_for_display (display, GDK_TOP_LEFT_ARROW); gdk_window_set_cursor (sheet->sheet_window, sheet->cursor_drag); } gdk_window_get_pointer (widget->window, &x, &y, &mods); if (! (mods & GDK_BUTTON1_MASK)) return FALSE; if (PSPPIRE_SHEET_IN_XDRAG (sheet)) { if (event->x != sheet->x_drag) { draw_xor_vline (sheet); sheet->x_drag = event->x; draw_xor_vline (sheet); } return TRUE; } if (PSPPIRE_SHEET_IN_YDRAG (sheet)) { if (event->y != sheet->y_drag) { draw_xor_hline (sheet); sheet->y_drag = event->y; draw_xor_hline (sheet); } return TRUE; } if (PSPPIRE_SHEET_IN_DRAG (sheet)) { PsppireSheetRange aux; column = column_from_xpixel (sheet, x)- sheet->drag_cell.col; row = row_from_ypixel (sheet, y) - sheet->drag_cell.row; if (sheet->select_status == PSPPIRE_SHEET_COLUMN_SELECTED) row = 0; if (sheet->select_status == PSPPIRE_SHEET_ROW_SELECTED) column = 0; sheet->x_drag = x; sheet->y_drag = y; aux = sheet->range; if (aux.row0 + row >= 0 && aux.rowi + row < psppire_axis_unit_count (sheet->vaxis) && aux.col0 + column >= 0 && aux.coli + column < psppire_axis_unit_count (sheet->haxis)) { aux = sheet->drag_range; sheet->drag_range.row0 = sheet->range.row0 + row; sheet->drag_range.col0 = sheet->range.col0 + column; sheet->drag_range.rowi = sheet->range.rowi + row; sheet->drag_range.coli = sheet->range.coli + column; if (aux.row0 != sheet->drag_range.row0 || aux.col0 != sheet->drag_range.col0) { draw_xor_rectangle (sheet, aux); draw_xor_rectangle (sheet, sheet->drag_range); } } return TRUE; } psppire_sheet_get_pixel_info (sheet, x, y, &row, &column); if (sheet->select_status == PSPPIRE_SHEET_NORMAL && row == sheet->active_cell.row && column == sheet->active_cell.col) return TRUE; if ( mods & GDK_BUTTON1_MASK) { if (PSPPIRE_SHEET_IN_SELECTION (sheet) ) { /* Redraw the old range */ psppire_sheet_unselect_range (sheet); sheet->range.rowi = row; sheet->range.coli = column; /* Redraw the new range */ psppire_sheet_select_range (sheet, &sheet->range); } else { PSPPIRE_SHEET_SET_FLAGS (sheet, PSPPIRE_SHEET_IN_SELECTION); } } return TRUE; } static gboolean psppire_sheet_crossing_notify (GtkWidget *widget, GdkEventCrossing *event) { PsppireSheet *sheet = PSPPIRE_SHEET (widget); if (event->window == sheet->column_title_window) sheet->column_title_under = event->type == GDK_ENTER_NOTIFY; else if (event->window == sheet->row_title_window) sheet->row_title_under = event->type == GDK_ENTER_NOTIFY; if (event->type == GDK_LEAVE_NOTIFY) gtk_widget_hide (sheet->hover_window->window); return TRUE; } static gboolean psppire_sheet_focus_in (GtkWidget *w, GdkEventFocus *event) { PsppireSheet *sheet = PSPPIRE_SHEET (w); gtk_widget_grab_focus (sheet->entry_widget); return TRUE; } static gint psppire_sheet_entry_key_press (GtkWidget *widget, GdkEventKey *key) { gboolean focus; g_signal_emit_by_name (widget, "key_press_event", key, &focus); return focus; } /* Number of rows in a step-increment */ #define ROWS_PER_STEP 1 static void page_vertical (PsppireSheet *sheet, GtkScrollType dir) { gint old_row = sheet->active_cell.row ; glong vpixel = psppire_axis_start_pixel (sheet->vaxis, old_row); gint new_row; vpixel -= psppire_axis_start_pixel (sheet->vaxis, min_visible_row (sheet)); switch ( dir) { case GTK_SCROLL_PAGE_DOWN: gtk_adjustment_set_value (sheet->vadjustment, sheet->vadjustment->value + sheet->vadjustment->page_increment); break; case GTK_SCROLL_PAGE_UP: gtk_adjustment_set_value (sheet->vadjustment, sheet->vadjustment->value - sheet->vadjustment->page_increment); break; default: g_assert_not_reached (); break; } vpixel += psppire_axis_start_pixel (sheet->vaxis, min_visible_row (sheet)); new_row = row_from_ypixel (sheet, vpixel); change_active_cell (sheet, new_row, sheet->active_cell.col); } static void step_sheet (PsppireSheet *sheet, GtkScrollType dir) { gint current_row = sheet->active_cell.row; gint current_col = sheet->active_cell.col; PsppireSheetCell new_cell ; gboolean forbidden = FALSE; new_cell.row = current_row; new_cell.col = current_col; switch ( dir) { case GTK_SCROLL_STEP_DOWN: new_cell.row++; break; case GTK_SCROLL_STEP_UP: new_cell.row--; break; case GTK_SCROLL_STEP_RIGHT: new_cell.col++; break; case GTK_SCROLL_STEP_LEFT: new_cell.col--; break; case GTK_SCROLL_STEP_FORWARD: new_cell.col++; if (new_cell.col >= psppire_sheet_model_get_column_count (sheet->model)) { new_cell.col = 0; new_cell.row++; } break; case GTK_SCROLL_STEP_BACKWARD: new_cell.col--; if (new_cell.col < 0) { new_cell.col = psppire_sheet_model_get_column_count (sheet->model) - 1; new_cell.row--; } break; default: g_assert_not_reached (); break; } g_signal_emit (sheet, sheet_signals[TRAVERSE], 0, &sheet->active_cell, &new_cell, &forbidden); if (forbidden) return; maximize_int (&new_cell.row, 0); maximize_int (&new_cell.col, 0); minimize_int (&new_cell.row, psppire_axis_unit_count (sheet->vaxis) - 1); minimize_int (&new_cell.col, psppire_axis_unit_count (sheet->haxis) - 1); change_active_cell (sheet, new_cell.row, new_cell.col); if ( new_cell.col > max_fully_visible_column (sheet)) { glong hpos = psppire_axis_start_pixel (sheet->haxis, new_cell.col + 1); hpos -= sheet->hadjustment->page_size; gtk_adjustment_set_value (sheet->hadjustment, hpos); } else if ( new_cell.col < min_fully_visible_column (sheet)) { glong hpos = psppire_axis_start_pixel (sheet->haxis, new_cell.col); gtk_adjustment_set_value (sheet->hadjustment, hpos); } if ( new_cell.row > max_fully_visible_row (sheet)) { glong vpos = psppire_axis_start_pixel (sheet->vaxis, new_cell.row + 1); vpos -= sheet->vadjustment->page_size; gtk_adjustment_set_value (sheet->vadjustment, vpos); } else if ( new_cell.row < min_fully_visible_row (sheet)) { glong vpos = psppire_axis_start_pixel (sheet->vaxis, new_cell.row); gtk_adjustment_set_value (sheet->vadjustment, vpos); } gtk_widget_grab_focus (GTK_WIDGET (sheet->entry_widget)); } static gboolean psppire_sheet_key_press (GtkWidget *widget, GdkEventKey *key) { PsppireSheet *sheet = PSPPIRE_SHEET (widget); PSPPIRE_SHEET_UNSET_FLAGS (sheet, PSPPIRE_SHEET_IN_SELECTION); switch (key->keyval) { case GDK_Tab: step_sheet (sheet, GTK_SCROLL_STEP_FORWARD); break; case GDK_Right: step_sheet (sheet, GTK_SCROLL_STEP_RIGHT); break; case GDK_ISO_Left_Tab: step_sheet (sheet, GTK_SCROLL_STEP_BACKWARD); break; case GDK_Left: step_sheet (sheet, GTK_SCROLL_STEP_LEFT); break; case GDK_Return: case GDK_Down: step_sheet (sheet, GTK_SCROLL_STEP_DOWN); break; case GDK_Up: step_sheet (sheet, GTK_SCROLL_STEP_UP); break; case GDK_Page_Down: page_vertical (sheet, GTK_SCROLL_PAGE_DOWN); break; case GDK_Page_Up: page_vertical (sheet, GTK_SCROLL_PAGE_UP); break; case GDK_Home: gtk_adjustment_set_value (sheet->vadjustment, sheet->vadjustment->lower); change_active_cell (sheet, 0, sheet->active_cell.col); break; case GDK_End: gtk_adjustment_set_value (sheet->vadjustment, sheet->vadjustment->upper - sheet->vadjustment->page_size - sheet->vadjustment->page_increment); /* change_active_cellx (sheet, psppire_axis_unit_count (sheet->vaxis) - 1, sheet->active_cell.col); */ break; case GDK_Delete: psppire_sheet_real_cell_clear (sheet, sheet->active_cell.row, sheet->active_cell.col); break; default: return FALSE; break; } return TRUE; } static void psppire_sheet_size_request (GtkWidget *widget, GtkRequisition *requisition) { PsppireSheet *sheet; g_return_if_fail (widget != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (widget)); g_return_if_fail (requisition != NULL); sheet = PSPPIRE_SHEET (widget); requisition->width = 3 * DEFAULT_COLUMN_WIDTH; requisition->height = 3 * DEFAULT_ROW_HEIGHT; /* compute the size of the column title area */ if (sheet->column_titles_visible) requisition->height += sheet->column_title_area.height; /* compute the size of the row title area */ if (sheet->row_titles_visible) requisition->width += sheet->row_title_area.width; } static void psppire_sheet_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { PsppireSheet *sheet; GtkAllocation sheet_allocation; gint border_width; g_return_if_fail (widget != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (widget)); g_return_if_fail (allocation != NULL); sheet = PSPPIRE_SHEET (widget); widget->allocation = *allocation; border_width = GTK_CONTAINER (widget)->border_width; if (GTK_WIDGET_REALIZED (widget)) gdk_window_move_resize (widget->window, allocation->x + border_width, allocation->y + border_width, allocation->width - 2 * border_width, allocation->height - 2 * border_width); sheet_allocation.x = 0; sheet_allocation.y = 0; sheet_allocation.width = allocation->width - 2 * border_width; sheet_allocation.height = allocation->height - 2 * border_width; if (GTK_WIDGET_REALIZED (widget)) gdk_window_move_resize (sheet->sheet_window, sheet_allocation.x, sheet_allocation.y, sheet_allocation.width, sheet_allocation.height); /* position the window which holds the column title buttons */ sheet->column_title_area.x = 0; sheet->column_title_area.y = 0; sheet->column_title_area.width = sheet_allocation.width ; /* position the window which holds the row title buttons */ sheet->row_title_area.x = 0; sheet->row_title_area.y = 0; sheet->row_title_area.height = sheet_allocation.height; if (sheet->row_titles_visible) sheet->column_title_area.x += sheet->row_title_area.width; if (sheet->column_titles_visible) sheet->row_title_area.y += sheet->column_title_area.height; if (GTK_WIDGET_REALIZED (widget) && sheet->column_titles_visible) gdk_window_move_resize (sheet->column_title_window, sheet->column_title_area.x, sheet->column_title_area.y, sheet->column_title_area.width, sheet->column_title_area.height); if (GTK_WIDGET_REALIZED (widget) && sheet->row_titles_visible) gdk_window_move_resize (sheet->row_title_window, sheet->row_title_area.x, sheet->row_title_area.y, sheet->row_title_area.width, sheet->row_title_area.height); size_allocate_global_button (sheet); if (sheet->haxis) { gint width = sheet->column_title_area.width; if ( sheet->row_titles_visible) width -= sheet->row_title_area.width; g_object_set (sheet->haxis, "minimum-extent", width, NULL); } if (sheet->vaxis) { gint height = sheet->row_title_area.height; if ( sheet->column_titles_visible) height -= sheet->column_title_area.height; g_object_set (sheet->vaxis, "minimum-extent", height, NULL); } /* set the scrollbars adjustments */ adjust_scrollbars (sheet); } static void draw_column_title_buttons (PsppireSheet *sheet) { gint x, width; if (!sheet->column_titles_visible) return; if (!GTK_WIDGET_REALIZED (sheet)) return; gdk_drawable_get_size (sheet->sheet_window, &width, NULL); x = 0; if (sheet->row_titles_visible) { x = sheet->row_title_area.width; } if (sheet->column_title_area.width != width || sheet->column_title_area.x != x) { sheet->column_title_area.width = width; sheet->column_title_area.x = x; gdk_window_move_resize (sheet->column_title_window, sheet->column_title_area.x, sheet->column_title_area.y, sheet->column_title_area.width, sheet->column_title_area.height); } if (max_visible_column (sheet) == psppire_axis_unit_count (sheet->haxis) - 1) gdk_window_clear_area (sheet->column_title_window, 0, 0, sheet->column_title_area.width, sheet->column_title_area.height); if (!GTK_WIDGET_DRAWABLE (sheet)) return; draw_column_title_buttons_range (sheet, min_visible_column (sheet), max_visible_column (sheet)); } static void draw_row_title_buttons (PsppireSheet *sheet) { gint y = 0; gint height; if (!sheet->row_titles_visible) return; if (!GTK_WIDGET_REALIZED (sheet)) return; gdk_drawable_get_size (sheet->sheet_window, NULL, &height); if (sheet->column_titles_visible) { y = sheet->column_title_area.height; } if (sheet->row_title_area.height != height || sheet->row_title_area.y != y) { sheet->row_title_area.y = y; sheet->row_title_area.height = height; gdk_window_move_resize (sheet->row_title_window, sheet->row_title_area.x, sheet->row_title_area.y, sheet->row_title_area.width, sheet->row_title_area.height); } if (max_visible_row (sheet) == psppire_axis_unit_count (sheet->vaxis) - 1) gdk_window_clear_area (sheet->row_title_window, 0, 0, sheet->row_title_area.width, sheet->row_title_area.height); if (!GTK_WIDGET_DRAWABLE (sheet)) return; draw_row_title_buttons_range (sheet, min_visible_row (sheet), max_visible_row (sheet)); } static void psppire_sheet_size_allocate_entry (PsppireSheet *sheet) { GtkAllocation entry_alloc; PsppireSheetCellAttr attributes = { 0 }; GtkEntry *sheet_entry; if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return; if (!GTK_WIDGET_MAPPED (GTK_WIDGET (sheet))) return; sheet_entry = psppire_sheet_get_entry (sheet); if ( ! psppire_sheet_get_attributes (sheet, sheet->active_cell.row, sheet->active_cell.col, &attributes) ) return ; if ( GTK_WIDGET_REALIZED (sheet->entry_widget) ) { GtkStyle *style = GTK_WIDGET (sheet_entry)->style; style->bg[GTK_STATE_NORMAL] = attributes.background; style->fg[GTK_STATE_NORMAL] = attributes.foreground; style->text[GTK_STATE_NORMAL] = attributes.foreground; style->bg[GTK_STATE_ACTIVE] = attributes.background; style->fg[GTK_STATE_ACTIVE] = attributes.foreground; style->text[GTK_STATE_ACTIVE] = attributes.foreground; } rectangle_from_cell (sheet, sheet->active_cell.row, sheet->active_cell.col, &entry_alloc); entry_alloc.x += sheet->cell_padding->left; entry_alloc.y += sheet->cell_padding->right; entry_alloc.width -= sheet->cell_padding->left + sheet->cell_padding->right; entry_alloc.height -= sheet->cell_padding->top + sheet->cell_padding->bottom; gtk_widget_set_size_request (sheet->entry_widget, entry_alloc.width, entry_alloc.height); gtk_widget_size_allocate (sheet->entry_widget, &entry_alloc); } /* Copy the sheet's font to the entry widget */ static void set_entry_widget_font (PsppireSheet *sheet) { GtkRcStyle *style = gtk_widget_get_modifier_style (sheet->entry_widget); pango_font_description_free (style->font_desc); style->font_desc = pango_font_description_copy (GTK_WIDGET (sheet)->style->font_desc); gtk_widget_modify_style (sheet->entry_widget, style); } static void create_sheet_entry (PsppireSheet *sheet) { if (sheet->entry_widget) { gtk_widget_unparent (sheet->entry_widget); } sheet->entry_widget = g_object_new (sheet->entry_type, NULL); g_object_ref_sink (sheet->entry_widget); gtk_widget_size_request (sheet->entry_widget, NULL); if ( GTK_IS_ENTRY (sheet->entry_widget)) { g_object_set (sheet->entry_widget, "has-frame", FALSE, NULL); } if (GTK_WIDGET_REALIZED (sheet)) { gtk_widget_set_parent_window (sheet->entry_widget, sheet->sheet_window); gtk_widget_set_parent (sheet->entry_widget, GTK_WIDGET (sheet)); gtk_widget_realize (sheet->entry_widget); } g_signal_connect_swapped (sheet->entry_widget, "key_press_event", G_CALLBACK (psppire_sheet_entry_key_press), sheet); set_entry_widget_font (sheet); gtk_widget_show (sheet->entry_widget); } /* Finds the last child widget that happens to be of type GtkEntry */ static void find_entry (GtkWidget *w, gpointer user_data) { GtkWidget **entry = user_data; if ( GTK_IS_ENTRY (w)) { *entry = w; } } GtkEntry * psppire_sheet_get_entry (PsppireSheet *sheet) { GtkWidget *w = sheet->entry_widget; g_return_val_if_fail (sheet != NULL, NULL); g_return_val_if_fail (PSPPIRE_IS_SHEET (sheet), NULL); g_return_val_if_fail (sheet->entry_widget != NULL, NULL); while (! GTK_IS_ENTRY (w)) { GtkWidget *entry = NULL; if (GTK_IS_CONTAINER (w)) { gtk_container_forall (GTK_CONTAINER (w), find_entry, &entry); if (NULL == entry) break; w = entry; } } return GTK_ENTRY (w); } static void draw_button (PsppireSheet *sheet, GdkWindow *window, PsppireSheetButton *button, gboolean is_sensitive, GdkRectangle allocation) { GtkShadowType shadow_type; gint text_width = 0, text_height = 0; PangoAlignment align = PANGO_ALIGN_LEFT; gboolean rtl ; gint state = 0; g_return_if_fail (sheet != NULL); g_return_if_fail (button != NULL); rtl = gtk_widget_get_direction (GTK_WIDGET (sheet)) == GTK_TEXT_DIR_RTL; gdk_window_clear_area (window, allocation.x, allocation.y, allocation.width, allocation.height); gtk_widget_ensure_style (sheet->button); gtk_paint_box (sheet->button->style, window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, &allocation, GTK_WIDGET (sheet->button), NULL, allocation.x, allocation.y, allocation.width, allocation.height); state = button->state; if (!is_sensitive) state = GTK_STATE_INSENSITIVE; if (state == GTK_STATE_ACTIVE) shadow_type = GTK_SHADOW_IN; else shadow_type = GTK_SHADOW_OUT; if (state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE) gtk_paint_box (sheet->button->style, window, button->state, shadow_type, &allocation, GTK_WIDGET (sheet->button), NULL, allocation.x, allocation.y, allocation.width, allocation.height); if ( button->overstruck) { GdkPoint points[2] = { {allocation.x, allocation.y}, {allocation.x + allocation.width, allocation.y + allocation.height} }; gtk_paint_polygon (sheet->button->style, window, button->state, shadow_type, NULL, GTK_WIDGET (sheet), NULL, points, 2, TRUE); } if (button->label_visible) { text_height = DEFAULT_ROW_HEIGHT - 2 * COLUMN_TITLES_HEIGHT; gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->fg_gc[button->state], &allocation); gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->white_gc, &allocation); allocation.y += 2 * sheet->button->style->ythickness; if (button->label && strlen (button->label) > 0) { PangoRectangle rect; gchar *line = button->label; PangoLayout *layout = NULL; gint real_x = allocation.x; gint real_y = allocation.y; layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), line); pango_layout_get_extents (layout, NULL, &rect); text_width = PANGO_PIXELS (rect.width); switch (button->justification) { case GTK_JUSTIFY_LEFT: real_x = allocation.x + COLUMN_TITLES_HEIGHT; align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT; break; case GTK_JUSTIFY_RIGHT: real_x = allocation.x + allocation.width - text_width - COLUMN_TITLES_HEIGHT; align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT; break; case GTK_JUSTIFY_CENTER: default: real_x = allocation.x + (allocation.width - text_width)/2; align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT; pango_layout_set_justify (layout, TRUE); } pango_layout_set_alignment (layout, align); gtk_paint_layout (GTK_WIDGET (sheet)->style, window, state, FALSE, &allocation, GTK_WIDGET (sheet), "label", real_x, real_y, layout); g_object_unref (layout); } gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->fg_gc[button->state], NULL); gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->white_gc, NULL); } psppire_sheet_button_free (button); } /* Draw the column title buttons FIRST through to LAST */ static void draw_column_title_buttons_range (PsppireSheet *sheet, gint first, gint last) { GdkRectangle rect; gint col; if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return; if (!sheet->column_titles_visible) return; g_return_if_fail (first >= min_visible_column (sheet)); g_return_if_fail (last <= max_visible_column (sheet)); rect.y = 0; rect.height = sheet->column_title_area.height; rect.x = psppire_axis_start_pixel (sheet->haxis, first) + CELL_SPACING; rect.width = psppire_axis_start_pixel (sheet->haxis, last) + CELL_SPACING + psppire_axis_unit_size (sheet->haxis, last); rect.x -= sheet->hadjustment->value; minimize_int (&rect.width, sheet->column_title_area.width); maximize_int (&rect.x, 0); gdk_window_begin_paint_rect (sheet->column_title_window, &rect); for (col = first ; col <= last ; ++col) { GdkRectangle allocation; gboolean is_sensitive = FALSE; PsppireSheetButton * button = psppire_sheet_model_get_column_button (sheet->model, col); allocation.y = 0; allocation.x = psppire_axis_start_pixel (sheet->haxis, col) + CELL_SPACING; allocation.x -= sheet->hadjustment->value; allocation.height = sheet->column_title_area.height; allocation.width = psppire_axis_unit_size (sheet->haxis, col); is_sensitive = psppire_sheet_model_get_column_sensitivity (sheet->model, col); draw_button (sheet, sheet->column_title_window, button, is_sensitive, allocation); } gdk_window_end_paint (sheet->column_title_window); } static void draw_row_title_buttons_range (PsppireSheet *sheet, gint first, gint last) { GdkRectangle rect; gint row; if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return; if (!sheet->row_titles_visible) return; g_return_if_fail (first >= min_visible_row (sheet)); g_return_if_fail (last <= max_visible_row (sheet)); rect.x = 0; rect.width = sheet->row_title_area.width; rect.y = psppire_axis_start_pixel (sheet->vaxis, first) + CELL_SPACING; rect.height = psppire_axis_start_pixel (sheet->vaxis, last) + CELL_SPACING + psppire_axis_unit_size (sheet->vaxis, last); rect.y -= sheet->vadjustment->value; minimize_int (&rect.height, sheet->row_title_area.height); maximize_int (&rect.y, 0); gdk_window_begin_paint_rect (sheet->row_title_window, &rect); for (row = first; row <= last; ++row) { GdkRectangle allocation; gboolean is_sensitive = FALSE; PsppireSheetButton *button = psppire_sheet_model_get_row_button (sheet->model, row); allocation.x = 0; allocation.y = psppire_axis_start_pixel (sheet->vaxis, row) + CELL_SPACING; allocation.y -= sheet->vadjustment->value; allocation.width = sheet->row_title_area.width; allocation.height = psppire_axis_unit_size (sheet->vaxis, row); is_sensitive = psppire_sheet_model_get_row_sensitivity (sheet->model, row); draw_button (sheet, sheet->row_title_window, button, is_sensitive, allocation); } gdk_window_end_paint (sheet->row_title_window); } /* SCROLLBARS * * functions: * adjust_scrollbars * vadjustment_value_changed * hadjustment_value_changed */ static void update_adjustment (GtkAdjustment *adj, PsppireAxis *axis, gint page_size) { double position = (adj->value + adj->page_size) / (adj->upper - adj->lower); const glong last_item = psppire_axis_unit_count (axis) - 1; if (isnan (position) || position < 0) position = 0; adj->upper = psppire_axis_start_pixel (axis, last_item) + psppire_axis_unit_size (axis, last_item) ; adj->lower = 0; adj->page_size = page_size; #if 0 adj->value = position * (adj->upper - adj->lower) - adj->page_size; if ( adj->value < adj->lower) adj->value = adj->lower; #endif gtk_adjustment_changed (adj); } static void adjust_scrollbars (PsppireSheet *sheet) { gint width, height; if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return; gdk_drawable_get_size (sheet->sheet_window, &width, &height); if ( sheet->row_titles_visible) width -= sheet->row_title_area.width; if (sheet->column_titles_visible) height -= sheet->column_title_area.height; if (sheet->vadjustment) { glong last_row = psppire_axis_unit_count (sheet->vaxis) - 1; sheet->vadjustment->step_increment = ROWS_PER_STEP * psppire_axis_unit_size (sheet->vaxis, last_row); sheet->vadjustment->page_increment = height - sheet->column_title_area.height - psppire_axis_unit_size (sheet->vaxis, last_row); update_adjustment (sheet->vadjustment, sheet->vaxis, height); } if (sheet->hadjustment) { gint last_col = psppire_axis_unit_count (sheet->haxis) - 1; sheet->hadjustment->step_increment = 1; sheet->hadjustment->page_increment = width; sheet->hadjustment->upper = psppire_axis_start_pixel (sheet->haxis, last_col) + psppire_axis_unit_size (sheet->haxis, last_col) ; update_adjustment (sheet->hadjustment, sheet->haxis, width); } } /* Subtracts the region of WIDGET from REGION */ static void subtract_widget_region (GdkRegion *region, GtkWidget *widget) { GdkRectangle rect; GdkRectangle intersect; GdkRegion *region2; gdk_region_get_clipbox (region, &rect); gtk_widget_intersect (widget, &rect, &intersect); region2 = gdk_region_rectangle (&intersect); gdk_region_subtract (region, region2); gdk_region_destroy (region2); } static void vadjustment_value_changed (GtkAdjustment *adjustment, gpointer data) { GdkRegion *region; PsppireSheet *sheet = PSPPIRE_SHEET (data); g_return_if_fail (adjustment != NULL); if ( ! GTK_WIDGET_REALIZED (sheet)) return; gtk_widget_hide (sheet->entry_widget); region = gdk_drawable_get_visible_region (GDK_DRAWABLE (sheet->sheet_window)); subtract_widget_region (region, sheet->button); gdk_window_begin_paint_region (sheet->sheet_window, region); draw_sheet_region (sheet, region); draw_row_title_buttons (sheet); psppire_sheet_draw_active_cell (sheet); gdk_window_end_paint (sheet->sheet_window); gdk_region_destroy (region); } static void hadjustment_value_changed (GtkAdjustment *adjustment, gpointer data) { GdkRegion *region; PsppireSheet *sheet = PSPPIRE_SHEET (data); g_return_if_fail (adjustment != NULL); if ( ! GTK_WIDGET_REALIZED (sheet)) return; gtk_widget_hide (sheet->entry_widget); region = gdk_drawable_get_visible_region (GDK_DRAWABLE (sheet->sheet_window)); subtract_widget_region (region, sheet->button); gdk_window_begin_paint_region (sheet->sheet_window, region); draw_sheet_region (sheet, region); draw_column_title_buttons (sheet); psppire_sheet_draw_active_cell (sheet); gdk_window_end_paint (sheet->sheet_window); gdk_region_destroy (region); } /* COLUMN RESIZING */ static void draw_xor_vline (PsppireSheet *sheet) { gint height; gint xpos = sheet->x_drag; gdk_drawable_get_size (sheet->sheet_window, NULL, &height); if (sheet->row_titles_visible) xpos += sheet->row_title_area.width; gdk_draw_line (GTK_WIDGET (sheet)->window, sheet->xor_gc, xpos, sheet->column_title_area.height, xpos, height + CELL_SPACING); } /* ROW RESIZING */ static void draw_xor_hline (PsppireSheet *sheet) { gint width; gint ypos = sheet->y_drag; gdk_drawable_get_size (sheet->sheet_window, &width, NULL); if (sheet->column_titles_visible) ypos += sheet->column_title_area.height; gdk_draw_line (GTK_WIDGET (sheet)->window, sheet->xor_gc, sheet->row_title_area.width, ypos, width + CELL_SPACING, ypos); } /* SELECTED RANGE */ static void draw_xor_rectangle (PsppireSheet *sheet, PsppireSheetRange range) { gint i = 0; GdkRectangle clip_area, area; GdkGCValues values; area.x = psppire_axis_start_pixel (sheet->haxis, range.col0); area.y = psppire_axis_start_pixel (sheet->vaxis, range.row0); area.width = psppire_axis_start_pixel (sheet->haxis, range.coli)- area.x+ psppire_axis_unit_size (sheet->haxis, range.coli); area.height = psppire_axis_start_pixel (sheet->vaxis, range.rowi)- area.y + psppire_axis_unit_size (sheet->vaxis, range.rowi); clip_area.x = sheet->row_title_area.width; clip_area.y = sheet->column_title_area.height; gdk_drawable_get_size (sheet->sheet_window, &clip_area.width, &clip_area.height); if (!sheet->row_titles_visible) clip_area.x = 0; if (!sheet->column_titles_visible) clip_area.y = 0; if (area.x < 0) { area.width = area.width + area.x; area.x = 0; } if (area.width > clip_area.width) area.width = clip_area.width + 10; if (area.y < 0) { area.height = area.height + area.y; area.y = 0; } if (area.height > clip_area.height) area.height = clip_area.height + 10; clip_area.x--; clip_area.y--; clip_area.width += 3; clip_area.height += 3; gdk_gc_get_values (sheet->xor_gc, &values); gdk_gc_set_clip_rectangle (sheet->xor_gc, &clip_area); gdk_draw_rectangle (sheet->sheet_window, sheet->xor_gc, FALSE, area.x + i, area.y + i, area.width - 2 * i, area.height - 2 * i); gdk_gc_set_clip_rectangle (sheet->xor_gc, NULL); gdk_gc_set_foreground (sheet->xor_gc, &values.foreground); } static void set_column_width (PsppireSheet *sheet, gint column, gint width) { g_return_if_fail (sheet != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (sheet)); if (column < 0 || column >= psppire_axis_unit_count (sheet->haxis)) return; if ( width <= 0) return; psppire_axis_resize (sheet->haxis, column, width - sheet->cell_padding->left - sheet->cell_padding->right); if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) { draw_column_title_buttons (sheet); adjust_scrollbars (sheet); psppire_sheet_size_allocate_entry (sheet); redraw_range (sheet, NULL); } } static void set_row_height (PsppireSheet *sheet, gint row, gint height) { g_return_if_fail (sheet != NULL); g_return_if_fail (PSPPIRE_IS_SHEET (sheet)); if (row < 0 || row >= psppire_axis_unit_count (sheet->vaxis)) return; if (height <= 0) return; psppire_axis_resize (sheet->vaxis, row, height - sheet->cell_padding->top - sheet->cell_padding->bottom); if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) ) { draw_row_title_buttons (sheet); adjust_scrollbars (sheet); psppire_sheet_size_allocate_entry (sheet); redraw_range (sheet, NULL); } } static gboolean psppire_sheet_get_attributes (const PsppireSheet *sheet, gint row, gint col, PsppireSheetCellAttr *attr) { GdkColor *fg, *bg; const GtkJustification *j ; GdkColormap *colormap; g_return_val_if_fail (sheet != NULL, FALSE); g_return_val_if_fail (PSPPIRE_IS_SHEET (sheet), FALSE); if (row < 0 || col < 0) return FALSE; attr->foreground = GTK_WIDGET (sheet)->style->black; attr->background = sheet->color[BG_COLOR]; attr->border.width = 0; attr->border.line_style = GDK_LINE_SOLID; attr->border.cap_style = GDK_CAP_NOT_LAST; attr->border.join_style = GDK_JOIN_MITER; attr->border.mask = 0; attr->border.color = GTK_WIDGET (sheet)->style->black; colormap = gtk_widget_get_colormap (GTK_WIDGET (sheet)); fg = psppire_sheet_model_get_foreground (sheet->model, row, col); if ( fg ) { gdk_colormap_alloc_color (colormap, fg, TRUE, TRUE); attr->foreground = *fg; } bg = psppire_sheet_model_get_background (sheet->model, row, col); if ( bg ) { gdk_colormap_alloc_color (colormap, bg, TRUE, TRUE); attr->background = *bg; } attr->justification = psppire_sheet_model_get_column_justification (sheet->model, col); j = psppire_sheet_model_get_justification (sheet->model, row, col); if (j) attr->justification = *j; return TRUE; } static void psppire_sheet_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data) { PsppireSheet *sheet = PSPPIRE_SHEET (container); g_return_if_fail (callback != NULL); if (sheet->button && sheet->button->parent) (* callback) (sheet->button, callback_data); if (sheet->entry_widget && GTK_IS_CONTAINER (sheet->entry_widget)) (* callback) (sheet->entry_widget, callback_data); } PsppireSheetModel * psppire_sheet_get_model (const PsppireSheet *sheet) { g_return_val_if_fail (PSPPIRE_IS_SHEET (sheet), NULL); return sheet->model; } PsppireSheetButton * psppire_sheet_button_new (void) { PsppireSheetButton *button = g_malloc (sizeof (PsppireSheetButton)); button->state = GTK_STATE_NORMAL; button->label = NULL; button->label_visible = TRUE; button->justification = GTK_JUSTIFY_FILL; button->overstruck = FALSE; return button; } void psppire_sheet_button_free (PsppireSheetButton *button) { if (!button) return ; g_free (button->label); g_free (button); } static void append_cell_text (GString *string, const PsppireSheet *sheet, gint r, gint c) { gchar *celltext = psppire_sheet_cell_get_text (sheet, r, c); if ( NULL == celltext) return; g_string_append (string, celltext); g_free (celltext); } static GString * range_to_text (const PsppireSheet *sheet) { gint r, c; GString *string; if ( !psppire_sheet_range_isvisible (sheet, &sheet->range)) return NULL; string = g_string_sized_new (80); for (r = sheet->range.row0; r <= sheet->range.rowi; ++r) { for (c = sheet->range.col0; c < sheet->range.coli; ++c) { append_cell_text (string, sheet, r, c); g_string_append (string, "\t"); } append_cell_text (string, sheet, r, c); if ( r < sheet->range.rowi) g_string_append (string, "\n"); } return string; } static GString * range_to_html (const PsppireSheet *sheet) { gint r, c; GString *string; if ( !psppire_sheet_range_isvisible (sheet, &sheet->range)) return NULL; string = g_string_sized_new (480); g_string_append (string, "\n"); g_string_append (string, "\n"); g_string_append (string, "\n"); for (r = sheet->range.row0; r <= sheet->range.rowi; ++r) { g_string_append (string, "\n"); for (c = sheet->range.col0; c <= sheet->range.coli; ++c) { g_string_append (string, "\n"); } g_string_append (string, "\n"); } g_string_append (string, "
"); append_cell_text (string, sheet, r, c); g_string_append (string, "
\n"); g_string_append (string, "\n"); g_string_append (string, "\n"); return string; } enum { SELECT_FMT_NULL, SELECT_FMT_TEXT, SELECT_FMT_HTML }; static void primary_get_cb (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data) { PsppireSheet *sheet = PSPPIRE_SHEET (data); GString *string = NULL; switch (info) { case SELECT_FMT_TEXT: string = range_to_text (sheet); break; case SELECT_FMT_HTML: string = range_to_html (sheet); break; default: g_assert_not_reached (); } gtk_selection_data_set (selection_data, selection_data->target, 8, (const guchar *) string->str, string->len); g_string_free (string, TRUE); } static void primary_clear_cb (GtkClipboard *clipboard, gpointer data) { PsppireSheet *sheet = PSPPIRE_SHEET (data); if ( ! GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return; psppire_sheet_unselect_range (sheet); } static void psppire_sheet_update_primary_selection (PsppireSheet *sheet) { static const GtkTargetEntry targets[] = { { "UTF8_STRING", 0, SELECT_FMT_TEXT }, { "STRING", 0, SELECT_FMT_TEXT }, { "TEXT", 0, SELECT_FMT_TEXT }, { "COMPOUND_TEXT", 0, SELECT_FMT_TEXT }, { "text/plain;charset=utf-8", 0, SELECT_FMT_TEXT }, { "text/plain", 0, SELECT_FMT_TEXT }, { "text/html", 0, SELECT_FMT_HTML } }; GtkClipboard *clipboard; if (!GTK_WIDGET_REALIZED (sheet)) return; clipboard = gtk_widget_get_clipboard (GTK_WIDGET (sheet), GDK_SELECTION_PRIMARY); if (psppire_sheet_range_isvisible (sheet, &sheet->range)) { if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets), primary_get_cb, primary_clear_cb, G_OBJECT (sheet))) primary_clear_cb (clipboard, sheet); } else { if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (sheet)) gtk_clipboard_clear (clipboard); } } pspp-master/lib/gtk-contrib/psppire-sheet.h000066400000000000000000000213301177044323000212630ustar00rootroot00000000000000/* Copyright (C) 2006, 2008 Free Software Foundation 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 . This file is derived from the gtksheet.c and extensively modified for the requirements of PSPPIRE. The changes are copyright by the Free Software Foundation. The copyright notice for the original work is below. GtkSheet widget for Gtk+. * Copyright (C) 1999-2001 Adrian E. Feiguin * * Based on GtkClist widget by Jay Painter, but major changes. * Memory allocation routines inspired on SC (Spreadsheet Calculator) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __PSPPIRE_SHEET_H__ #define __PSPPIRE_SHEET_H__ #include #include "gtkextra-sheet.h" #include #include G_BEGIN_DECLS /* sheet->select_status */ enum { PSPPIRE_SHEET_NORMAL, PSPPIRE_SHEET_ROW_SELECTED, PSPPIRE_SHEET_COLUMN_SELECTED, PSPPIRE_SHEET_RANGE_SELECTED }; #define PSPPIRE_TYPE_SHEET_RANGE (psppire_sheet_range_get_type ()) #define PSPPIRE_TYPE_SHEET_CELL (psppire_sheet_cell_get_type ()) #define PSPPIRE_TYPE_SHEET (psppire_sheet_get_type ()) #define PSPPIRE_SHEET(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPPIRE_TYPE_SHEET, PsppireSheet) #define PSPPIRE_SHEET_CLASS(klass) G_TYPE_CHECK_CLASS_CAST ((klass), PSPPIRE_TYPE_SHEET, PsppireSheetClass) #define PSPPIRE_IS_SHEET(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_SHEET) typedef struct _PsppireSheetClass PsppireSheetClass; typedef struct _PsppireSheetCellAttr PsppireSheetCellAttr; typedef struct _PsppireSheetHoverTitle PsppireSheetHoverTitle; struct _PsppireSheetCellAttr { GtkJustification justification; GdkColor foreground; GdkColor background; PsppireSheetCellBorder border; }; struct _PsppireSheetHoverTitle { GtkWidget *window; GtkWidget *label; gint row, column; }; enum { BG_COLOR, GRID_COLOR, n_COLORS }; struct _PsppireSheet { GtkBin parent; gboolean dispose_has_run; PsppireAxis *haxis; PsppireAxis *vaxis; guint16 flags; PsppireSheetModel *model; /* Component colors */ GdkColor color[n_COLORS]; gboolean show_grid; /* active cell */ PsppireSheetCell active_cell; /* The GtkEntry used for editing the cells */ GtkWidget *entry_widget; /* The type of entry_widget */ GType entry_type; /* global selection button */ GtkWidget *button; /* sheet state */ gint select_status; /* selected range */ PsppireSheetRange range; /* The space between a cell's contents and its border */ GtkBorder *cell_padding; /* the scrolling window and its height and width to * make things a little speedier */ GdkWindow *sheet_window; /* border shadow style */ GtkShadowType shadow_type; /* Column Titles */ GdkRectangle column_title_area; GdkWindow *column_title_window; gboolean column_titles_visible; /* TRUE if the cursor is over the column title window */ gboolean column_title_under; /* Row Titles */ GdkRectangle row_title_area; GdkWindow *row_title_window; gboolean row_titles_visible; /* TRUE if the cursor is over the row title window */ gboolean row_title_under; /*scrollbars*/ GtkAdjustment *hadjustment; GtkAdjustment *vadjustment; /* xor GC for the verticle drag line */ GdkGC *xor_gc; /* gc for drawing unselected cells */ GdkGC *fg_gc; GdkGC *bg_gc; /* cursor used to indicate dragging */ GdkCursor *cursor_drag; /* the current x-pixel location of the xor-drag vline */ gint x_drag; /* the current y-pixel location of the xor-drag hline */ gint y_drag; /* current cell being dragged */ PsppireSheetCell drag_cell; /* current range being dragged */ PsppireSheetRange drag_range; /* Used for the subtitle (popups) */ gint motion_timer; PsppireSheetHoverTitle *hover_window; gulong update_handler_id; }; struct _PsppireSheetClass { GtkBinClass parent_class; gboolean (*set_scroll_adjustments) (PsppireSheet *sheet, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment); void (*select_row) (PsppireSheet *sheet, gint row); void (*select_column) (PsppireSheet *sheet, gint column); void (*select_range) (PsppireSheet *sheet, PsppireSheetRange *range); void (*resize_range) (PsppireSheet *sheet, PsppireSheetRange *old_range, PsppireSheetRange *new_range); void (*move_range) (PsppireSheet *sheet, PsppireSheetRange *old_range, PsppireSheetRange *new_range); gboolean (*traverse) (PsppireSheet *sheet, gint row, gint column, gint *new_row, gint *new_column); gboolean (*activate) (PsppireSheet *sheet, gint row, gint column); void (*changed) (PsppireSheet *sheet, gint row, gint column); }; GType psppire_sheet_get_type (void); GType psppire_sheet_range_get_type (void); /* create a new sheet */ GtkWidget * psppire_sheet_new (PsppireSheetModel *model); /* create a new sheet with custom entry */ GtkWidget * psppire_sheet_new_with_custom_entry (GType entry_type); /* Change entry */ void psppire_sheet_change_entry (PsppireSheet *sheet, GType entry_type); GtkEntry *psppire_sheet_get_entry (PsppireSheet *sheet); void psppire_sheet_get_selected_range (PsppireSheet *sheet, PsppireSheetRange *range); void psppire_sheet_show_grid (PsppireSheet *sheet, gboolean show); gboolean psppire_sheet_grid_visible (PsppireSheet *sheet); /* scroll the viewing area of the sheet to the given column * and row; row_align and col_align are between 0-1 representing the * location the row should appear on the screen, 0.0 being top or left, * 1.0 being bottom or right; if row or column is negative then there * is no change */ void psppire_sheet_moveto (PsppireSheet *sheet, gint row, gint column, gfloat row_align, gfloat col_align); void psppire_sheet_show_row_titles (PsppireSheet *sheet); void psppire_sheet_hide_row_titles (PsppireSheet *sheet); void psppire_sheet_show_column_titles (PsppireSheet *sheet); void psppire_sheet_hide_column_titles (PsppireSheet *sheet); /* select the row. The range is then highlighted, and the bounds are stored * in sheet->range */ void psppire_sheet_select_row (PsppireSheet * sheet, gint row); /* select the column. The range is then highlighted, and the bounds are stored * in sheet->range */ void psppire_sheet_select_column (PsppireSheet * sheet, gint column); /* highlight the selected range and store bounds in sheet->range */ void psppire_sheet_select_range (PsppireSheet *sheet, const PsppireSheetRange *range); void psppire_sheet_get_visible_range (PsppireSheet *sheet, PsppireSheetRange *range); /* obvious */ void psppire_sheet_unselect_range (PsppireSheet *sheet); /* set active cell where the entry will be displayed */ void psppire_sheet_set_active_cell (PsppireSheet *sheet, gint row, gint column); /* Sets *ROW and *COLUMN to be the coordinates of the active cell. ROW and/or COLUMN may be null if the caller is not interested in their values */ void psppire_sheet_get_active_cell (PsppireSheet *sheet, gint *row, gint *column); /* get cell contents */ gchar *psppire_sheet_cell_get_text (const PsppireSheet *sheet, gint row, gint col); void psppire_sheet_set_model (PsppireSheet *sheet, PsppireSheetModel *model); PsppireSheetModel * psppire_sheet_get_model (const PsppireSheet *sheet); G_END_DECLS #endif /* __PSPPIRE_SHEET_H__ */ pspp-master/lib/linreg/000077500000000000000000000000001177044323000153605ustar00rootroot00000000000000pspp-master/lib/linreg/.gitignore000066400000000000000000000000251177044323000173450ustar00rootroot00000000000000Makefile Makefile.in pspp-master/lib/linreg/OChangeLog000066400000000000000000000011561177044323000172540ustar00rootroot00000000000000Sun Jan 9 00:57 2006 Jason Stover * pspp_linreg.h: Altered the coefficient structure to include variable/value pairs. * coefficient.c: Added functions to handle the matching between model coefficients and their corresponding variables and values. * linreg.c: (pspp_linreg_cache_free) Added pspp_linreg_coeff_free () to free coefficient structures. Sun Oct 23 13:46:56 2005 Ben Pfaff * linreg.c: (pspp_linreg) Removed unused variable `mse'. ---------------------------------------------------------------------- Local Variables: mode: change-log version-control: never End: pspp-master/lib/linreg/automake.mk000066400000000000000000000003561177044323000175230ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in -*- makefile -*- noinst_LTLIBRARIES += lib/linreg/liblinreg.la lib_linreg_liblinreg_la_SOURCES = \ lib/linreg/sweep.c lib/linreg/sweep.h EXTRA_DIST += lib/linreg/OChangeLog pspp-master/lib/linreg/sweep.c000066400000000000000000000077231177044323000166600ustar00rootroot00000000000000/* PSPP - a program for statistical analysis. Copyright (C) 2005, 2009, 2011 Free Software Foundation, Inc. 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 . */ /* Find the least-squares estimate of b for the linear model: Y = Xb + Z where Y is an n-by-1 column vector, X is an n-by-p matrix of independent variables, b is a p-by-1 vector of regression coefficients, and Z is an n-by-1 normally-distributed random vector with independent identically distributed components with mean 0. This estimate is found via the sweep operator, which is a modification of Gauss-Jordan pivoting. References: Matrix Computations, third edition. GH Golub and CF Van Loan. The Johns Hopkins University Press. 1996. ISBN 0-8018-5414-8. Numerical Analysis for Statisticians. K Lange. Springer. 1999. ISBN 0-387-94979-8. Numerical Linear Algebra for Applications in Statistics. JE Gentle. Springer. 1998. ISBN 0-387-98542-5. */ #include #include "sweep.h" #include /* The matrix A will be overwritten. In ordinary uses of the sweep operator, A will be the matrix __ __ |X'X X'Y| | | |Y'X Y'Y| -- -- X refers to the design matrix and Y to the vector of dependent observations. reg_sweep sweeps on the diagonal elements of X'X. The matrix A is assumed to be symmetric, so the sweep operation is performed only for the upper triangle of A. LAST_COL is considered to be the final column in the augmented matrix, that is, the column to the right of the '=' sign of the system. */ int reg_sweep (gsl_matrix * A, int last_col) { int i; int j; int k; gsl_matrix *B; if (A == NULL) return GSL_EFAULT; if (A->size1 != A->size2) return GSL_ENOTSQR; assert (last_col < A->size1); gsl_matrix_swap_rows (A, A->size1 - 1, last_col); gsl_matrix_swap_columns (A, A->size1 - 1 , last_col); B = gsl_matrix_alloc (A->size1, A->size2); for (k = 0; k < (A->size1 - 1); k++) { const double sweep_element = gsl_matrix_get (A, k, k); if (fabs (sweep_element) > GSL_DBL_MIN) { gsl_matrix_set (B, k, k, -1.0 / sweep_element); /* Rows before current row k. */ for (i = 0; i < k; i++) { for (j = i; j < A->size2; j++) { /* Use only the upper triangle of A. */ double tmp; if (j < k) { tmp = gsl_matrix_get (A, i, j) - gsl_matrix_get (A, i, k) * gsl_matrix_get (A, j, k) / sweep_element; } else if (j > k) { tmp = gsl_matrix_get (A, i, j) - gsl_matrix_get (A, i, k) * gsl_matrix_get (A, k, j) / sweep_element; } else { tmp = gsl_matrix_get (A, i, k) / sweep_element; } gsl_matrix_set (B, i, j, tmp); } } /* Current row k. */ for (j = k + 1; j < A->size1; j++) { double tmp = gsl_matrix_get (A, k, j) / sweep_element; gsl_matrix_set (B, k, j, tmp); } /* Rows after the current row k. */ for (i = k + 1; i < A->size1; i++) { for (j = i; j < A->size2; j++) { double tmp = gsl_matrix_get (A, i, j) - gsl_matrix_get (A, k, i) * gsl_matrix_get (A, k, j) / sweep_element; gsl_matrix_set (B, i, j, tmp); } } } gsl_matrix_memcpy (A, B); } gsl_matrix_free (B); gsl_matrix_swap_columns (A, A->size1 - 1 , last_col); gsl_matrix_swap_rows (A, A->size1 - 1, last_col); return GSL_SUCCESS; } pspp-master/lib/linreg/sweep.h000066400000000000000000000040711177044323000166560ustar00rootroot00000000000000/* PSPP - a program for statistical analysis. Copyright (C) 2005 Free Software Foundation, Inc. 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 . */ #ifndef SWEEP_H #define SWEEP_H /* Find the least-squares estimate of b for the linear model: Y = Xb + Z where Y is an n-by-1 column vector, X is an n-by-p matrix of independent variables, b is a p-by-1 vector of regression coefficients, and Z is an n-by-1 normally-distributed random vector with independent identically distributed components with mean 0. This estimate is found via the sweep operator, which is a modification of Gauss-Jordan pivoting. References: Matrix Computations, third edition. GH Golub and CF Van Loan. The Johns Hopkins University Press. 1996. ISBN 0-8018-5414-8. Numerical Analysis for Statisticians. K Lange. Springer. 1999. ISBN 0-387-94979-8. Numerical Linear Algebra for Applications in Statistics. JE Gentle. Springer. 1998. ISBN 0-387-98542-5. */ /* The matrix A will be overwritten. In ordinary uses of the sweep operator, A will be the matrix __ __ |X'X X'Y| | | |Y'X Y'Y| -- -- X refers to the design matrix and Y to the vector of dependent observations. reg_sweep sweeps on the diagonal elements of X'X. The matrix A is assumed to be symmetric, so the sweep operation is performed only for the upper triangle of A. */ #include #include int reg_sweep (gsl_matrix *, int); #endif pspp-master/lib/tukey/000077500000000000000000000000001177044323000152415ustar00rootroot00000000000000pspp-master/lib/tukey/README000066400000000000000000000001051177044323000161150ustar00rootroot00000000000000This is not part of the GNU PSPP program, but is used with GNU PSPP. pspp-master/lib/tukey/automake.mk000066400000000000000000000003751177044323000174050ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in -*- makefile -*- noinst_LTLIBRARIES += lib/tukey/libtukey.la lib_tukey_libtukey_la_SOURCES = \ lib/tukey/ptukey.c \ lib/tukey/qtukey.c \ lib/tukey/tukey.h EXTRA_DIST += lib/tukey/README pspp-master/lib/tukey/ptukey.c000066400000000000000000000315621177044323000167350ustar00rootroot00000000000000/* PSPP - a program for statistical analysis. Copyright (C) 2011 Free Software Foundation, Inc. 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 . */ /* This file is taken from the R project source code, and modified. The original copyright notice is reproduced below: */ /* * Mathlib : A C Library of Special Functions * Copyright (C) 1998 Ross Ihaka * Copyright (C) 2000--2007 The R Development Core Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, a copy is available at * http://www.r-project.org/Licenses/ * * SYNOPSIS * * #include * double ptukey(q, rr, cc, df, lower_tail, log_p); * * DESCRIPTION * * Computes the probability that the maximum of rr studentized * ranges, each based on cc means and with df degrees of freedom * for the standard error, is less than q. * * The algorithm is based on that of the reference. * * REFERENCE * * Copenhaver, Margaret Diponzio & Holland, Burt S. * Multiple comparisons of simple effects in * the two-way analysis of variance with fixed effects. * Journal of Statistical Computation and Simulation, * Vol.30, pp.1-15, 1988. */ #include #include "libpspp/compiler.h" #include "tukey.h" #include #include #include #include #define R_D__0 (log_p ? ML_NEGINF : 0.) /* 0 */ #define R_D__1 (log_p ? 0. : 1.) /* 1 */ #define R_DT_0 (lower_tail ? R_D__0 : R_D__1) /* 0 */ #define R_DT_1 (lower_tail ? R_D__1 : R_D__0) /* 1 */ #define R_D_val(x) (log_p ? log(x) : (x)) /* x in pF(x,..) */ #define R_D_Clog(p) (log_p ? log1p(-(p)) : (0.5 - (p) + 0.5)) /* [log](1-p) */ #define R_DT_val(x) (lower_tail ? R_D_val(x) : R_D_Clog(x)) #define ME_PRECISION 8 static inline double pnorm(double x, double mu, double sigma, int lower_tail, int log_p) { assert (lower_tail == 1); assert (log_p == 0); assert (sigma == 1.0); return gsl_cdf_gaussian_P (x - mu, sigma); } static double wprob (double w, double rr, double cc) { const double M_1_SQRT_2PI = 1 / sqrt (2 * M_PI); /* wprob() : This function calculates probability integral of Hartley's form of the range. w = value of range rr = no. of rows or groups cc = no. of columns or treatments ir = error flag = 1 if pr_w probability > 1 pr_w = returned probability integral from (0, w) program will not terminate if ir is raised. bb = upper limit of legendre integration iMax = maximum acceptable value of integral nleg = order of legendre quadrature ihalf = int ((nleg + 1) / 2) wlar = value of range above which wincr1 intervals are used to calculate second part of integral, else wincr2 intervals are used. C1, C2, C3 = values which are used as cutoffs for terminating or modifying a calculation. M_1_SQRT_2PI = 1 / sqrt(2 * pi); from abramowitz & stegun, p. 3. M_SQRT2 = sqrt(2) xleg = legendre 12-point nodes aleg = legendre 12-point coefficients */ #define nleg 12 #define ihalf 6 /* looks like this is suboptimal for double precision. (see how C1-C3 are used) */ /* const double iMax = 1.; not used if = 1 */ static const double C1 = -30.; static const double C2 = -50.; static const double C3 = 60.; static const double bb = 8.; static const double wlar = 3.; static const double wincr1 = 2.; static const double wincr2 = 3.; static const double xleg[ihalf] = { 0.981560634246719250690549090149, 0.904117256370474856678465866119, 0.769902674194304687036893833213, 0.587317954286617447296702418941, 0.367831498998180193752691536644, 0.125233408511468915472441369464 }; static const double aleg[ihalf] = { 0.047175336386511827194615961485, 0.106939325995318430960254718194, 0.160078328543346226334652529543, 0.203167426723065921749064455810, 0.233492536538354808760849898925, 0.249147045813402785000562436043 }; double a, ac, pr_w, b, binc, blb, c, cc1, pminus, pplus, qexpo, qsqz, rinsum, wi, wincr, xx; long double bub, einsum, elsum; int j, jj; qsqz = w * 0.5; /* if w >= 16 then the integral lower bound (occurs for c=20) */ /* is 0.99999999999995 so return a value of 1. */ if (qsqz >= bb) return 1.0; /* find (f(w/2) - 1) ^ cc */ /* (first term in integral of hartley's form). */ pr_w = 2 * pnorm (qsqz, 0., 1., 1, 0) - 1.; /* erf(qsqz / M_SQRT2) */ /* if pr_w ^ cc < 2e-22 then set pr_w = 0 */ if (pr_w >= exp (C2 / cc)) pr_w = pow (pr_w, cc); else pr_w = 0.0; /* if w is large then the second component of the */ /* integral is small, so fewer intervals are needed. */ if (w > wlar) wincr = wincr1; else wincr = wincr2; /* find the integral of second term of hartley's form */ /* for the integral of the range for equal-length */ /* intervals using legendre quadrature. limits of */ /* integration are from (w/2, 8). two or three */ /* equal-length intervals are used. */ /* blb and bub are lower and upper limits of integration. */ blb = qsqz; binc = (bb - qsqz) / wincr; bub = blb + binc; einsum = 0.0; /* integrate over each interval */ cc1 = cc - 1.0; for (wi = 1; wi <= wincr; wi++) { elsum = 0.0; a = 0.5 * (bub + blb); /* legendre quadrature with order = nleg */ b = 0.5 * (bub - blb); for (jj = 1; jj <= nleg; jj++) { if (ihalf < jj) { j = (nleg - jj) + 1; xx = xleg[j - 1]; } else { j = jj; xx = -xleg[j - 1]; } c = b * xx; ac = a + c; /* if exp(-qexpo/2) < 9e-14, */ /* then doesn't contribute to integral */ qexpo = ac * ac; if (qexpo > C3) break; pplus = 2 * pnorm (ac, 0., 1., 1, 0); pminus = 2 * pnorm (ac, w, 1., 1, 0); /* if rinsum ^ (cc-1) < 9e-14, */ /* then doesn't contribute to integral */ rinsum = (pplus * 0.5) - (pminus * 0.5); if (rinsum >= exp (C1 / cc1)) { rinsum = (aleg[j - 1] * exp (-(0.5 * qexpo))) * pow (rinsum, cc1); elsum += rinsum; } } elsum *= (((2.0 * b) * cc) * M_1_SQRT_2PI); einsum += elsum; blb = bub; bub += binc; } /* if pr_w ^ rr < 9e-14, then return 0 */ pr_w = einsum + pr_w; if (pr_w <= exp (C1 / rr)) return 0.; pr_w = pow (pr_w, rr); if (pr_w >= 1.) /* 1 was iMax was eps */ return 1.; return pr_w; } /* wprob() */ double ptukey (double q, double rr, double cc, double df, int lower_tail, int log_p) { const double ML_NEGINF = -1.0 / 0.0; /* function ptukey() [was qprob() ]: q = value of studentized range rr = no. of rows or groups cc = no. of columns or treatments df = degrees of freedom of error term ir[0] = error flag = 1 if wprob probability > 1 ir[1] = error flag = 1 if qprob probability > 1 qprob = returned probability integral over [0, q] The program will not terminate if ir[0] or ir[1] are raised. All references in wprob to Abramowitz and Stegun are from the following reference: Abramowitz, Milton and Stegun, Irene A. Handbook of Mathematical Functions. New York: Dover publications, Inc. (1970). All constants taken from this text are given to 25 significant digits. nlegq = order of legendre quadrature ihalfq = int ((nlegq + 1) / 2) eps = max. allowable value of integral eps1 & eps2 = values below which there is no contribution to integral. d.f. <= dhaf: integral is divided into ulen1 length intervals. else d.f. <= dquar: integral is divided into ulen2 length intervals. else d.f. <= deigh: integral is divided into ulen3 length intervals. else d.f. <= dlarg: integral is divided into ulen4 length intervals. d.f. > dlarg: the range is used to calculate integral. M_LN2 = log(2) xlegq = legendre 16-point nodes alegq = legendre 16-point coefficients The coefficients and nodes for the legendre quadrature used in qprob and wprob were calculated using the algorithms found in: Stroud, A. H. and Secrest, D. Gaussian Quadrature Formulas. Englewood Cliffs, New Jersey: Prentice-Hall, Inc, 1966. All values matched the tables (provided in same reference) to 30 significant digits. f(x) = .5 + erf(x / sqrt(2)) / 2 for x > 0 f(x) = erfc( -x / sqrt(2)) / 2 for x < 0 where f(x) is standard normal c. d. f. if degrees of freedom large, approximate integral with range distribution. */ #define nlegq 16 #define ihalfq 8 /* const double eps = 1.0; not used if = 1 */ static const double eps1 = -30.0; static const double eps2 = 1.0e-14; static const double dhaf = 100.0; static const double dquar = 800.0; static const double deigh = 5000.0; static const double dlarg = 25000.0; static const double ulen1 = 1.0; static const double ulen2 = 0.5; static const double ulen3 = 0.25; static const double ulen4 = 0.125; static const double xlegq[ihalfq] = { 0.989400934991649932596154173450, 0.944575023073232576077988415535, 0.865631202387831743880467897712, 0.755404408355003033895101194847, 0.617876244402643748446671764049, 0.458016777657227386342419442984, 0.281603550779258913230460501460, 0.950125098376374401853193354250e-1 }; static const double alegq[ihalfq] = { 0.271524594117540948517805724560e-1, 0.622535239386478928628438369944e-1, 0.951585116824927848099251076022e-1, 0.124628971255533872052476282192, 0.149595988816576732081501730547, 0.169156519395002538189312079030, 0.182603415044923588866763667969, 0.189450610455068496285396723208 }; double ans, f2, f21, f2lf, ff4, otsum, qsqz, rotsum, t1, twa1, ulen, wprb; int i, j, jj; assert (! (isnan (q) || isnan (rr) || isnan (cc) || isnan (df))); if (q <= 0) return R_DT_0; /* df must be > 1 */ /* there must be at least two values */ assert (! (df < 2 || rr < 1 || cc < 2)); if (!isfinite (q)) return R_DT_1; if (df > dlarg) return R_DT_val (wprob (q, rr, cc)); /* calculate leading constant */ f2 = df * 0.5; /* lgammafn(u) = log(gamma(u)) */ f2lf = ((f2 * log (df)) - (df * M_LN2)) - gsl_sf_lngamma (f2); f21 = f2 - 1.0; /* integral is divided into unit, half-unit, quarter-unit, or */ /* eighth-unit length intervals depending on the value of the */ /* degrees of freedom. */ ff4 = df * 0.25; if (df <= dhaf) ulen = ulen1; else if (df <= dquar) ulen = ulen2; else if (df <= deigh) ulen = ulen3; else ulen = ulen4; f2lf += log (ulen); /* integrate over each subinterval */ ans = 0.0; for (i = 1; i <= 50; i++) { otsum = 0.0; /* legendre quadrature with order = nlegq */ /* nodes (stored in xlegq) are symmetric around zero. */ twa1 = (2 * i - 1) * ulen; for (jj = 1; jj <= nlegq; jj++) { if (ihalfq < jj) { j = jj - ihalfq - 1; t1 = (f2lf + (f21 * log (twa1 + (xlegq[j] * ulen)))) - (((xlegq[j] * ulen) + twa1) * ff4); } else { j = jj - 1; t1 = (f2lf + (f21 * log (twa1 - (xlegq[j] * ulen)))) + (((xlegq[j] * ulen) - twa1) * ff4); } /* if exp(t1) < 9e-14, then doesn't contribute to integral */ if (t1 >= eps1) { if (ihalfq < jj) { qsqz = q * sqrt (((xlegq[j] * ulen) + twa1) * 0.5); } else { qsqz = q * sqrt (((-(xlegq[j] * ulen)) + twa1) * 0.5); } /* call wprob to find integral of range portion */ wprb = wprob (qsqz, rr, cc); rotsum = (wprb * alegq[j]) * exp (t1); otsum += rotsum; } /* end legendre integral for interval i */ /* L200: */ } /* if integral for interval i < 1e-14, then stop. * However, in order to avoid small area under left tail, * at least 1 / ulen intervals are calculated. */ if (i * ulen >= 1.0 && otsum <= eps2) break; /* end of interval i */ /* L330: */ ans += otsum; } assert (otsum <= eps2); /* not converged */ if (ans > 1.) ans = 1.; return R_DT_val (ans); } pspp-master/lib/tukey/qtukey.c000066400000000000000000000165071177044323000167400ustar00rootroot00000000000000/* PSPP - a program for statistical analysis. Copyright (C) 2011 Free Software Foundation, Inc. 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 . */ /* This file is taken from the R project source code, and modified. The original copyright notice is reproduced below: */ /* * Mathlib : A C Library of Special Functions * Copyright (C) 1998 Ross Ihaka * Copyright (C) 2000--2005 The R Development Core Team * based in part on AS70 (C) 1974 Royal Statistical Society * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, a copy is available at * http://www.r-project.org/Licenses/ * * SYNOPSIS * * #include * double qtukey(p, rr, cc, df, lower_tail, log_p); * * DESCRIPTION * * Computes the quantiles of the maximum of rr studentized * ranges, each based on cc means and with df degrees of freedom * for the standard error, is less than q. * * The algorithm is based on that of the reference. * * REFERENCE * * Copenhaver, Margaret Diponzio & Holland, Burt S. * Multiple comparisons of simple effects in * the two-way analysis of variance with fixed effects. * Journal of Statistical Computation and Simulation, * Vol.30, pp.1-15, 1988. */ #include #include "tukey.h" #include #include #define TRUE (1) #define FALSE (0) #define ML_POSINF (1.0 / 0.0) #define ML_NEGINF (-1.0 / 0.0) #define R_D_Lval(p) (lower_tail ? (p) : (0.5 - (p) + 0.5)) /* p */ #define R_DT_qIv(p) (log_p ? (lower_tail ? exp(p) : - expm1(p)) \ : R_D_Lval(p)) static double fmax2(double x, double y) { if (isnan(x) || isnan(y)) return x + y; return (x < y) ? y : x; } #define R_Q_P01_boundaries(p, _LEFT_, _RIGHT_) \ if (log_p) { \ assert (p <= 0); \ if(p == 0) /* upper bound*/ \ return lower_tail ? _RIGHT_ : _LEFT_; \ if(p == ML_NEGINF) \ return lower_tail ? _LEFT_ : _RIGHT_; \ } \ else { /* !log_p */ \ assert (p >= 0 && p <= 1); \ if(p == 0) \ return lower_tail ? _LEFT_ : _RIGHT_; \ if(p == 1) \ return lower_tail ? _RIGHT_ : _LEFT_; \ } /* qinv() : * this function finds percentage point of the studentized range * which is used as initial estimate for the secant method. * function is adapted from portion of algorithm as 70 * from applied statistics (1974) ,vol. 23, no. 1 * by odeh, r. e. and evans, j. o. * * p = percentage point * c = no. of columns or treatments * v = degrees of freedom * qinv = returned initial estimate * * vmax is cutoff above which degrees of freedom * is treated as infinity. */ static double qinv(double p, double c, double v) { static const double p0 = 0.322232421088; static const double q0 = 0.993484626060e-01; static const double p1 = -1.0; static const double q1 = 0.588581570495; static const double p2 = -0.342242088547; static const double q2 = 0.531103462366; static const double p3 = -0.204231210125; static const double q3 = 0.103537752850; static const double p4 = -0.453642210148e-04; static const double q4 = 0.38560700634e-02; static const double c1 = 0.8832; static const double c2 = 0.2368; static const double c3 = 1.214; static const double c4 = 1.208; static const double c5 = 1.4142; static const double vmax = 120.0; double ps, q, t, yi; ps = 0.5 - 0.5 * p; yi = sqrt (log (1.0 / (ps * ps))); t = yi + (((( yi * p4 + p3) * yi + p2) * yi + p1) * yi + p0) / (((( yi * q4 + q3) * yi + q2) * yi + q1) * yi + q0); if (v < vmax) t += (t * t * t + t) / v / 4.0; q = c1 - c2 * t; if (v < vmax) q += -c3 / v + c4 * t / v; return t * (q * log (c - 1.0) + c5); } /* * Copenhaver, Margaret Diponzio & Holland, Burt S. * Multiple comparisons of simple effects in * the two-way analysis of variance with fixed effects. * Journal of Statistical Computation and Simulation, * Vol.30, pp.1-15, 1988. * * Uses the secant method to find critical values. * * p = confidence level (1 - alpha) * rr = no. of rows or groups * cc = no. of columns or treatments * df = degrees of freedom of error term * * ir(1) = error flag = 1 if wprob probability > 1 * ir(2) = error flag = 1 if ptukey probability > 1 * ir(3) = error flag = 1 if convergence not reached in 50 iterations * = 2 if df < 2 * * qtukey = returned critical value * * If the difference between successive iterates is less than eps, * the search is terminated */ double qtukey(double p, double rr, double cc, double df, int lower_tail, int log_p) { static const double eps = 0.0001; const int maxiter = 50; double ans = 0.0, valx0, valx1, x0, x1, xabs; int iter; if (isnan(p) || isnan(rr) || isnan(cc) || isnan(df)) { /* ML_ERROR(ME_DOMAIN, "qtukey"); */ return p + rr + cc + df; } /* df must be > 1 ; there must be at least two values */ /* ^^ JMD: The comment says 1 but the code says 2. Which is correct? */ assert (df >= 2); assert (rr >= 1); assert (cc >= 2); R_Q_P01_boundaries (p, 0, ML_POSINF); p = R_DT_qIv(p); /* lower_tail,non-log "p" */ /* Initial value */ x0 = qinv(p, cc, df); /* Find prob(value < x0) */ valx0 = ptukey(x0, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p; /* Find the second iterate and prob(value < x1). */ /* If the first iterate has probability value */ /* exceeding p then second iterate is 1 less than */ /* first iterate; otherwise it is 1 greater. */ if (valx0 > 0.0) x1 = fmax2(0.0, x0 - 1.0); else x1 = x0 + 1.0; valx1 = ptukey(x1, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p; /* Find new iterate */ for(iter=1 ; iter < maxiter ; iter++) { ans = x1 - ((valx1 * (x1 - x0)) / (valx1 - valx0)); valx0 = valx1; /* New iterate must be >= 0 */ x0 = x1; if (ans < 0.0) { ans = 0.0; valx1 = -p; } /* Find prob(value < new iterate) */ valx1 = ptukey(ans, rr, cc, df, /*LOWER*/TRUE, /*LOG_P*/FALSE) - p; x1 = ans; /* If the difference between two successive */ /* iterates is less than eps, stop */ xabs = fabs(x1 - x0); if (xabs < eps) return ans; } /* The process did not converge in 'maxiter' iterations */ assert (0); return ans; } pspp-master/lib/tukey/tukey.h000066400000000000000000000017021177044323000165530ustar00rootroot00000000000000/* PSPP - a program for statistical analysis. Copyright (C) 2011 Free Software Foundation, Inc. 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 . */ #ifndef TUKEY_H #define TUKEY_H 1 double qtukey(double p, double rr, double cc, double df, int lower_tail, int log_p); double ptukey (double q, double rr, double cc, double df, int lower_tail, int log_p); #endif pspp-master/perl-module/000077500000000000000000000000001177044323000155575ustar00rootroot00000000000000pspp-master/perl-module/COPYING000066400000000000000000001043741177044323000166230ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. 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. Copyright (C) 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 . 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: Copyright (C) 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 . 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 . pspp-master/perl-module/Changes000066400000000000000000000005651177044323000170600ustar00rootroot00000000000000Revision history for Perl extension Pspp. 0.7.0 Sun Jan 11 10:35:56 2009 Integrated the module into Pspp's build environment. Added support for reading from an existing system file. 0.4.3 Sat May 19 14:24:05 2007 - first release 0.01 Fri Apr 6 14:13:45 2007 - original version; created by h2xs 1.23 with options -A -n Pspp pspp/src/libpspp/version.h pspp-master/perl-module/Examples.pod000066400000000000000000000067111177044323000200460ustar00rootroot00000000000000=pod =head1 PSPP::Examples This page shows some simple examples of using the PSPP module. See L for details on each of the subroutines. =head2 A Simple example This example creates a system file called F, containing one variable called "id". It contains no data. use PSPP; my $dict = PSPP::Dict->new (); my $var = PSPP::Var->new ($dict, "id"); my $sysfile = PSPP::Sysfile->new ("foo.sav", $dict); $sysfile->close(); =head2 A slightly more complex example In this example there are three variables, called "id", "name" and "dob". Their formats are F2.0, A80 and DATETIME17 respectively. use PSPP; my $dict = PSPP::Dict->new (); PSPP::Var->new ($dict, "id", (fmt=>PSPP::Fmt::F, width=>2, decimals=>0) ); PSPP::Var->new ($dict, "name", (fmt=>PSPP::Fmt::A, width=>80) ); PSPP::Var->new ($dict, "dob", (fmt=>PSPP::Fmt::DATETIME) ); my $sysfile = PSPP::Sysfile->new ("foo.sav", $dict); $sysfile->close(); =head2 Changing the properties of variables After a variable has been created, parameters may be set for it. use PSPP; my $dict = PSPP::Dict->new (); my $var1 = PSPP::Var->new ($dict, "id"); $var1->set_label ("A unique identifier"); $var1->add_value_label (0, "Zero"); $var1->add_value_label (1, "One"); =head2 Appending data to the file When a file is created, it contains no data. Data is added by appending cases to the file. This example creates a file with 3 cases. use PSPP; my $dict = PSPP::Dict->new (); PSPP::Var->new ($dict, "id", (fmt=>PSPP::Fmt::F, width=>2, decimals=>0) ); PSPP::Var->new ($dict, "name", (fmt=>PSPP::Fmt::A, width=>8) ); my $sysfile = PSPP::Sysfile->new ("foo.sav", $dict); $sysfile->append_case ( [1, "Alf"] ); $sysfile->append_case ( [2, "Bert"] ); $sysfile->append_case ( [3, "Charlie"] ); $sysfile->close(); =head2 Variables with differing input and output formats By default, a variable's output format corresponds to the input format. However, the output format may be changed after the variable has been created. This example shows how to create a DATETIME variable using the current time as its value. Since pspp uses a different epoch to perl, the constant PSPP::PERL_EPOCH needs to be added to the value returned from time(), in order that it be correctly represented by pspp. use PSPP; my $dict = PSPP::Dict->new (); my $var1 = PSPP::Var->new ($dict, "entrytime", (fmt=>PSPP::Fmt::F) ); $var1->set_output_format ( (fmt=>PSPP::Fmt::DATETIME, width=>20) ); my $sysfile = PSPP::Sysfile->new ("foo.sav", $dict); my $now = time (); $sysfile->append_case ( [ $now + PSPP::PERL_EPOCH] ) || die "Cant write case"; $sysfile->close(); =head2 Reading data Data can be read from a system file or other source: use PSPP; my $sf = PSPP::Reader->open ("foo.sav"); my $dict = $sf->get_dict (); Once opened, the dictionary can be used like any other. for ($v = 0 ; $v < $dict->get_var_cnt() ; $v++) { my $var = $dict->get_var ($v); # Print the variables my $name = $var->get_name (); my $label = $var->get_label (); print "Var: $name, Label: $label\n"; # Retrieve and print the value labels my $vl = $var->get_value_labels (); print "$_: $vl->{$_}\n" for keys %$vl; } Reading of data must be done sequentially using the C method. while (my $c = $sf->get_next_case () ) { my $v; for ($v = 0; $v < $dict->get_var_cnt(); $v++) { print "val$v: @$c[$v] "; } print "\n"; } =cutpspp-master/perl-module/MANIFEST000066400000000000000000000002001177044323000167000ustar00rootroot00000000000000Changes const-c.inc const-xs.inc COPYING Examples.pod lib/PSPP.pm Makefile.PL MANIFEST ppport.h PSPP.xs README t/Pspp.t typemap pspp-master/perl-module/Makefile.PL000066400000000000000000000042741177044323000175400ustar00rootroot00000000000000use 5.008008; use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. do 'pspp-module-config' || do { my $build = prompt ("Enter the location of the build directory of the configured pspp source:", "" ); my $src = $top_srcdir; %Locations = (SourceDir => "$src", BuildDir => "$build"); }; WriteMakefile( FULLPERL => "PSPP_TEST_CMD=\"$Locations{BuildDir}/src/ui/terminal/pspp\" \$(PERL)", NAME => 'PSPP', DISTNAME => 'PSPP-Perl', VERSION_FROM => "$Locations{BuildDir}/src/libpspp/version.c", PREREQ_PM => {POSIX=>0}, PM => {"lib/PSPP.pm", "\$(INST_LIBDIR)/PSPP.pm"}, ($] >= 5.005 ? ## Add these new keywords supported since 5.005 (ABSTRACT => 'Perl extension to PSPP', AUTHOR => 'John Darrington ') : ()), INC => "-I $Locations{SourceDir} -I $Locations{SourceDir}/src -I $Locations{SourceDir}/gl -I $Locations{BuildDir}/gl -I $Locations{BuildDir}", MYEXTLIB => "$Locations{BuildDir}/src/.libs/libpspp-core.\$(SO)", MAN3PODS => {"lib/PSPP.pm", "\$(INST_MAN3DIR)/PSPP.3pm", "Examples.pod", "\$(INST_MAN3DIR)/PSPP::Examples.3pm"} ); if (eval {require ExtUtils::Constant; 1}) { # If you edit these definitions to change the constants used by this module, # you will need to use the generated const-c.inc and const-xs.inc # files to replace their "fallback" counterparts before distributing your # changes. my @names = (qw()); ExtUtils::Constant::WriteConstants( NAME => 'PSPP', NAMES => \@names, DEFAULT_TYPE => 'IV', C_FILE => 'const-c.inc', XS_FILE => 'const-xs.inc', ); } else { use File::Copy; use File::Spec; foreach my $file ('const-c.inc', 'const-xs.inc') { my $fallback = File::Spec->catfile('fallback', $file); copy ($fallback, $file) or die "Can't copy $fallback to $file: $!"; } } pspp-master/perl-module/PSPP.xs000066400000000000000000000364651177044323000167330ustar00rootroot00000000000000/* PSPP - computes sample statistics. Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include /* The Gnulib "strftime" module defines my_strftime in for use by gl/strftime.c. Perl also defines my_strftime in embed.h for some other purpose. The former definition doesn't matter in this file, so suppress it to avoid a compiler warning. */ #undef my_strftime #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #include "minmax.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct fmt_spec input_format ; typedef struct fmt_spec output_format ; /* A thin wrapper around sfm_writer */ struct sysfile_info { bool opened; /* A pointer to the writer. The writer is owned by the struct */ struct casewriter *writer; /* A pointer to the dictionary. Owned externally */ const struct dictionary *dict; /* The scalar containing the dictionary */ SV *dict_sv; }; /* A thin wrapper around sfm_reader */ struct sysreader_info { struct sfm_read_info opts; /* A pointer to the reader. The reader is owned by the struct */ struct casereader *reader; /* A pointer to the dictionary. */ struct dictionary *dict; }; /* A message handler which writes messages to PSPP::errstr */ static void message_handler (const struct msg *m, void *aux) { SV *errstr = get_sv("PSPP::errstr", TRUE); sv_setpv (errstr, m->text); } static int sysfile_close (struct sysfile_info *sfi) { int retval ; if ( ! sfi->opened ) return 0; retval = casewriter_destroy (sfi->writer); if (retval > 0 ) sfi->opened = false; return retval; } static void scalar_to_value (union value *val, SV *scalar, const struct variable *var) { if ( var_is_numeric (var)) { if ( SvNOK (scalar) || SvIOK (scalar) ) val->f = SvNV (scalar); else val->f = SYSMIS; } else { STRLEN len; const char *p = SvPV (scalar, len); int width = var_get_width (var); value_set_missing (val, width); memcpy (value_str_rw (val, width), p, len); } } static SV * value_to_scalar (const union value *val, const struct variable *var) { if ( var_is_numeric (var)) { if ( var_is_value_missing (var, val, MV_SYSTEM)) return newSVpvn ("", 0); return newSVnv (val->f); } else { int width = var_get_width (var); return newSVpvn (value_str (val, width), width); } } static void var_set_input_format (struct variable *v, input_format ip_fmt) { struct fmt_spec *if_copy = malloc (sizeof (*if_copy)); memcpy (if_copy, &ip_fmt, sizeof (ip_fmt)); var_attach_aux (v, if_copy, var_dtor_free); } static void make_value_from_scalar (union value *uv, SV *val, const struct variable *var) { value_init (uv, var_get_width (var)); scalar_to_value (uv, val, var); } MODULE = PSPP MODULE = PSPP PACKAGE = PSPP PROTOTYPES: ENABLE void onBoot (ver) const char *ver CODE: /* Check that the version is correct up to the length of 'ver'. This allows PSPP autobuilders to add a "-build#" suffix to the PSPP version without causing failures here. */ assert (0 == strncmp (ver, bare_version, strlen (ver))); i18n_init (); msg_set_handler (message_handler, NULL); settings_init (); fh_init (); SV * format_value (val, var) SV *val struct variable *var CODE: SV *ret; const struct fmt_spec *fmt = var_get_print_format (var); union value uv; char *s; make_value_from_scalar (&uv, val, var); s = data_out (&uv, var_get_encoding (var), fmt); value_destroy (&uv, var_get_width (var)); ret = newSVpv (s, fmt->w); free (s); RETVAL = ret; OUTPUT: RETVAL int value_is_missing (val, var) SV *val struct variable *var CODE: union value uv; int ret; make_value_from_scalar (&uv, val, var); ret = var_is_value_missing (var, &uv, MV_ANY); value_destroy (&uv, var_get_width (var)); RETVAL = ret; OUTPUT: RETVAL MODULE = PSPP PACKAGE = PSPP::Dict struct dictionary * pxs_dict_new() CODE: RETVAL = dict_create ("UTF-8"); OUTPUT: RETVAL void DESTROY (dict) struct dictionary *dict CODE: dict_destroy (dict); int get_var_cnt (dict) struct dictionary *dict CODE: RETVAL = dict_get_var_cnt (dict); OUTPUT: RETVAL void set_label (dict, label) struct dictionary *dict char *label CODE: dict_set_label (dict, label); void set_documents (dict, docs) struct dictionary *dict char *docs CODE: dict_set_documents_string (dict, docs); void add_document (dict, doc) struct dictionary *dict char *doc CODE: dict_add_document_line (dict, doc, false); void clear_documents (dict) struct dictionary *dict CODE: dict_clear_documents (dict); void set_weight (dict, var) struct dictionary *dict struct variable *var CODE: dict_set_weight (dict, var); struct variable * pxs_get_variable (dict, idx) struct dictionary *dict SV *idx INIT: SV *errstr = get_sv("PSPP::errstr", TRUE); sv_setpv (errstr, ""); if ( SvIV (idx) >= dict_get_var_cnt (dict)) { sv_setpv (errstr, "The dictionary doesn't have that many variables."); XSRETURN_UNDEF; } CODE: RETVAL = dict_get_var (dict, SvIV (idx)); OUTPUT: RETVAL struct variable * pxs_get_var_by_name (dict, name) struct dictionary *dict const char *name INIT: SV *errstr = get_sv("PSPP::errstr", TRUE); sv_setpv (errstr, ""); CODE: struct variable *var = dict_lookup_var (dict, name); if ( ! var ) sv_setpv (errstr, "No such variable."); RETVAL = var; OUTPUT: RETVAL MODULE = PSPP PACKAGE = PSPP::Var struct variable * pxs_dict_create_var (dict, name, ip_fmt) struct dictionary * dict char *name input_format ip_fmt INIT: SV *errstr = get_sv("PSPP::errstr", TRUE); sv_setpv (errstr, ""); if ( ! id_is_plausible (name, false)) { sv_setpv (errstr, "The variable name is not valid."); XSRETURN_UNDEF; } CODE: struct fmt_spec op_fmt; struct variable *v; op_fmt = fmt_for_output_from_input (&ip_fmt); v = dict_create_var (dict, name, fmt_is_string (op_fmt.type) ? op_fmt.w : 0); if ( NULL == v ) { sv_setpv (errstr, "The variable could not be created (probably already exists)."); XSRETURN_UNDEF; } var_set_both_formats (v, &op_fmt); var_set_input_format (v, ip_fmt); RETVAL = v; OUTPUT: RETVAL int set_missing_values (var, v1, ...) struct variable *var; SV *v1; INIT: int i; union value val[3]; if ( items > 4 ) croak ("No more than 3 missing values are permitted"); for (i = 0; i < items - 1; ++i) scalar_to_value (&val[i], ST(i+1), var); CODE: struct missing_values mv; mv_init (&mv, var_get_width (var)); for (i = 0 ; i < items - 1; ++i ) mv_add_value (&mv, &val[i]); var_set_missing_values (var, &mv); void set_label (var, label) struct variable *var; char *label CODE: var_set_label (var, label, false); void clear_value_labels (var) struct variable *var; CODE: var_clear_value_labels (var); SV * get_write_format (var) struct variable *var CODE: HV *fmthash = (HV *) sv_2mortal ((SV *) newHV()); const struct fmt_spec *fmt = var_get_write_format (var); hv_store (fmthash, "fmt", 3, newSVnv (fmt->type), 0); hv_store (fmthash, "decimals", 8, newSVnv (fmt->d), 0); hv_store (fmthash, "width", 5, newSVnv (fmt->w), 0); RETVAL = newRV ((SV *) fmthash); OUTPUT: RETVAL SV * get_print_format (var) struct variable *var CODE: HV *fmthash = (HV *) sv_2mortal ((SV *) newHV()); const struct fmt_spec *fmt = var_get_print_format (var); hv_store (fmthash, "fmt", 3, newSVnv (fmt->type), 0); hv_store (fmthash, "decimals", 8, newSVnv (fmt->d), 0); hv_store (fmthash, "width", 5, newSVnv (fmt->w), 0); RETVAL = newRV ((SV *) fmthash); OUTPUT: RETVAL void pxs_set_write_format (var, fmt) struct variable *var output_format fmt CODE: var_set_write_format (var, &fmt); void pxs_set_print_format (var, fmt) struct variable *var output_format fmt CODE: var_set_print_format (var, &fmt); void pxs_set_output_format (var, fmt) struct variable *var output_format fmt CODE: var_set_both_formats (var, &fmt); int add_value_label (var, key, label) struct variable *var SV *key char *label INIT: SV *errstr = get_sv("PSPP::errstr", TRUE); sv_setpv (errstr, ""); CODE: union value the_value; int width = var_get_width (var); int ok; value_init (&the_value, width); if ( var_is_numeric (var)) { if ( ! looks_like_number (key)) { sv_setpv (errstr, "Cannot add label with string key to a numeric variable"); value_destroy (&the_value, width); XSRETURN_IV (0); } the_value.f = SvNV (key); } else { value_copy_str_rpad (&the_value, width, SvPV_nolen(key), ' '); } ok = var_add_value_label (var, &the_value, label); value_destroy (&the_value, width); if (!ok) { sv_setpv (errstr, "Something went wrong"); XSRETURN_IV (0); } XSRETURN_IV (1); SV * get_attributes (var) struct variable *var CODE: HV *attrhash = (HV *) sv_2mortal ((SV *) newHV()); struct attrset *as = var_get_attributes (var); if ( as ) { struct attrset_iterator iter; struct attribute *attr; for (attr = attrset_first (as, &iter); attr; attr = attrset_next (as, &iter)) { int i; const char *name = attribute_get_name (attr); AV *values = newAV (); for (i = 0 ; i < attribute_get_n_values (attr); ++i ) { const char *value = attribute_get_value (attr, i); av_push (values, newSVpv (value, 0)); } hv_store (attrhash, name, strlen (name), newRV_noinc ((SV*) values), 0); } } RETVAL = newRV ((SV *) attrhash); OUTPUT: RETVAL const char * get_name (var) struct variable * var CODE: RETVAL = var_get_name (var); OUTPUT: RETVAL const char * get_label (var) struct variable * var CODE: RETVAL = var_get_label (var); OUTPUT: RETVAL SV * get_value_labels (var) struct variable *var CODE: HV *labelhash = (HV *) sv_2mortal ((SV *) newHV()); const struct val_lab *vl; struct val_labs_iterator *viter = NULL; const struct val_labs *labels = var_get_value_labels (var); if ( labels ) { for (vl = val_labs_first (labels); vl; vl = val_labs_next (labels, vl)) { SV *sv = value_to_scalar (&vl->value, var); STRLEN len; const char *s = SvPV (sv, len); hv_store (labelhash, s, len, newSVpv (val_lab_get_label (vl), 0), 0); } } RETVAL = newRV ((SV *) labelhash); OUTPUT: RETVAL MODULE = PSPP PACKAGE = PSPP::Sysfile struct sysfile_info * pxs_create_sysfile (name, dict_ref, opts_hr) char *name SV *dict_ref SV *opts_hr INIT: SV *dict_sv = SvRV (dict_ref); struct dictionary *dict = (void *) SvIV (dict_sv); struct sfm_write_options opts; if (!SvROK (opts_hr)) { opts = sfm_writer_default_options (); } else { HV *opt_h = (HV *) SvRV (opts_hr); SV** readonly = hv_fetch(opt_h, "readonly", 8, 0); SV** compress = hv_fetch(opt_h, "compress", 8, 0); SV** version = hv_fetch(opt_h, "version", 7, 0); opts.create_writeable = readonly ? ! SvIV (*readonly) : true; opts.compress = compress ? SvIV (*compress) : false; opts.version = version ? SvIV (*version) : 3 ; } CODE: struct file_handle *fh = fh_create_file (NULL, name, fh_default_properties () ); struct sysfile_info *sfi = xmalloc (sizeof (*sfi)); sfi->writer = sfm_open_writer (fh, dict, opts); sfi->dict = dict; sfi->opened = true; sfi->dict_sv = dict_sv; SvREFCNT_inc (sfi->dict_sv); RETVAL = sfi; OUTPUT: RETVAL int close (sfi) struct sysfile_info *sfi CODE: RETVAL = sysfile_close (sfi); OUTPUT: RETVAL void DESTROY (sfi) struct sysfile_info *sfi CODE: sysfile_close (sfi); SvREFCNT_dec (sfi->dict_sv); free (sfi); int append_case (sfi, ccase) struct sysfile_info *sfi SV *ccase INIT: SV *errstr = get_sv("PSPP::errstr", TRUE); sv_setpv (errstr, ""); if ( (!SvROK(ccase))) { XSRETURN_UNDEF; } CODE: int i = 0; AV *av_case = (AV*) SvRV (ccase); const struct variable **vv; size_t nv; struct ccase *c; SV *sv; if ( av_len (av_case) >= dict_get_var_cnt (sfi->dict)) XSRETURN_UNDEF; c = case_create (dict_get_proto (sfi->dict)); dict_get_vars (sfi->dict, &vv, &nv, 1u << DC_ORDINARY | 1u << DC_SYSTEM); for (sv = av_shift (av_case); SvOK (sv); sv = av_shift (av_case)) { const struct variable *v = vv[i++]; const struct fmt_spec *ifmt = var_get_aux (v); /* If an input format has been set, then use it. Otherwise just convert the raw value. */ if ( ifmt ) { struct substring ss = ss_cstr (SvPV_nolen (sv)); char *error; bool ok; error = data_in (ss, SvUTF8(sv) ? UTF8: "iso-8859-1", ifmt->type, case_data_rw (c, v), var_get_width (v), dict_get_encoding (sfi->dict)); ok = error == NULL; free (error); if ( !ok ) { RETVAL = 0; goto finish; } } else { scalar_to_value (case_data_rw (c, v), sv, v); } } /* The remaining variables must be sysmis or blank string */ while (i < dict_get_var_cnt (sfi->dict)) { const struct variable *v = vv[i++]; union value *val = case_data_rw (c, v); value_set_missing (val, var_get_width (v)); } casewriter_write (sfi->writer, c); RETVAL = 1; finish: free (vv); OUTPUT: RETVAL MODULE = PSPP PACKAGE = PSPP::Reader struct sysreader_info * pxs_open_sysfile (name) char * name CODE: struct casereader *reader; struct sysreader_info *sri = NULL; struct file_handle *fh = fh_create_file (NULL, name, fh_default_properties () ); sri = xmalloc (sizeof (*sri)); sri->reader = sfm_open_reader (fh, NULL, &sri->dict, &sri->opts); if ( NULL == sri->reader) { free (sri); sri = NULL; } RETVAL = sri; OUTPUT: RETVAL struct dictionary * pxs_get_dict (reader) struct sysreader_info *reader; CODE: RETVAL = reader->dict; OUTPUT: RETVAL SV * get_case_cnt (sfr) struct sysreader_info *sfr; CODE: SV *ret; casenumber n = casereader_get_case_cnt (sfr->reader); if (n == CASENUMBER_MAX) ret = &PL_sv_undef; else ret = newSViv (n); RETVAL = ret; OUTPUT: RETVAL void get_next_case (sfr) struct sysreader_info *sfr; PPCODE: struct ccase *c; if ((c = casereader_read (sfr->reader)) != NULL) { int v; EXTEND (SP, dict_get_var_cnt (sfr->dict)); for (v = 0; v < dict_get_var_cnt (sfr->dict); ++v ) { const struct variable *var = dict_get_var (sfr->dict, v); const union value *val = case_data (c, var); PUSHs (sv_2mortal (value_to_scalar (val, var))); } case_unref (c); } pspp-master/perl-module/README000066400000000000000000000032671177044323000164470ustar00rootroot00000000000000PSPP version 0.7 ================ This module provides an interface allowing perl programs to create pspp system files. INSTALLATION To install you must have first installed and built pspp 0.7.2 or later. The Perl module does not use the installed PSPP binaries, but it does require the libpspp-core-$VERSION.so library installed with PSPP (see below). To install this module type the following: perl Makefile.PL make make install make test For "make test" to succeed, Perl must be able to find libpspp-core-$VERSION.so. It can do so if "make install" has been run (as shown above), or if LD_LIBRARY_PATH points to it (e.g. in src/.libs). Running "make check" from the top-level build directory will automatically set LD_LIBRARY_PATH. DEPENDENCIES This module requires the POSIX module. The modules Test::More, Text::Diff, File::Temp and the pspp source are required during installation, but are not needed to run the module. COPYRIGHT AND LICENCE Copyright (C) 2007, 2009, 2010 by Free Software Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. pspp-master/perl-module/automake.mk000066400000000000000000000040401177044323000177140ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in -*- makefile -*- # PSPP module_sources = \ perl-module/Changes \ perl-module/COPYING \ perl-module/Examples.pod \ perl-module/Makefile.PL \ perl-module/MANIFEST \ perl-module/ppport.h \ perl-module/PSPP.xs \ perl-module/README \ perl-module/typemap \ perl-module/lib/PSPP.pm \ perl-module/t/Pspp.t PERL_MAKEFLAGS = $(AM_MAKEFLAGS) LD_RUN_PATH=$(pkglibdir) perl-module/pspp-module-config: Makefile (echo '%Locations = (';\ printf " SourceDir => '";\ (cd $(top_srcdir) && echo `pwd`\', ) ;\ printf " BuildDir => '";\ (cd $(top_builddir) && echo `pwd`\' );\ echo ');') > $(top_builddir)/perl-module/pspp-module-config perl-module/Makefile: perl-module/Makefile.PL perl-module/pspp-module-config $(module_sources) cd perl-module && $(PERL) Makefile.PL PREFIX=$(prefix) perl-module/PSPP-Perl-$(VERSION_FOR_PERL).tar.gz: $(module_sources) perl-module/Makefile rm -f $@ cd perl-module && $(MAKE) $(PERL_MAKEFLAGS) tardist PHONY += module-make module-make: perl-module/Makefile cd perl-module && $(MAKE) $(PERL_MAKEFLAGS) ALL_LOCAL += perl_module_tarball perl_module_tarball: $(module_sources) src/libpspp-core.la @if test x"$(top_builddir)" != x"$(top_srcdir)" ; then \ for f in $(module_sources); do \ destdir=`dirname $$f` ;\ mkdir -p $$destdir ;\ if test ! -e "$(top_builddir)/$$f" || \ test "$(top_srcdir)/$$f" -nt "$(top_builddir)/$$f" ; then \ cp $(top_srcdir)/$$f $$destdir ; \ echo cp $(top_srcdir)/$$f $$destdir ; \ fi ; \ done \ fi $(MAKE) $(PERL_MAKEFLAGS) module-make perl-module/PSPP-Perl-$(VERSION_FOR_PERL).tar.gz CLEAN_LOCAL += perl_module_clean perl_module_clean: cd perl-module && $(MAKE) $(AM_MAKEFLAGS) clean || true if test x"$(top_builddir)" != x"$(top_srcdir)" ; then \ rm -f $(module_sources) ; \ fi rm -f perl-module/Makefile.old CLEANFILES += \ perl-module/PSPP-Perl-$(VERSION_FOR_PERL).tar.gz \ perl-module/pspp-module-config \ perl-module/const-c.inc \ perl-module/const-xs.inc EXTRA_DIST += $(module_sources) pspp-master/perl-module/lib/000077500000000000000000000000001177044323000163255ustar00rootroot00000000000000pspp-master/perl-module/lib/PSPP.pm.in000066400000000000000000000257501177044323000200630ustar00rootroot00000000000000use 5.008008; use strict; use warnings; =head1 NAME PSPP-Perl - Perl extension to PSPP =head1 SYNOPSIS use PSPP; =head1 DESCRIPTION PSPP-Perl provides an interface to the libraries used by pspp to read and write system files. =head1 EXPORT None by default. =cut BEGIN { $PSPP::VERSION='@VERSION_FOR_PERL@'; require XSLoader; XSLoader::load('PSPP', $PSPP::VERSION); } PSPP::onBoot($PSPP::VERSION); =pod =head1 PROGRAMMER'S INTERFACE The subroutines in this package return zero or unref on error. When errors occur, a string describing the error is written to C<$PSPP::errstr>. =cut package PSPP; use POSIX ; use constant { SYSMIS => -(POSIX::DBL_MAX), PERL_EPOCH => 12219379200 # Number of seconds between # 14th October 1582 # and # 1st January 1970 }; package PSPP::Dict; =pod =head2 PSPP::Dict::new Creates a new dictionary. This returned dictionary will be empty. Returns undef on failure. =head3 set_documents ($string) Sets the documents (comments) to C. =head3 add_document ($string) Appends C to the documents. =head3 clear_documents () Removes all documents. =head3 set_weight ($var) Sets the weighting variable to C. =cut sub new { my $class = shift; my $self = pxs_dict_new (); bless ($self, $class); return $self; } =pod =head3 get_var_cnt () Returns the number of variables in the dictionary. =head3 get_var ($idx) Returns the Cth variable from the dictionary. Returns undef if C is greater than or equal to the number of variables in the dictionary. =cut sub get_var { my $dict = shift; my $idx = shift; my $var = pxs_get_variable ($dict, $idx); if ( ref $var ) { bless ($var, "PSPP::Var"); } return $var; } =pod =head3 get_var_by_name ($name) Returns the variable from the dictionary whose name is C. If there is no such variable, a null reference will be returned. =cut sub get_var_by_name { my $dict = shift; my $name = shift; my $var = pxs_get_var_by_name ($dict, $name); if ( ref $var ) { bless ($var, "PSPP::Var"); } return $var; } package PSPP::Fmt; =pod =head2 PSPP::Fmt Contains constants used to denote variable format types. The identifiers are the same as those used in pspp to denote formats. For example C defines floating point format, and C denotes string format. =cut # These must correspond to the values in src/data/format.h use constant { F => 0, COMMA => 1, DOT => 2, DOLLAR => 3, PCT => 4, E => 5, CCA => 6, CCB => 7, CCC => 8, CCD => 9, CCE => 10, N => 11, Z => 12, P => 13, PK => 14, IB => 15, PIB => 16, PIBHEX => 17, RB => 18, RBHEX => 19, DATE => 20, ADATE => 21, EDATE => 22, JDATE => 23, SDATE => 24, QYR => 25, MOYR => 26, WKYR => 27, DATETIME => 28, TIME => 29, DTIME => 30, WKDAY => 31, MONTH => 32, A => 33, AHEX => 34 }; =head2 PSPP::Var =cut package PSPP::Var; =head3 new ($dict, $name, %input_fmt) Creates and returns a new variable in the dictionary C. The new variable will have the name C. C must be a valid UTF8 string. The input format is set by the C parameter (See L). By default, the write and print formats are the same as the input format. The write and print formats may be changed (See L), L). The input format may not be changed after the variable has been created. If the variable cannot be created, undef is returned. =cut sub new { my $class = shift; my $dict = shift; my $name = shift; my %format = @_; my $self = pxs_dict_create_var ($dict, $name, \%format); if ( ref $self ) { bless ($self, $class); } return $self; } =pod =head3 set_label ($label) Sets the variable label to C