diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-11 23:54:59 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-11 23:54:59 +0000 |
commit | 73d6e84e9abddfa83de47e661b8e92322f795df6 (patch) | |
tree | a8a8f7e2edc28b86d5adf0828a03bfe92a4a1170 /Master | |
parent | c1ee0fb339e096b45a6ad34cf573e427ffe4c253 (diff) |
trunk/Master/texmf-dist/source/latex/mdwtools
git-svn-id: svn://tug.org/texlive/trunk@378 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/COPYING | 339 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/README | 501 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/at.dtx | 750 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/cmtt.dtx | 520 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/doafter.dtx | 516 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/footnote.dtx | 699 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/mdwlist.dtx | 756 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/mdwmath.dtx | 930 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/mdwtab.dtx | 5441 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/mdwtools.ins | 79 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/sverb.dtx | 1186 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/mdwtools/syntax.dtx | 2823 |
12 files changed, 14540 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/mdwtools/COPYING b/Master/texmf-dist/source/latex/mdwtools/COPYING new file mode 100644 index 00000000000..a43ea2126fb --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Master/texmf-dist/source/latex/mdwtools/README b/Master/texmf-dist/source/latex/mdwtools/README new file mode 100644 index 00000000000..dd5538672ac --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/README @@ -0,0 +1,501 @@ + + =============== + + M D W T O O L S + + =============== + + +--- Licence note --- + +mdwtools package release note +Copyright (c) 1996 Mark Wooding, except doafter, which is Copyright (c) 1996 +Peter Schmitt and Mark Wooding. + +These programs are free software; you can redistribute them and/or modify +them 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. + +These programs are distributed in the hope that they 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 these programs; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +--- What it's all about --- + +This is a bunch of LaTeX 2e packages which have made my life as a LaTeX user +easier, so I thought I'd share them. I'm mainly an ARM assembler hacker +(which explains why my TeX code looks so horrible), although I have been +known to write documentation for programs. This may explain the sort of +things these packages do, and where I'm coming from. + + +--- Licencing --- + +The packages are made available under the GNU General Public Licence (not the +usual LaTeX agreement). A copy of this licence is supplied in the file +COPYING. You should read this document if you haven't read it already, even +if it's just for educational value. I'm not actually sure how good a thing +the GNU GPL actually is, so I'm sort of testing the water. The idea that +this is how all software should be distributed still fills me with a certain +amount of trepidation. + + +--- What's in the box --- + +You should have received the following files in whatever sort of archive +thing this suite came in: + + README -- You've got this file for sure, because it's this one + COPYING -- A textual version of the GNU General Public Licence + at.dtx -- Documentation and code for `at.sty' package + cmtt.dtx -- Documentation and code for `cmtt.sty'package and + associated files + doafter.dtx -- Documentation and code for `doafter.sty' package; the + code is also used in `syntax.sty' and `mdwtab.sty' + mdwlist.dtx -- Documentation and code for `mdwlist.sty' package + mdwmath.dtx -- Documentation and code for `mdwmath.sty' package + mdwtab.dtx -- Documentation and code for `mdwtab.sty' and `mathenv.sty' + packages + footnote.dtx -- Documentation and code for `footnote.sty' package; the + code is used in `mdwtab.sty' + sverb.dtx -- Documentation and code for `sverb.stx' package + syntax.dtx -- Documentation and code for `syntax.dtx' package + mdwtools.ins -- Installation script for all the packages + gpl.tex -- LaTeX version of the GNU General Public Licence + mdwtools.tex -- Definitions for typesetting the documentation + +If you're missing any of these files, complain at whoever gave the rest of +them to you, and get them quickly. However, if you're lucky, you may have +received some other files: + + at.sty -- Unpacked `at.sty' package + cmtt.sty -- Unpacked `cmtt.sty' package + mTTenc.def -- Unpacked encoding definition file for `cmtt.sty' + mTTcmtt.fd -- Unpacked font definition file for `cmtt.sty' + doafter.sty -- Unpacked `doafter.sty' package for LaTeX + doafter.tex -- Unpacked `doafter.tex' package for Plain TeX + mathenv.sty -- Unpacked `mathenv.sty' package + mdwlist.sty -- Unpacked `mdwlist.sty' package + mdwmath.sty -- Unpacked `mdwmath.sty' package + mdwtab.sty -- Unpacked `mdwtab.sty' package + footnote.sty -- Unpackad `savenot.dty' package + sverb.sty -- Unpacked `sverb.sty' package + syntax.sty -- Unpacked `syntax.sty' package + + at.dvi -- Typeset documentation for `at.sty' + cmtt.dvi -- Typeset documentation for `cmtt.sty' and co. + doafter.dvi -- Typeset documentation for `doafter.sty' + mdwlist.dtx -- Typeset documentation for `mdwlist.sty' + mdwmath.dvi -- Typeset documentation for `mdwmath.sty' + mdwtab.dvi -- Typeset documentation for `mdwtab.sty' and `mathenv.sty' + footnote.dvi -- Typeset documentation for `footnote.sty' + sverb.dvi -- Typeset documentation for `sverb.sty' + syntax.dvi -- Typeset documentation for `syntax.sty' + +If you've already got these, then great, because you don't have to generate +them. If you haven't, it's not a big deal. You might also have a bunch of +files with extensions like `.log', `.aux', `.tmp', `.ilg' and so on. These +files are really not at all interesting, and you might as well get rid of +them now. + + +--- What the packages do --- + +Before we can get anywhere, you need to know what the packages do, roughly +speaking. Here's a quick rundown: + +at.sty -- Allows you to use `@' as a sort of `command-introducing' + character, a bit like `\' is already. This gives you + a lot more short command names which you can assign to + common constructions. For example, you can set up + @/<text>/ as a command to put <text> in italics. + +cmtt.sty -- Provides an `mTT' encoding for the Computer Modern + Typewriter font, which solves lots of messy problems. + +doafter.sty -- Provides a TeX programmer's utility + \doafter <token> <group> + which does the <token> after the group is complete, + including any \aftergroup things. The code was originally + written by Peter Schmitt in answer to a `challenge' I made + on comp.text.tex;I tweaked it a bit to make it work + slightly better. doafter.tex is a plain TeX version of + the same macro. + +mathenv.sty -- Contains a collection of mathematical environments with + a theme of aligning things in columns. There's a + rewritten version of `eqnarray' which is much more + powerful than the old one, and it gets the spacing right. + This package requires `mdwtab.sty' in order to work. It + is extracted from `mdwtab.dtx'. In general, the AmS + things to a better job, although it seems that the mathenv + matrix and script handling environments give prettier + results than the AmS equivalents (at least to my eyes). + +mdwlist.sty -- Various list related environments. There's a more + versatile `description' environment, and some stuff for + making `compacted' lists (with no extra space between + items). + +mdwmath.sty -- Contains a few trivial definitions for mathematical + things. The main thing is that the \sqrt command for + doing square roots has been improved -- there's a \sqrt* + command which stops the line being drawn over the formula + being square-rooted, and the positioning of the root + index (the optional argument) has been improved. + +mdwtab.sty -- A complete ground-up rewrite of LaTeX's `tabular' and + `array' environments. Has lots of advantages over + the standard version, and over the version in `array.sty'. + It works correctly with all the table-related packages in + the Tools bundle (longtable, delarray, hhline, tabularx + and dcolumn). This package includes most of the code + from `doafter.sty' and `footnote.sty' (it doesn't load + the packages -- it has its own copies built-in, although + you won't waste memory if you do load these packages). + To generate `mdwtab.sty', you require `mdwtab.dtx', + `doafter.dtx' and `footnote.dtx'; the last two provide + the shared code. + +footnote.sty -- Provides commands for saving executing footnotes; the + author has noticed several packages which attempt to + enable footnotes in tables, all of which eat an extra + token list register. This is an attempt to offer shared + code to do the job, saving space and effort. It also + provides a `footnote' environment which allows verbatim + text. + +sverb.sty -- A bunch of macros for doing verbatim things. Required + for typesetting all the documentation for the other + packages. + +syntax.sty -- A load of commands for describing syntax. There's an + environment for typesetting BNF grammars. But best of + all, there's a load of commands and environments for + drawing syntax diagrams. Required for typesetting all + the documentation for the other packages. If you're + extracting syntax.sty from syntax.dtx, you also need + doafter.dtx. + +With the exception of the dependencies listed above, the packages will all +work independently of each other. If you want to typeset the documentation, +you'll need `sverb.sty' and `syntax.sty'. Typesetting the documentation +isn't essential, although it will probably help if you can see what the +various commands actually do. + + +--- Extracting the packages --- + +If you don't have the various .sty files already, you'll need to extract them +from the .dtx files. This requires docstrip.tex, which should be part of +your base LaTeX 2e distribution. If you have docstrip vsersion 2.3d, which +is available with the December 1995 release of LaTeX, things will go rather +faster. If your LaTeX release is much older than this, you should upgrade, +because the packages need a fairly new LaTeX anyway. (I could do something +about this, but I won't, because I want to encourage everyone to upgrade.) + +If everything's set up correctly, all you should need to do is say + + tex mdwtools.ins + +or + + latex mdwtools.ins + +or whatever incantation is necessary to run TeX or LaTeX on the supplied +`mdwtools.ins' file on your system. + +TeX will grind away at the files for a bit, and then say `Done' at you. (This +could take a while, so be patient.) You will then have a mdwtools.log file, +which you can throw away, and a collection of sparkly new .sty files, which +you should put somewhere where TeX can find them easily. + + +--- Typesetting the documentation --- + +If you want to typeset the documentation for a package, you'll need the +`mdwtools.tex' file provided, and the `syntax.sty' and `sverb.sty' packages. +You'll also need the `.dtx' file for the package you want documentation on, +and any packages it generated. + +For example, if you want documentation on `mathenv.sty', you need: + + mdwtools.tex -- Shared defintions for all the documentation files + syntax.sty -- Syntax typesetting commands + sverb.sty -- Verbatim text handling commands + mathenv.sty -- So the documentation can use it to demonstrate its + features + mdwtab.sty -- Required by `mathenv.sty' + mdwtab.dtx -- The documentation file from which `mathenv.sty' was + extracted, and therefore the file which contains the + documentation you want to read + +Make sure you've got all the files, and then run LaTeX on the .dtx file you +want to read. + +TeX will start hammering away for a very short while, and then stop and ask +you whether you want to build the indexing files. Generating index files +takes a lot longer (I'd guess that it doubled the amount of time taken to +typeset the `.dtx' file) so I don't recommend it unless: + + * you've got a very fast processor, or + * you're very interested in how the package works internally, or + * you just like everything to be complete, or + * you're a masochist. + +Even so, there's no point writing indexing information the first time you +run LaTeX on a file, because the table of contents hasn't been created yet, +and when you LaTeX the file the second time, all the references will change. + +If you want the index files anyway, type `y' when you're asked. Otherwise, +type 'n'. You know you want to type `n' really... + +If you want to do the job properly, you need to run LaTeX a second time +to read in the contents table. /This/ is the correct time to turn on +indexing, if you really want it. + +If you did build the index files, you should now sort the index by saying + + makeindex -s gind.ist <name>.idx + +where <name> is the same as the name of the `.dtx' file. The `gind.ist' file +should have come with LaTeX. Having done this, you should run the `.dtx' +file though LaTeX one final time, to insert the formatted index. + +You can now print or preview the generated `.dvi' file using whatever tools +you usually use for such things. + + +--- What changed? --- + +Here's a list of what changed in the various releases. + +Version Changes + +1.00 * First general releases of everything. + + +1.01 * Fixed typos in various bits of documentation. + + * (mdwtab.sty) Added enhanced \cline command. Added + hhline.sty to list of supported table-related packages. + (I guess it always worked -- I just forgot about it.) + Made some of the section titles a little sillier ;-) + + * (mathenv.sty) Added some new random environments, mainly + because I saw some more interesting examples in /The/ + /TeXbook/ and had an idea... Now support nesting of + various environments, albeit rather imperfectly. + + * (at.sty) Made @-commands really properly robust. Fixed + some lies in the documentation. Removed some truly insane + bits of old code here too. Made package sort of + cooperate with amsmath's use of @-commands -- suggestions + for improvement welcomed. + + * (mdwtools.tex) Fixed /really/ stupid mistake in which made + typesetting the documentation about fifty times slower + than it should have been (bashes self on head several + times). Changed the structure here a bit too, to handle + document classes as well as packages. Made TeX much + quieter while it's typesetting the documentation. + + * (sverb.sty) Fixed duff paragraph formatting in listing + environment and \verbinput command (due to the `wrong + sort' of grouping). (My excuse for missing this one is + that my standard document class sets \parskip=0pt.) + + * (mdwtools.ins) Fixed this in line with the documentation + which hints that it should work with older docstrips. + It's a bit hacky but it works. + + +1.02 * (gpl.tex) Fixed some bugs which made typesetting go wrong + in larger documents. Restructured preamble so that it + can be typeset on its own. Put in eplicit item numbers + in the enumerate environments, for more obvious conformance + to the original. + + * (mdwtab.sty) Lots of changes here, many suggested by + David Carlisle (so oodles of thanks to him for taking + an interest in my humble hackings). Fixed bugs, including + one which put entirely incorrect interline spacing in + `p' type columns. Redone the handling of [t] and [b] + tables with top and bottom rules, and removed the + `\rulefudge' parameter which is no longer necessary. + Miscellaneous other changes. + + * (mdwtab.dtx) Tidied up some nastinesses in the + documentation, and removed the `\over' commands from the + maths demos, to keep certain people happy. Floated a few + more of the demonstrations to make page breaking better. + There's a danger that some of the demos are drifting too + far away from their text, but it's not too bad yet. + + * (syntax.sty) Used \doafter here to fix some colour handling + problems. + + * (syntax.sty) Tidied up the `grammar' environment quite a + bit (it now uses `\item', rather than trying to emulate it + internally), and fixed some vicious bugs in it and some + other code. + + * (doafter.sty etc.) A new addition, to make the various + packages handle colour properly. Mainly written by + Peter Scmitt, actually, I just fiddled with it a little. + Then Peter gave me a better version, and I've tried to + upgrade this one. + + * (footnote.sty) A new addition, to offer some shared things + for handling footnotes. It also enables footnotes in + parboxes, which used to be difficult, and provides a + `footnote' environment which allows verbatim text. + + * (mdwlist.sty} A new addition, providing miscellanous + list-related macros. It's a sort of mixed bag of things + I've had lying around various document preambles, combined + with some ideas from the Companion. + + * (at.sty) Rewritten command name parser to be much nicer. + Added support for digits within @-command names (subject + to being enabled by an option). This is in response to + requests in comp.text.tex for digits in command names. + + * (mathenv.sty) Totally overhauled the matrix spacing rules. + Added `script' environment. Improved numbering things, + with `\eqnumber'. + + * (mdwtools.tex) Some minor changes here to fix some buglets. + Played with some more float parameters, to discourage + float pages a bit more. Then revamped completely, turned + into a docced program (although it isn't docstripped), + rewritten title generation, and made much more + customisable. + + +1.02a * (mdwtab.sty) Added support for table beautification in + longtable. Documented how to do this. + + +1.03 * (mdwtab.sty) Completely redone the paragraph-cell handling: + list environments now work properly inside tables (without + funny extra space appearing at the top and bottom). Also + fixed a bug in the newline handling, which ignored negative + interrow space in the \\ command. + + * (syntax.sty) Changed the underscore handling, and some + other bits, to fit in rather better with LaTeX's output + encoding system. It's nastier and hackier inside, but it + works better with things like the DC fonts. Also stopped + re-lowercasing of `~' from escaping and messing everything + up for everyone. Improved underscore appearance by + lowering it some more. + + * (syntax.sty) Replaced some `2's with `\tw@'s. Added a + comment about dvips's inaccurate positioning of rules. + + * (sverb.sty) Made non-* environments build end text from + the name of the current environment, rather than having it + hardcoded. Also stopped `unignore' environments being + a group. + + * (sverb.dtx) Removed some porkies from the documentation. + + * (mdwtab.sty) Fixed some miscellaneous typos. Removed + `\rulefudge' from the table of tweakables, because it + was withdrawn in release 1.02. + + * (cmtt.dtx) New package, for handling the `cmtt' font + better. It introduces a special encoding for the font, + and provides a command which allows you to use all the + characters without the disadvantages of verbatim text. + + * (other changes) Improved distribution building and + testing stuff which you can't see because I'm not + releasing it. + + +1.04 * (syntax.sty) Provided some new commands for playing with + interword spacing in `tt' fonts. + + * (doafter.dtx and footnote.dtx) Added some docstrip guards + around the meta-comments, so that the charactertable and + the GPL header aren't put into other packages. + Unfortunately the version of docstrip which understands + this hasn't been released yet... + + * RCSified everything, so I can find old revisions, and I'm + less likely to destroy everything. + + * (footnote.dtx) Added a check for AMS environments doing + measuring passes, to avoid duplicated footnotes. (Spotted + by Roberto Bagnara.) + + +1.05 * (mdwtab.dtx) Fixed stupid bug in paragraph cells which + left 1000pt high table rows. (Spotted by Rowland.) + + * (mdwtab.dtx) Fixed horizontal spacing problems with + empty paragraph cells. + + * (mdwlist.dtx) Allowed compact lists and resumed lists + to pass arguments on to the underlying environments. + + * (syntax.dtx) Fix bug affecting underscore handling in + syntax abbreviations. + +--- Future plans --- + +doafter.sty Add Peter Schmitt's testing for implicit/explicit braces, + as a package or docstrip option. (This extra testing is + a significant chunk of code, and I don't think it's worth + burdening the standard version with it. Peter agrees with + me.) + +mathenv.sty Do postprocessing on display maths environments to position + the equations and equation numbers properly, so they don't + overlap (like the AMS environments do, although more + robustly). Once this is done, I think I'll have a reasonable + case for saying that this provides an alternative to the + AMS environments, although quite what the advantage is I + don't know: mdwtab.sty isn't exactly small. + + Work is currently `in progress' on this one. + +mdwtab.sty Consider doing postprocessing on tables (yuk) in a blkarray + sort of way. + +footnote.sty Merge with Robin Fairbairn's package of the same name. Allow + different rules for continued notes (suggested by Donald + Arseneau, after a news article by Jonathan Wand). + +New packages I'm currently working on a little something for typesetting + poetry properly (centring poems horizontally based on the + longest line, etc.), handling footnotes properly, doing + line numbering etc. If anyone has any wishes for this, + little things a tyro like me ought to know, or knows that + it's already done better than I could manage, then let me + know. + + +--- Contacting the author --- + +The author can be reached by email at mdw@excessus.demon.co.uk. This is his +personal dial-up account, paid for privately, so don't expect replies after +five minutes or anything like that. + +If you do have any comments regarding the code, its documentation, or +anything else to do with these packages, don't leave me guessing -- let me +know. While I won't guarantee to do anything about your comments, chances +are that I'll right any wrongs and rescue any damsels in distress (oh, no, +wrong spiel). + + +----------------------------------------------------------------------------- diff --git a/Master/texmf-dist/source/latex/mdwtools/at.dtx b/Master/texmf-dist/source/latex/mdwtools/at.dtx new file mode 100644 index 00000000000..ea72376c88a --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/at.dtx @@ -0,0 +1,750 @@ +% \begin{meta-comment} +% +% $Id: at.dtx,v 1.3 1996/11/19 20:46:55 mdw Exp $ +% +% Allow @-commands +% +% (c) 1995 Mark Wooding +% +%----- Revision history ----------------------------------------------------- +% +% $Log: at.dtx,v $ +% Revision 1.3 1996/11/19 20:46:55 mdw +% Entered into RCS +% +% +% \end{meta-comment} +% +% \begin{meta-comment} <general public licence> +%% +%% at package -- support for `@' commands' +%% Copyright (c) 1996 Mark Wooding +%% +%% This program is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation; either version 2 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program; if not, write to the Free Software +%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +%% +% \end{meta-comment} +% +% \begin{meta-comment} <Package preamble> +%<+package>\NeedsTeXFormat{LaTeX2e} +%<+package>\ProvidesPackage{at} +%<+package> [1996/05/02 1.3 @-command support (MDW)] +% \end{meta-comment} +% +% \CheckSum{355} +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%% +% +% \begin{meta-comment} <driver> +% +%<*driver> +\input{mdwtools} +\describespackage{at} +\aton +\atlet p=\package +\atdef at{\package{at}} +\atdef={\mbox{-}} +\atdef-{@@@=} +\atlet.=\syntax +\mdwdoc +%</driver> +% +% \end{meta-comment} +% +% \section{User guide} +% +% The @at\ package is an attempt to remove a lot of tedious typing that +% ends up in \LaTeX\ documents, by expanding the number of short command +% names available. The new command names begin with the `|@|' character, +% rather than the conventional `|\|', so you can tell them apart. +% +% The package provides some general commands for defining @-commands, and +% then uses them to define some fairly simple ones which will be useful to +% most people. +% +% The rules for @-command names aren't terribly complex: +% \begin{itemize} +% \item If the first character of the name is a letter, then the command name +% consists of all characters up to, but not including, the first +% nonletter. Spaces following the command name are ignored. +% \item If the first character of the name is a backslash, then the @-command +% name consists of the control sequence introduced by the backslash. +% \item Otherwise, the command name consists only of that first character. +% Spaces following the name are not ignored, unless that character +% was itself a space character. +% \end{itemize} +% +% Usually, digits are not considered to be letters. However, the +% \package{at} package will consider digits to be letters if you give it the +% \textsf{digits} option in the |\usepackage| command. (Note that this +% only affects the \package{at} package; it won't change the characters +% allowed in normal command names.) +% +% \DescribeMacro{\atallowdigits} +% \DescribeMacro{\atdisallowdigits} +% You can enable and disable digits being considered as letters dynamically. +% The |\atallowdigits| command allows digits to be used as letters; +% |\atdisallowdigits| prevents this. Both declarations follow \LaTeX's +% usual scoping rules. Both of these commands have corresponding +% environments with the same names (without the leading `|\|', obviously). +% +% \subsection{Defining @-commands} +% +% \DescribeMacro{\newatcommand} +% \DescribeMacro{\renewatcommand} +% The |\newatcommand| command will define a new @-command using a syntax +% similar to |\newcommand|. For example, you could define +% \begin{listing} +%\newatcommand c[1]{\chapter{#1}} +% \end{listing} +% to make @.{"@c{"<name>"}"} equivalent to @.{"\\chapter{"<name>"}"}. +% +% A |\renewatcommand| is also provided to redefine existing commands, should +% the need arise. +% +% \DescribeMacro{\atdef} +% For \TeX\ hackers, the |\atdef| command defines @-commands using a syntax +% similar to \TeX's built-in |\def|. +% +% As an example, the following command makes @.{"@/"<text>"/"} write its +% argument \<text> in italics: +% \begin{listing} +%\atdef/#1/{\textit{#1}} +% \end{listing} +% The real implementation of the |@/|\dots|/| command is a bit more +% complex, and is given in the next section. +% +% You can use all of \TeX's features for defining the syntax of your +% command. (See chapter~20 of @/The \TeX book/ for more details.) +% +% \DescribeMacro{\atlet} +% Since |\atdef| is provided to behave similarly to |\def|, @at\ provides +% |\atlet| which works similarly to |\let|. For example you can say +% \begin{listing} +%\atlet!=\index +% \end{listing} +% to allow the short |@!| to behave exactly like |\index|. +% +% Note that all commands defined using these commands are robust even if you +% use fragile commands in their definitions. Unless you start doing very +% strange things, @-commands never need |\protect|ing. +% +% \subsection{Predefined @-commands} +% +% A small number of hopefully useful commands are provided by default. +% These are described in the table below: +% +% \bigskip \begin{center} \begin{tabular}{lp{3in}} \hline +% \bf Command & \bf Meaning \\ \hline +% @.{"@@"} & Typesets an `@@' character. \\ +% @.{"@/"<text>"/"} & In text (LR or paragraph) mode, typesets its +% argument emphasised. In maths mode, it +% always chooses italics. \\ +% @.{"@*"<text>"*"} & Typesets its argument \<text> in bold. \\ +% @.{"@i{"<text>"}"} & Equivalent to `@.{"\\index{"<text>"}"}'. \\ +% @.{"@I{"<text>"}"} & As for |@i|, but also writes its argument +% to the document. \\ \hline +% \end{tabular} \end{center} \bigskip +% +% Package writers should not rely on any predefined @-commands -- they're +% provided for users, and users should be able to redefine them without +% fear of messing anything up. (This includes the `standard' commands +% provided by the @at\ package, by the way. They're provided in the vague +% hope that they might be useful, and as examples.) +% +% \implementation +% +% \section{Implementation} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \subsection{Options handling} +% +% We need a switch to say whether digits should be allowed. Since this +% is a user thing, I'll avoid |\newif| and just define the thing by hand. +% +% \begin{macrocode} +\def\atallowdigits{\let\ifat@digits\iftrue} +\def\atdisallowdigits{\let\ifat@digits\iffalse} +% \end{macrocode} +% +% Now define the options. +% +% \begin{macrocode} +\DeclareOption{digits}{\atallowdigits} +\DeclareOption{nodigits}{\atdisallowdigits} +\ExecuteOptions{nodigits} +\ProcessOptions +% \end{macrocode} +% +% \subsection{How the commands work} +% +% Obviously we make the `@@' character active. It inspects the next +% character (or argument, actually -- it can be enclosed in braces for +% longer commands, although this is a bit futile), and builds the command +% name from that. +% +% The |\at| command is equivalent to the active `@@' character always. +% +% +% \subsection{Converting command names} +% +% We need to be able to read an @-command name, and convert it to a normal +% \TeX\ control sequence. First, we declare some control sequences for +% braces, which we need later. +% +% \begin{macrocode} +\begingroup +\catcode`\<1 +\catcode`\>2 +\catcode`\{12 +\catcode`\}12 +\gdef\at@lb<{> +\gdef\at@rb<}> +\gdef\at@spc< > +\endgroup +% \end{macrocode} +% +% I'll set up some helper routines now, to help me read the command +% names. The way this works is that we |\futurelet| the token into +% |\@let@token|. These routines will then sort out what to do next. +% +% \begin{macro}{\at@test} +% +% Given an |\if|\dots\ test, does its first or second argument. +% +% \begin{macrocode} +\def\at@test#1\then{% + #1\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\at@ifcat} +% +% Checks the category code of the current character. If it matches the +% argument, it does its second argument, otherwise it does the third. +% +% \begin{macrocode} +\def\at@ifcat#1{\at@test\ifcat#1\noexpand\@let@token\then} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\at@ifletter} +% +% This routine tests the token to see if it's a letter, and if so adds +% it to the token list and does the first argument; otherwise it does the +% second argument. It accepts digits as letters if the switch is turned +% on. +% +% There's some fun later, so I'll describe this slowly. First, we compare +% the category code to a letter, and if we have a match, we know we're done; +% we need to pick up the letter as an argument. If the catcode is `other', +% we must compare with numbers to see if it's in range. +% +% \begin{macrocode} +\def\at@ifletter#1#2{% + \at@ifcat x% + {\at@ifletter@ii{#1}}% + {\at@ifcat 0% + {\at@ifletter@i{#1}{#2}}% + {#2}% + }% +} +% \end{macrocode} +% +% Right. It's `other' (so it's safe to handle as a macro argument) and we +% need to know if it's a digit. This is a little tricky: I use |\if| to +% compare two characters. The first character is~`1' or~`0' depending on the +% `digit' switch; the second is~`1' or~`x' depending on whether it's actually +% a digit. They'll only match if everything's worked out OK. +% +% \begin{macrocode} +\def\at@ifletter@i#1#2#3{% + \at@test\if% + \ifat@digits1\else0\fi% + \ifnum`#3<`0x\else\ifnum`#3>`9x\else1\fi\fi% + \then% + {\at@ifletter@ii{#1}{#3}}% + {#2#3}% +} +% \end{macrocode} +% +% Right; we have the character, so add it to the list and carry on. +% +% \begin{macrocode} +\def\at@ifletter@ii#1#2{\toks@\expandafter{\the\toks@#2}#1} +% \end{macrocode} +% +% \end{macro} +% +% Now we define the command name reading routines. We have @/almost/ the +% same behaviour as \TeX, although we can't support `|%|' characters for +% reasons to do with \TeX's tokenising algorithm. +% +% \begin{macro}{\at@read@name} +% +% The routine which actually reads the command name works as follows: +% \begin{enumerate} +% \item Have a peek at the next character. If it's a left or right brace, +% then use the appropriate character. +% \item If the character is not a letter, just use the character (or whole +% control sequence. +% \item Finally, if it's a letter, keep reading letters until we find one +% that wasn't. +% \end{enumerate} +% +% First, we do some setting up and read the first character +% +% \begin{macrocode} +\def\at@read@name#1{% + \let\at@next=#1% + \toks@{}% + \futurelet\@let@token\at@rn@i% +} +% \end{macrocode} +% +% Next, sort out what to do, based on the category code. +% +% \begin{macrocode} +\def\at@rn@i{% + \def\@tempa{\afterassignment\at@rn@iv\let\@let@token= }% + \at@ifletter% + {\futurelet\@let@token\at@rn@iii}% + {\at@ifcat\bgroup% + {\toks@\expandafter{\at@lb}\@tempa}% + {\at@ifcat\egroup% + {\toks@\expandafter{\at@rb}\@tempa}% + {\at@ifcat\at@spc% + {\toks@{ }\@tempa}% + {\at@rn@ii}% + }% + }% + }% +} +% \end{macrocode} +% +% Most types of tokens can be fiddled using |\string|. +% +% \begin{macrocode} +\def\at@rn@ii#1{% + \toks@\expandafter{\string#1}% + \at@rn@iv% +} +% \end{macrocode} +% +% We've found a letter, so we should check for another one. +% +% \begin{macrocode} +\def\at@rn@iii{% + \at@ifletter% + {\futurelet\@let@token\at@rn@iii}% + {\@ifnextchar.\at@rn@iv\at@rn@iv}% +} +% \end{macrocode} +% +% Finally, we need to pass the real string, as an argument, to the +% macro. We make |\@let@token| relax, since it might be something which will +% upset \TeX\ later, e.g., a |#| character. +% +% \begin{macrocode} +\def\at@rn@iv{% + \let\@let@token\relax% + \expandafter\at@next\csname at.\the\toks@\endcsname% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\at@cmdname} +% +% Given a control sequence, work out which @-command it came from. +% +% \begin{macrocode} +\def\at@cmdname#1{\expandafter\at@cmdname@i\string#1\@@foo} +% \end{macrocode} +% +% Now extract the trailing bits. +% +% \begin{macrocode} +\def\at@cmdname@i#1.#2\@@foo{#2} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\at@decode} +% +% The |\at@decode| macro takes an extracted @-command name, and tries to +% execute the correct control sequence derived from it. +% +% \begin{macrocode} +\def\at@decode#1{% + \at@test\ifx#1\relax\then{% + \PackageError{at}{Unknown @-command `@\at@cmdname#1'}{% + The @-command you typed wasn't recognised, so I've ignored it. + }% + }{% + #1% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\@at} +% +% We'd like a measure of compatibility with @p{amsmath}. The @-commands +% provided by @p{amsmath} work only in maths mode, so this gives us a way of +% distinguishing. If the control sequence |\Iat| is defined, and we're in +% maths mode, we'll call that instead of doing our own thing. +% +% \begin{macrocode} +\def\@at{% + \def\@tempa{\at@read@name\at@decode}% + \ifmmode\ifx\Iat\not@@defined\else% + \let\@tempa\Iat% + \fi\fi% + \@tempa% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Defining new commands} +% +% \begin{macro}{\at@buildcmd} +% +% First, we define a command to build these other commands: +% +% \begin{macrocode} +\def\at@buildcmd#1#2{% + \expandafter\def\csname\expandafter + \@gobble\string#1@decode\endcsname##1{#2##1}% + \edef#1{% + \noexpand\at@read@name% + \expandafter\noexpand% + \csname\expandafter\@gobble\string#1@decode\endcsname% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\newatcommand} +% \begin{macro}{\renewatcommand} +% \begin{macro}{\provideatcommand} +% \begin{macro}{\atdef} +% \begin{macro}{\atshow} +% +% Now we define the various operations on @-commands. +% +% \begin{macrocode} +\at@buildcmd\newatcommand\newcommand +\at@buildcmd\renewatcommand\renewcommand +\at@buildcmd\provideatcommand\providecommand +\at@buildcmd\atdef\def +\at@buildcmd\atshow\show +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\atlet} +% +% |\atlet| is rather harder than the others, because we want to allow people +% to say things like @.{"\\atlet"<name>"=@"<name>}. The following hacking +% does the trick. I'm trying very hard to duplicate |\let|'s behaviour with +% respect to space tokens here, to avoid any surprises, although there +% probably will be some differences. In particular, |\afterassignment| +% won't work in any sensible way. +% +% First, we read the name of the @-command we're defining. We also open +% a group, to stop messing other people up, and make `@@' into an `other' +% token, so that it doesn't irritatingly look like its meaning as a control +% sequence. +% +% \begin{macrocode} +\def\atlet{% + \begingroup% + \@makeother\@% + \at@read@name\atlet@i% +} +% \end{macrocode} +% +% Put the name into a scratch macro for later use. Now see if there's an +% equals sign up ahead. If not, this will gobble any spaces in between the +% @-command name and the argument. +% +% \begin{macrocode} +\def\atlet@i#1{% + \def\at@temp{#1}% + \@ifnextchar=\atlet@ii{\atlet@ii=}% +} +% \end{macrocode} +% +% Now we gobble the equals sign (whatever catcode it is), and peek at the +% next token up ahead using |\let| with no following space. +% +% \begin{macrocode} +\def\atlet@ii#1{\afterassignment\atlet@iii\global\let\at@gnext=} +% \end{macrocode} +% +% The control sequence |\at@gnext| is now |\let| to be whatever we want the +% @-command to be, unless it's picked up an `@@' sign. If it has, we've +% eaten the |@| token, so just read the name and pass it on. Otherwise, +% we can |\let| the @-command directly to |\at@gnext|. There's some +% nastiness here to make |\the\toks@| expand before we close the group and +% restore its previous definition. +% +% \begin{macrocode} +\def\atlet@iii{% + \if @\noexpand\at@gnext% + \expandafter\at@read@name\expandafter\atlet@iv% + \else% + \expandafter\endgroup% + \expandafter\let\at@temp= \at@gnext% + \fi% +} +% \end{macrocode} +% +% We've read the source @-command name, so just copy the definitions over. +% +% \begin{macrocode} +\def\atlet@iv#1{% + \expandafter\endgroup% + \expandafter\let\at@temp=#1% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Robustness of @-commands} +% +% We want all @-commands to be robust. We could leave them all being +% fragile, although making robust @-commands would then be almost impossible. +% There are two problems which we must face: +% +% \begin{itemize} +% +% \item The `|\@at|' command which scans the @-command name is (very) +% fragile. I could have used |\DeclareRobustCommand| for it (and in +% fact I did in an earlier version), but that doesn't help the other +% problem at all. +% +% \item The `name' of the @-command may contain active characters or control +% sequences, which will be expanded at the wrong time unless we do +% something about it now. +% +% \end{itemize} +% +% We must also be careful not to introduce extra space characters into any +% files written, because spaces are significant in @-commands. Finally, +% we have a minor problem in that most auxiliary files are read in with +% the `@@' character set to be a letter. +% +% \begin{macro}{\at} +% +% Following the example of \LaTeX's `short' command handling, we'll define +% |\at| to decide what to do depending on what |\protect| looks like. If +% we're typesetting, we just call |\@at| (above) and expect it to cope. +% Otherwise we call |\at@protect|, which scoops up the |\fi| and the |\@at|, +% and inserts other magic. +% +% \begin{macrocode} +\def\at{\ifx\protect\@typeset@protect\else\at@protect\fi\@at} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\at@protect} +% +% Since we gobbled the |\fi| from the above, we must put that back. We then +% need to do things which are more complicated. If |\protect| is behaving +% like |\string|, then we do one sort of protection. Otherwise, we assume +% that |\protect| is being like |\noexpand|. +% +% \begin{macrocode} +\def\at@protect\fi#1{% + \fi% + \ifx\protect\string% + \expandafter\at@protect@string% + \else% + \expandafter\at@protect@noexpand% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\at@protect@string} +% +% When |\protect| is |\string|, we don't need to be able to recover the +% original text particularly accurately -- it's for the user to look at. +% Therefore, we just output a $|@|_{11}$ and use |\string| on the next +% token. This must be sufficient, since we only allow multi-token command +% names if the first token is a letter (code~11). +% +% \begin{macrocode} +\def\at@protect@string{@\string} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\at@protect@noexpand} +% +% This is a little more complex, since we're still expecting to be executed +% properly at some stage. However, there's a cheeky dodge we can employ +% since the |\at| command is thoroughly robustified (or at least it will be +% by the time we've finished this). All |\@unexpandable@protect| does +% is confer repeated robustness on a fragile command. Since our command +% is robust, we don't need this and we can get away with just using a +% single |\noexpand|, both for the |\@at@| command and the following token +% (which we must robustify, because no-one else can do it for us -- if +% anyone tries, they end up using the |@\protect| command which is rather +% embarassing). +% +% I'll give the definition, and then examine how this expands in various +% cases. +% +% \begin{macrocode} +\def\at@protect@noexpand{\noexpand\@at@ @\noexpand} +\def\@at@#1{\at} +% \end{macrocode} +% +% A few points, before we go into the main examination of the protection. +% I've inserted a $|@|_{11}$ token, which is gobbled by |\@at@| when the +% thing is finally expanded fully. This prevents following space tokens +% in an |\input| file from being swallowed because they follow a control +% sequence. (I can't use the normal $|@|_{13}$ token, because when files +% like the |.aux| file are read in, |@| is given code~11 by +% |\makeatletter|.) +% +% \setbox0\hbox{|@at@|} +% Now for a description of why this works. When |\at| is expanded, it works +% out that |\protect| is either |\noexpand| or |\@unexpandable@protect|, and +% becomes |\at@protect@noexpand|. Because of the |\noexpand| tokens, this +% stops being expanded once it reaches $\fbox{\box0}\,|@|_{11}\,x$ (where +% $x$ is the token immediately following the $|@|_{13}$ character). If this +% is expanded again, for example in another |\edef|, or in a |\write| or a +% |\mark|, the |\@at@| wakes up, gobbles the following |@| (whatever catcode +% it is -- there may be intervening |\write| and |\input| commands) and +% becomes |\at|, and the whole thing can start over again. +% +% \end{macro} +% +% +% \subsection{Enabling and disabling @-commands} +% +% \begin{macro}{\aton} +% +% We define the |\aton| command to enable all of our magic. We store +% the old catcode in the |\atoff| command, make `@@' active, and make it +% do the stuff. +% +% \begin{macrocode} +\def\aton{% + \ifnum\catcode`\@=\active\else% + \edef\atoff{\catcode`\noexpand\@\the\catcode`\@}% + \catcode`\@\active% + \lccode`\~`\@% + \lowercase{\let~\at}% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\atoff} +% +% The |\atoff| command makes `@@' do the stuff it's meant to. We remember +% the old catcode and revert to it. This is largely unnecessary. +% +% \begin{macrocode} +\def\atoff{\catcode`\@12} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\makeatother} +% +% Now we make our active `@@' the default outside of package files. +% +% \begin{macrocode} +\let\makeatother\aton +% \end{macrocode} +% +% \end{macro} +% +% And we must make sure that the user can use all of our nice commands. +% Once the document starts, we allow @-commands. +% +% \begin{macrocode} +\AtBeginDocument{\aton} +% \end{macrocode} +% +% \begin{macro}{\dospecials} +% \begin{macro}{\@sanitize} +% +% We must add the `@@' character to the various specials lists. +% +% \begin{macrocode} +\expandafter\def\expandafter\dospecials\expandafter{\dospecials\do\@} +\expandafter\def\expandafter\@sanitize\expandafter{% + \@sanitize\@makeother\@} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% +% \subsection{Default @-commands} +% +% We define some trivial examples to get the user going. +% +% \begin{macrocode} +\expandafter\chardef\csname at.@\endcsname=`\@ +\atdef*#1*{\ifmmode\mathbf{#1}\else\textbf{#1}\fi} +\atdef/#1/{\ifmmode\mathit{#1}\else\emph{#1}\fi} +\atlet i=\index +\atdef I#1{#1\index{#1}} +%</package> +% \end{macrocode} +% +% \hfill Mark Wooding, \today +% +% \Finale +% +\endinput diff --git a/Master/texmf-dist/source/latex/mdwtools/cmtt.dtx b/Master/texmf-dist/source/latex/mdwtools/cmtt.dtx new file mode 100644 index 00000000000..8ae706f77e2 --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/cmtt.dtx @@ -0,0 +1,520 @@ +% \begin{meta-comment} +% +% $Id: cmtt.dtx,v 1.1 1996/11/19 20:47:55 mdw Exp $ +% +% Nicer handling of the Computer Modern Typewriter font +% +% (c) 1996 Mark Wooding +% +%----- Revision history ----------------------------------------------------- +% +% $Log: cmtt.dtx,v $ +% Revision 1.1 1996/11/19 20:47:55 mdw +% Initial revision +% +% +% \end{meta-comment} +% +% \begin{meta-comment} <general public licence> +%% +%% mdwlist package -- various list-related things +%% Copyright (c) 1996 Mark Wooding +%% +%% This program is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation; either version 2 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program; if not, write to the Free Software +%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +%% +% \end{meta-comment} +% +% +% \begin{meta-comment} <Package preambles> +%<+sty>\NeedsTeXFormat{LaTeX2e} +%<+sty>\ProvidesPackage{cmtt} +%<+fd>\ProvidesFile{mTTcmtt.fd} +%<+def>\ProvidesFile{mTTcmtt.def} +%<+sty|fd|def> [1996/05/25 1.1 Handing of the cmtt font] +% \end{meta-comment} +% +% ^^A \CheckSum{174} +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%% +% +% \begin{meta-comment} +% +%<*driver> +\input{mdwtools} +\describespackage{cmtt} +\mdwdoc +%</driver> +% +% \end{meta-comment} +% +%^^A------------------------------------------------------------------------- +% \section{Introductory note} +% +% \LaTeX\ has a rather cunning encoding handling system, which makes funny +% commands like accents work properly independent of the current font's +% actual layout. While this works rather well most of the time, the standard +% \mtt{tt} font has been rather left out of things. \LaTeX\ assumes that +% the Computer Modern Typewriter fonts have exactly the same layout as the +% more normal Computer Modern Roman family (i.e., that both conform to the +% \mtt{OT1} encoding). This plainly isn't true, since the Typewriter font +% contains a bunch of standard ASCII characters which are omitted from the +% standard Computer Modern fonts, such as curly braces \mtt{\{} and \mtt{\}}, +% and the backslash \mtt{\\}; these are usually dug up from the maths fonts, +% which looks fine in normal text, but looks really odd in monospace text. +% Compare `\texttt{\textbackslash begin\{document\}}' to +% `\mtt{\\begin\{document\}}', for example. +% +% There are two possibilities for dealing with this problem. One is to use +% the \mtt{\\verb} command, which works since all the extra characters in +% the Typewriter font are in the correct places, or use the DC~fonts, which +% have a proper encoding set up which contains all of these special +% characters anyway. +% +% Neither of these solutions is perfect. Using \mtt{\\verb} causes all +% manner of little niggly problems: you can't use it in footnotes or +% section headings, for example. (There are of course workarounds for this +% sort of thing: the author's \package{footnote} package provides a +% \env{footnote} environment which will allow verbatim text, and verbatim +% text in section headings can be achieved if one is sufficiently +% \TeX nical.) Using the DC~fonts is fine, although you actually lose a +% glyph or two. As far as the author is aware, the character \mtt{\'} (an +% `unsexed' single quote) is not present in the \mtt{T1}-encoded version of +% Computer Modern Typewriter, although it is hidden away in the original +% version. The author has found a need for this character in computer +% listings, and was horrified to discover that it was replaced by a German +% single quote character (\mtt{\\quotesinglbase}). +% +% This package defines a special encoding for the Computer Modern Typewriter +% font, so that documents can take advantage of its ASCII characters without +% resorting to verbatim text. (The main advantage of the DC~fonts, that +% words containing accents can be hyohenated, doesn't really apply to the +% Typewriter font, since it doesn't allow hyphenation by default anyway.) +% +% There are several files you'll need to create: +% \begin{description} \def\makelabel#1{\hskip\labelsep\mttfamily#1\hfil} +% +% \item [cmtt.sty] tells \LaTeX\ that there's a new encoding. It also +% provides some options for customising some aspects of the +% encoding, and defines some useful commands. +% +% \item [mTTenc.def] describes the encoding to \LaTeX: it sets up all the +% appropriate text commands so that they produce beautiful results. +% +% \item [mTTcmtt.fd] describes the re-encoded version of the font. This +% is more or less a copy of the file \mtt{OT1cmtt.fd}. +% +% \end{description} +% +% The package accepts some options which may be useful: +% \begin{description} \def\makelabel#1{\hskip\labelsep\sffamily#1\hfil} +% +% \item [override] overrides the meaning of the \mtt{\\ttfamily} command +% (and therefore also the \mtt{\\texttt} command too), making it the +% same as the new \mtt{\\mttfamily} command. This isn't the default +% just in case the change breaks something in an unexpected way. +% +% \item [t1] informs the package that you're using the \mtt{T1} encoding, +% and therefore can borrow some accented characters from the DC~version +% of Computer Modern Typewriter. This will probably be unnecessary, +% since the package attempts to work out what to do all by itself. +% +% \item [ot1] forces the package \emph{not} to use the DC~version of the +% Computer Modern Typewriter font for funny accents. Only use this +% option if the package thinks it should use the DC~Typewriter font +% when it shouldn't. +% +% \end{description} +% +% \DescribeMacro{\mttfamily} +% The command \mtt{\\mttfamily} selects the properly-encoded Typewriter +% font. It's a declaration which works just like the \mtt{\\ttfamily} +% command, except that comamnds like \mtt{\\\}} and \mtt{\\\_} use the +% characters from the font rather than choosing odd-looking versions from +% the maths fonts. All of the accent commands still work properly. In fact, +% some accent commands which didn't work before have been fixed. For +% example, saying `\mtt{\\texttt\{P\\'al Erd\\H os\}}' would produce +% something truly appalling like `\texttt{P\'al Erd\H os}', which is +% obviously ghastly. The new encoding handles this properly, and produces +% `\textmtt{P\'al Erd\H os}'.\footnote{ +% This isn't quite perfect. The accent, which isn't actually present in +% the Typewriter font, is taken from the Computer Modern bold font, but +% it doesn't look too bad. However, if you pass the option \textsf{t1} +% to the \package{cmtt} package when you load it, the accent will be taken +% from the DC~Typewriter font, and it will look totally wonderful.} +% +% \DescribeMacro{\textmtt} +% Font changing commands are much more convenient than th declarations, +% so a command \mtt{\\textmtt} is provided: it just typesets its argument +% in the re-encoded Typewriter font. +% +% \DescribeMacro{\mtt} +% Rather more excitingly, the \mtt{\\mtt} command allows you to generate +% almost-verbatim text very easily, without any of the restrictions of +% the \mtt{\\verb} command. This command was inspired by something which +% David Carlisle said to me in an email correspondence regarding the +% overuse of verbatim commands. +% +% \mtt{\\mtt} redefines several `short' commands to typeset the obvious +% characters. The complete list is shown below: there are some oddities, +% so watch out. +% +% ^^A This is an evil table. See if I care. (This is based on lots of +% ^^A hacking I did in glyphs.tex, but a good deal less horrible.) +% +% \medskip +% \hbox to \hsize\bgroup +% \hfil\vbox\bgroup +% \def\ex#1#2{\strut +% \enskip +% \mtt{\\\char`#2}\quad\hfil% +% \mtt{#2}\enskip} +% \def\h{\noalign{\hrule}} +% \def\v{height2pt&\omit&&\omit&&\omit&&\omit&&\omit&\cr} +% \let~\relax +% \offinterlineskip +% \ialign\bgroup&\vrule#&\ex#\cr \h\v +% &~\\&&~\{&&~\}&&~\_&&~\^&\cr \v\h\v +% &~\$&&~\%&&~\&&&~\#&&~\~&\cr \v\h\v +% &~\"&&~\'&&~\ &&~\|&&\omit\hfil&\cr \v\h +% \egroup\egroup +% \hfil\egroup +% \medskip +% +% As well as redefining these commands, \mtt{\\mtt} will endeavour to make +% single special characters display themselves in a verbatim-like way. This +% only works on `active' characters (like \mtt{~}), and \mtt{\\mtt} makes +% no attempt to change the category codes of any characters. +% +% Among other things, you'll probably noticed that several accent-making +% commands have been redefined. You can still use these accents through +% the \mtt{\\a} command, by saying \mtt{\\a'}, \mtt{\\a\^} and so on, +% as in the \env{tabbing} environment. +% +% There are also some oddities in the table: \mtt{\|} and \mtt{\"} can be +% accessed easily without playing with silly commands. Well, that's almost +% the case: these two characters are both often used as `short' verbatim +% commands, so they are forced back to their normal meanings so you can +% type them. +% +% Finally, a word on spacing. The \mtt{\\\ } command has been hijacked +% to produce a funny `visible space' character. You can still produce +% multiple spaces by saying something like `\mtt{\ \{\}\ \{\}}\dots\mtt{\ }', +% which is a bit contrived, but that's tough. Also, \mtt{~} has been stolen +% so that you can type \mtt{~} characters (e.g., in URLs), so the only +% way you can tpye a nonbreaking space is by using the \mtt{\\nobreakspace} +% command, which is a bit of a mouthful. There's an abbreviation, though: +% \mtt{\\nbsp} now means exactly the same thing. +% +% Was that not all supremely useful? Oh, just a note: this document doesn't +% use a single verbatim command or environment (except in the listings, +% where it's unavoidable) -- it's all done with \mtt{\\mtt}. +% +% \implementation +% +% \section{Implementation} +% +% \subsection{The package} +% +% \begin{macrocode} +%<*sty> +% \end{macrocode} +% +% I'll start with some options handling. +% +% \begin{macrocode} +\newif\ifcmtt@override +\newif\ifcmtt@dcfonts +\def\@tempa{T1}\ifx\encodingdefault\@tempa + \cmtt@dcfontstrue +\fi +\DeclareOption{override}{\cmtt@overridetrue} +\DeclareOption{t1}{\cmtt@dcfontstrue} +\DeclareOption{ot1}{\cmtt@dcfontsfalse} +\ProcessOptions +% \end{macrocode} +% +% This bit is really trivial. I'll just declare the font encoding. Oh, that +% was easy. +% +% \begin{macrocode} +\DeclareFontEncoding{mTT}{}{} +% \end{macrocode} +% +% Wait: there's a problem. \LaTeX\ will now complain bitterly that it can't +% find the font \mtt{mTT/cmr/m/n}, which is readonable, since I haven't +% declared any such font. The following line should sort this out, +% +% \begin{macrocode} +\DeclareFontSubstitution{mTT}{cmtt}{m}{n} +% \end{macrocode} +% +% Now I'd better load all the text commands I'll need when in this funny +% font variant. +% +% \begin{macrocode} +\input{mTTenc.def} +% \end{macrocode} +% +% \begin{macro}{\mttfamily} +% \begin{macro}{\textmtt} +% +% Finally, I'll need to define a command which switches to this funny font, +% and a \mtt{\\text}\dots\ command for it. +% +% \begin{macrocode} +\DeclareRobustCommand{\mttfamily}{% + \fontencoding{mTT}\fontfamily{\ttdefault}\selectfont% +} +\DeclareTextFontCommand{\textmtt}{\mttfamily} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% +% If an override was requested, make \mtt{\\ttfamily} the same as +% \mtt{\\mttfamily}. +% +% \begin{macrocode} +\ifcmtt@override + \let\ttfamily\mttfamily +\fi +% \end{macrocode} +% +% Well, that's all that's needed for the font definition. Here's a command +% which will typeset its argument in the typewriter font, allowing easy +% access to all the funny characters, and printing them properly in the +% correct font (which \mtt{\\\{} doesn't do, for example). +% +% \begin{macro}{\mtt@setchar} +% +% This macro assigns the given meaning to the given control sequence. Also, +% if the character named in the control sequence is currently set active, +% it will set the active meaning of the character to the same value. +% +% \begin{macrocode} +\def\mtt@setchar#1#2{% + \ifx#1#2\chardef#1`#1\else\let#1#2\fi% + \ifnum\catcode`#1=13% + \begingroup% + \lccode`\~=`#1% + \lowercase{\endgroup\let~#1}% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\mtt@chars} +% +% This macro lists the various control sequences which should be set up, +% so that they can be easily added to. +% +% \begin{macrocode} +\def\mtt@chars{% + \do\#\#% + \do\%\%% + \do\&\&% + \do\^\^% + \do\~\~% + \do\'\textquotesingl% + \do\"\textquotedbl% + \do\|\textbar% + \do\$\textdollar% + \do\_\textunderscore% + \do\{\textbraceleft% + \do\}\textbraceright% + \do\\\textbackslash% + \do\ \textvisiblespace% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\mtt@do} +% +% This just sets up all the special characters listed above. It's a simple +% abbreviation, really. +% +% \begin{macrocode} +\def\mtt@do{\let\do\mtt@setchar\mtt@chars} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\mtt} +% +% And finally, the macro itself. Ta-da! +% +% \begin{macrocode} +\DeclareRobustCommand\mtt[1]{\textmtt{\mtt@do#1}} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\@tabacckludge} +% +% The otherwise almost totally perfect \mtt{\\@tabacckludge} gets very +% upset when its argument is an active character. (If you're wondering, +% this is the command which is responsible for the behaviour of the \mtt{\\a} +% command.) Adding a \mtt{\\string} makes everything work perfectly. +% +% \begin{macrocode} +\def\@tabacckludge#1{% + \expandafter\@changed@cmd\csname\string#1\endcsname\relax% +} +\let\a\@tabacckludge +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\nbsp} +% +% Make an abbreviation for \mtt{\\nobreakspace}. +% +% \begin{macrocode} +\let\nbsp\nobreakspace +% \end{macrocode} +% +% \end{macro} +% +% I think that's all that I have to do for the package. If there's any +% more to do, I'll add it later. +% +% \begin{macrocode} +%</sty> +% \end{macrocode} +% +% +% \subsection{The font definition file} +% +% This is obviously copied almost verbatim from the file \mtt{OT1cmtt.fd}. +% +% \begin{macrocode} +%<*fd> +\DeclareFontFamily{mTT}{cmtt}{\hyphenchar\font\m@ne} +\DeclareFontShape{mTT}{cmtt}{m}{n}{ + <5> <6> <7> <8> cmtt8 + <9> cmtt9 + <10> <10.95> cmtt10 + <12> <14.4> <17.28> <20.74> <24.88> cmtt12 +}{} +\DeclareFontShape{mTT}{cmtt}{m}{it}{ + <5> <6> <7> <8> <9> <10> <10.95> <12> <14.4> <17.28> <20.74> <24.88> + cmitt10 +}{} +\DeclareFontShape{mTT}{cmtt}{m}{sl}{ + <5> <6> <7> <8> <9> <10> <10.95> <12> <14.4> <17.28> <20.74> <24.88> + cmsltt10 +}{} +\DeclareFontShape{mTT}{cmtt}{m}{sc}{ + <5> <6> <7> <8> <9> <10> <10.95> <12> <14.4> <17.28> <20.74> <24.88> + cmtcsc10 +}{} +\DeclareFontShape{mTT}{cmtt}{m}{ui} {<->sub * cmtt/m/it} {} +\DeclareFontShape{mTT}{cmtt}{bx}{n} {<->sub * cmtt/m/n} {} +\DeclareFontShape{mTT}{cmtt}{bx}{it} {<->sub * cmtt/m/it} {} +\DeclareFontShape{mTT}{cmtt}{bx}{ui} {<->sub * cmtt/m/it} {} +%</fd> +% \end{macrocode} +% +% +% \subsection{The encoding definitions file} +% +% I've saved the trickiest bit until last. This file defines the mappings +% from text commands to glyphs in the font. +% +% \begin{macrocode} +%<*def> +% \end{macrocode} +% +% First for some fun with accents. The |cmtt| font doesn't contain all of +% the accents which the other Computer Modern fonts do, because those slots +% contain the standard ASCII characters which usually have to be `borrowed' +% from the maths fonts. +% +% Anyway, there's a load which don't need any special treatment. These are +% chosen from the \mtt{OT1} encoding by default anyway, so I needn't +% bother unless I'm really bothered about speed. I'm not, so I'll save +% the memory. +% +% Following the example of the \TeX book, I'll use the bold roman font +% for accents, so that they don't look really spindly. This is actually +% remarkably difficult to do, because the \textsf{NFSS} keeps getting in +% the way. I'll look after the old font name in a macro (it's handy that +% \textsf{NFSS} maintains this for me) and change to a known font, do the +% accent, change font back again, do the argument to the accent, and then +% close the group I did all of this in, so that no-one else notices what a +% naughty chap I am, really. This is startlingly evil. +% +% \begin{macrocode} +\def\cmtt@accent#1#2{{% + \let\@old@font\font@name% + \ifcmtt@dcfonts% + \fontencoding{T1}\selectfont% + \else% + \usefont{OT1}{cmr}{bx}{n}% + \fi% + #1{\@old@font#2}% +}} +% \end{macrocode} +% +% And now for the actual offending accents. +% +% \begin{macrocode} +\DeclareTextCommand{\H}{mTT}{\cmtt@accent\H} +\DeclareTextCommand{\.}{mTT}{\cmtt@accent\.} +% \end{macrocode} +% +% The `under' accents are all OK, so I shan't bother to define them either. +% Similarly, lots of the text symbol commands are fine as they are by +% default and I don't need to try and define them again. +% +% This, then, is the remaining commands which really need sorting out. +% (By the way, the only reason I've redefined \mtt{\\textellipsis} is +% because otherwise it will mess up the nice monospacing.) +% +% \begin{macrocode} +\DeclareTextSymbol{\textbackslash}{mTT}{92} +\DeclareTextSymbol{\textbar}{mTT}{124} +\DeclareTextSymbol{\textbraceleft}{mTT}{123} +\DeclareTextSymbol{\textbraceright}{mTT}{125} +\DeclareTextSymbol{\textless}{mTT}{60} +\DeclareTextSymbol{\textgreater}{mTT}{62} +\DeclareTextSymbol{\textunderscore}{mTT}{95} +\DeclareTextSymbol{\textvisiblespace}{mTT}{32} +\DeclareTextCommand{\textellipsis}{mTT}{...} +\DeclareTextSymbol{\textquotedbl}{mTT}{34} +\DeclareTextSymbol{\textquotesingl}{mTT}{13} +% \end{macrocode} +% +% That's all there is. Please return to your homes. +% +% \Finale +% +\endinput diff --git a/Master/texmf-dist/source/latex/mdwtools/doafter.dtx b/Master/texmf-dist/source/latex/mdwtools/doafter.dtx new file mode 100644 index 00000000000..8642bbba1e9 --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/doafter.dtx @@ -0,0 +1,516 @@ +% \begin{meta-comment} +% +% $Id: doafter.dtx,v 1.2 1996/11/19 20:49:08 mdw Exp $ +% +% Insert tokens to be read after a group has been processed +% +% (c) 1996 Peter Schmitt and Mark Wooding +% +%----- Revision history ----------------------------------------------------- +% +% $Log: doafter.dtx,v $ +% Revision 1.2 1996/11/19 20:49:08 mdw +% Entered into RCS +% +% +% \end{meta-comment} +% +% \begin{meta-comment} <general public licence> +%% +%% doafter package -- insert a token really after a group +%% Copyright (c) 1996 Peter Schmitt and Mark Wooding +%<*package> +%% +%% This program is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation; either version 2 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program; if not, write to the Free Software +%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +%</package> +%% +% \end{meta-comment} +% +% \begin{meta-comment} <Package preamble> +%<+latex2e>\NeedsTeXFormat{LaTeX2e} +%<+latex2e>\ProvidesPackage{doafter} +%<+latex2e> [1996/05/08 1.2 Aftergroup hacking (PS/MDW)] +% \end{meta-comment} +% +% \CheckSum{259} +%\iffalse +%<*package> +%\fi +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%% +%\iffalse +%</package> +%\fi +% +% \begin{meta-comment} <driver> +% +%<*driver> +\input{mdwtools} +\describespackage{doafter} +\author{Peter Schmitt\thanks{% + Peter came up with the basic implementation after I posed the problem + in the \texttt{comp.text.tex} newsgroup. I fixed some really piddly little + things, to improve it a bit, wrote the documentation, and turned the code + into a nice \package{doc}ced package. Then Peter gave me an updated + version, and I upgraded this from memory. Then he gave me some more tweaks + which I haven't incorporated.} + \and Mark Wooding} +\def\author#1{} +\mdwdoc +%</driver> +% +% \end{meta-comment} +% +% \section{Description} +% +% \subsection{What it's all about} +% +% \DescribeMacro{\doafter} +% It's common for the \TeX\ primitive |\aftergroup| to be used to `tidy up' +% after a group. For example, \LaTeX's colour handling uses this to insert +% appropriate |\special|s when the scope of a colour change ends. This +% causes several problems, though; for example, extra grouping must be added +% within boxes to ensure that the |\special|s don't `leak' out of their box +% and appear in odd places in the document. \LaTeX\ usually solves this +% problem by reading the box contents as an argument, although this isn't +% particularly desirable. The |\doafter| macro provided here will solve the +% problem in a different way, by allowing a macro to regain control after +% all the |\aftergroup| things have been processed. +% +% The macro works like this: +% \begin{grammar} +% <doafter-cmd> ::= \[[ +% "\\doafter" <token> <group> +% \]] +% \end{grammar} +% The \<token> can be any token you like, except an explicit braces, since +% it's read as an undelimited macro argument. The \<group> is a normal +% \TeX\ group, surrounded by either implicit or explicit braces, or by +% |\begingroup| and |\endgroup| tokens. Once the final closing token of the +% \<group> is read, and any tokens saved up by |\aftergroup| have been +% processed, the \<token> is inserted and processed. Under normal +% circumstances, this will be a macro. +% +% There are some subtle problems with the current implementation, which you +% may need to be aware of: +% +% \begin{itemize} +% +% \item Since we're inserting things after all the |\aftergroup| tokens, +% those tokens might read something they're not expecting if they try +% to look ahead at the text after the group (e.g., with |\futurelet|). +% This is obviously totally unavoidable. +% +% \item Implicit braces (like |\bgroup| and |\egroup|) inserted using +% |\aftergroup| may be turned into \emph{explicit} $|{|_1$ and $|}|_2$ +% characters within a |\doafter| group. This can cause probems under +% very specialised circumstances. The names |\bgroup| and |\egroup| +% are treated specially, and they will work normally (remaining as +% implicit braces). This should minimise problems caused by this +% slight difference. (This only applies to the last |\aftergroup| +% token in a group.) +% +% \item To handle the |\aftergroup| tokens properly, |\doafter| has to insert +% some |\aftergroup| tokens of its own. It will then process the +% other tokens some more, and set them up to be read again. This does +% mean that after the group ends, some assignments and other `stomach +% operations' will be performed, which may cause problems in +% alignments and similar places. +% +% \end{itemize} +% +% +% \subsection{Package options} +% +% There are a fair few \textsf{docstrip} options provided by this packge: +% +% \begin{description} +% \item [driver] extracts the documentation driver. This isn't usually +% necessary. +% \item [package] extracts the code as a standalone package, formatted for +% either \LaTeXe\ or Plain~\TeX. +% \item [latex2e] inserts extra identification code for a \LaTeXe\ package. +% \item [plain] inserts some extra code for a Plain \TeX\ package. +% \item [macro] just extracts the raw code, for inclusion in another package. +% \item [test] extracts some code for testing the current implementation. +% \end{description} +% +% +% \implementation +% +% \section{Implementation} +% +% \subsection{The main macro} +% +% We start outputting code here. If this is a Plain~\TeX\ package, we must +% make \lit{@} into a letter. +% +% \begin{macrocode} +%<*macro|package> +%<+plain>\catcode`\@=11 +% \end{macrocode} +% +% \begin{macro}{\doafter} +% +% The idea is to say \syntax{"\\doafter" <token> <group>} and expect the +% \synt{token} to be processed after the group has finished its stuff, +% even if it contains |\aftergroup| things. My eternal gratitude goes to +% Peter Schmitt, who came up with most of the solution implemented here; +% I've just tidied up some very minor niggles and things later. +% +% Let's start with some preamble. I'll save the (hopefully) primitive +% |\aftergroup| in a different token. +% +% \begin{macrocode} +\let\@@aftergroup\aftergroup +% \end{macrocode} +% +% Now to define the `user' interface. It takes a normal undelimited +% argument, although this must be a single token; otherwise eveything will +% go wrong. It assumes that the token following is some kind of group +% opening thing (an explicit or implicit character with catcode~1, or +% a |\begingroup| token). To make this work, I'll save the token, +% together with an |\@@aftergroup| (to save an |\expandafter| later) in +% a temporary macro which no-one will mind me using, and then look ahead at +% the beginning-group token. +% +% \begin{macrocode} +\def\doafter#1{% + \def\@tempa{\@@aftergroup#1}% + \afterassignment\doafter@i\let\@let@token% +} +% \end{macrocode} +% +% I now have the token in |\@let@token|, so I'll put that in. I'll then +% make |\aftergroup| do my thing rather than the normal thing, and queue +% the tokens |\@prepare@after| and the |\doafter| argument for later use. +% +% \begin{macrocode} +\def\doafter@i{% + \@let@token% + \let\aftergroup\@my@aftergroup% + \@@aftergroup\@prepare@after\@tempa% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\@my@aftergroup} +% +% Now the cleverness begins. We keep two macros (Peter's original used +% count registers) which keep counts of the numbers of |\aftergroup|s, +% both locally and globally. Let's call the local counter~$n$ and the +% global one $N$. Every time we get a call to our |\aftergroup| hack, +% we set~$n := n+1$ and~$N := n$, and leave the token given to us for later +% processing. When we actually process an |\aftergroup| token properly, +% set~$N := N-1$ to indicate that it's been handled; when they're all done, +% we'll have $N=n$, which is exactly what we'd have if there weren't any +% to begin with. +% +% \begin{macrocode} +\def\ag@cnt@local{0 } +\let\ag@cnt@global\ag@cnt@local +% \end{macrocode} +% +% Now we come to the definition of my version of |\aftergroup|. I'll just +% add the token |\@after@token| before every |\aftergroup| token I find. +% This means there's two calls to |\aftergroup| for every one the user makes, +% but these things aren't all that common, so it's OK really. I'll also +% bump the local counter, and synchronise them. +% +% \begin{macrocode} +\def\@my@aftergroup{% + \begingroup% + \count@\ag@cnt@local% + \advance\count@\@ne% + \xdef\ag@cnt@global{\the\count@\space}% + \endgroup% + \let\ag@cnt@local\ag@cnt@global% + \@@aftergroup\@after@token\@@aftergroup% +} +% \end{macrocode} +% +% \end{macro} +% +% Now what does |\@after@token| we inserted above actually do? Well, this +% is more exciting. There are actually two different variants of the +% macro, which are used at different times. +% +% \begin{macro}{\@after@token} +% +% The default |\@after@token| starts a group, which will `catch' +% |\aftergroup| tokens which I throw at it. I put the two counters into +% some scratch count registers. (There's a slight problem here: Plain \TeX\ +% only gives us one. For the sake of evilness I'll use |\clubpenalty| as the +% other one. Eeeek.) I then redefine |\@after@token| to the second +% variant, and execute it. The |\@start@after@group| macro starts the +% group, because this code is shared with |\@prepare@after| below. +% +% \begin{macrocode} +\def\@after@token{% + \@start@after@group% + \@after@token% +} +\def\@start@after@group{% + \begingroup% + \count@\ag@cnt@global% + \clubpenalty\ag@cnt@local% + \let\@after@token\@after@token@i% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\@after@token@i} +% +% I have $|\count@| = N$ and $|\@tempcnta| = n$. I'll decrement~$N$, +% and if I have $N = n$, I know that this is the last token to do, so I +% must insert an |\@after@all| after the token. This will close the group, +% and maybe insert the original |\doafter| token if appropriate. +% +% \begin{macrocode} +\def\@after@token@i{% + \advance\count@\m@ne% + \ifnum\count@=\clubpenalty% + \global\let\ag@cnt@global\ag@cnt@local% + \expandafter\@after@aftertoken\expandafter\@after@all% + \else% + \expandafter\@@aftergroup% + \fi% +} +% \end{macrocode} +% +% Finally, establish a default meaning for |\@after@all|. +% +% \begin{macrocode} +\let\@after@all\endgroup +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\@prepare@after} +% +% If this group is handled by |\doafter|, then the first |\aftergroup| token +% isn't |\@after@token|; it's |\@prepare@after|. +% +% There are some extra cases to deal with: +% \begin{itemize} +% \item If $N=n$ then there were no |\aftergroup| tokens, so we have an easy +% job. I'll just let the token do its stuff directly. +% \item Otherwise, $N>n$, and there are |\aftergroup| tokens. I'll open +% the group, and let |\@after@token| do all the handling. +% \end{itemize} +% +% \begin{macrocode} +\def\@prepare@after{% + \ifx\ag@cnt@local\ag@cnt@global\else% + \expandafter\@prepare@after@i% + \fi% +} +\def\@prepare@after@i#1{% + \@start@after@group% + \def\@after@all{\@@aftergroup#1\endgroup}% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\@after@aftertoken} +% +% This is where all the difficulty lies. The next token in the stream is +% an |\aftergroup| one, which could be more or less anything. We have an +% argument, which is some code to do \emph{after} the token has been +% |\aftergroup|ed. +% +% If the token is anything other than a brace (i.e., an explicit character +% of category~1 or~2) then I have no problem; I can scoop up the token with +% an undelimited macro argument. But the only way I can decide if this token +% is a brace (nondestructively) is with |\futurelet|, which makes the token +% implicit, so I can't decide whether it's really dangerous. +% +% There is a possible way of doing this\footnote{Due to Peter Schmitt, +% again.} which relates to nobbling the offending token with |\string| and +% sifting through the results. The problem here involves scooping up all the +% tokens of a |\string|ed control sequence, which may turn out to be +% `|\csname\endcsname|' or something equally horrid. +% +% The solution I've used is much simpler: I'll change |\bgroup| and |\egroup| +% to stop them from being implicit braces before comparing. +% +% \begin{macrocode} +\def\@after@aftertoken#1{% + \let\bgroup\relax\let\egroup\relax% + \toks@{#1}% + \futurelet\@let@token\@after@aftertoken@i% +} +\def\@after@aftertoken@i{% + \ifcat\noexpand\@let@token{% + \@@aftergroup{% + \else\ifcat\noexpand\@let@token}% + \@@aftergroup}% + \else% + \def\@tempa##1{\@@aftergroup##1\the\toks@}% + \expandafter\expandafter\expandafter\@tempa% + \fi\fi% +} +% \end{macrocode} +% +% \end{macro} +% +% +% Phew! +% +% \begin{macrocode} +%<+plain>\catcode`\@=12 +%</macro|package> +% \end{macrocode} +% +% \subsection{Test code} +% +% The following code gives |\doafter| a bit of a testing. It's based on +% the test suite I gave to comp.text.tex, although it's been improved a +% little since then. +% +% The first thing to do is define a control sequence with an \lit{@} sign +% in its name, so we can test catcode changes. This also hides an +% |\aftergroup| within a macro, making life more difficult for prospective +% implementations. +% +% \begin{macrocode} +%<*test> +\catcode`\@=11 +\def\at@name{\aftergroup\saynine} +\def\saynine{\say{ix}} +\catcode`\@=12 +% \end{macrocode} +% +% Now define a command to write a string to the terminal. The name will +% probably be familiar to REXX hackers. +% +% \begin{macrocode} +\def\say{\immediate\write16} +% \end{macrocode} +% +% Test one: This is really easy; it just tests that the thing works at all. +% If your implementation fails this, it's time for a major rethink. +% +% \begin{macrocode} +\say{Test one... (1--2)} +\def\saytwo{\say{ii}} +\doafter\saytwo{\say{i}} +% \end{macrocode} +% +% Test two: Does |\aftergroup| work? +% +% \begin{macrocode} +\say{Test two... (1--4)} +\def\saythree{\say{iii}} +\def\sayfour{\say{iv}} +\doafter\sayfour{\say{i}\aftergroup\saythree\say{ii}} +% \end{macrocode} +% +% Test three: Test braces and |\iffalse| working as they should. Several +% proposed solutions based on |\write|ing the group to a file get upset by +% this test, although I forgot to include it in the torture test. It also +% tests whether literal braces can be |\aftergroup|ed properly. (Added a new +% test here, making sure that |\bgroup| is left as an implicit token.) +% +% \begin{macrocode} +\say{Test three... (1--4, `\string\bgroup', 5)} +\def\sayfive{\say{v}} +\doafter\sayfive{% + \say{i}% + \aftergroup\say% + \aftergroup{% + \aftergroup\romannumeral\aftergroup3% + \aftergroup}% + \iffalse}\fi% + \aftergroup\def% + \aftergroup\sayfouretc% + \aftergroup{% + \aftergroup\say% + \aftergroup{% + \aftergroup i% + \aftergroup v% + \aftergroup}% + \aftergroup\say% + \aftergroup{% + \aftergroup\string% + \aftergroup\bgroup% + \aftergroup}% + \aftergroup}% + \aftergroup\sayfouretc% + \say{ii}% +} +% \end{macrocode} +% +% Test four: Make sure the implementation isn't leaking things. This just +% makes sure that |\aftergroup| is its normal reasonable self. +% +% \begin{macrocode} +\say{Test four... (1--3)} +{\say{i}\aftergroup\saythree\say{ii}} +% \end{macrocode} +% +% Test five: Nesting, aftergroup, catcodes, grouping. This is the `torture' +% test I gave to comp.text.tex, slightly corrected (oops) and amended. It +% ensures that nested groups and |\doafter|s work properly (the latter is +% actually more likely than might be imagined). +% +% \begin{macrocode} +\say{Test five... (1--14)} +\def\sayten{\say{x}} +\def\saythirteen{\say{xiii}} +\def\sayfourteen{\say{xiv}} +\doafter\sayfourteen\begingroup% + \say{i}% + {\say{ii}\aftergroup\sayfour\say{iii}}% + \def\saynum{\say{viii}}% + \doafter\sayten{% + \say{v}% + \def\saynum{\say{vii}}% + \catcode`\@=11% + \aftergroup\saynum% + \say{vi}% + \at@name% + \saynum% + }% + \say{xi}% + \aftergroup\saythirteen% + \say{xii}% +\endgroup +\end +%</test> +% \end{macrocode} +% +% That's it. All present and correct. +% +% \Finale +% +\endinput diff --git a/Master/texmf-dist/source/latex/mdwtools/footnote.dtx b/Master/texmf-dist/source/latex/mdwtools/footnote.dtx new file mode 100644 index 00000000000..16e94ae2a29 --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/footnote.dtx @@ -0,0 +1,699 @@ +% \begin{meta-comment} +% +% $Id: footnote.dtx,v 1.13 1997/01/28 19:45:16 mdw Exp $ +% +% Save footnotes around boxing environments and things +% +% (c) 1996 Mark Wooding +% +%----- Revision history ----------------------------------------------------- +% +% $Log: footnote.dtx,v $ +% Revision 1.13 1997/01/28 19:45:16 mdw +% Fixed stupid bug in AMS environment handling which stops the thing from +% working properly if you haven't included amsmath. Doh. +% +% Revision 1.12 1997/01/18 00:45:37 mdw +% Fix problems with duplicated footnotes in broken AMS environments which +% typeset things multiple times. This is a nasty kludge. +% +% Revision 1.11 1996/11/19 20:50:05 mdw +% Entered into RCS +% +% +% \end{meta-comment} +% +% \begin{meta-comment} <general public licence> +%% +%% footnote package -- Save footnotes around boxing environments +%% Copyright (c) 1996 Mark Wooding +%<*package> +%% +%% This program is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation; either version 2 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program; if not, write to the Free Software +%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +%</package> +%% +% \end{meta-comment} +% +% \begin{meta-comment} <Package preamble> +%<+package>\NeedsTeXFormat{LaTeX2e} +%<+package>\ProvidesPackage{footnote} +%<+package> [1997/01/28 1.13 Save footnotes around boxes] +% \end{meta-comment} +% +% \CheckSum{327} +%\iffalse +%<*package> +%\fi +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%% +%\iffalse +%</package> +%\fi +% +% \begin{meta-comment} <driver> +% +%<*driver> +\input{mdwtools} +\describespackage{footnote} +\mdwdoc +%</driver> +% +% \end{meta-comment} +% +% \section{User guide} +% +% This package provides some commands for handling footnotes slightly +% better than \LaTeX\ usually does; there are several commands and +% environments (notably |\parbox|, \env{minipage} and \env{tabular} +% \begin{footnote} +% The \package{mdwtab} package, provided in this distribution, handles +% footnotes correctly anyway; it uses an internal version of this package +% to do so. +% \end{footnote}) +% which `trap' footnotes so that they can't escape and appear at the bottom +% of the page. +% +% \DescribeEnv{savenotes} +% The \env{savenotes} environment saves up any footnotes encountered within +% it, and performs them all at the end. +% +% \DescribeMacro{\savenotes} +% \DescribeMacro{\spewnotes} +% If you're defining a command or environment, you can use the |\savenotes| +% command to start saving up footnotes, and the |\spewnotes| command to +% execute them all at the end. Note that |\savenotes| and |\spewnotes| +% enclose a group, so watch out. You can safely nest the commands and +% environments -- they work out if they're already working and behave +% appropriately. +% +% \DescribeEnv{minipage*} +% To help things along a bit, the package provides a $*$-version of the +% \env{minipage} environment, which doesn't trap footnotes for itself (and +% in fact sends any footnotes it contains to the bottom of the page, where +% they belong). +% +% \DescribeMacro{\makesavenoteenv} +% The new \env{minipage$*$} environment was created with a magic command +% called |\makesavenoteenv|. It has a fairly simple syntax: +% +% \begin{grammar} +% <make-save-note-env-cmd> ::= \[[ +% "\\makesavenoteenv" +% \begin{stack} \\ "[" <new-env-name> "]" \end{stack} +% "{" <env-name> "}" +% \]] +% \end{grammar} +% +% Without the optional argument, it redefines the named environment so that +% it handles footnotes correctly. With the optional argument, it makes +% the new environment named by \<new-env-name> into a footnote-friendly +% version of the \<env-name> environment. +% +% \DescribeMacro{\parbox} +% The package also redefines the |\parbox| command so that it works properly +% with footnotes. +% +% \DescribeEnv{footnote} +% The other problem which people tend to experience with footnotes is that +% you can't put verbatim text (with the |\verb| comamnd or the \env{verbatim} +% environment) into the |\footnote| command's argument. This package +% provides a \env{footnote} \emph{environment}, which \emph{does} allow +% verbatim things. You use the environment just like you do the command. +% It's really easy. It even has an optional argument, which works the same +% way. +% +% \DescribeEnv{footnotetext} +% To go with the \env{footnote} environment, there's a \env{footnotetext} +% environment, which just puts the text in the bottom of the page, like +% |\footnotetext| does. +% +% There's a snag with these environments, though. Some other nonstandard +% environments, like \env{tabularx}, try to handle footnotes their own +% way, because they won't work otherwise. The way they do this is not +% compatible with the way that the \env{footnote} and \env{footnotetext} +% environments work, and you will get strange results if you try (there'll +% be odd vertical spacing, and the footnote text may well be incorrect). +% \begin{footnote} +% The solution to this problem is to send mail to David Carlisle persuading +% him to use this package to handle footnotes, rather than doing it his +% way. +% \end{footnote} +% +% \implementation +% +% \section{Implementation} +% +% Most implementations of footnote-saving (in particular, that used in +% the \package{tabularx} and \package{longtable} packages) use a token +% list register to store the footnote text, and then expand it when whatever +% was preventing footnotes (usually a vbox) stops. This is no good at all +% if the footnotes contain things which might not be there by the time the +% expansion occurs. For example, references to things in temporary boxes +% won't work. +% +% This implementation therefore stores the footnotes up in a box register. +% This must be just as valid as using tokens, because all I'm going to do +% at the end is unbox the box). +% +% \begin{macrocode} +%<*macro|package> +\ifx\fn@notes\@@undefined% + \newbox\fn@notes% +\fi +% \end{macrocode} +% +% I'll need a length to tell me how wide the footnotes should be at the +% moment. +% +% \begin{macrocode} +\newdimen\fn@width +% \end{macrocode} +% +% Of course, I can't set this up until I actually start saving footnotes. +% Until then I'll use |\columnwidth| (which works in \package{multicol} +% even though it doesn't have any right to). +% +% \begin{macrocode} +\let\fn@colwidth\columnwidth +% \end{macrocode} +% +% And now a switch to remember if we're already handling footnotes, +% +% \begin{macrocode} +\newif\if@savingnotes +% \end{macrocode} +% +% +% \subsection{Building footnote text} +% +% I need to emulate \LaTeX's footnote handling when I'm putting the notes +% into my box; this is also useful in the verbatim-in-footnotes stuff. +% +% \begin{macro}{\fn@startnote} +% +% Here's how a footnote gets started. Most of the code here is stolen +% from |\@footnotetext|. +% +% \begin{macrocode} +\def\fn@startnote{% + \hsize\fn@colwidth% + \interlinepenalty\interfootnotelinepenalty% + \reset@font\footnotesize% + \floatingpenalty\@MM% Is this right??? + \@parboxrestore% + \protected@edef\@currentlabel{\csname p@\@mpfn\endcsname\@thefnmark}% + \color@begingroup% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\fn@endnote} +% +% Footnotes are finished off by this macro. This is the easy bit. +% +% \begin{macrocode} +\let\fn@endnote\color@endgroup +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Footnote saving} +% +% \begin{macro}{\fn@fntext} +% +% Now to define how to actually do footnotes. I'll just add the notes to +% the bottom of the footnote box I'm building. +% +% There's some hacking added here to handle the case that a footnote is +% in an |\intertext| command within a broken \package{amsmath} alignment +% environment -- otherwise the footnotes get duplicated due to the way that +% that package measures equations. +% \begin{footnote} +% The correct solution of course is to +% implement aligning environments in a sensible way, by building the table +% and leaving penalties describing the intended format, and then pick that +% apart in a postprocessing phase. If I get the time, I'll start working +% on this again. I have a design worked out and the beginnings of an +% implementation, but it's going to be a long time coming. +% \end{footnote} +% +% \begin{macrocode} +\def\fn@fntext#1{% + \ifx\ifmeasuring@\@@undefined% + \expandafter\@secondoftwo\else\expandafter\@iden% + \fi% + {\ifmeasuring@\expandafter\@gobble\else\expandafter\@iden\fi}% + {% + \global\setbox\fn@notes\vbox{% + \unvbox\fn@notes% + \fn@startnote% + \@makefntext{% + \rule\z@\footnotesep% + \ignorespaces% + #1% + \@finalstrut\strutbox% + }% + \fn@endnote% + }% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\savenotes} +% +% The |\savenotes| declaration starts saving footnotes, to be spewed at a +% later date. We'll also remember which counter we're meant to use, and +% redefine the footnotes used by minipages. +% +% The idea here is that we'll gather up footnotes within the environment, +% and output them in whatever format they were being typeset outside the +% environment. +% +% I'll take this a bit at a time. The start is easy: we need a group in +% which to keep our local definitions. +% +% \begin{macrocode} +\def\savenotes{% + \begingroup% +% \end{macrocode} +% +% Now, if I'm already saving footnotes away, I won't bother doing anything +% here. Otherwise I need to start hacking, and set the switch. +% +% \begin{macrocode} + \if@savingnotes\else% + \@savingnotestrue% +% \end{macrocode} +% +% I redefine the |\@footnotetext| command, which is responsible for adding +% a footnote to the appropriate insert. I'll redefine both the current +% version, and \env{minipage}'s specific version, in case there's a nested +% minipage. +% +% \begin{macrocode} + \let\@footnotetext\fn@fntext% + \let\@mpfootnotetext\fn@fntext% +% \end{macrocode} +% +% I'd better make sure my box is empty before I start, and I must set up +% the column width so that later changes (e.g., in \env{minipage}) don't +% upset things too much. +% +% \begin{macrocode} + \fn@width\columnwidth% + \let\fn@colwidth\fn@width% + \global\setbox\fn@notes\box\voidb@x% +% \end{macrocode} +% +% Now for some yuckiness. I want to ensure that \env{minipage} doesn't +% change how footnotes are handled once I've taken charge. I'll store the +% current values of |\thempfn| (which typesets a footnote marker) and +% |\@mpfn| (which contains the name of the current footnote counter). +% +% \begin{macrocode} + \let\fn@thempfn\thempfn% + \let\fn@mpfn\@mpfn% +% \end{macrocode} +% +% The \env{minipage} environment provides a hook, called |\@minipagerestore|. +% Initially it's set to |\relax|, which is unfortunately unexpandable, so if +% I want to add code to it, I must check this possibility. I'll make it +% |\@empty| (which expands to nothing) if it's still |\relax|. Then I'll +% add my code to the hook, to override |\thempfn| and |\@mpfn| set up by +% \env{minipage}. +% +% Note that I can't just force the |mpfootnote| counter to be equal to +% the |footnote| one, because \env{minipage} clears |\c@mpfootnote| to zero +% when it starts. This method will ensure that even so, the current counter +% works OK. +% +% \begin{macrocode} + \ifx\@minipagerestore\relax\let\@minipagerestore\@empty\fi% + \expandafter\def\expandafter\@minipagerestore\expandafter{% + \@minipagerestore% + \let\thempfn\fn@thempfn% + \let\@mpfn\fn@mpfn% + }% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\spewnotes} +% +% Now I can spew out the notes we saved. This is a bit messy, actually. +% Since the standard |\@footnotetext| implementation tries to insert funny +% struts and things, I must be a bit careful. I'll disable all this bits +% which start paragraphs prematurely. +% +% \begin{macrocode} +\def\spewnotes{% + \endgroup% + \if@savingnotes\else\ifvoid\fn@notes\else\begingroup% + \let\@makefntext\@empty% + \let\@finalstrut\@gobble% + \let\rule\@gobbletwo% + \@footnotetext{\unvbox\fn@notes}% + \endgroup\fi\fi% +} +% \end{macrocode} +% +% \end{macro} +% +% Now make an environment, for users. +% +% \begin{macrocode} +\let\endsavenotes\spewnotes +% \end{macrocode} +% +% That's all that needs to be in the shared code section. +% +% \begin{macrocode} +%</macro|package> +%<*package> +% \end{macrocode} +% +% +% \subsection{The \env{footnote} environment} +% +% Since |\footnote| is a command with an argument, things like \env{verbatim} +% are unwelcome in it. Every so often someone on |comp.text.tex| moans +% about it and I post a nasty hack to make it work. However, as a more +% permanent and `official' solution, here's an environment which does the +% job rather better. Lots of this is based on code from my latest attempt +% on the newsgroup. +% +% I'll work on this in a funny order, although I think it's easier to +% understand. First, I'll do some macros for reading the optional argument +% of footnote-related commands. +% +% \begin{macro}{\fn@getmark} +% +% Saying \syntax{"\\fn@getmark{"<default-code>"}{"<cont-code>"}"} will read +% an optional argument giving a value for the footnote counter; if the +% argument isn't there, the \<default-code> is executed, and it's expected +% to set up the appropriate counter to the current value. The footnote +% marker text is stored in the macro |\@thefnmark|, as is conventional for +% \LaTeX's footnote handling macros. Once this is done properly, the +% \<cont-code> is called to continue handling things. +% +% Since the handling of the optional argument plays with the footnote +% counter locally, I'll start a group right now to save some code. Then I'll +% decide what to do based on the presence of the argument. +% +% \begin{macrocode} +\def\fn@getmark#1#2{% + \begingroup% + \@ifnextchar[% + {\fn@getmark@i{#1}}% + {#1\fn@getmark@ii{#2}}% +} +% \end{macrocode} +% +% There's an optional argument, so I need to read it and assign it to the +% footnote counter. +% +% \begin{macrocode} +\def\fn@getmark@i#1[#2]{% + \csname c@\@mpfn\endcsname#2% + \fn@getmark@ii% +} +% \end{macrocode} +% +% Finally, set up the macro properly, and end the group. +% +% \begin{macrocode} +\def\fn@getmark@ii#1{% + \unrestored@protected@xdef\@thefnmark{\thempfn}% + \endgroup% + #1% +} +% \end{macrocode} +% +% \end{macro} +% +% From argument reading, I'll move on to footnote typesetting. +% +% \begin{macro}{\fn@startfntext} +% +% The |\fn@startfntext| macro sets everything up for building the footnote +% in a box register, ready for unboxing into the footnotes insert. The +% |\fn@prefntext| macro is a style hook I'll set up later. +% +% \begin{macrocode} +\def\fn@startfntext{% + \setbox\z@\vbox\bgroup% + \fn@startnote% + \fn@prefntext% + \rule\z@\footnotesep% + \ignorespaces% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\fn@endfntext} +% +% Now I'll end the vbox, and add it to the footnote insertion. Again, I +% must be careful to prevent |\@footnotetext| from adding horizontal mode +% things in bad places. +% +% \begin{macrocode} +\def\fn@endfntext{% + \@finalstrut\strutbox% + \fn@postfntext% + \egroup% + \begingroup% + \let\@makefntext\@empty% + \let\@finalstrut\@gobble% + \let\rule\@gobbletwo% + \@footnotetext{\unvbox\z@}% + \endgroup% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{footnote} +% +% I can now start on the environment proper. First I'll look for an +% optional argument. +% +% \begin{listing} +%\def\footnote{% +% \end{listing} +% +% Oh. I've already come up against the first problem: that name's already +% used. I'd better save the original version. +% +% \begin{macrocode} +\let\fn@latex@@footnote\footnote +% \end{macrocode} +% +% The best way I can think of for seeing if I'm in an environment is to +% look at |\@currenvir|. I'll need something to compare with, then. +% +% \begin{macrocode} +\def\fn@footnote{footnote} +% \end{macrocode} +% +% Now to start properly. |;-)| +% +% \begin{macrocode} +\def\footnote{% + \ifx\@currenvir\fn@footnote% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + {\fn@getmark{\stepcounter\@mpfn}% + {\leavevmode\unskip\@footnotemark\fn@startfntext}}% + {\fn@latex@@footnote}% +} +% \end{macrocode} +% +% Ending the environment is simple. +% +% \begin{macrocode} +\let\endfootnote\fn@endfntext +% \end{macrocode} +% +% \end{environment} +% +% \begin{environment}{footnotetext} +% +% I'll do the same magic as before for |\footnotetext|. +% +% \begin{macrocode} +\def\fn@footnotetext{footnotetext} +\let\fn@latex@@footnotetext\footnotetext +\def\footnotetext{% + \ifx\@currenvir\fn@footnotetext% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + {\fn@getmark{}\fn@startfntext}% + {\fn@latex@@footnotetext}% +} +\let\endfootnotetext\endfootnote +% \end{macrocode} +% +% \end{environment} +% +% \begin{macro}{\fn@prefntext} +% \begin{macro}{\fn@postfntext} +% +% Now for one final problem. The style hook for footnotes is the command +% |\@makefntext|, which takes the footnote text as its argument. Clearly +% this is utterly unsuitable, so I need to split it into two bits, where +% the argument is. This is very tricky, and doesn't deserve to work, +% although it appears to be a good deal more effective than it has any right +% to be. +% +% \begin{macrocode} +\long\def\@tempa#1\@@#2\@@@{\def\fn@prefntext{#1}\def\fn@postfntext{#2}} +\expandafter\@tempa\@makefntext\@@\@@@ +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% +% +% \subsection{Hacking existing environments} +% +% Some existing \LaTeX\ environments ought to have footnote handling but +% don't. Now's our chance. +% +% \begin{macro}{\makesavenoteenv} +% +% The |\makesavenoteenv| command makes an environment save footnotes around +% itself. +% +% It would also be nice to make |\parbox| work with footnotes. I'll do this +% later. +% +% \begin{macrocode} +\def\makesavenoteenv{\@ifnextchar[\fn@msne@ii\fn@msne@i} +% \end{macrocode} +% +% We're meant to redefine the environment. We'll copy it (using |\let|) to +% a magic name, and then pass it on to stage~2. +% +% \begin{macrocode} +\def\fn@msne@i#1{% + \expandafter\let\csname msne$#1\expandafter\endcsname% + \csname #1\endcsname% + \expandafter\let\csname endmsne$#1\expandafter\endcsname% + \csname end#1\endcsname% + \fn@msne@ii[#1]{msne$#1}% +} +% \end{macrocode} +% +% Now we'll define the new environment. The start is really easy, since we +% just need to insert a |\savenotes|. The end is more complex, since we +% need to preserve the |\if@endpe| flag so that |\end| can pick it up. I +% reckon that proper hooks should be added to |\begin| and |\end| so that +% environments can define things to be done outside the main group as +% well as within it; still, we can't all have what we want, can we? +% +% \begin{macrocode} +\def\fn@msne@ii[#1]#2{% + \expandafter\edef\csname#1\endcsname{% + \noexpand\savenotes% + \expandafter\noexpand\csname#2\endcsname% + }% + \expandafter\edef\csname end#1\endcsname{% + \expandafter\noexpand\csname end#2\endcsname% + \noexpand\expandafter% + \noexpand\spewnotes% + \noexpand\if@endpe\noexpand\@endpetrue\noexpand\fi% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{minipage*} +% +% Let's define a \env{minipage$*$} environment which handles footnotes +% nicely. Really easy: +% +% \begin{macrocode} +\makesavenoteenv[minipage*]{minipage} +% \end{macrocode} +% +% \end{environment} +% +% \begin{macro}{\parbox} +% +% Now to alter |\parbox| slightly, so that it handles footnotes properly. +% I'm going to do this fairly inefficiently, because I'm going to try and +% change it as little as possible. +% +% First, I'll save the old |\parbox| command. If I don't find a \lit{*}, +% I'll just call this command. +% +% \begin{macrocode} +\let\fn@parbox\parbox +% \end{macrocode} +% +% This is the clever bit: I don't know how many optional arguments +% Mr~Mittelbach and his chums will add to |\parbox|, so I'll handle any +% number. I'll store them all up in my first argument and call myself +% every time I find a new one. If I run out of optional arguments, +% I'll call the original |\parbox| command, surrounding it with |\savenotes| +% and |\spewnotes|. +% +% \begin{macrocode} +\def\parbox{\@ifnextchar[{\fn@parbox@i{}}{\fn@parbox@ii{}}} +\def\fn@parbox@i#1[#2]{% + \@ifnextchar[{\fn@parbox@i{#1[#2]}}{\fn@parbox@ii{#1[#2]}}% +} +\long\def\fn@parbox@ii#1#2#3{\savenotes\fn@parbox#1{#2}{#3}\spewnotes} +% \end{macrocode} +% +% \end{macro} +% +% Done! +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \hfill Mark Wooding, \today +% +% \Finale +% +\endinput diff --git a/Master/texmf-dist/source/latex/mdwtools/mdwlist.dtx b/Master/texmf-dist/source/latex/mdwtools/mdwlist.dtx new file mode 100644 index 00000000000..40d56f1b95d --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/mdwlist.dtx @@ -0,0 +1,756 @@ +% \begin{meta-comment} +% +% $Id: mdwlist.dtx,v 1.1 1996/11/19 20:52:26 mdw Exp $ +% +% Various list-related things +% +% (c) 1996 Mark Wooding +% +%----- Revision history ----------------------------------------------------- +% +% $Log: mdwlist.dtx,v $ +% Revision 1.1 1996/11/19 20:52:26 mdw +% Initial revision +% +% +% \end{meta-comment} +% +% \begin{meta-comment} <general public licence> +%% +%% mdwlist package -- various list-related things +%% Copyright (c) 1996 Mark Wooding +%% +%% This program is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation; either version 2 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program; if not, write to the Free Software +%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +%% +% \end{meta-comment} +% +% \begin{meta-comment} <Package preambles> +%<+package>\NeedsTeXFormat{LaTeX2e} +%<+package>\ProvidesPackage{mdwlist} +%<+package> [1996/05/02 1.1 Various list-related things] +% \end{meta-comment} +% +% \CheckSum{179} +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%% +% +% \begin{meta-comment} +% +%<*driver> +\input{mdwtools} +\describespackage{mdwlist} +\def\defaultdesc{% + \desclabelwidth{80pt}% + \desclabelstyle\nextlinelabel% + \def\makelabel{\bfseries}% +} +\newenvironment{cmdlist} + {\basedescript{\let\makelabel\cmd}} + {\endbasedescript} +\mdwdoc +%</driver> +% +% \end{meta-comment} +% +% \section{User guide} +% +% This package provides some vaguely useful list-related commands and +% environments: +% \begin{itemize*} +% \item A way of building \env{description}-like environments. +% \item Commands for making `compacted' versions of list environments +% \item A method for suspending and resuming enumerated lists. +% \end{itemize*} +% +% \subsection{Description list handling} +% +% Different sorts of description-type lists require different sorts of +% formatting: I think that's fairly obvious. There are essentially three +% different attributes which should be changable: +% \begin{itemize*} +% \item the indentation of the items being described, +% \item the handling of labels which don't fit properly, and +% \item the style used to typeset the label text. +% \end{itemize*} +% The first two items should usually be decided for all description-like +% lists in the document, to ensure consistency of appearance. The last +% depends much more on the content of the labels. +% +% \DescribeEnv{basedescript} +% The \env{basedescript} environment acts as a `skeleton' for description +% environments. It takes one argument, which contains declarations to +% be performed while constructing the list. I'd consider it unusual for +% the \env{basedescript} environment to be used in the main text: it's +% intended to be used to build other environments. +% +% The declarations which can be used to define description-type environments +% include all of those which are allowed when setting up a list (see the +% \LaTeX\ book for information here). Some others, which apply specifically +% to description lists, are also provided: +% +% \begin{itemize} +% +% \item \DescribeMacro{\desclabelwidth} +% The \syntax{"\\desclabelwidth{"<length>"}"} declaration sets labels +% to be left-aligned, with a standard width of \<length>; the item +% text is indented by \<length> plus the value of |\labelsep|. +% +% \item \DescribeMacro{\desclabelstyle} +% The label style determines how overlong labels are typeset. A style +% may be set using the \syntax{"\\desclabelstyle{"<style>"}"} +% declaration. The following \<style>s are provided: +% \begin{cmdlist} +% \item [\nextlinelabel] If the label is too wide to fit next to the +% first line of text, then it is placed on a line by itself; +% the main text is started on the next line with the usual +% indentation. +% \item [\multilinelabel] The label is typeset in a parbox with the +% appropriate width; if it won't fit on one line, then the +% text will be split onto subsequent lines. +% \item [\pushlabel] If the label is too wide to fit in the space +% allocated to it, the start of the item's text will be `pushed' +% over to the right to provide space for the label. This is +% the standard \LaTeX\ \env{description} behaviour. +% \end{cmdlist} +% +% \item \DescribeMacro{\makelabel} +% The |\makelabel| command is responsible for typesetting a label. +% It is given one argument, which is the text given as an argument +% to the |\item| command; it should typeset it appropriately. The +% text will then be arranged appropriately according to the chosen +% label style. This command should be redefined using |\renewcommand|. +% +% \end{itemize} +% +% \begin{figure} +% \begin{demo}[w]{Various labelling styles} +%\begin{basedescript}{\desclabelstyle{\nextlinelabel}} +%\item [Short label] This is a short item, although it has quite a +% lot of text attached to it. +%\item [Slightly longer label text] This is a rather longer piece +% of text, with a correspondingly slightly longer label. +%\end{basedescript} +%\medskip +%\begin{basedescript}{\desclabelstyle{\multilinelabel}} +%\item [Short label] This is a short item, although it has quite a +% lot of text attached to it. +%\item [Slightly longer label text] This is a rather longer piece +% of text, with a correspondingly slightly longer label. +%\end{basedescript} +%\medskip +%\begin{basedescript}{\desclabelstyle{\pushlabel}} +%\item [Short label] This is a short item, although it has quite a +% lot of text attached to it. +%\item [Slightly longer label text] This is a rather longer piece +% of text, with a correspondingly slightly longer label. +%\end{basedescript} +% \end{demo} +% \end{figure} +% +% \DescribeMacro{\defaultdesc} +% To allow document designers to control the global appearance of description +% lists, the |\defaultdesc| command may be redefined; it is called while +% setting up a new \env{basedescript} list, before performing the user's +% declarations. By default, it attempts to emulate the standard \LaTeX\ +% \env{description} environment:\footnote{^^A +% This is a slightly sanitised version of the real definition, which is +% given in the implementation section of this document.} +% \begin{listing} +%\providecommand{\defaultdesc}{% +% \desclabelstyle{\pushlabel}% +% \renewcommand{\makelabel}[1]{\bfseries##1}% +% \setlength{\labelwidth}{0pt}% +%} +% \end{listing} +% Unfortunately, \LaTeX\ doesn't provide a means for overriding a command +% which may or may not have been defined yet; in this case, I'd probably +% recommend using the \TeX\ primitive |\def| to redefine |\defaultdesc|. +% +% If you want to redefine the \env{description} environment in terms of +% the commands in this package, the following method is recommended: +% \begin{listing} +%\renewenvironment{description}{% +% \begin{basedescript}{% +% \renewcommand{\makelabel}[1]{\bfseries##1}% +% }% +%}{% +% \end{basedescript}% +%} +% \end{listing} +% This ensures that labels are typeset in bold, as is usual, but other +% properties of the list are determined by the overall document style. +% +% \subsection{Compacted lists} +% +% \LaTeX\ tends to leave a certain amount of vertical space between list +% items. While this is normally correct for lists in which the items are +% several lines long, it tends to look odd if all or almost all the items +% are only one line long. +% +% \DescribeMacro{\makecompactlist} +% The command +% \syntax{"\\makecompactlist{"<new-env-name>"}{"<old-env-name>"}"} +% defines a new environment \<new-env-name> to be a `compacted' version of +% the existing environment \<old-env-name>; i.e., the two environments are +% the same except that the compacted version leaves no space between items +% or paragraphs within the list. +% +% \DescribeEnv{itemize*} +% \DescribeEnv{enumerate*} +% \DescribeEnv{description*} +% So that the most common cases are already handled, the package creates +% compacted $*$-variants of the \env{itemize}, \env{enumerate} and +% \env{description} environments. These were created using the commands +% \begin{listing} +%\makecompactlist{itemize*}{itemize} +%\makecompactlist{enumerate*}{enumerate} +%\makecompactlist{description*}{description} +% \end{listing} +% +% Some list environments accept arguments. You can pass an argument to a +% list environment using an optional argument to its compact variant. For +% example, +% \begin{listing} +%\begin{foolist*}[{someargument}] +% \end{listing} +% +% \subsection{Suspending and resuming list environments} +% +% \DescribeMacro{\suspend} +% \DescribeMacro{\resume} +% The |\suspend| and |\resume| commands allow you to temporarily end a list +% environment and then pick it up where you left off. The syntax is fairly +% simple: +% +% \begin{grammar} +% +% <suspend-cmd> ::= \[[ +% "\\suspend" +% \begin{stack} \\ "[" <name> "]" \end{stack} "{" <env-name> "}" +% \]]% +% +% <resume-cmd> ::= \[[ +% "\\resume" +% \begin{stack} \\ "[" <name> "]" \end{stack} "{" <env-name> "}" +% \begin{stack} \\ "[" <text> "]" \end{stack} +% \]]% +% +% \end{grammar} +% +% The \<env-name> is the name of the environment; this will more often than +% not be the \env{enumerate} environment. The \<name> is a magic name you +% can use to identify the suspended environment; if you don't specify this, +% the environment name is used instead. +% +% \begin{demo}{Suspended environments} +%Here's some initial text. It's +%not very interesting. +%\begin{enumerate*} +%\item This is an item. +%\item This is another. +%\suspend{enumerate*} +%Some more commentry text. +%\resume{enumerate*} +%\item Another item. +%\end{enumerate*} +% \end{demo} +% +% You can pass arguments to a resumed list environment through the second +% optional argument of the |\resume| command. If, for example, you're using +% David Carlisle's \package{enumerate} package, you could say something like +% \begin{listing} +%\begin{enumerate}[\bfseries{Item} i] +%\item An item +%\item Another item +%\suspend{enumerate} +%Some intervening text. +%\resume{enumerate}[{[\bfseries{Item} i]}] +%\item Yet another item +%\end{enumerate} +% \end{listing} +% +% \implementation +% +% \section{Implementation} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \subsection{Description lists} +% +% \subsubsection{Label styles} +% +% \begin{macro}{\nextlinelabel} +% +% The idea here is that if the label is too long to fit in its box, we put +% it on its own line and start the text of the item on the next. I've +% used |\sbox| here to capture colour changes properly, even though I have +% deep moral objections to the use of \LaTeX\ boxing commands. Anyway, +% I capture the text in box~0 and compare its width to the amount of space +% I have in the label box. If there's enough, I can just unbox the box; +% otherwise I build a vbox containing the label text and an empty hbox -- +% |\baselineskip| glue inserted between the two boxes makes sure we get +% the correct spacing between the two lines, and the vboxness of the vbox +% ensures that the baseline of my strange thing is the baseline of the +% \emph{bottom} box. I then bash the vbox on the nose, so as to make its +% width zero, and leave that as the result. Either way, I then add glue +% to left align whatever it is I've created. +% +% \begin{macrocode} +\def\nextlinelabel#1{% + \sbox\z@{#1}% + \ifdim\wd\z@>\labelwidth% + \setbox\z@\vbox{\box\z@\hbox{}}% + \wd\z@\z@% + \box\z@% + \else% + \unhbox\z@% + \fi% + \hfil% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\multilinelabel} +% +% A different idea -- make the label text wrap around onto the next line if +% it's too long. This is really easy, actually. I use a parbox to contain +% the label text, set to be ragged right, because there won't be enough +% space to do proper justification. There's also a funny hskip there -- +% this is because \TeX\ only hyphenates things it finds sitting \emph{after} +% glue items. The parbox is top-aligned, so the label text and the item +% run downwards together. I put the result in box~0, and remove the depth, +% so as not to make the top line of the item text look really strange. +% +% All this leaves a little problem, though: if the item text isn't very long, +% the label might go further down the page than the main item, and possibly +% collide with the label below. I must confess that I'm not actually sure +% how to deal with this possibility, so I just hope it doesn't happen. +% +% By the way, I don't have moral objections to |\parbox|. +% +% \begin{macrocode} +\def\multilinelabel#1{% + \setbox\z@\hbox{% + \parbox[t]\labelwidth{\raggedright\hskip\z@skip#1}% + }% + \dp\z@\z@% + \box\z@% + \hfil% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\pushlabel} +% +% Now we implement the old style behaviour -- if the label is too wide, we +% just push the first line of the item further over to the right. This +% is really very easy indeed -- we just stick some |\hfil| space on the +% right hand side (to left align if the label comes up too short). The +% `push' behaviour is handled automatically by \LaTeX's item handling. +% +% \begin{macrocode} +\def\pushlabel#1{{#1}\hfil} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{The main environment} +% +% \begin{macro}{\desclabelstyle} +% +% This is a declaration intended to be used only in the argument to the +% \env{basedescript} environment. It sets the label style for the list. +% All we do is take the argument and assign it to a magic control sequence +% which \env{basedescript} will understand later. +% +% \begin{macrocode} +\def\desclabelstyle#1{\def\desc@labelstyle{#1}} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\desclabelwidth} +% +% We set the label width and various other bits of information which will +% make all the bits of the description line up beautifully. We set +% |\labelwidth| to the value we're given (using |\setlength|, so that +% people can use the \package{calc} package if they so wish), and make +% the |\leftmargin| equal $|\labelwidth|+|\labelsep|$. +% +% \begin{macrocode} +\def\desclabelwidth#1{% + \setlength\labelwidth{#1}% + \leftmargin\labelwidth% + \advance\leftmargin\labelsep% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{basedescript} +% +% This is the new description environment. It does almost everything you +% could want from a description environment, I think. The argument is a +% collection of declarations to be performed while setting up the list. +% +% This environment isn't really intended to be used by users -- it's here +% so that you can define other description environments in terms of it, +% +% The environment is defined in two bits -- the `start' bit here simply +% starts the list and inserts the user declarations in an appropriate +% point, although sensible details will be inerted if the argument was +% empty. +% +% \begin{macrocode} +\def\basedescript#1{% +% \end{macrocode} +% +% We must start the list. If the |\item| command's optional argument is +% missing, we should just leave a blank space, I think. +% +% \begin{macrocode} + \list{}{% +% \end{macrocode} +% +% So far, so good. Now put in some default declarations. I'll use a +% separate macro for this, so that the global appearance of lists can be +% configured. +% +% \begin{macrocode} + \defaultdesc% +% \end{macrocode} +% +% Now we do the user's declarations. +% +% \begin{macrocode} + #1% +% \end{macrocode} +% +% Now set up the other parts of the list. We set |\itemindent| so that the +% label is up against the current left margin. (The standard version +% actually leaves the label hanging to the left of the margin by a +% distance of |\labelsep| for a reason I can't quite comprehend -- there's +% an |\hspace{\labelsep}| in the standard |\makelabel| to compensate for +% this. Strange\dots) +% +% To make the label start in the right place, the text of the item must +% start a distance of $|\labelwidth|+|\labelsep|$ from the (pre-list) left +% hand margin; this means that we must set |\itemindent| to be +% $|\labelwidth|+|\labelsep|-|\leftmargin|$. Time for some \TeX\ arithmetic. +% +% \begin{macrocode} + \itemindent\labelwidth% + \advance\itemindent\labelsep% + \advance\itemindent-\leftmargin% +% \end{macrocode} +% +% Now we must set up the label typesetting. We'll take the |\makelabel| +% provided by the user, remember it, and then redefine |\makelabel| in +% terms of the |\desclabelstyle| and the saved |\makelabel|. +% +% \begin{macrocode} + \let\desc@makelabel\makelabel% + \def\makelabel##1{\desc@labelstyle{\desc@makelabel{##1}}}% +% \end{macrocode} +% +% I can't think of anything else which needs doing, so I'll call it a day +% there. +% +% \begin{macrocode} + }% +} +% \end{macrocode} +% +% Now we define the `end-bit' of the environment. Since all we need to do +% is to close the list, we can be ever-so slightly clever and use |\let|. +% +% \begin{macrocode} +\let\endbasedescript\endlist +% \end{macrocode} +% +% Note that with these definitions, the standard \env{description} +% environment can be emulated by saying simply: +% \begin{listing} +%\renewenvironment{description}{% +% \begin{basedescript}{}% +%}{% +% \end{basedescript} +%} +% \end{listing} +% +% \end{environment} +% +% \begin{macro}{\defaultdesc} +% +% Now to set up the standard description appearance. In the absence +% of any other declarations, the label will `push' the text out the way if +% the text is too long. The standard |\labelsep| and |\leftmargin| are not +% our problem. We typeset the label text in bold by default. Also, +% |\labelwidth| is cleared to 0\,pt, because this is what \LaTeX's usual +% \env{description} does. +% +% \begin{macrocode} +\providecommand\defaultdesc{% + \desclabelstyle\pushlabel% + \def\makelabel##1{\bfseries##1}% + \labelwidth\z@% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{An example} +% +% \begin{environment}{note} +% +% The \env{note} environment is a simple application of the general +% description list shown above. It typesets the label (by default, the +% text `\textbf{note}') at the left margin, and the note text indented by +% the width of the label. +% +% The code is simple -- we take the environment's argument (which may have +% been omitted), store it in a box (using |\sbox| again, to handle colour +% changes correctly), set the label width from the width of the box, and +% then create a single item containing the label text. The text of the +% environment then appears in exactly the desired place. +% +% I've not used |\newcommand| here, for the following reasons: +% \begin{itemize} +% +% \item I don't like it much, to be honest. +% +% \item Until very recently, |\newcommand| only allowed you to define +% `long' commands, where new paragraphs were allowed to be started +% in command arguments; this removes a useful check which traps +% common errors like missing out `|}|' characters. I'd prefer to +% be compatible with older \LaTeX s than to use the new |\newcommand| +% which provides a $*$-form to work around this restriction. +% +% \end{itemize} +% +% \begin{macrocode} +\def\note{\@ifnextchar[\note@i{\note@i[Note:]}} +\def\note@i[#1]{% + \basedescript{% + \sbox\z@{\makelabel{#1}}% + \desclabelwidth{\wd\z@}% + }% + \item[\box\z@]% +} +\let\endnote\endbasedescript +% \end{macrocode} +% +% \end{environment} +% +% +% \subsection{Compacted environments} +% +% Normal lists tend to have rather too much space between items if all or +% most of the item texts are one line or less each. We therefore define +% a macro |\makecompactlist| whuch creates `compacted' versions of existing +% environments. +% +% \begin{macro}{\makecompactlist} +% +% We're given two arguments: the name of the new environment to create, and +% the name of the existing list environment to create. +% +% The first thing to do is to ensure that the environment we're creating is +% actually valid (i.e., it doesn't exist already, and it has a sensible +% name). We can do this with the internal \LaTeX\ macro |\@ifdefinable|. +% +% \begin{macrocode} +\def\makecompactlist#1#2{% + \expandafter\@ifdefinable\csname#1\endcsname% + {\makecompactlist@i{#1}{#2}}% +} +% \end{macrocode} +% +% We also ought to ensure that the other environment already exists. This +% isn't too tricky. We'll steal \LaTeX's error and message for this. +% +% \begin{macrocode} +\def\makecompactlist@i#1#2{% + \@ifundefined{#2}{\me@err{Environment `#2' not defined}\@ehc}{}% +% \end{macrocode} +% +% The main work for starting a compact list is done elsewhere. +% +% \begin{macrocode} + \@namedef{#1}{\@compact@list{#2}}% +% \end{macrocode} +% +% Now to define the end of the environment; this isn't terribly difficult. +% +% \begin{macrocode} + \expandafter\let\csname end#1\expandafter\endcsname% + \csname end#2\endcsname% +% \end{macrocode} +% +% That's a compacted environment created. Easy, no? +% +% \begin{macrocode} +} +% \end{macrocode} +% +% The general case macro has to try slurping some arguments, calling the +% underlying environment, and removing vertical space. +% +% \begin{macrocode} +\def\@compact@list#1{\@testopt{\@compact@list@i{#1}}{}} +\def\@compact@list@i#1[#2]{% + \@nameuse{#1}#2% + \parskip\z@% + \itemsep\z@% +}% +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{itemize*} +% \begin{environment}{enumerate*} +% \begin{environment}{description*} +% +% Let's build some compacted environments now. These are easy now that +% we've done all the work above. +% +% \begin{macrocode} +\makecompactlist{itemize*}{itemize} +\makecompactlist{enumerate*}{enumerate} +\makecompactlist{description*}{description} +% \end{macrocode} +% +% \end{environment} +% \end{environment} +% \end{environment} +% +% +% \subsection{Suspending and resuming lists} +% +% This is nowhere near perfect; it relies a lot on the goodwill of the user, +% although it seems to work fairly well. +% +% \begin{macro}{\suspend} +% +% The only thing that needs saving here is the list counter, whose name +% is stored in |\@listctr|. When I get a request to save the counter, I'll +% build a macro which will restore it when the environment is restored later. +% +% The first thing to do is to handle the optional argument. |\@dblarg| will +% sort this out, giving me a copy of the mandatory argument if there's no +% optional one provided. +% +% \begin{macrocode} +\def\suspend{\@dblarg\suspend@i} +% \end{macrocode} +% +% That's all we need to do here. +% +% \begin{macrocode} +\def\suspend@i[#1]#2{% +% \end{macrocode} +% +% Now I have a little problem; when I |\end| the environment, it will close +% off the grouping level, and the counter value will be forgotten. This is +% bad. I'll store all my definitions into a macro, and build the |\end| +% command into it; that way, everything will be expanded correctly. This +% requires the use of |\edef|, which means I must be a little careful. +% +% \begin{macrocode} + \edef\@tempa{% +% \end{macrocode} +% +% The first thing to do is to end the environment. I don't want |\end| +% expanded yet, so I'll use |\noexpand|. +% +% \begin{macrocode} + \noexpand\end{#2}% +% \end{macrocode} +% +% Now I must define the `resume' macro. I'll use |\csname| to build the +% named identifier into the name, so it won't go wrong (maybe). There's +% a little fun here to make the control sequence name but not expand it +% here. +% +% \begin{macrocode} + \def\expandafter\noexpand\csname resume.#1\endcsname{% +% \end{macrocode} +% +% The counter name is hidden inside |\@listctr|, so the actual counter is +% called `|\csname c@\@listctr\endcsname|'. I'll use |\the| to read its +% current value, and assign it to the counter when the macro is used later. +% +% \begin{macrocode} + \csname c@\@listctr\endcsname\the\csname c@\@listctr\endcsname% +% \end{macrocode} +% +% That's all we need to do there. Now close the macros and run them. +% +% \begin{macrocode} + }% + }% + \@tempa% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\resume} +% +% Resuming environments is much easier. Since I use |\csname| to build the +% name, nothing happens if you try to resume environments which weren't +% suspended. I'll trap this and raise an error. Provide an optional +% argument for collecting arguments to the target list. +% +% \begin{macrocode} +\def\resume{\@dblarg\resume@i} +\def\resume@i[#1]#2{\@testopt{\resume@ii{#1}{#2}}{}} +\def\resume@ii#1#2[#3]{% + \begin{#2}#3% + \@ifundefined{resume.#1}{\ml@err@resume}{\@nameuse{resume.#1}}% +} +% \end{macrocode} +% +% \end{macro} +% +% That's all there is. +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \hfill Mark Wooding, \today +% +% \Finale +% +\endinput diff --git a/Master/texmf-dist/source/latex/mdwtools/mdwmath.dtx b/Master/texmf-dist/source/latex/mdwtools/mdwmath.dtx new file mode 100644 index 00000000000..3dc85872f80 --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/mdwmath.dtx @@ -0,0 +1,930 @@ +% \begin{meta-comment} +% +% $Id: mdwmath.dtx,v 1.1 1996/11/19 20:53:21 mdw Exp $ +% +% Various nicer mathematical things +% +% (c) 1996 Mark Wooding +% +%----- Revision history ----------------------------------------------------- +% +% $Log: mdwmath.dtx,v $ +% Revision 1.1 1996/11/19 20:53:21 mdw +% Initial revision +% +% +% \end{meta-comment} +% +% \begin{meta-comment} <general public licence> +%% +%% mdwmath package -- various nicer mathematical things +%% Copyright (c) 1996 Mark Wooding +%% +%% This program is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation; either version 2 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program; if not, write to the Free Software +%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +%% +% \end{meta-comment} +% +% \begin{meta-comment} <Package preamble> +%<+package>\NeedsTeXFormat{LaTeX2e} +%<+package>\ProvidesPackage{mdwmath} +%<+package> [1996/04/11 1.1 Nice mathematical things] +%<+oldeqnarray>\NeedsTeXFormat{LaTeX2e} +%<+oldeqnarray>\ProvidesPackage{eqnarray} +%<+oldeqnarray> [1996/04/11 1.1 Old enhanced eqnarray] +% \end{meta-comment} +% +% \CheckSum{259} +% \begin{old-eqnarray} +% \CheckSum{484} +% \end{old-eqnarray} +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%% +% +% \begin{meta-comment} +% +%<*driver> +\input{mdwtools} +\describespackage{mdwmath} +% \describespackage{eqnarray} +\ignoreenv{old-eqnarray} +% \unignoreenv{old-eqnarray} +\mdwdoc +%</driver> +% +% \end{meta-comment} +% +% \section{User guide} +% +% \subsection{Square root typesetting} +% +% \DescribeMacro{\sqrt} +% The package supplies a star variant of the |\sqrt| command which omits the +% vinculum over the operand (the line over the top). While this is most +% useful in simple cases like $\sqrt*{2}$ it works for any size of operand. +% The package also re-implements the standard square root command so that it +% positions the root number rather better. +% +% \begin{figure} +% \begin{demo}[w]{Examples of the new square root command} +%\[ \sqrt*{2} \quad \mbox{rather than} \quad \sqrt{2} \] +%\[ \sqrt*[3]{2} \quad \mbox{ rather than } \quad \sqrt[3]{2} \] +%\[ \sqrt{x^3 + \sqrt*[y]{\alpha}} - \sqrt*[n+1]{a} \] +%\[ x = \sqrt*[3]{\frac{3y}{7}} \] +%\[ q = \frac{2\sqrt*{2}}{5}+\sqrt[\frac{n+1}{2}]{2x^2+3xy-y^2} \] +% \end{demo} +% \end{figure} +% +% [Note that omission of the vinculum was originally a cost-cutting exercise +% because the radical symbol can just fit in next to its operand and +% everything ends up being laid out along a line. However, I find that the +% square root without vinculum is less cluttered, so I tend to use it when +% it doesn't cause ambiguity.] +% +% \subsection{Some maths symbols you already have} +% +% Having just tried to do some simple things, I've found that there are maths +% symbols missing. Here they are, in all their glory: +% +% \begin{center} \unverb\| \begin{tabular}{cl|cl|cl} +% $\&$ & "\&" & $\bitor$ & "\bitor" & $\dbland$ & "\dbland" \\ +% $\bitand$ & "\bitand" & $\dblor$ & "\dblor" & +% \end{tabular} \end{center} +% +% \begin{ignore} +% There used to be an eqnarray here, but that's migrated its way into the +% \package{mdwtab} package. Maybe the original version, without dependency +% on \package{mdwtab} ought to be releasable separately. I'll keep it around +% just in case. +% +% The following is the documentation for the original version. There's an +% updated edition in \package{mdwtab}. +% \end{ignore} +% +% \begin{old-eqnarray} +% +% \subsection{A new \env{eqnarray} environment} +% +% \LaTeX's built-in \env{eqnarray} is horrible -- it puts far too much space +% between the items in the array. This environment is rather nearer to the +% \env{amsmath} \env{align} environments, although rather less capable. +% +% \bigskip +% \DescribeEnv{eqnarray} +% {\synshorts +% \setbox0\hbox{"\\begin{eqnarray}["<preamble>"]" \dots "\\end{eqnarray}"} +% \leavevmode \hskip-\parindent \fbox{\box0} +% } +% \smallskip +% +% The new version of \env{eqnarray} tries to do everything which you really +% want it to. The \synt{preamble} string allows you to define the column +% types in a vaguely similar way to the wonderful \env{tabular} environment. +% The types provided (and it's easy-ish to add more) are: +% +% \def\ch{\char`} +% \begin{description} \def\makelabel{\hskip\labelsep\normalfont\ttfamily} +% \item [r] Right aligned equation +% \item [c] Centre-aligned equation +% \item [l] Left aligned equation +% \item [\textrm{\texttt{Tr}, \texttt{Tc} and \texttt{Tl}}] Right, centre and +% left aligned text (not maths) +% \item [L] Left aligned zero-width equation +% \item [x] Centred entire equation +% \item [:] Big gap separating sets of equations +% \item [q] Quad space +% \item [>\ch\{\synt{text}\ch\}] Insert text before column +% \item [<\ch\{\synt{text}\ch\}] Insert text after column +% \end{description} +% +% Some others are also defined: don't use them because they do complicated +% things which are hard to explain and they aren't much use anyway. +% +% The default preamble, if you don't supply one of your own, is \lit{rcl}. +% Most of the time, \lit{rl} is sufficient, although compatibility is more +% important to me. +% +% By default, there is no space between columns, which makes formul\ae\ in an +% \env{eqnarray} environment look just like formul\ae\ typeset on their own, +% except that things get aligned in columns. This is where the default +% \env{eqnarray} falls down: it leaves |\arraycolsep| space between each +% column making the thing look horrible. +% +% An example would be good here, I think. This one's from exercise 22.9 of +% the \textit{\TeX book}. +% +% \begin{demo}[w]{Simultaneous equations} +%\begin{eqnarray}[rcrcrcrl] +% 10w & + & 3x & + & 3y & + & 18z & = 1 \\ +% 6w & - & 17x & & & - & 5z & = 2 +%\end{eqnarray} +% \end{demo} +% +% Choosing a more up-to-date example, here's one demonstrating the \lit{:} +% column specifier from the \textit{\LaTeX\ Companion}. +% +% \begin{demo}[w]{Lots of equations} +%\begin{eqnarray}[rl:rl:l] +% V_i &= v_i - q_i v_j, & X_i &= x_i - q_i x_j, & +% U_i = u_i, \qquad \mbox{for $i \ne j$} \label{eq:A} \\ +% V_j &= v_j, & X_j &= x_j & +% U_j u_j + \sum_{i \ne j} q_i u_i. +%\end{eqnarray} +% \end{demo} +% +% We can make things more interesting by adding a plain text column. Here we +% go: +% +% \begin{demo}[w]{Plain text column} +%\begin{eqnarray}[rlqqTl] +% x &= y & by (\ref{eq:A}) \\ +% x' &= y' & by definition \\ +% x + x' &= y + y' & by Axiom~1 +%\end{eqnarray} +% \end{demo} +% +% The new features also mean that you don't need to mess about with +% |\lefteqn| any more. This is handled by the \lit{L} column type: +% +% \begin{demo}{Splitting example} +%\begin{eqnarray*}[Ll] +% w+x+y+z = \\ +% & a+b+c+d+e+ \\ +% & f+g+h+i+j +%\end{eqnarray*} +% \end{demo} +% +% Finally, just to prove that the spacing's right at last, here's another one +% from the \textit{Companion}. +% +% \begin{demo}{Spacing demonstration} +%\begin{equation} +% x^2 + y^2 = z^2 +%\end{equation} +%\begin{eqnarray}[rl] +% x^2 + y^2 &= z^2 \\ +% y^2 &< z^2 +%\end{eqnarray} +% \end{demo} +% +% Well, that was easy enough. Now on to numbering. As you've noticed, the +% equations above are numbered. You can use the \env{eqnarray$*$} +% environment to turn off the numbering in the whole environment, or say +% |\nonumber| on a line to suppress numbering of that one in particular. +% More excitingly, you can say \syntax{"\\nonumber["<text>"]"} to choose +% what text to display. +% +% A note for cheats: you can use the sparkly new \env{eqnarray} for simple +% equations simply by specifying \lit{x} as the column description. Who +% needs \AmSTeX? |;-)| +% +% \end{old-eqnarray} +% +% \implementation +% +% \section{Implementation} +% +% This isn't really complicated (honest) although it is a lot hairier than I +% think it ought to be. +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \subsection{Square roots} +% +% \subsubsection{Where is the square root sign?} +% +% \LaTeX\ hides the square root sign away somewhere without telling anyone +% where it is. I extract it forcibly by peeking inside the |\sqrtsign| macro +% and scrutinising the contents. Here we go: prepare for yukkiness. +% +% \begin{macrocode} +\newcount\sq@sqrt +\begingroup + \catcode`\|0 \catcode`\\12 + |def|sq@readrad#1"#2\#3|relax{|global|sq@sqrt"#2|relax} + |expandafter|sq@readrad|meaning|sqrtsign|relax +|endgroup +\def\sq@delim{\delimiter\sq@sqrt\relax} +% \end{macrocode} +% +% \subsubsection{Drawing fake square root signs} +% +% \TeX\ absolutely insists on drawing square root signs with a vinculum over +% the top. In order to get the same effect, we have to attempt to emulate +% \TeX's behaviour. +% +% \begin{macro}{\sqrtdel} +% +% This does the main job of typesetting a vinculum-free radical.\footnote{^^A +% Note for chemists: this is nothing to do with short-lived things which +% don't have their normal numbers of electrons. And it won't reduce the +% appearance of wrinkles either.} +% It's more or less a duplicate of what \TeX\ does internally, so it might be +% a good plan to have a copy of Appendix~G open while you examine this. +% +% We start off by using |\mathpalette| to help decide how big things should +% be. +% +% \begin{macrocode} +\def\sqrtdel{\mathpalette\sqrtdel@i} +% \end{macrocode} +% +% Read the contents of the radical into a box, so we can measure it. +% +% \begin{macrocode} +\def\sqrtdel@i#1#2{% + \setbox\z@\hbox{$\m@th#1#2$}% %%% Bzzzt -- uncramps the mathstyle +% \end{macrocode} +% +% Now try and sort out the values needed in this calculation. We'll assume +% that $\xi_8$ is 0.6\,pt, the way it usually is. Next try to work out the +% value of $\varphi$. +% +% \begin{macrocode} + \ifx#1\displaystyle% + \@tempdima1ex% + \else% + \@tempdima.6\p@% + \fi% +% \end{macrocode} +% +% That was easy. Now for $\psi$. +% +% \begin{macrocode} + \@tempdimb.6\p@% + \advance\@tempdimb.25\@tempdima% +% \end{macrocode} +% +% Build the `delimiter' in a box of height $h(x)+d(x)+\psi+\xi_8$, as +% requested. Box~2 will do well for this purpose. +% +% \begin{macrocode} + \dimen@.6\p@% + \advance\dimen@\@tempdimb% + \advance\dimen@\ht\z@% + \advance\dimen@\dp\z@% + \setbox\tw@\hbox{% + $\left\sq@delim\vcenter to\dimen@{}\right.\n@space$% + }% +% \end{macrocode} +% +% Now we need to do some more calculating (don't you hate it?). As far as +% Appendix~G is concerned, $\theta=h(y)=0$, because we want no rule over the +% top. +% +% \begin{macrocode} + \@tempdima\ht\tw@% + \advance\@tempdima\dp\tw@% + \advance\@tempdima-\ht\z@% + \advance\@tempdima-\dp\z@% + \ifdim\@tempdima>\@tempdimb% + \advance\@tempdima\@tempdimb% + \@tempdimb.5\@tempdima% + \fi% +% \end{macrocode} +% +% Work out how high to raise the radical symbol. Remember that Appendix~G +% thinks that the box has a very small height, although this is untrue here. +% +% \begin{macrocode} + \@tempdima\ht\z@% + \advance\@tempdima\@tempdimb% + \advance\@tempdima-\ht\tw@% +% \end{macrocode} +% +% Build the output (finally). The brace group is there to turn the output +% into a mathord, one of the few times that this is actually desirable. +% +% \begin{macrocode} + {\raise\@tempdima\box\tw@\vbox{\kern\@tempdimb\box\z@}}% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{The new square root command} +% +% This is where we reimplement all the square root stuff. Most of this stuff +% comes from the \PlainTeX\ macros, although some is influenced by \AmSTeX\ +% and \LaTeXe, and some is original. I've tried to make the spacing vaguely +% automatic, so although it's not configurable like \AmSTeX's version, the +% output should look nice more of the time. Maybe. +% +% \begin{macro}{\sqrt} +% +% \LaTeX\ says this must be robust, so we make it robust. The first thing to +% do is to see if there's a star and pass the appropriate squareroot-drawing +% command on to the rest of the code. +% +% \begin{macrocode} +\DeclareRobustCommand\sqrt{\@ifstar{\sqrt@i\sqrtdel}{\sqrt@i\sqrtsign}} +% \end{macrocode} +% +% Now we can sort out an optional argument to be displayed on the root. +% +% \begin{macrocode} +\def\sqrt@i#1{\@ifnextchar[{\sqrt@ii{#1}}{\sqrt@iv{#1}}} +% \end{macrocode} +% +% Stages~2 and~3 below are essentially equivalents of \PlainTeX's +% |\root|\dots|\of| and |\r@@t|. Here we also find the first wrinkle: the +% |\rootbox| used to store the number is spaced out on the left if necessary. +% There's a backspace after the end so that the root can slip underneath, and +% everything works out nicely. Unfortunately size is fixed here, although +% doesn't actually seem to matter. +% +% \begin{macrocode} +\def\sqrt@ii#1[#2]{% + \setbox\rootbox\hbox{$\m@th\scriptscriptstyle{#2}$}% + \ifdim\wd\rootbox<6\p@% + \setbox\rootbox\hb@xt@6\p@{\hfil\unhbox\rootbox}% + \fi% + \mathpalette{\sqrt@iii{#1}}% +} +% \end{macrocode} +% +% Now we can actually build everything. Note that the root is raised by its +% depth -- this prevents a common problem with letters with descenders. +% +% \begin{macrocode} +\def\sqrt@iii#1#2#3{% + \setbox\z@\hbox{$\m@th#2#1{#3}$}% + \dimen@\ht\z@% + \advance\dimen@-\dp\z@% + \dimen@.6\dimen@% + \advance\dimen@\dp\rootbox% + \mkern-3mu% + \raise\dimen@\copy\rootbox% + \mkern-10mu% + \box\z@% +} +% \end{macrocode} +% +% Finally handle a non-numbered root. We read the rooted text in as an +% argument, to stop problems when people omit the braces. (\AmSTeX\ does +% this too.) +% +% \begin{macrocode} +\def\sqrt@iv#1#2{#1{#2}} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\root} +% +% We also re-implement \PlainTeX's |\root| command, just in case someone uses +% it, and supply a star-variant. This is all very trivial. +% +% \begin{macrocode} +\def\root{\@ifstar{\root@i\sqrtdel}{\root@i\sqrtsign}} +\def\root@i#1#2\of{\sqrt@ii{#1}[#2]} +% \end{macrocode} +% +% \end{macro} +% +% \subsection{Some magic new maths characters} +% +% This is all really easy. +% +% \begin{macrocode} +\DeclareMathSymbol{&}{\mathbin}{operators}{`\&} +\DeclareMathSymbol{\bitand}{\mathbin}{operators}{`\&} +\def\bitor{\mathbin\mid} +\def\dblor{\mathbin{\mid\mid}} +\def\dbland{\mathbin{\mathrel\bitand\mathrel\bitand}} +% \end{macrocode} +% +% \subsection{Biggles} +% +% Now for some user-controlled delimiter sizing. The standard bigness of +% plain \TeX's delimiters are all right, but it's a little limiting. +% +% The biggness of delimiters is based on the size of the current |\strut|, +% which \LaTeX\ keeps up to date all the time. This will make the various +% delimiters grow in proportion when the text gets bigger. Actually, I'm +% not sure that this is exactly right -- maybe it should be nonlinear, +% +% \begin{macro}{\bbigg} +% \begin{macro}{\bbiggl} +% \begin{macro}{\bbiggr} +% \begin{macro}{\bbiggm} +% +% This is where the bigness is done. This is more similar to the plain \TeX\ +% big delimiter stuff than to the \package{amsmath} stuff, although there's +% not really a lot of difference. +% +% The two arguments are a multiplier for the delimiter size, and a small +% increment applied \emph{before} the multiplication (which is optional). +% +% This is actually a front for a low-level interface which can be called +% directly for efficiency. +% +% \begin{macrocode} +\def\bbigg{\@bbigg\mathord} +\def\bbiggl{\@bbigg\mathopen} +\def\bbiggr{\@bbigg\mathclose} +\def\bbiggm{\@bbigg\mathrel} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@bbigg} +% +% This is an optional argument parser providing a front end for the main +% macro |\bbigg@|. +% +% \begin{macrocode} +\def\@bbigg#1{\@ifnextchar[{\@bigg@i{#1}}{\@bigg@i{#1}[\z@]}} +\def\@bigg@i#1[#2]#3#4{#1{\bbigg@{#2}{#3}{#4}}} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\bbigg@} +% +% This is it, at last. The arguments are as described above: an addition +% to be made to the strut height, and a multiplier. Oh, and the delimiter, +% of course. +% +% This is a bit messy. The smallest `big' delimiter, |\big|, is the same +% height as the current strut box. Other delimiters are~$1\frac12$, $2$ +% and~$2\frac12$ times this height. I'll set the height of the delimiter by +% putting in a |\vcenter| of the appropriate size. +% +% Given an extra height~$x$, a multiplication factor~$f$ and a strut +% height~$h$ and depth~$d$, I'll create a vcenter with total height +% $f(h+d+x)$. Easy, isn't it? +% +% \begin{macrocode} +\def\bbigg@#1#2#3{% + \hbox{$% + \dimen@\ht\strutbox\advance\dimen@\dp\strutbox% + \advance\dimen@#1% + \dimen@#2\dimen@% + \left#3\vcenter to\dimen@{}\right.\n@space% + $}% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\big} +% \begin{macro}{\Big} +% \begin{macro}{\bigg} +% \begin{macro}{\Bigg} +% +% Now for the easy macros. +% +% \begin{macrocode} +\def\big{\bbigg@\z@\@ne} +\def\Big{\bbigg@\z@{1.5}} +\def\bigg{\bbigg@\z@\tw@} +\def\Bigg{\bbigg@\z@{2.5}} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{ignore} +% The following is the original definition of the enhanced eqnarray +% environment. It's not supported, although if you can figure out how to +% extract it, it's all yours. +% \end{ignore} +% +% \begin{old-eqnarray} +% +% \subsection{The sparkly new \env{eqnarray}} +% +% Start off by writing a different package. +% +% \begin{macrocode} +%</package> +%<*oldeqnarray> +% \end{macrocode} +% +% \subsubsection{Options handling} +% +% We need to be able to cope with \textsf{fleqn} and \textsf{leqno} options. +% This will adjust our magic modified \env{eqnarray} environment +% appropriately. +% +% \begin{macrocode} +\newif\if@fleqn +\newif\if@leqno +\DeclareOption{fleqn}{\@fleqntrue} +\DeclareOption{leqno}{\@leqnotrue} +\ProcessOptions +% \end{macrocode} +% +% This is all really different to the \LaTeX\ version. I've looked at the +% various \env{tabular} implementations, the original \env{eqnarray} and the +% \textit{\TeX book} to see how best to do this, and then went my own way. +% If it doesn't work it's all my fault. +% +% \subsubsection{Some useful registers} +% +% The old \LaTeX\ version puts the equation numbers in by keeping a count of +% where it is in the alignment. Since I don't know how may columns there are +% going to be, I'll just use a switch in the preamble to tell me to stop +% tabbing. +% +% \begin{macrocode} +\newif\if@eqalast +% \end{macrocode} +% +% Now define some useful length parameters. First allocate them: +% +% \begin{macrocode} +\newskip\eqaopenskip +\newskip\eqacloseskip +\newskip\eqacolskip +\newskip\eqainskip +% \end{macrocode} +% +% Now assign some default values. Users can play with these if they really +% want although I can't see the point myself. +% +% \begin{macrocode} +\if@fleqn + \AtBeginDocument{\eqaopenskip\leftmargini} +\else + \eqaopenskip\@centering +\fi +\eqacloseskip\@centering +\eqacolskip\@centering +\eqainskip\z@ +% \end{macrocode} +% +% We allow the user to play with the style if this is really wanted. I dunno +% why, really. Maybe someone wants very small alignments. +% +% \begin{macrocode} +\let\eqa@style\displaystyle +% \end{macrocode} +% +% \subsubsection{The main environments} +% +% We define the toplevel commands here. They just add in default arguments +% and then call |\@eqnarray| with a preamble string. The only difference is +% the last column they add in -- \env{eqnarray$*$} throws away the last +% column by sticking it in box~0. (I used to |\@gobble| it but that caused +% the |\cr| to be lost.) +% +% \begin{macrocode} +\def\eqnarray{\@ifnextchar[\eqnarray@i{\eqnarray@i[rcl]}} +\def\eqnarray@i[#1]{% + \@eqnarray{#1!{\hb@xt@\z@{\hss##}\tabskip\z@}} +} +\@namedef{eqnarray*}{\@ifnextchar[\eqnarray@s@i{\eqnarray@s@i[rcl]}} +\def\eqnarray@s@i[#1]{% + \@eqnarray{#1!{\nonumber\setbox\z@\hbox{##}\tabskip\z@}}% +} +% \end{macrocode} +% +% \subsubsection{Set up the initial display} +% +% \begin{macro}{\@eqnarray} +% +% The |\@eqnarray| command does most of the initial work. It sets up some +% flags and things, builds the |\halign| preamble, and returns. +% +% \begin{macrocode} +\def\@eqnarray#1{% +% \end{macrocode} +% +% Start playing with the counter here. The original does some icky internal +% playing, which isn't necessary. The |\if@eqnsw| switch is |true| if the +% user hasn't supplied an equation number. The |\if@eqalast| switch is +% |true| in the final equation-number column. +% +% \begin{macrocode} + \refstepcounter{equation}% + \@eqalastfalse% + \global\@eqnswtrue% + \m@th% +% \end{macrocode} +% +% Set things up for the |\halign| which is coming up. +% +% \begin{macrocode} + \openup\jot% + \tabskip\eqaopenskip% + \let\\\@eqncr% + \everycr{}% + $$% +% \end{macrocode} +% +% We'll build the real |\halign| and preamble in a token register. All we +% need to do is stuff the header in the token register, clear a switch +% (that'll be explained later), parse the preamble and then expand the +% tokens we collected. Easy, no? +% +% \begin{macrocode} + \toks@{\halign to\displaywidth\bgroup}% + \@tempswafalse% + \eqa@preamble#1\end% + \the\toks@\cr% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Parsing the preamble} +% +% All this actually involves is reading the next character and building a +% command from it. That can pull off an argument if it needs it. Just make +% sure we don't fall off the end and we'll be OK. +% +% \begin{macrocode} +\def\eqa@preamble#1{% + \ifx\end#1\else\csname eqa@char@#1\expandafter\endcsname\fi% +} +% \end{macrocode} +% +% Adding stuff to the preamble tokens is a simple matter of using +% |\expandafter| in the correct way.\footnote{^^A +% I have no idea why \LaTeX\ uses \cmd\edef\ for building its preamble. It +% seems utterly insane to me -- the amount of bodgery that \env{tabular} +% has to go through to make everything expand at the appropriate times is +% scary. Maybe Messrs~Lamport and Mittelbach just forgot about token +% registers when they were writing the code. Maybe I ought to rewrite the +% thing properly some time. Sigh. +% +% As a sort of postscript to the above, I \emph{have} rewritten the +% \env{tabular} environment, and made a damned fine job of it, in my +% oh-so-humble opinion. All this \env{eqnarray} stuff has been remoulded +% in terms of the generic column-defining things in \package{mdwtab}. +% You're reading the documentation of the old version, which isn't +% supported any more, so any bugs here are your own problem.} +% +% \begin{macrocode} +\def\eqa@addraw#1{\expandafter\toks@\expandafter{\the\toks@#1}} +% \end{macrocode} +% +% Now for some cleverness again. In order to put all the right bits of +% |\tabskip| glue in the right places we must \emph{not} terminate each +% column until we know what the next one is. We set |\if@tempswa| to be +% |true| if there's a column waiting to be closed (so it's initially +% |false|). The following macro adds a column correctly, assuming we're in +% a formula. Other column types make their own arrangements. +% +% \begin{macrocode} +\def\eqa@add#1{% + \if@tempswa% + \eqa@addraw{\tabskip\eqainskip}% + \else% + \eqa@addraw{#1}% + \fi% + \@tempswatrue% +} +% \end{macrocode} +% +% Now to defining column types. Let's define a macro which allows us to +% define column types: +% +% \begin{macrocode} +\def\eqa@def#1{\expandafter\def\csname eqa@char@#1\endcsname} +% \end{macrocode} +% +% Now we can define the column types. Each column type must loop back to +% |\eqa@preamble| once it's finished, to read the rest of the preamble +% string. Note the positioning of ord atoms in the stuff below. This will +% space out relations and binops correctly when they occur at the edges of +% columns, and won't affect ord atoms at the edges, because ords pack +% closely. +% +% First the easy onces. Just stick |\hfil| in the right places and +% everything will be all right. +% +% \begin{macrocode} +\eqa@def r{\eqa@add{\hfil$\eqa@style##{}$}\eqa@preamble} +\eqa@def c{\eqa@add{\hfil$\eqa@style{}##{}$\hfil}\eqa@preamble} +\eqa@def l{\eqa@add{$\eqa@style{}##$\hfil}\eqa@preamble} +\eqa@def x{\eqa@add{\hfil$\eqa@style##$\hfil}\eqa@preamble} +% \end{macrocode} +% +% Now for the textual ones. This is also fairly easy. +% +% \begin{macrocode} +\eqa@def T#1{% + \eqa@add{}% + \if#1l\else\eqa@addraw{\hfil}\fi% + \eqa@addraw{##}% + \if#1r\else\eqa@addraw{\hfil}\fi% + \eqa@preamble% +} +% \end{macrocode} +% +% Sort of split types of equations. I mustn't use |\rlap| here, or +% everything goes wrong -- |\\| doesn't get noticed by \TeX\ in the same way +% as |\cr| does. +% +% \begin{macrocode} +\eqa@def L{\eqa@add{\hb@xt@\z@{$\eqa@style##$\hss}\qquad}\eqa@preamble} +% \end{macrocode} +% +% The \lit{:} column type is fairly simple. We set |\tabskip| up to make +% lots of space and close the current column, because there must be one.^^A +% \footnote{This is an assumption.} +% +% \begin{macrocode} +\eqa@def :{% + \eqa@addraw{\tabskip\eqacolskip&}\@tempswafalse\eqa@preamble% +} +\eqa@def q{\eqa@add{\quad}\@tempswafalse\eqa@preamble} +% \end{macrocode} +% +% The other column types just insert given text in an appropriate way. +% +% \begin{macrocode} +\eqa@def >#1{\eqa@add{#1}\@tempswafalse\eqa@preamble} +\eqa@def <#1{\eqa@addraw{#1}\eqa@preamble} +% \end{macrocode} +% +% Finally, the magical \lit{!} column type, which sets the equation number. +% We set up the |\tabskip| glue properly, tab on, and set the flag which +% marks the final column. +% +% \begin{macrocode} +\eqa@def !#1{% + \eqa@addraw{\tabskip\eqacloseskip&\@eqalasttrue#1}\eqa@preamble% +} +% \end{macrocode} +% +% \subsubsection{Newline codes} +% +% Newline sequences (|\\|) get turned into calls of |\@eqncr|. The job is +% fairly simple, really. However, to avoid reading `|&|' characters +% prematurely, we set up a magic brace (from the \package{array} package -- +% this avoids creating ord atoms and other nastyness). +% +% \begin{macrocode} +\def\@eqncr{% + \iffalse{\fi\ifnum0=`}\fi% + \@ifstar{\eqacr@i{\@M}}{\eqacr@i{\interdisplaylinepenalty}}% +} +\def\eqacr@i#1{\@ifnextchar[{\eqacr@ii{#1}}{\eqacr@ii{#1}[\z@]}} +\def\eqacr@ii#1[#2]{% + \ifnum0=`{}\fi% + \eqa@eqnum% + \noalign{\penalty#1\vskip#2\relax}% +} +% \end{macrocode} +% +% \subsubsection{Setting equation numbers} +% +% Before we start, we need to generalise the flush-left number handling bits. +% The macro |\eqa@eqpos| will put its argument in the right place. +% +% \begin{macrocode} +\if@leqno + \def\eqa@eqpos#1{% + \hb@xt@.01\p@{}\rlap{\normalfont\normalcolor\hskip-\displaywidth#1}% + } +\else + \def\eqa@eqpos#1{\normalfont\normalcolor#1} +\fi +% \end{macrocode} +% +% First we need to move into the right column. Then we just set the equation +% number appropriately. There is some subtlety here, ish. The |\relax| is +% important, to delay expansion of the |\if|\dots\ until the new column has +% been started. The two helper macros are important too, to hide `|&|'s and +% `|\cr|'s from \TeX's scanner until the right time. +% +% \begin{macrocode} +\def\eqa@eqnum{% + \relax% + \if@eqalast\expandafter\eqa@eqnum@i\else\expandafter\eqa@eqnum@ii\fi% +} +\def\eqa@eqnum@i{% + \if@eqnsw% + \eqa@eqpos{(\theequation)}\stepcounter{equation}% + \else% + \eqa@eqpos\eqa@number% + \fi% + \global\@eqnswtrue% + \cr% +} +\def\eqa@eqnum@ii{&\eqa@eqnum} +% \end{macrocode} +% +% \subsubsection{Numbering control} +% +% This is trivial. We set the |\if@eqnsw| flag to be |false| and store the +% text in a macro. +% +% \begin{macrocode} +\let\nonumber\relax +\newcommand\nonumber[1][]{\global\@eqnswfalse\global\def\eqa@number{#1}} +% \end{macrocode} +% +% \subsubsection{Closing the environments off} +% +% This is really easy. Set the final equation number, close the |\halign|, +% tidy up the equation counter (it's been stepped once too many times) and +% close the display. +% +% \begin{macrocode} +\def\endeqnarray{% + \eqa@eqnum% + \egroup% + \global\advance\c@equation\m@ne% + $$% + \global\@ignoretrue% +} +\expandafter\let\csname endeqnarray*\endcsname\endeqnarray +% \end{macrocode} +% +% Now start up the other package again. +% +% \begin{macrocode} +%</oldeqnarray> +%<*package> +% \end{macrocode} +% +% \end{old-eqnarray} +% +% That's all there is. Byebye. +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \hfill Mark Wooding, \today +% +% \Finale +\endinput diff --git a/Master/texmf-dist/source/latex/mdwtools/mdwtab.dtx b/Master/texmf-dist/source/latex/mdwtools/mdwtab.dtx new file mode 100644 index 00000000000..84d67f07242 --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/mdwtab.dtx @@ -0,0 +1,5441 @@ +% \begin{meta-comment} +% +% $Id: mdwtab.dtx,v 1.8 1996/12/09 23:20:42 mdw Exp $ +% +% Another rewrite of the tabular environment, and maths alignments +% +% (c) 1996 Mark Wooding +% +%----- Revision history ----------------------------------------------------- +% +% $Log: mdwtab.dtx,v $ +% Revision 1.8 1996/12/09 23:20:42 mdw +% (\tab@setstrut): Fixed so that it uses \dimen\tw@ for the strut depth, +% as advertised. +% +% Revision 1.7 1996/11/29 21:59:16 mdw +% Fixed a little formatting mistake in a syntax diagram, and switched over +% to the new syntax diagram commands on the grounds that they're slightly +% less messy. Maybe. +% +% Revision 1.6 1996/11/19 20:54:33 mdw +% Entered into RCS +% +% +% \end{meta-comment} +% +% \begin{meta-comment} <general public licence> +%% +%% mdwtab package -- another rewrite of the tabular environment, etc. +%% Copyright (c) 1996 Mark Wooding +%% +%% This program is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation; either version 2 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program; if not, write to the Free Software +%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +%% +% \end{meta-comment} +% +% \begin{meta-comment} <Package preambles> +%<+mdwtab>\NeedsTeXFormat{LaTeX2e} +%<+mdwtab>\ProvidesPackage{mdwtab} +%<+mdwtab> [1998/04/28 1.9 Table typesetting with style] +%<+mathenv>\NeedsTeXFormat{LaTeX2e} +%<+mathenv>\ProvidesPackage{mathenv} +%<+mathenv> [1998/04/28 1.9 Various maths environments] +% \end{meta-comment} +% +% \CheckSum{2758} +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%% +% +% \begin{meta-comment} +% +%<*driver> +\input{mdwtools} +\describespackage{mdwtab} +\describespackage{mathenv} +\addcontents{lot}{\listoftables} +\mdwdoc +%</driver> +% +% \end{meta-comment} +% +%^^A------------------------------------------------------------------------- +% \renewcommand{\tabstyle}{\small} +% +% \section{User guide} +% +% +% The \package{mdwtab} package contains a reimplementation of the standard +% \LaTeX\ \env{tabular} and \env{array} environments. This is not just an +% upgraded version: it's a complete rewrite. It has several advantages over +% the official \package{array} package (not raw \LaTeX's, which is even less +% nice), and it's more-or-less compatible. Most of these are rather +% technical, I'll admit. +% +% \begin{itemize} +% +% \item The newcolumn system is properly and perfectly integrated into the +% system. There are now \emph{no} `primitive' column types -- all the +% standard types are created as user-defined columns. +% +% \item You can define entirely different table-like environments using the +% equipment here. It's still hard work, although less so than before. +% I'll do an example of this some time. +% +% \item Construction of the preamble is generally much tidier. I've used +% token registers rather than |\edef|, and it's all done very nicely. +% +% \item Fine spacing before and after rules (described by DEK as `a mark of +% quality') is now utterly trivial, since the preamble-generator will +% store the appropriate information. +% +% \item You can use \env{array} in LR and paragraph modes without having +% to surround it with `|$|' signs. +% +% \item Usually you don't want tables in the middle of paragraphs. For these +% cases, I've provided a simpler way to position the table +% horizontally. +% +% \item Footnotes work properly inside \env{tabular} environments (hoorah!). +% You can `catch' footnotes using the \env{minipage} environment if +% you like. (It uses an internal version of the \package{footnote} +% package to handle footnotes, which doesn't provide extra goodies like +% the \env{footnote} environment; you'll need to load the full package +% explicitly to get them.) +% +% \item Standard \LaTeX\ tabular environments have a problem with lining up +% ruled tables. The |\firsthline| command given in the \textit{\LaTeX\ +% Companion} helps a bit, but it's not really good enough, and besides, +% it doesn't \emph{actually} line the text up right after all. The +% \package{mdwtab} package does the job properly to begin with, so you +% don't need to worry. +% +% \end{itemize} +% +% I've tested the following packages with \package{mdwtab}, and they all +% work. Some of the contortions required to make them work weren't pleasant, +% but you don't need to know about them. By a strange coincidence, all the +% packages were written by David Carlisle. Anyway, here's the list: +% \begin{itemize} +% \item The quite nice \package{dcolumn} package. +% \item The more useful \package{delarray} package. +% \item The rather spiffy \package{hhline} package. +% \item The truly wonderful \package{tabularx} package. +% \item The utterly magnificent \package{longtable} package. +% \end{itemize} +% +% Note that I've looked at \package{supertabular} as well: it won't work, so +% use \package{longtable} instead, 'cos it's much better. +% +% +% \subsection{The downside} +% +% There's no such thing as a free lunch. The \package{mdwtab} environment +% is not 100\% compatible with the \env{tabular} environment found in +% \LaTeXe\ or the \package{array} package. +% +% The differences between \package{mdwtab} and \LaTeXe's \env{tabular} +% environment are as follows: +% +% \begin{itemize} \synshorts \let\`=\lq +% +% \item The vertical spacing in \env{array} environments is different to +% that in \env{tabular} environments. This produces more attractive +% results in most mathematical uses of \env{array}s, in the author's +% opinion. The spacing can be modified by playing with length +% parameters. +% +% \item The presence of horizontal and vertical rules will alter the spacing +% of the table (so a pair of columns separated by a `|' is wider than +% a pair with no separation by "\\arrayrulewidth". This does mean that +% horizontal and vertical rules match up properly -- the usual \LaTeX\ +% environment makes the horizontal rules stop just short of the edge +% of the table, making an ugly mess (check out the \textit{\LaTeX\ +% book} if you don't believe me -- page~62 provides a good example). +% The \package{array} package handles rules in the same way as +% \package{mdwtab}. +% +% \setbox0=\hbox{\footnotesize`\\def\\xcs{\\tabskip=\\fill}'} +% \setbox2=\hbox{\footnotesize`...@{\\span\\xcs}...'} +% \item In common with the \package{array} package, there are some +% restrictions on the use of the "\\extracolsep" command in preambles: +% you may use at most one "\\extracolsep" command in each `@' or `!' +% expression. Also, you can't say +% \begin{listing} +%\newcommand{\xcs}{\extracolsep{\fill}} +% \end{listing} +% and then expect something like `...@{\\xcs}...' to actually work -- +% the "\\extracolsep" mustn't be hidden inside any other +% commands. Because things like `@' expressions aren't expanded at +% the time, "\\extracolsep" has to be searched and processed +% \`by hand'.\footnote{^^A +% All \cs{extracolsep} does is modify the \cs{tabskip} glue, so +% if you were an evil \TeX\ hacker like me, you could just say +% \unhbox0\ and put \unhbox2\ in your preamble. That'd work nicely. +% It also works with the \package{array} package.} +% +% \item Control sequences (commands) in a table's preamble aren't expanded +% before the preamble is read. In fact, commands in the preamble are +% considered to be column types, and their names are entirely +% independent of normal \LaTeX\ commands. No column types of this +% nature have yet been defined\footnote{^^A +% There used to be an internal \cs{@magic} type used by +% \env{eqnarray}, but you're not supposed to know about that. +% Besides, it's not there any more.} +% but the possibility's always there. Use the "\\newcolumntype" or +% "\\coldef" commands to define new column types. +% +% \item The preamble parsing works in a completely different way. There is +% a certain amount of compatibility provided, although it's heavily +% geared towards keeping \package{longtable} happy and probably won't +% work with other packages. +% +% \item Obscure constructs which were allowed by the old preamble parser but +% violate the syntax shown in the next section (e.g., `|@{}|' to +% suppress the "\\doublerulesep" space between two vertical rules, +% described in \textit{The \LaTeX\ Companion} as \`a misuse of the +% `@{...}' qualifier') are now properly outlawed. You will be given +% an error message if you attempt to use such a construction. +% +% \item The `*' forms (which repeat column types) are now expanded at a +% different time. Previously, preambles like `c@*{4}{{:}@}{--}c' +% were considered valid (the example would expand to +% `c@{:}@{:}@{:}@{:}@{--}c'), because `*'s were expanded before the +% preamble was actually parsed. In the new system, `*' is treated +% just like any other preamble character (it just has a rather odd +% action), and preambles like this will result in an error (and +% probably a rather confusing one). +% +% \end{itemize} +% +% There are also several incompatibilities between \package{mdwtab} and +% \package{array}: +% +% \begin{itemize} \synshorts \let\`=\lq +% +% \item Because of the way "\\newcolumntype" works in the \package{array} +% package, a horrid construction like +% \begin{listing} +%\newcolumntype{x}{{:}} +%\begin{tabular}{|c!xc|} +% \end{listing} +% is considered to be valid, and is interpreted as `|c!{:}c|'. My +% reading of pages~54 and~55 of the \textit{\LaTeX\ book} tells me +% that this sort of thing is forbidden in normal \LaTeX\ commands. +% The \package{mdwtab} preamble parser now treats column type letters +% much more like commands with the result that the hacking above won't +% work any more. The construction above would actually be interpreted +% as `|c!{x}c|' (i.e., the `x' column type wouldn't be expanded to +% `{:}' because the parser noticed that it was the argument to the +% `!' modifier\footnote{^^A +% This is a direct result of the way \TeX\ treats undelimited +% arguments. See chapters~5 and~20 of \textit{The \TeX book} for +% more information about how grouping affects argument reading.}). +% +% \item Most of the points above, particularly those relating to the +% handling of the preamble, also apply to the \package{array} package. +% it's not such an advance over the \LaTeXe\ version as everyone said +% it was. +% +% \end{itemize} +% +% +% \subsection{Syntax} +% +% \DescribeEnv{tabular} +% \DescribeEnv{tabular*} +% \DescribeEnv{array} +% So that everyone knows where I stand, here's a complete syntax for my +% version of the \env{tabular} environment, and friends +% +% \begin{grammar} +% +% <tabular-env> ::= \[[ +% "\\begin" +% \begin{stack} +% "{tabular}" \\ "{tabular*}" "{" <length> "}" \\ +% "{array}" \\ "{smarray}" +% \end{stack} +% \[ "[" <position-arg> "]" \] +% "{" <preamble> "}" <text> +% "\\end" +% \( "{tabular}" \\ "{tabular*}" \\ "{array}" \\ "{smarray}" \) +% \]] +% +% <position-arg> ::= (see below) +% +% <preamble> ::= \[[ +% <first-column> +% \[ \< <column> \> \] +% \]] +% +% <first-column> ::= \[[ \[ <rule> \] <column> \]] +% +% <column> ::= \[[ +% \[ <spacing> \] \[ \< <user-pre-text> \> \] <column-type> +% \[ \< <user-post-text> \> \] \[ <spacing> \] \[ <rule> \] +% \]] +% +% <spacing> ::= \[[ "@" "{" <text> "}" \]] +% +% <user-pre-text> ::= \[[ ">" "{" <text> "}" \]] +% +% <column-type> ::= \[[ +% \begin{stack} +% \[ "T" \\ "M" \] \( "l" \\ "c" \\ "r" \) \\ +% \( "p" \\ "m" \\ "b" \) "{" <length> "}" \\ +% "#" "{" <raw-pre-text> "}" "{" <raw-post-text> "}" +% \end{stack} +% \]] +% +% <user-post-text> ::= \[[ "<" "{" <text> "}" \]] +% +% <rule> ::= \[[ \( "|" \\ "!" "{" <text> "}" \) \]] +% +% \end{grammar} +% +% If you examine the above very carefully, you'll notice a slight deviation +% from the original -- an |@|-expression \emph{following} a rule is +% considered to be part of the \emph{next} column, not the current one. This +% is, I think, an almost insignificant change, and essential for some of the +% new features. You'll also notice the new |#| column type form, which +% allows you to define new real column types instead of just modifying +% existing ones. It's not intended for direct use in preambles -- it's +% there mainly for the benefit of people who know what they're doing and +% insist on using |\newcolumntype| anyway. +%% +% The actual column types are shown in table~\ref{tbl:columns}. +% +% \begin{table} +% \begin{tabular}[C]{| >{\synshorts} c | m{3in} |} \hlx{hv[1]} +% +% \multicolumn{2}{|c|}{\bf Column types} \\ \hlx{v[1]hv} +% \bf Name & \bf Meaning \\ \hlx{vhv.} +% "l" & Left aligned text (\env{tabular}) or +% equation (\env{array}). \\ \hlx{.} +% "c" & Centred text (\env{tabular}) or +% equation (\env{array}). \\ \hlx{.} +% "r" & Right aligned text (\env{tabular}) or +% equation (\env{array}). \\ \hlx{vhv.} +% "Ml", "Mc" and "Mr" & Left, centre and right aligned +% equations.* \\ \hlx{.} +% "Tl", "Tc" and "Tr" & Left, centre and right aligned +% text.* \\ \hlx{vhv.} +% "p{"<width>"}" & Top aligned paragraph with the given +% width. \\ \hlx{.} +% "m{"<width>"}" & Vertically centred paragraph with +% the given width. \\ \hlx{.} +% "b{"<width>"}" & Bottom aligned paragraph with the +% given width. \\ \hlx{vhv.} +% "#{"<pre>"}{"<post>"}" & User defined column type: +% \<pre> is inserted before the +% cell entry, \<post> is inserted +% afterwards.* \\ \hlx{vhhv[1]} +% +% \multicolumn{2}{|c|}{\bf Other modifier characters} \\ \hlx{v[1]hv} +% \bf Name & \bf Meaning \\ \hlx{vhv.} +% "|" & Inserts a vertical rule between +% columns. \\ \hlx{.} +% "!{"<text>"}" & Inserts \<text> between columns, +% treating it as a vertical rule. \\ \hlx{vhv.} +% "@{"<text>"}" & Inserts \<text> instead of the +% usual intercolumn space. \\ \hlx{vhv.} +% ">{"<text>"}" & Inserts \<text> just before the +% actual column entry. \\ \hlx{.} +% "<{"<text>"}" & Inserts \<text> just after the +% actual column entry. \\ \hlx{vhv.} +% "*{"<count>"}{"<chars>"}" & Inserts \<count> +% copies of the \<chars> into the +% preamble. \\ \hlx{vhs} +% +% \multicolumn{2}{@{}l}{* This column type is a new feature} +% \end{tabular} +% +% \caption{\package{array} and \package{tabular} column types and modifiers} +% \label{tbl:columns} +% \end{table} +% +% Now that's sorted everything out, there shouldn't be any arguments at all +% about what a column means. +% +% The lowercase \<position-arg>s \lit{t}, \lit{c} and \lit{b} do exactly +% what they did before: control the vertical positioning of the table. The +% uppercase ones control the \emph{horizontal} positioning -- this is how you +% create \emph{unboxed} tables. You can only create unboxed tables in +% paragraph mode. +% +% Note that unboxed tables still can't be broken across pages. Use +% the \package{longtable} package for this, because it already does an +% excellent job. +% +% \DescribeMacro{\tabpause} +% One thing you can to with unboxed tables, however, is to `interrupt' them, +% do some normal typesetting, and then continue. This is achieved by the +% |\tabpause| command: its argument is written out in paragraph mode, and +% the table is continued after the argument finishes. +% Note that it isn't a real argument as far as commands like |\verb| are +% concerned -- they'll work inside |\tabpause| without any problems. +% +% \DescribeMacro{\vline} +% The |\vline| command draws a vertical rule the height of the current table +% cell (unless the current cell is being typeset in paragraph mode -- it +% only works in the simple LR-mode table cells, or in \lit{@} or \lit{!} +% modifiers). It's now been given an optional argument which gives the +% width of the rule to draw: +% +% { \let\tabstyle=\relax +% \begin{demo}{An example of \cmd\vline} +%\large +%\begin{tabular} +% {| c !{\vline[2pt]} c | c |} +% \hlx{hv} +% \bf A & \it B & \sf C \\ +% \hlx{vhv} +% \bf D & \it E & \sf F \\ +% \hlx{vh} +%\end{tabular} +% \end{demo} +% } +% +% \DescribeMacro{smarray} +% You've probably noticed that there's an unfamiliar environment mentioned +% in the syntax shown above. The \env{smarray} environment produces a +% `small' array, with script size cells rather than the normal full text +% size cells. I've seen examples of this sort of construction\footnote{^^A +% There's a nasty use of \env{smallmatrix} in the |testmath.tex| file which +% comes with the \package{amslatex} distribution. It's actually there to +% simulate a `smallcases' environment, which the \package{mathenv} package +% includes, based around \env{smarray}.} +% being implemented by totally unsuitable commands. Someone may find it +% handy. +% +% +% \subsection{An updated \cs{cline} command} +% +% \DescribeMacro{\cline} +% The standard \LaTeX\ |\cline| command has been updated. As well as just +% passing a range of columns to draw lines through, you can now pass a comma +% separated list of column numbers and ranges: +% +% \begin{grammar} +% <cline-cmd> ::= \[[ +% "\\cline" "{" \< <number> \[ "-" <number> \] \\ "," \> "}" +% \]] +% \end{grammar} +% +% The positioning of the horizontal lines has also been improved a bit, so +% that they meet up with the vertical lines properly. Displays like the one +% in the example below don't look good unless this has been done properly. +% +% {\let\tabstyle\relax +% \begin{demo}[w]{A \cs{cline} example} +%\newcommand{\mc}{\multicolumn{1}} +%\begin{tabular}[C]{|c|c|c|c|} \cline{2,4} +% \mc{c|}{one} & two & three & four \\ \hline +% five & six & seven & \mc{c}{eight} \\ \cline{1,3} +%\end{tabular} +% \end{demo} +% } +% +% \subsection{Spacing control} +% +% One of the most irritating things about \LaTeX's tables is that there isn't +% enough space around horizontal rules. Donald Knuth, in \textit{The +% \TeX book}, describes addition of some extra vertical space here as `a mark +% of quality', and since \TeX\ was designed to produce `beautiful documents' +% it seems a shame that \LaTeX\ doesn't allow this to be done nicely. Well, +% it does now. +% +% \DescribeMacro{\vgap} +% The extra vertical space is added using a command |\vgap|, with the +% following syntax: +% +% \begin{grammar} +% +% <vgap-cmd> ::= \[[ +% "\\vgap" \[ "[" <which-cols> "]" \] "{" <length> "}" +% \]] +% +% <which-cols> ::= \[[ \< <number> \[ "-" <number> \] \\ "," \> \]] +% +% \end{grammar} +% +% This command must appear either immediately after the beginning of the +% table or immediately after the |\\| which ends a row. (Actually, there are +% other commands which also have this requirement -- you can specify a +% collection of them wherever you're allowed to give any one.) It adds some +% vertical space (the amount is given by the \<length>) to the table, +% making sure that the vertical rules of the table are extended correctly. +% +% The |\vgap| command relies on information stored while your table preamble +% is being examined. However, it's possible that you might not want some +% of the rules drawn (e.g., if you've used |\multicolumn|). The optional +% \<which-cols> argument allows you to specify which rules are \emph{not} +% to be drawn. You can specify either single column numbers or ranges. The +% rule at the very left hand side is given the number~0; the rules at the +% end of column~$n$ are numbered~$n$. It's easy really. +% +% \DescribeMacro{\hlx} +% Using |\vgap| is all very well, but it's a bit cumbersome, and takes up a +% lot of typing, especially when combined with |\hline| commands. The |\hlx| +% command tries to tidy things. +% +% The syntax is simple: +% \begin{grammar} +% +% <hlx-cmd> ::= \[[ +% "\\hlx" "{" +% \begin{rep} +% \begin{stack} +% "h" \\ +% \tok{"v["<which-cols>"]["<length>"]"} \\ +% \tok{"s["<length>"]"} \\ +% \tok{"c{"<which-cols>"}"} \\ +% "b" \\ +% \tok{"/["<number>"]"} \\ +% "." +% \end{stack} +% \end{rep} +% "}" +% \]] +% +% \end{grammar} +% The argument works a bit like a table preamble, really. Each letter is a +% command. The following are supported: +% +% \begin{description} +% +% \item [\lit*{h}] Works just like |\hline|. If you put two adjacent to each +% other, a gap will be put between them. +% +% \item [\lit*{v[}\<which-cols>\lit*{][}\<length>\lit*{]}] Works +% like \syntax{"\\vgap["<which-cols>"]{"<length>"}"}. If the +% \<length> is omitted, the value of |\doublerulesep| is used. +% This usually looks right. +% +% \item [\lit*{s[}\<length>\lit*{]}] Leaves a vertical gap with the +% given size. If you omit the \<length> then |\doublerulesep| is +% used. This is usually right. +% +% \item [\lit*{c\char`\{}\<which-cols>\lit*{\char`\}}] Works just like +% |\cline|. +% +% \item [\lit*{b}] Inserts a backspace the width of a rule. This is useful +% when doing \package{longtable}s. +% +% \item [\lit*{/[}\<number>\lit*{]}] Allows a page break in a table. Don't +% use this except in a \env{longtable} environment. The \<number> +% works exactly the same as it does in the |\pagebreak| command, +% except that the default is 0, which just permits a break without +% forcing it. +% +% \item [\lit*{.}] (That's a dot) Starts the next row of the table. No +% more characters may follow the dot, and no |\hline|, |\hlx|, |\vgap| +% or |\multicolumn| commands may be used after it. You don't have to +% include it, and most of the time it's totally useless. It can be +% handy for some macros, though. I used it in (and in fact added it +% especially for) the table of column types. +% +% \end{description} +% +% An example of the use of |\hlx| is given, so you can see what's going on. +% +% \begin{figure} +% \let\tabstyle\relax +% \begin{demo}[w]{Beautiful table example} +%\newcommand{\zerowidth}[1]{\hbox to 0pt{\hss#1\hss}} +%\setlength{\tabcolsep}{1.5em} +%\begin{tabular}[C]{| r | c | r |} \hlx{hv[1,2]} +% \multicolumn{3}{|c|}{\bf AT\&T Common Stock} \\ \hlx{v[1,2]hv} +% \multicolumn{1}{|c|}{\zerowidth{\bf Year}} & +% \multicolumn{1}{c|}{\zerowidth{\bf Price}} & +% \multicolumn{1}{c|}{\zerowidth{\bf Dividend}} \\ \hlx{vhv} +% 1971 & 41--54 & \$2.60 \\ +% 2 & 41--54 & 2.70 \\ +% 3 & 46--55 & 2.87 \\ +% 4 & 40--53 & 3.24 \\ +% 5 & 45--52 & 3.40 \\ +% 6 & 51--59 & .95\rlap{*} \\ \hlx{vhs} +% \multicolumn{3}{@{}l}{* (first quarter only)} +%\end{tabular} +% \end{demo} +% \end{figure} +% +% +% \subsection{Creating beautiful long tables} +% +% You can use the |\vgap| and |\hlx| commands with David Carlisle's +% stunning \package{longtable} package. However, there are some things you +% should be away of to ensure that your tables always come out looking +% lovely. +% +% The \package{longtable} package will break a table at an |\hline| command, +% leaving a rule at the bottom of the page and another at the top of the +% next page. This means that a constructions like |\hlx{vhv}| will be +% broken into something like |\hlx{vh}| at the bottom of the page and +% |\hlx{hv}| at the top of the next. You need to design the table headers +% and footers with this in mind. +% +% However, there appears to be a slight problem:\footnote +% {You might very well call it a bug. I couldn't possibly comment.} +% if the footer starts with an |\hline|, and a page is broken at an |\hline|, +% then you get an extra thick rule at the bottom of the page. This is a bit +% of a problem, because if the rule isn't there in the footer and you get +% a break between two rows \emph{without} a rule between them, then the page +% looks very odd. +% +% If you want to do ruled longtables, I'd recommend that you proceed as +% follows: +% \begin{itemize} +% \item End header sections with an |\hlx{vh}|. +% \item Begin footer sections with an |\hlx{bh}|. +% \item Begin the main table with |\hlx{v}|. +% \item Insert |\hlx{vhv}| commands in the main table body as usual. +% \end{itemize} +% If \package{longtable} gets modified appropriately, the use of the \lit{b} +% command won't be necessary. +% +% Here's an example of the sort of thing you'd type. +% +% \begin{listinglist} \listingsize +% \verb"\begin{longtable}[c]{|c|l|} \hlx{hv}" \\ +% \verb"\bf Heading & \bf Also heading \\ \hlx{vh}" \\ +% \verb"\endhead" \\ +% \verb"\hlx{bh}" \\ +% \verb"\endfoot" \\ +% \verb"\hlx{v}" \\ +% \verb"First main & table line \\ \hlx{vhv}" \\ +% \verb"Lots of text & like this \\ \hlx{vhv}" \\ +% \null\quad\vdots \\ +% \verb"Lots of text & like this \\ \hlx{vhv}" \\ +% \verb"Last main & table line \\ \hlx{vh}" \\ +% \verb"\end{longtable}" +% \end{listinglist} +% +% +% \subsection{Rules and vertical positioning} +% +% In the \LaTeXe\ and \package{array.sty} versions of \env{tabular}, you run +% into problems if you try to use ruled tables together with the \lit{[t]} or +% \lit{[b]} position specifiers -- the top or bottom rule ends up being +% nicely lined up with the text baseline, giving you an effect which is +% nothing like the one you expected. The \textit{\LaTeX\ Companion} gives +% two commands |\firsthline| and |\lasthline| which are supposed to help with +% this problem. (These commands have since migrated into the \package{array} +% package.) Unfortunately, |\firsthline| doesn't do its job properly -- +% it gets the text position wrong by exactly the width of the table rules. +% +% The \package{mdwtab} package makes all of this automatic. It gets the +% baseline positions exactly right, whether or not you use rules. Earlier +% versions of this package required that you play with a length parameter +% called |\rulefudge|; this is no longer necessary (or even possible -- the +% length parameter no longer exists). The package now correctly compensates +% for all sorts of rules and |\vgap|s at the top and bottom of a table and +% it gets the positioning right all by itself. You've never had it so good. +% +% +% \subsection{User serviceable parts} +% +% There are a lot of parameters which you can modify in order to make arrays +% and tables look nicer. They are all listed in table~\ref{tbl:config}. +% +% \begin{table} +% \begin{tabular}[C]{| l | m{3in} |} \hlx{hv} +% \bf Parameter & \bf Meaning \\ \hlx{vhv} +% |\tabstyle| & A command executed at the beginning of +% a \env{tabular} or \env{tabular$*$} +% environment. By default does nothing. +% Change using |\renewcommand|. \\ \hlx{vhv} +% |\extrarowheight| & A length added to the height of every +% row, used to stop table rules +% overprinting ascenders. Default 0\,pt. +% Usage is deprecated now: use |\hlx| +% instead. \\ \hlx{vhv} +% |\tabextrasep| & Extra space added between rows in a +% \env{tabular} or \env{tabular$*$} +% environment (added \emph{before} any +% following |\hline|). Default 0\,pt. \\ +% |\arrayextrasep| & Analogous to |\tabextrasep|, but for +% \env{array} environments. Default +% 1\,jot (3\,pt). \\ +% |\smarrayextrasep| & Analogous to |\tabextrasep|, but for +% \env{smarray} environments. Default +% 1\,pt. \\ \hlx{vhv} +% |\tabcolsep| & Space added by default on each side of +% a table cell (unless suppressed by an +% \lit{@}-expression) in \env{tabular} +% environments. Default is defined by +% your document class. \\ +% |\arraycolsep| & Analogous to |\tabcolsep|, but for +% \env{array} environments. Default is +% defined by your document class. \\ +% |\smarraycolsep| & Analogous to |\tabcolsep|, but for +% \env{smarray} environments. Default +% is 3\,pt. \\ \hlx{vhv} +% |\arrayrulewidth| & The width of horizontal and vertical +% rules in tables. \\ +% |\doublerulesep| & Space added between two adjacent +% vertical or horizontal rules. Also +% used by |\hlx{v}|. \\ \hlx{vhv} +% |\arraystretch| & Command containing a factor to +% multiply the default row height. +% Default is defined by your document +% class (usually 1). \\ \hlx{vh} +% \end{tabular} +% +% \caption{Parameters for configuring table environments} +% \label{tbl:config} +% +% \end{table} +% +% +% \subsection{Defining column types} +% +% \DescribeMacro{\newcolumntype} +% The easy way to define new column types is using |\newcolumntype|. It +% works in more or less the same way as |\newcommand|: +% +% \begin{grammar} +% +% <new-col-type-cmd> ::= \[[ +% "\\newcolumntype" +% "{" <column-name> "}" +% \[ "[" <num-args> "]" \] +% \[ "[" <default-arg> "]" \] +% "{" <first-column> \[ \< <column> \> \] "}" +% \]] +% +% \end{grammar} +% +% (The \env{array.sty} implementation doesn't accept the \<default-arg> +% argument. I've no idea why not, 'cos it was very easy to implement.) +% +% \DescribeMacro{\colset} +% This implementation allows you to define lots of different sets of columns. +% You can change the current set using the |\colset| declaration: +% \begin{grammar} +% <colset-cmd> ::= \[[ "\\colset" "{" <set-name> "}" \]] +% \end{grammar} +% This leaves a problem, though: at any particular moment, the current +% column set could be anything, since other macros and packages can change +% it. +% +% \DescribeMacro{\colpush} +% \DescribeMacro{\colpop} +% What actually happens is that a stack of column sets is maintained. The +% |\colset| command just replaces the item at the top of the stack. The +% command |\colpush| pushes its argument onto the top of the stack, making +% it the new current set. The corresponding |\colpop| macro (which doesn't +% take any arguments) removes the top item from the stack, reinstating the +% previous current column set. +% +% \begin{grammar} +% <colpush-cmd> ::= \[[ "\\colpush" "{" <set-name> "}" \]] +% <colpop-cmd> ::= \[[ "\\colpop" \]] +% \end{grammar} +% +% The macros which manipulate the column set stack work \emph{locally}. +% The contents of the stack are saved when you open a new group. +% +% To make sure everyone behaves themselves properly, these are the rules for +% using the column set stack: +% +% \begin{itemize} +% +% \item Packages defining column types must ensure that they preserve the +% current column set. Either they must push their own column type +% and pop it off when they're finished defining columns, or they must +% avoid changing the stack at all, and use the optional arguments to +% |\coldef| and |\collet|. +% +% \item Packages must not assume that any particular column set is current +% unless they have made sure of it themselves. +% +% \item Packages must ensure that they pop exactly as much as they push. +% There isn't much policing of this (perhaps there should be more), +% so authors are encouraged to behave responsibly. +% +% \item Packages must change the current column set (using |\colset|) when +% they start up their table environment. This will be restored when +% the environment closes. +% +% \end{itemize} +% +% \DescribeMacro{\coldef} +% |\newcolumntype| is probably enough for most purposes. However, Real +% \TeX nicians, and people writing new table-generating environments, require +% something lower-level. +% +% \begin{grammar} +% <coldef-cmd> ::= \[[ +% "\\coldef" +% \[ "[" <set-name> "]" \] +% <col-name> <arg-template> "{" <replacement-text> "}" +% \]] +% \end{grammar} +% +% Note that this defines a column type in the current colset. It works +% almost exactly the same way as \TeX's primitive |\def|. There is a +% potential gotcha here: a |\tab@mkpream| token is inserted at the end of +% your replacement text. If you need to read an optional argument or +% something, you'll need to gobble this token before you carry on. The +% |\@firstoftwo| macro could be handy here: +% \begin{listing} +%\coldef x{\@firstoftwo{\@ifnextchar[\@xcolumn@i\@xcolumn@ii}}} +% \end{listing} +% This isn't a terribly pretty state of affairs, and I ought to do something +% about it. I've not seen any use for an optional argument yet, though. +% Note that if you do gobble the |\tab@mkpream|, it's your responsibility to +% insert another one at the very end of your macro's expansion (so that +% further preamble characters can be read). +% +% The replacement text is inserted directly. It's normal to insert preamble +% elements here. There are several to choose from: +% +% \begin{description} +% +% \item [Column items] provide the main `meat' of a column. You insert a +% column element by saying +% \syntax{"\\tabcoltype{"<pre-text>"}{"<post-text>"}"}. +% The user's text gets inserted between these two. (So do user pre- +% and post-texts. Bear this in mind.) +% +% \item [User pre-text items] work like the \lit{>} preamble command. You +% use the \syntax{"\\tabuserpretype{"<text>"}"} command to insert it. +% User pre-texts are written in \emph{reverse} order between the +% pre-text of the column item and the text from the table cell. +% +% \item [User post-text items] work like the \lit{<} preamble command. You +% use the \syntax{"\\tabuserposttype{"<text>"}"} command to insert it. +% Like user pre-texts, user post-texts are written in reverse order, +% between the table cell text and the column item post-text. +% +% \item [Space items] work like the \lit{@} preamble command. They're +% inserted with the \syntax{"\\tabspctype{"<text>"}"} command. +% +% \item [Rule items] work like the `\verb"|"' and \lit{!} commands. You +% insert them with the \syntax{"\\tabruletype{"<text>"}"} command. +% Note that the text is inserted by |\vgap| too, so it should contain +% things which adjust their vertical size nicely. If you really need +% to, you can test |\iftab@vgap| to see if you're in a |\vgap|. +% +% \end{description} +% +% \DescribeMacro{\collet} +% As well as defining columns, you can copy definitions (rather like |\let| +% allows you to copy macros). The syntax is like this: +% +% \begin{grammar} +% +% <collet-cmd> ::= \[[ +% \[ "[" <set-name> "]" \] <col-name> \[ "=" \] \[ "[" <set-name> "]" \] +% <col-name> +% \]] +% +% \end{grammar} +% +% (In other words, you can copy defintions from other column sets.) +% +% +% \subsection{Defining new table-generating environments} +% +% Quite a few routines are provided specifically to help you to define new +% environments which do alignment in a nice way. +% +% \subsubsection{Reading preambles} +% +% The main tricky bit in doing table-like environments is parsing preambles. +% No longer. +% +% \DescribeMacro{\tab@readpreamble} +% \DescribeMacro{\tab@doreadpream} +% The main parser routine is called |\tab@doreadpream|. Given a user +% preamble string as an argument, it will build an |\halign| preamble to +% return to you. However, the preamble produced won't be complete. This is +% because you can actually make multiple calls to |\tab@doreadpream| with +% bits of user preambles. The |\newcolumntype| system uses this mechanism, +% as does the \lit{*} (repeating) modifier. When there really is no more +% preamble to read, you need to \emph{commit} the heldover tokens to the +% output. The |\tab@readpreamble| routine will do this for you -- given a +% user preamble, it builds a complete output from it. +% +% A token register |\tab@preamble| is used to store the generated preamble. +% Before starting, you must iniitialise this token list to whatever you want. +% There's another token register, |\tab@shortline|, which is used to store +% tokens used by |\vgap|. For each column in the table, the list contains +% an |\omit| (to override the standard preamble) and an |\hfil| space taking +% up most of the column. Finally, for each rule item in the user preamble, +% the shortline list contains an entry of the form: +% \begin{quote} \synshorts +% "\\tab@ckr{"<column-number>"}{"<rule-text>"}" +% \end{quote} +% This is used to decide whether to print the rule or an empty thing of the +% same width. You probably ought to know that the very first column does +% \emph{not} have a leading |\omit| -- this is supplied by |\vgap| so that +% it can then look for optional arguments. +% +% \DescribeMacro{\tab@initread} +% As well as initialising |\tab@preamble| and emptying |\tab@shortline|, +% there are several other operations required to initialise a preamble read. +% These are all performed by the |\tab@initread| macro, although you may want +% to change some of the values for your specific application. For reference, +% the actions performed are: +% \begin{itemize} +% \item initialising the parser state by setting $|\tab@state| = +% |\tab@startstate|$; +% \item clearing the token lists |\tab@preamble| and |\tab@shortlist|; +% \item initialising the macros |\tab@tabtext|, |\tab@midtext|, and +% |\tab@multicol| to their default values of `|&|', +% `|\ignorespaces#\unskip|' and the empty token list respectively.^^A +% \footnote{^^A +% These are macros rather than token lists to avoid hogging all +% the token list registers. Actually, the package only allocates +% two, although it does use almost all of the temporary registers as +% well. Also, there's a lie: \cs{unskip} is too hamfisted to remove +% trailing spaces properly; I really use a macro called +% \cs{@maybe@unskip}} +% \item clearing the internal token list registers |\tab@pretext|, +% |tab@userpretext| and |\tab@posttext|; +% \item clearing the column counter |\tab@columns| to zero; +% \item clearing the action performed when a new column is started (by making +% the |\tab@looped| macro equal to |\relax|; this is used to make +% |\multicolumn| macro raise an error if you try to do more than one +% column); and +% \item setting up some other switches used by the parser (|\iftab@rule|, +% |\iftab@initrule| and |\iftab@firstcol|, all of which are set to be +% |true|). +% \end{itemize} +% +% The macro |\tab@multicol| is used by the |\multicolumn| command to insert +% any necessary items (e.g., struts) before the actual column text. If you +% set this to something non-empty, you should probably consider adding a +% call to the macro to the beginning of |\tab@preamble|. +% +% When parsing is finally done, the count register |\tab@columns| contains +% the number of columns in the alignment. Don't corrupt this value, because +% it's used for handling |\hline| commands. +% +% \subsubsection{Starting new lines} +% +% The other messy bit required by table environments is the newline command +% |\\|. There are nasty complications involved with starting new lines, some +% of which can be handled by this package, and some on which I can only give +% advice. +% +% \DescribeMacro{\tab@cr} +% The optional arguments and star-forms etc. can be read fairly painlessly +% using the |\tab@cr| command: +% +% \begin{grammar} +% <tabcr-cmd> ::= \[[ +% "\\tab@cr" <command> "{" <non-star-text> "}" "{" <star-text> "}" +% \]] +% \end{grammar} +% +% This will call your \<command> with two arguments. The first is the +% contents of the optional argument, or `|\z@|' if there wasn't one. The +% second is either \<star-text> or \<non-star-text> depending on +% whether the user wrote the $*$-form or not. +% +% Somewhere in your \<command>, you'll have to use the |\cr| primitive to +% end the table row. After you've done this, you \emph{must} ensure that you +% don't do anything that gets past \TeX's mouth without protecting it -- +% otherwise |\hline| and co.\ won't work. I usually wrap things up in a +% |\noalign| to protect them, although there are other methods. Maybe. +% +% You might like to have a look at the \env{eqnarray} implementation provided +% to see how all this gets put into practice. +% +% +% \subsection{The \env{mathenv} package alignment environments} +% +% The \env{mathenv} package provides several environments for aligning +% equations in various ways. They're mainly provided as a demonstration of +% the table handling macros in \package{mdwtab}, so don't expect great +% things. If you want truly beautiful mathematics, use +% \package{amsmath}.\footnote{^^A +% Particularly since nice commands like \cmd\over\ are being reactivated +% in a later release of \package{amsmath}.} +% However, the various environments do nest in an approximately useful way. +% I also think that the \env{matrix} and \env{script} environments provided +% here give better results than their \package{amsmath} equivalents, and +% they are certainly more versatile. +% +% \subsubsection{The new \env{eqnarray} environment} +% +% \DescribeEnv{eqnarray} +% \DescribeEnv{eqnarray*} +% As an example of the new column defining features, and because the original +% isn't terribly good, I've included a rewritten version of the +% \env{eqnarray} environment. The new implementation closes the gap between +% \env{eqnarray} and \AmSTeX\ alignment features. It's in a separate, +% package called \package{mathenv}, to avoid wasting your memory. +% +% \begin{grammar} +% +% <eqnarray-env> ::= \[[ +% <begin-eqnarray> \< <row> \\ "\\\\" \> <end-eqnarray> +% \]] +% +% <begin-eqnarray> ::= \[[ +% "\\begin" \( "{eqnarray}" \\ "{eqnarray*}" \) +% \[ "[" \< <eqa-column> \> "]" \] +% \]] +% +% <eqa-column> ::= \[[ +% \[ "q" \\ ":" \] +% \[ \< ">" "{" <pre-text> "}" \> \] +% \begin{stack} +% \[ "T" \] \( "r" \\ "c" \\ "l" \) \\ +% "L" \\ +% "x" +% \end{stack} +% \[ \< "<" "{" <post-text> "}" \> \] +% \]] +% +% <end-eqnarray> ::= \[[ +% "\\end" \begin{stack} "{eqnarray}" \\ "{eqnarray*}" \end{stack} +% \]] +% +% \end{grammar} +% +% Descriptions of the various column types are given in +% table~\ref{tbl:eqnarray}. +% +% \begin{table} +% \begin{tabular}[C]{| >{\synshorts} c | m{3in} |} \hlx{hv[1]} +% +% \multicolumn{2}{|c|}{\bf Column types} \\ \hlx{v[1]hv} +% \bf Name & \bf Meaning \\ \hlx{vhv.} +% "l" & Left aligned piece of equation. \\ \hlx{.} +% "c" & Centred piece of equation. \\ \hlx{.} +% "x" & Centred or flush-left whole equation +% (depending on \textsf{fleqn} option). \\ \hlx{.} +% "r" & Right aligned piece of equation. \\ \hlx{vhv.} +% "L" & Left aligned piece of equation whose +% width is considered to be 2\,em. \\ \hlx{vhv.} +% "Tl", "Tc" and "Tr" & Left, centre and right aligned +% text. \\ \hlx{vhhv[1]} +% +% \multicolumn{2}{|c|}{\bf Other modifier characters} \\ \hlx{v[1]hv} +% \bf Name & \bf Meaning \\ \hlx{vhv.} +% ":" & Leaves a big gap between equations. +% By default, the `chunks' separated by +% \lit{:}s are equally spaced on the +% line. \\ \hlx{.} +% "q" & Inserts 1\,em of space \\ \hlx{vhv.} +% ">{"<text>"}" & Inserts \<text> just before the +% actual column entry. \\ \hlx{.} +% "<{"<text>"}" & Inserts \<text> just after the +% actual column entry. \\ \hlx{vhv.} +% "*{"<count>"}{"<chars>"}" & Inserts \<count> +% copies of the \<chars> into the +% preamble. \\ \hlx{vh} +% \end{tabular} +% +% \caption{\package{eqnarray} column types and modifiers} +% \label{tbl:eqnarray} +% \end{table} +% +% The default preamble, if you don't supply one of your own, is \lit{rcl}. +% Most of the time, \lit{rl} is sufficient, although compatibility is more +% important to me. +% +% By default, there is no space between columns, which makes formul\ae\ in an +% \env{eqnarray} environment look just like formul\ae\ typeset on their own, +% except that things get aligned in columns. This is where the default +% \env{eqnarray} falls down: it leaves |\arraycolsep| space between each +% column making the thing look horrible. +% +% An example would be good here, I think. This one's from exercise 22.9 of +% the \textit{\TeX book}. +% +% \begin{demo}[w]{Simultaneous equations} +%\begin{eqnarray}[*3{rc}rl] +% 10w & + & 3x & + & 3y & + & 18z & = 1 \\ +% 6w & - & 17x & & & - & 5z & = 2 +%\end{eqnarray} +% \end{demo} +% +% Choosing a more up-to-date example, here's some examples from the +% \textit{\LaTeX\ Companion}. +% +% \begin{demo}[w]{Lots of equations} +%\begin{eqnarray}[rl:rl:lq] +% V_i &= v_i - q_i v_j, & X_i &= x_i - q_i x_j, & +% U_i = u_i, \qquad \mbox{for $i \ne j$} \\ +% V_j &= v_j, & X_j &= x_j & +% U_j u_j + \sum_{i \ne j} q_i u_i. \label{eq:A} +%\end{eqnarray} +% \end{demo} +% +% \begin{figure} +% \begin{demo}[w]{Plain text column and \cs{tabpause}} +%\begin{eqnarray}[rlqqTl] +% x &= y & by (\ref{eq:A}) \\ +% x' &= y' & by definition \\ +%\tabpause{and} +% x + x' &= y + y' & by Axiom~1 +%\end{eqnarray} +% \end{demo} +% \end{figure} +% +% The new features also mean that you don't need to mess about with +% |\lefteqn| any more. This is handled by the \lit{L} column type: +% +% \begin{demo}{Splitting example} +%\begin{eqnarray*}[Ll] +% w+x+y+z = \\ +% & a+b+c+d+e+ \\ +% & f+g+h+i+j +%\end{eqnarray*} +% \end{demo} +% +% Finally, just to prove that the spacing's right at last, here's another one +% from the \textit{Companion}. +% +% \begin{demo}{Spacing demonstration} +%\begin{equation} +% x^2 + y^2 = z^2 +%\end{equation} +%\begin{eqnarray}[rl] +% x^2 + y^2 &= z^2 \\ +% y^2 &< z^2 +%\end{eqnarray} +% \end{demo} +% +% Well, that was easy enough. Now on to numbering. As you've noticed, the +% equations above are numbered. You can use the \env{eqnarray$*$} +% environment to turn off the numbering in the whole environment, or say +% |\nonumber| on a line to suppress numbering of that one in particular. +% +% \DescribeMacro{\eqnumber} +% More excitingly, you can say |\eqnumber| to enable numbering for a +% particular equation, or \syntax{"\\eqnumber["<text>"]"} to choose what to +% show instead of the line number. This works for both starred and unstarred +% versions of the environment. Now |\nonumber| becomes merely a synonym for +% `|\eqnumber[]|'. +% +% A note for cheats: you can use the sparkly new \env{eqnarray} for simple +% equations by specifying \lit{x} as the column description. Who needs +% \AmSTeX?\ |;-)| +% +% \DescribeEnv{eqlines} +% \DescribeEnv{eqlines*} +% In fact, there's a separate environment \env{eqlines}, which is equivalent +% to \env{eqnarray} with a single \lit{x} column; the result is that you can +% insert a collection of displayed equations separated by |\\| commands. If +% you don't like numbering, use \env{eqlines$*$} insead. +% +% \subsubsection{The \env{eqnalign} environment} +% +% \DescribeEnv{eqnalign} +% There's a new environment, \env{eqnalign}, which does almost the same +% thing as \env{eqnarray} but not quite. It doesn't do equation numbers, +% and it wraps its contents up in a box. The result of this is that: +% +% \begin{itemize} +% +% \item You can use \env{eqnalign} for just a part of a formula. +% The \env{eqnarray} environment must take up the whole display. +% +% \item You can use \env{eqnalign} within \env{eqnarray} for extra fine +% alignment of subsidiary bits. +% +% \item You can break off from doing an \env{eqnarray} using the |\tabpause| +% command. You can't use |\tabpause| inside +% \env{eqnalign}.\footnote{^^A +% Well, technically speaking there's nothing to stop you. However, +% the results won't be pretty.} +% +% \end{itemize} +% +% The \env{eqnalign} environment works like this: +% +% \begin{grammar} +% +% <eqnalign-env> ::= \[[ +% <begin-eqnalign> <contents> <end-eqnalign> +% \]] +% +% <begin-eqnalign> ::= \[[ +% "\\begin" "{eqnalign}" +% \[ "[" \< <eqa-column> \> "]" \] +% \[ "[" \( "t" \\ "c" \\ "b" \) "]" \] +% \]] +% +% <end-eqnalign> ::= \[[ "\\end" "{eqnalign}" \]] +% +% \end{grammar} +% +% As the syntax suggests, the preamble for the \env{eqnalign} environment +% works exactly the same way as for \env{eqnarray}. Example time: another +% one from the \textit{\TeX book}. +% +% \begin{figure} +% \begin{demo}[w]{Example of \env{eqnalign}} +%\[ +% \left\{ \begin{eqnalign}[rl] +% \alpha &= f(z) \\ \beta &= f(z^2) \\ +% \gamma &= f(z^3) +% \end{eqnalign} \right\} +% \qquad +% \left\{ \begin{eqnalign}[rl] +% x &= \alpha^2 - \beta \\ y &= 2\gamma +% \end{eqnalign} \right\}. +%\] +% \end{demo} +% \end{figure} +% +% \DescribeMacro{\multicolumn} +% The |\multicolumn| command works correctly in both the \env{eqnarray} and +% \env{eqnalign} environments, although you should bear in mind that you +% should give \env{eqnarray} column types, not \env{array} ones. +% +% \subsubsection{A note on spacing in alignment environments} +% +% Most of the time, equations in \env{eqnarray} and \env{eqnalign} +% environments will be beautiful. However, there are some things you should +% bear in mind when you produce beautiful equations. +% +% The main problem with spacing is making sure that binary relations and +% binary operators have the correct amount of space on each side of them. +% The alignment environments insert `hidden' objects at the ends of table +% cells to assist with the spacing: \lit{l} column types have a hidden object +% on the left, \lit{r} types have a hidden object on the right, and \lit{c} +% types have a hidden object on \emph{both} ends. These hidden objects add +% the correct space when there's a binary operator or relation next to them. +% If some other sort of object is lurking there, no space is added. So far, +% so good. +% +% The only problem comes when you have something like this: +% +% \begin{demo}{How not to do an \env{eqnarray}} +%\begin{eqnarray*}[rcl] +% x + y & = & 12 \\ +% 2x - 5y & = & -6 +%\end{eqnarray*} +% \end{demo} +% +% The `$-$' sign in the second equation has been treated as a binary operator +% when really it should be a unary prefix operator, but \TeX\ isn't clever +% enough to know the difference. (Can you see the difference in the spacing +% between $-6$~and~${}-6$?) There are two possible solutions to the +% problem. You could wrap the `|-6|' up in a group (`|{-6}|'), or just the +% $-$ sign (`|{-}6|'). A better plan, though, is to get rid of the middle +% column altogether: +% +% \begin{demo}{How to do an \env{eqnarray}} +%\begin{eqnarray*}[rl] +% x + y & = 12 \\ +% 2x - 5y & = -6 +%\end{eqnarray*} +% \end{demo} +% +% Since the things in the middle column were the same width, it's not +% actually doing any good. Also, now that \TeX\ can see that the thing on +% the left of the `$-$' sign is a relation (the `$=$' sign), it will space +% the formula correctly. +% +% In this case, it might be even better to add some extra columns, and line +% up the $x$ and $y$ terms in the left hand side: +% +% \begin{demo}{Extra beautiful \env{eqnarray}} +%\begin{eqnarray*}[rrl] +% x + & y & = 12 \\ +% 2x - & 5y & = -6 +%\end{eqnarray*} +% \end{demo} +% +% ^^A Some hacking now to display box sizes. +% +% { +% \catcode`p=12 \catcode`t=12 +% \gdef\magni#1pt{#1} +% } +% +% \newcommand{\widthof}[1]{^^A +% \settowidth{\dimen0 }{#1}^^A +% \expandafter\magni\the\dimen0\,pt^^A +% } +% +% ^^A The text below makes an assumption which looks correct to me (I asked +% ^^A TeX, and it agreed with me), although in case anything changes, I want +% ^^A to be informed. +% +% \sbox0{$+$} \sbox2{$-$} \ifdim\wd0=\wd2\else% +% \errmessage{Assertion failed: `+' and `-' are different widths!} +% \fi +% +% There's no need to put the `$+$' and `$-$' operators in their own column +% here, because they're both \widthof{$+$} wide, even though they don't +% look it. +% +% \subsubsection{Configuring the alignment environments} +% +% There are a collection of parameters you can use to make the equation +% alignment environments (\env{eqnarray} and \env{eqnalign}) look the way +% you like them. These are all shown in table~\ref{tbl:eqnparms}. +% +% \begin{table} +% \begin{tabular}[C]{| l | p{3in} |} \hlx{hv} +% \bf Parameter & \bf Use \\ \hlx{vhv} +% |\eqaopenskip| & Length put on the left of an +% \env{eqnarray} environment. By +% default, this is |\@centering| (to +% centre the alignment) or |\mathindent| +% (to left align) depending on whether +% you're using the \textsf{fleqn} +% document class option. \\ +% |\eqacloseskip| & Length put on the right of an +% \env{eqnarray} environment. By +% default, this is |\@centering|, to +% align the environment correctly. \\ \hlx{vhv} +% |\eqacolskip| & Space added by the \lit{:} column +% modifier. This should be a rubber +% length, although it only stretches in +% \env{eqnarray}, not in \env{eqnalign}. +% The default value is 1\smallf1/2\,em +% with 1000\,pt of stretch. \\ +% |\eqainskip| & Space added at each side of a normal +% column. By default this is 0\,pt. \\ \hlx{vhv} +% |\eqastyle| & The maths style used in the alignment. +% By default, this is |\textstyle|, +% and you probably won't want to change +% it. \\ \hlx{vh} +% \end{tabular} +% +% \caption{Parameters for the \env{eqnarray} and \env{eqnalign} environments} +% \label{tbl:eqnparms} +% \end{table} +% +% +% \subsection{Other multiline equations} +% +% Sometimes there's no sensible alignment point for splitting equations. The +% normal thing to do under these circumstances is to put the first line way +% over to the left of the page, and the last line over to the right. (If +% there are more lines, I imagine we put them in the middle.) +% +% \DescribeEnv{spliteqn} +% \DescribeEnv{spliteqn*} +% The \env{spliteqn} environment allows you to do such splitting of +% equations. Rather than tediously describe it, I'll just give an example, +% because it's really easy. The $*$-version works the same, except it +% doesn't put an equation number in. +% +% \begin{figure} +% \begin{demo}[w]{A split equation} +%\begin{spliteqn} +% \sum_{1\le j\le n} +% \frac {1} { (x_j - x_1) \ldots (x_j - x_{j-1}) +% (x - x_j) (x_j - x_{j+1}) \ldots (x_j - x_n) } +% \\ +% = \frac {1} { (x - x_1) \ldots (x - x_n) }. +%\end{spliteqn} +% \end{demo} +% \end{figure} +% +% \DescribeEnv{subsplit} +% If you have a very badly behaved equation, you might want to split a part +% of it (say, a bit of a fraction), particularly if you're doing things in +% narrow columns. +% +% \begin{figure} +% \begin{demo}[w]{A \env{subsplit} environment} +%\begin{equation} +% \frac{ +% \begin{subsplit} +% q^{\frac{1}{2} n(n+1)}(ea; q^2)_\infty (eq/a; q^2)_\infty \\ +% (caq/e; q^2)_\infty (cq^2/ae; q^2)_\infty +% \end{subsplit} +% }{ +% (e; q)_\infty (cq/e; q)_\infty +% } +%\end{equation} +% \end{demo} +% \end{figure} +% +% \subsection{Matrices} +% +% Also included in the \package{mathenv} package is a collection of things +% for typesetting matrices. The standard \env{array} doesn't (in my opinion) +% provide the right sort of spacing for matrices. \PlainTeX\ provides some +% quite nice matrix handling macros, but they don't work in the appropriate +% \LaTeX\ way. +% +% \textbf{Warning:} These definitions will make old versions of +% \package{plain.sty} unhappy; newer versions correctly restore the +% Plain~\TeX\ macros |\matrix| and |\pmatrix|. +% +% \DescribeEnv{matrix} +% The simple way to do matrices is with the \env{matrix} environment. +% +% \begin{grammar} +% +% <matrix-env> ::= \[[ <begin-matrix> <contents> <end-matrix> \]] +% +% <begin-matrix> ::= \[[ "\\begin{matrix}" \[ "[" <matrix-cols> "]" \] \]] +% +% <matrix-cols> ::= \[[ +% \< \[ "[" \] \[ "T" \] \( "l" \\ "c" \\ "r" \) \> +% \]] +% +% <end-matrix> ::= \[[ "\\end{stack}" \]] +% +% \end{grammar} +% +% The \lit{l}, \lit{c} and \lit{r} columns are fairly obvious -- they align +% their contents in the appropriate way. The \lit{[} character is more +% complicated. It means `repeat the remaining column types forever', so a +% preamble of \lit{cc[lr} means `two centred columns, then alternating left- +% and right-aligned columns for as often as needed'. The default preamble, +% if you don't specify one, is \lit{[c} -- `any number of centred columns'. +% +% \DescribeMacro{\multicolumn} +% The |\multicolumn| command works correctly in matrices, although you should +% bear in mind that you should give \env{matrix} column types, not +% \env{array} ones. +% +% \DescribeEnv{pmatrix} +% The standard \env{matrix} environment doesn't put any delimiters around the +% matrix. You can use the standard |\left| and |\right| commands, although +% this is a bit nasty. The \env{pmatrix} environment will put parentheses +% around the matrix it creates; it's otherwise exactly the same as +% \env{matrix}. +% +% \DescribeEnv{dmatrix} +% A \env{dmatrix} environment is also provided. It takes two extra +% arguments: the left and right delimiter characters (without |\left| or +% |\right|). +% +% \begin{figure} +% \begin{demo}[w]{Various \env{matrix} environments} +%\[ \begin{matrix} 1 & 0 \\ 0 & -1 \end{matrix} \quad +% \begin{pmatrix} +% \cos\theta & \sin\theta \\ +% -\sin\theta & \cos\theta +% \end{pmatrix} \quad +% \begin{dmatrix}[] 0 & -i \\ i & 0 \end{dmatrix} +%\] +% \end{demo} +% \end{figure} +% +% \DescribeEnv{smatrix} +% Normal matrices always come out the same size; they don't change size +% according to the surrounding context (unfortunately). However, it can be +% occasionally useful to put matrices in running text, so you can talk about +% $A$ being $\bigl( \begin{smatrix} a & b \\ b & c \end{smatrix} \bigr)$ +% being its own transpose (i.e., $A = A^T$). This is accomplished using the +% \env{smatrix} (the `s' stands for `small' -- I thought that `smallmatrix' +% was too big to type inline). As well as inline text, the \env{smatrix} +% can be useful in displays, if the matrix is deep in a subformula. I can't +% think of any examples offhand, though. +% +% \DescribeEnv{spmatrix} +% \DescribeEnv{sdmatrix} +% The \env{smatrix} environment doesn't supply any delimiters, like +% \env{matrix}. There are \env{spmatrix} and \env{sdmatrix} environments +% which do, though. Note that delimiters have a tendency to get too big and +% mess up the line spacing -- I had to use explicitly |\big| delimiters +% in the above example. +% +% \DescribeEnv{pmatrix*} +% \DescribeEnv{spmatrix*} +% \DescribeEnv{sdmatrix*} +% All the small matrix environments have starred versions, which are more +% suitable for use in displays, since they have more space between the rows. +% They're intended for typesetting really big matrices in displays. +% +% \DescribeMacro{\ddots} +% \DescribeMacro{\vdots} +% The standard |\vdots| and |\ddots| commands don't produce anything at all +% nice in small matrices, so this package redefines them so that they scale +% properly to smaller sizes. +% +% \DescribeEnv{genmatrix} +% Actually, all these environments are special cases of one: \env{genmatrix}. +% This takes oodles of arguments: +% \begin{quote} \synshorts +% "\\begin{genmatrix}{"<matrix-style>"}{"<outer-style>"}" \\ +% \null \qquad "{"<spacing>"}{"<left-delim>"}{"<right-delim>"}" \\ +% \null \quad\vdots \\ +% "\\end{genmatrix}" +% \end{quote} +% The two `style' arguments should be things like |\textstyle| or +% |\scriptstyle|; the first, \<matrix-style>, is the style to use for the +% matrix elements, and the second, \<outer-style>, is the style to assume +% for the surrounding text (this affects the spacing within the matrix; it +% should usually be the same as \<matrix-style>). The \<spacing> is inserted +% between the matrix and the delimiters, on each side of the matrix. It's +% usually `|\,|' in full-size matrices, and blank for small ones. The +% delimiters are inserted around the matrices, and sized appropriately. +% +% \DescribeEnv{newmatrix} +% You can create your own matrix environments if you like, using the +% |\newmatrix| command. It takes two arguments, although they're a bit +% odd. The first is the name of the environment, and the second contains +% the arguments to pass to \env{genmatrix}. For example, the \env{pmatrix} +% environment was defined by saying +% +% \begin{listing} +%\newmatrix{pmatrix}{{\textstyle}{\textstyle}{\,}{(}{)}} +% \end{listing} +% +% If you don't pass all three arguments, then you end up requiring the +% user to specify the remaining ones. This is how \env{dmatrix} works. +% +% \DescribeEnv{script} +% Finally, although it's not really a matrix, stacked super- and subscripts +% follow much the same sorts of spacing rules. The \env{script} environment +% allows you to do this sort of thing very easily. It essentially provides +% a `matrix' with the right sort of spacing. The default preamble string is +% \lit{c}, giving you centred scripts, although you can say +% |\begin{script}[l]| for left-aligned scripts, which is better if the +% script is being placed to the right of its operator. If you're really +% odd, you can have more than one column. +% +% \begin{demo}{Example of \env{script}} +%\[ \mathop{{\sum}'}_{x \in A} +% f(x) +% \stackrel{\mathrm{def}}{=} +% \sum_{\begin{script} +% x \in A \\ x \ne 0 +% \end{script}} f(x) +%\] +% \end{demo} +% +% +% \subsection{Other \package{mathenv} environments} +% +% The \package{mathenv} package contains some other environments which may +% be useful, based on the enhanced \env{tabular} and \env{array} +% environments. +% +% \DescribeEnv{cases} +% The \env{cases} environment lets you say things like the following: +% +% \begin{demo}[w]{Example of \env{cases}} +%\[ P_{r-j} = \begin{cases} +% 0 & if $r-j$ is odd \\ +% r!\,(-1)^{(r-j)/2} & if $r-j$ is even +% \end{cases} +%\] +% \end{demo} +% +% The spacing required for this is a bit messy, so providing an environment +% for it is quite handy. +% +% \DescribeEnv{smcases} +% The \env{smcases} environment works the same way as \env{cases}, but with +% scriptsize lettering. +% +% \implementation +% +% +%^^A------------------------------------------------------------------------- +% \section{Implementation of table handling} +% +% +% Here we go. It starts horrid and gets worse. However, it does stay nicer +% than the original, IMHO. +% +% \begin{macrocode} +%<*mdwtab> +% \end{macrocode} +% +% +% \subsection{Registers, switches and things} +% +% We need lots of these. It's great fun. +% +% The two count registers are simple enough: +% +% \begin{description} +% \item [\cs{tab@state}] contains the current parser state. Since we +% probably won't be parsing preambles recursively, this is a global +% variable. +% \item [\cs{tab@columns}] contains the number of the current column. +% \item [\cs{tab@hlstate}] contains the state required for hline management. +% \end{description} +% +% \begin{macrocode} +\newcount\tab@state +\newcount\tab@columns +% \end{macrocode} +% +% We need \emph{lots} of token registers. Fortunately, most of them are only +% used during parsing. We'll use \PlainTeX's scratch tokens for this. Note +% that |\toks\tw@| isn't used here. It, and |\toks@|, are free for use by +% column commands. +% +% \begin{macrocode} +\newtoks\tab@preamble +\newtoks\tab@shortline +\toksdef\tab@pretext 4 +\toksdef\tab@posttext 6 +\toksdef\tab@userpretext 8 +% \end{macrocode} +% +% The dimens are fairly straightforward. The inclusion of |\col@sep| is a +% sacrifice to compatibility -- judicious use of |\let| in \package{array} +% would have saved a register. +% +% \begin{macrocode} +\newdimen\extrarowheight +\newdimen\tabextrasep +\newdimen\arrayextrasep +\newdimen\smarraycolsep +\newdimen\smarrayextrasep +\newdimen\tab@width +\newdimen\col@sep +\newdimen\tab@endheight +% \end{macrocode} +% +% Some skip registers too. Phew. +% +% \begin{macrocode} +\newskip\tab@leftskip +\newskip\tab@rightskip +% \end{macrocode} +% +% And some switches. The first three are for the parser. +% +% \begin{macrocode} +\newif\iftab@firstcol +\newif\iftab@initrule +\newif\iftab@rule +\newif\iftab@vgap +% \end{macrocode} +% +% Now assign some default values to new dimen parameters. These definitions +% are essentially the equivalent of an |\openup 1\jot| in \env{array}, but +% not in \env{tabular}. This looks nice, I think. +% +% \begin{macrocode} +\tabextrasep\z@ +\arrayextrasep\jot +\smarraycolsep\thr@@\p@ +\smarrayextrasep\z@ +% \end{macrocode} +% +% Set some things up for alien table environments. +% +% \begin{macrocode} +\let\tab@extrasep\tabextrasep +\let\tab@penalty\relax +% \end{macrocode} +% +% +% \subsection{Some little details} +% +% \begin{macro}{\@maybe@unskip} +% +% This macro solves a little problem. In an alignment (and in other places) +% it's desirable to suppress trailing space. The usual method, to say +% |\unskip|, is a little hamfisted, because it removes perfectly reasonable +% aligning spaces like |\hfil|s. While as a package writer I can deal with +% this sort of thing by saying |\kern\z@| in appropriate places, it can +% annoy users who are trying to use |\hfill| to override alignment in funny +% places. +% +% My current solution seems to be acceptable. I'll remove the natural width +% of the last glue item, so that it can still stretch and shrink if +% necessary. The implementation makes use of the fact that multiplying +% a \<skip> by a \<number> kills off the stretch. (Bug fix: don't do this +% when we're in vertical mode.) +% +% \begin{macrocode} +\def\@maybe@unskip{\ifhmode\hskip\m@ne\lastskip\relax\fi} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\q@delim} +% +% Finally, for the sake of niceness, here's a delimiter token I can use +% for various things. It's a `quark', for what it's worth (i.e., it expands +% to itself) although I'm not really sure why this is a good thing. As far +% as I'm concerned, it's important that it has a unique meaning (i.e., that +% it won't be |\ifx|-equal to other things, or something undefined) and that +% it won't be used where I don't expect it to be used. \TeX\ will loop +% horridly if it tries to expand this, so I don't think that quarks are +% wonderfully clever thing to use. (Maybe it should really expand to +% something like `\syntax{<quark>"."}', which will rapdly fill \TeX's memory +% if it gets accidentally expanded. Still, I'll leave it as it is until +% such time as I understand the idea more.) +% +% \begin{macrocode} +\def\q@delim{\q@delim} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Parser states} +% +% Now we start on the parser. It's really simple, deep down. We progress +% from state to state, extracing tokens from the preamble and building +% command names from them. Each command calls one of the element-building +% routines, which works out which state it should be in. We go through each +% of the states in between (see later) doing default things for the ones we +% missed out. +% +% Anyway, here's some symbolic names for the states. It makes my life +% easier. +% +% \begin{macrocode} +\chardef\tab@startstate 0 +\chardef\tab@loopstate 1 +\chardef\tab@rulestate 1 +\chardef\tab@prespcstate 2 +\chardef\tab@prestate 3 +\chardef\tab@colstate 4 +\chardef\tab@poststate 5 +\chardef\tab@postspcstate 6 +\chardef\tab@limitstate 7 +% \end{macrocode} +% +% +% \subsection{Adding things to token lists} +% +% Define some macros for adding stuff to the beginning and end of token +% lists. This is really easy, actually. Here we go. +% +% \begin{macrocode} +\def\tab@append#1#2{#1\expandafter{\the#1#2}} +\def\tab@prepend#1#2{% + \toks@{#2}#1\expandafter{\the\expandafter\toks@\the#1}% +} +% \end{macrocode}% +% +% +% \subsection{Committing a column to the preamble} +% +% Each time we pass the `rule' state, we `commit' the tokens we've gathered +% so far to the main preamble token list. This is how we do it. Note the +% icky use of |\expandafter|. +% +% \begin{macrocode} +\def\tab@commit{% +% \end{macrocode} +% +% If this isn't the first column, then we need to put in a column separator. +% +% \begin{macrocode} + \iftab@firstcol\else% + \expandafter\tab@append\expandafter\tab@preamble% + \expandafter{\tab@tabtext}% + \fi% +% \end{macrocode} +% +% Now we spill the token registers into the main list in a funny order (which +% is why we're doing it in this strange way in the first place. +% +% \begin{macrocode} + \toks@\expandafter{\tab@midtext}% + \tab@preamble\expandafter{% + \the\expandafter\tab@preamble% + \the\expandafter\tab@pretext% + \the\expandafter\tab@userpretext% + \the\expandafter\toks@% + \the\tab@posttext% + }% +% \end{macrocode} +% +% Now reset token lists and things for the next go round. +% +% \begin{macrocode} + \tab@firstcolfalse% + \tab@pretext{}% + \tab@userpretext{}% + \tab@posttext{}% +} +% \end{macrocode} +% +% +% \subsection{Playing with parser states} +% +% \begin{macro}{\tab@setstate} +% +% This is how we set new states. The algorithm is fairly simple, really. +% +% ^^A Let's see how good my TeX really is... ;-) +% ^^A Actually, it doesn't seem to have worked out too badly. Maybe I should +% ^^A write a package to do this automatically. It's rather tricky, though. +% +% \def\qq{\mbox{\quad}} +% \sbox{0}{\itshape\textunderscore}\def\_{\usebox{0}} +% +% \begin{quote} +% {\bf while} $\it tab\_state \ne s$ {\bf do} \\ +% \qq $\mathit{tab\_state = tab\_state}+1$; \\ +% \qq {\bf if} $\it tab\_state = tab\_limitState$ {\bf then} +% $\it tab\_state=tab\_loopState$; \\ +% \qq {\bf if} $\it tab\_state = tab\_preSpcState$ {\bf then} \\ +% \qq \qq {\bf if} $\it tab\_initRule$ {\bf then} \\ +% \qq \qq \qq $\it tab\_initRule = {\bf false}$; \\ +% \qq \qq {\bf else} \\ +% \qq \qq \qq {\bf if} $\it tab\_inMultiCol$ {\bf then moan}; \\ +% \qq \qq \qq $\it commit$; \\ +% \qq \qq \qq $\it append(tab\_shortLine,\hbox{`|&\omit|')}$; \\ +% \qq \qq {\bf end\,if}; \\ +% \qq {\bf end\,if}; \\ +% \qq {\bf if} $\it tab\_state \ne s$ {\bf then} +% $\it do\_default(tab\_state)$; \\ +% {\bf end\,while}; +% \end{quote} +% +% First we decide if there's anything to do. If so, we call another macro to +% do it for us. +% +% \begin{macrocode} +\def\tab@setstate#1{% + \ifnum#1=\tab@state\else% + \def\@tempa{\tab@setstate@i{#1}}% + \@tempa% + \fi% +} +% \end{macrocode} +% +% This is where the fun is. First we bump the state by one, and loop back +% if we fall off the end. +% +% \begin{macrocode} +\def\tab@setstate@i#1{% + \global\advance\tab@state\@ne% + \ifnum\tab@state>\tab@limitstate% + \global\tab@state\tab@loopstate% + \fi% +% \end{macrocode} +% +% Now, if we've just passed the ruleoff state, we commit the current text +% \emph{unless} this was the strange initial rule at the very beginning. We +% provide a little hook here so that |\multicolumn| can moan if you try and +% give more than one column there. We also add another tab/omit pair to the +% list we use for |\vgap|. +% +% \begin{macrocode} + \ifnum\tab@state=\tab@prespcstate% + \iftab@initrule% + \tab@initrulefalse% + \else% + \tab@looped% + \tab@commit% + \tab@append\tab@shortline{&\omit}% + \fi% + \fi% +% \end{macrocode} +% +% Now we decide whether to go round again. If not, we do the default thing +% for this state. This is mainly here so that we can put the |\tabcolsep| or +% whatever in if the user didn't give an \lit{@} expression. +% +% \begin{macrocode} + \ifnum#1=\tab@state% + \let\@tempa\relax% + \else% + \csname tab@default@\number\tab@state\endcsname% + \fi% + \@tempa% +} +% \end{macrocode} +% +% \end{macro} +% +% Now we set up the default actions for the various states. +% +% In state~2 (pre-space) we add in the default gap if either we didn't have +% an \lit{@} expression in the post-space state or there was an explicit +% intervening rule. +% +% \begin{macrocode} +\@namedef{tab@default@2}{% + \iftab@rule% + \tab@append\tab@pretext{\hskip\col@sep}% + \fi% +} +% \end{macrocode} +% +% If the user omits the column type, we insert an `l'-type column and moan +% a lot. +% +% \begin{macrocode} +\@namedef{tab@default@4}{% + \tab@err@misscol% + \tab@append\tab@pretext{\tab@bgroup\relax}% + \tab@append\tab@posttext{\relax\tab@egroup\hfil}% + \tab@append\tab@shortline{\hfil}% + \advance\tab@columns\@ne% +} +% \end{macrocode} +% +% Finally we deal with the post-space state. We set a marker so that we +% put in the default space in the pre-space state later too. +% +% \begin{macrocode} +\@namedef{tab@default@6}{% + \tab@append\tab@posttext{\hskip\col@sep}% + \tab@ruletrue% +} +% \end{macrocode} +% +% +% \subsection{Declaring token types} +% +% \begin{macro}{\tab@extracol} +% +% Before we start, we need to handle |\extracolsep|. This is a right pain, +% because the original version of \env{tabular} worked on total expansion, +% which is a Bad Thing. On the other hand, turning |\extracolsep| into a +% |\tabskip| is also a major pain. +% +% \begin{macrocode} +\def\tab@extracol#1#2{\tab@extracol@i#1#2\extracolsep{}\extracolsep\end} +\def\tab@extracol@i#1#2\extracolsep#3#4\extracolsep#5\end{% + \ifx @#3@% + \def\@tempa{#1{#2}}% + \else% + \def\@tempa{#1{#2\tabskip#3\relax#4}}% + \fi% + \@tempa% +} +% \end{macrocode} +% +% \end{macro} +% +% This is where we do the work for inserting preamble elements. +% +% \begin{macro}{\tabruletype} +% +% Inserting rules is interesting, because we have to decide where to put +% them. If this is the funny initial rule, it goes in the pre-text list, +% otherwise it goes in the post-text list. We work out what to do first +% thing: +% +% \begin{macrocode} +\def\tabruletype#1{\tab@extracol\tabruletype@i{#1}}% +\def\tabruletype@i#1{% + \iftab@initrule% + \let\tab@tok\tab@pretext% + \else% + \let\tab@tok\tab@posttext% + \fi% +% \end{macrocode} +% +% Now if we're already in the rule state, we must have just done a rule. +% This means we must put in the |\doublerulesep| space, both here and in the +% shortline list. Otherwise we just stick the rule in. +% +% This is complicated, because |\vgap| needs to be able to remove some bits +% of rule. We pass each one to a macro |\tab@ckr|, together with the column +% number, which is carefully bumped at the right times, and this macro will +% vet the rules and output the appropriate ones. There's lots of extreme +% |\expandafter| nastiness as a result. Amazingly, this actually works. +% +% \begin{macrocode} + \ifnum\tab@state=\tab@rulestate% + \tab@append\tab@tok{\hskip\doublerulesep\begingroup#1\endgroup}% + \expandafter\tab@append\expandafter\tab@shortline\expandafter{% + \expandafter\hskip\expandafter\doublerulesep% + \expandafter\tab@ckr\expandafter{\the\tab@columns}% + {\begingroup#1\endgroup}% + }% + \else% + \tab@setstate\tab@rulestate% + \tab@append\tab@tok{\begingroup#1\endgroup}% + \expandafter\tab@append\expandafter\tab@shortline\expandafter{% + \expandafter\tab@ckr\expandafter{\the\tab@columns}% + {\begingroup#1\endgroup}% + }% + \fi% +% \end{macrocode} +% +% Finally, we say there was a rule here, so that default space gets put in +% after this. Otherwise we lose lots of generality. +% +% \begin{macrocode} + \tab@ruletrue% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tabspctype} +% +% We need to work out which space-state we should be in. Then we just put +% the text in. Easy, really. +% +% \begin{macrocode} +\def\tabspctype#1{\tab@extracol\tabspctype@i{#1}}% +\def\tabspctype@i#1{% + \tab@rulefalse% + \ifnum\tab@state>\tab@prespcstate% + \tab@setstate\tab@postspcstate% + \let\tab@tok\tab@posttext% + \else% + \tab@setstate\tab@prespcstate% + \let\tab@tok\tab@pretext% + \fi% + \tab@append\tab@tok{\begingroup#1\endgroup}% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tabcoltype} +% +% If we're already in the column state, we bump the state and loop round +% again, to get all the appropriate default behaviour. We bump the column +% counter, and add the bits of text we were given to appropriate token lists. +% We also add the |\hfil| glue to the shortline list, to space out the rules +% properly. +% +% \begin{macrocode} +\def\tabcoltype#1#2{% + \ifnum\tab@state=\tab@colstate% + \global\advance\tab@state\@ne% + \fi% + \advance\tab@columns\@ne% + \tab@setstate\tab@colstate% + \tab@append\tab@pretext{#1}% + \tab@append\tab@posttext{#2}% + \tab@append\tab@shortline{\hfil}% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tabuserpretype} +% \begin{macro}{\tabuserposttype} +% +% These are both utterly trivial. +% +% \begin{macrocode} +\def\tabuserpretype#1{% + \tab@setstate\tab@prestate% + \tab@prepend\tab@userpretext{#1}% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\tabuserposttype#1{% + \tab@setstate\tab@poststate% + \tab@prepend\tab@posttext{#1}% +} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% +% +% \subsection{The colset stack} +% +% Let's start with something fairly easy. We'll keep a stack of column sets +% so that users don't get confused by package authors changing the current +% column set. This is fairly easy, really. +% +% \begin{macro}{\tab@push} +% \begin{macro}{\tab@pop} +% \begin{macro}{\tab@head} +% +% These are the stack management routines. The only important thing to note +% is that |\tab@head| must take place \emph{only} in \TeX's mouth, so we can +% use it in |\csname|\dots|\endcsname| constructions. +% +% \begin{macrocode} +\def\tab@push#1#2{% + \toks@{{#2}}% + \expandafter\def\expandafter#1\expandafter{\the\expandafter\toks@#1}% +} +\def\tab@pop#1{\expandafter\def\expandafter#1\expandafter{\@gobble#1}} +\def\tab@head#1{\expandafter\tab@head@i#1\relax} +\def\tab@head@i#1#2\relax{#1} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\colset} +% \begin{macro}{\colpush} +% \begin{macro}{\colpop} +% +% Now we can define the user macros. +% +% \begin{macrocode} +\def\tab@colstack{{tabular}} +\def\colset{\colpop\colpush} +\def\colpush{\tab@push\tab@colstack} +\def\colpop{\tab@pop\tab@colstack} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\tab@colset} +% +% Now we define a shortcut for reading the top item off the stack. +% +% \begin{macrocode} +\def\tab@colset{\tab@head\tab@colstack} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{The main parser routine} +% +% \begin{macro}{\tab@initread} +% +% This macro sets up lots of variables to their normal states prior to +% parsing a preamble. Some things may need changing, but not many. +% +% \begin{macrocode} +\def\tab@initread{% +% \end{macrocode} +% +% First, reset the parser state to the start state. +% +% \begin{macrocode} + \global\tab@state\tab@startstate% +% \end{macrocode} +% +% We clear the token lists to sensible values, mostly. The midtext macro +% contains what to put in the very middle of each template -- |\multicolumn| +% will insert its argument here. +% +% \begin{macrocode} + \tab@preamble{}% + \tab@shortline{}% + \def\tab@tabtext{&}% + \def\tab@midtext{\ignorespaces####\@maybe@unskip}% + \tab@pretext{}% + \tab@userpretext{}% + \tab@posttext{}% + \let\tab@multicol\@empty% + \def\tab@startpause{\penalty\postdisplaypenalty\medskip}% + \def\tab@endpause{\penalty\predisplaypenalty\medskip}% +% \end{macrocode} +% +% Finally, reset the column counter, don't raise errors when we loop, and set +% some parser flags to their appropriate values. +% +% \begin{macrocode} + \tab@columns\z@% + \let\tab@looped\relax% + \tab@ruletrue% + \tab@initruletrue% + \tab@firstcoltrue% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@readpreamble} +% +% This is the main macro for preamble handling. Actually, all it does is +% gobble its argument's leading brace and call another macro, but it does it +% with style. +% +% \begin{macrocode} +\def\tab@readpreamble#1{% + \tab@doreadpream{#1}% + \iftab@initrule\global\tab@state\tab@prespcstate\fi% + \tab@setstate\tab@rulestate% + \tab@commit% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@doreadpream} +% +% The preamble is in an argument. Previous versions used a nasty trick using +% |\let| and |\afterassignment|. Now we use an explicit end token, to allow +% dodgy column type handlers to scoop up the remaining preamble tokens +% and process them. Not that anyone would want to do that, oh no (see +% the \lit{[} type in the \env{eqnarray} environment |;-)|). +% +% \begin{macrocode} +\def\tab@doreadpream#1{\tab@mkpreamble#1\q@delim} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@mkpreamble} +% +% This is the main parser routine. It takes each token in turn, scrutinises +% it carefully, and does the appropriate thing with it. +% +% The preamble was given as an argument to |\tab@doreadpream|, and that has +% helpfully stripped off the initial |{| character. We need to pick off the +% next token (whatever it is) so we can examine it. We'll use |\futurelet| +% so we can detect groups and things in funny places. +% +% \begin{macrocode} +\def\tab@mkpreamble{\futurelet\@let@token\tab@mkpreamble@i} +% \end{macrocode} +% +% If we find a space token, we'll go off and do something a bit special, +% since spaces are sort of hard to handle. Otherwise we'll do it in the old +% fashioned way. +% +% \begin{macrocode} +\def\tab@mkpreamble@i{% + \ifx\@let@token\@sptoken% + \expandafter\tab@mkpreamble@spc% + \else% + \expandafter\tab@mkpreamble@ii% + \fi% +} +% \end{macrocode} +% +% If we find a |\@@endpreamble| token, that's it and we're finished. We just +% gobble it and return. Otherwise, if it's an open group character, we'll +% complain because someone's probably tried to put an argument in the wrong +% place. Finally, if none of the other things apply, we'll deal with the +% character below. +% +% \begin{macrocode} +\def\tab@mkpreamble@ii{% + \ifx\@let@token\q@delim% + \def\@tempa{\let\@let@token}% + \else% + \ifcat\bgroup\noexpand\@let@token% + \tab@err@oddgroup% + \def\@tempa##1{\tab@mkpreamble}% + \else% + \let\@tempa\tab@mkpreamble@iii% + \fi% + \fi% + \@tempa% +} +% \end{macrocode} +% +% Handle a character. This involves checking to see if it's actually +% defined, and then doing it. Doing things this way means we won't get +% stranded in mid-preamble unless a package author has blown it. +% +% \begin{macrocode} +\def\tab@mkpreamble@iii#1{% + \@ifundefined{\tab@colset!col.\string#1}{% + \tab@err@undef{#1}\tab@mkpreamble% + }{% + \@nameuse{\tab@colset!col.\string#1}% + }% +} +% \end{macrocode} +% +% If we get given a space character, we'll look up the command name as +% before. If no-one's defined the column type we'll just skip it silently, +% which lets users do pretty formatting if they like. +% +% \begin{macrocode} +\@namedef{tab@mkpreamble@spc} {% + \@ifundefined{\tab@colset!col. }{% + \tab@mkpreamble% + }{% + \@nameuse{\tab@colset!col. }% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\coldef} +% +% Here's how to define column types the nice way. Some dexterity is required +% to make everything work right, but it's simple really. +% +% \begin{macrocode} +\def\coldef{\@ifnextchar[\coldef@i{\coldef@i[\tab@colset]}} +\def\coldef@i[#1]#2#3#{\coldef@ii[#1]{#2}{#3}} +\def\coldef@ii[#1]#2#3#4{% + \expandafter\def\csname#1!col.\string#2\endcsname#3{% + #4\tab@mkpreamble% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\collet} +% +% We'd like to let people copy column types from other places. This is how +% to do it. +% +% \begin{macrocode} +\def\collet{\@ifnextchar[\collet@i{\collet@i[\tab@colset]}} +\def\collet@i[#1]#2{% + \@ifnextchar=% + {\collet@ii[#1]{#2}}% + {\collet@ii[#1]{#2}=}% +} +\def\collet@ii[#1]#2={% + \@ifnextchar[% + {\collet@iii[#1]{#2}}% + {\collet@iii[#1]{#2}[\tab@colset]}% +} +\def\collet@iii[#1]#2[#3]#4{% + \expandafter\let\csname#1!col.\string#2\expandafter\endcsname% + \csname#3!col.\string#4\endcsname% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\newcolumntype} +% +% We just bundle the text off to |\newcommand| and expect it to cope. It +% ought to. The column type code inserts the user's tokens directly, rather +% than calling |\tab@doreadpream| recursively. The magic control sequence +% is the one looked up by the parser. +% +% There's some additional magic here for compatiblity with the obscure way +% that \package{array} works. +% +% \begin{macrocode} +\def\newcolumntype#1{\@ifnextchar[{\nct@i{#1}}{\nct@i#1[0]}} +\def\nct@i#1[#2]{\@ifnextchar[{\nct@ii{#1}[#2]}{\nct@iii{#1}{[#2]}}} +\def\nct@ii#1[#2][#3]{\nct@iii{#1}{[#2][#3]}} +\def\nct@iii#1#2#3{% + \expandafter\let\csname\tab@colset!col.\string#1\endcsname\relax% + \expandafter\newcommand\csname\tab@colset!col.\string#1\endcsname#2{% + \tab@deepmagic{#1}% + \tab@mkpreamble% + #3% + }% +} +% \end{macrocode} +% +% Now for some hacking for compatibility with \package{tabularx}. +% +% \begin{macrocode} +\def\newcol@#1[#2]{\nct@iii{#1}{[#2]}} +% \end{macrocode} +% +% And now some more. This is seriously deep magic. Hence the name. +% +% \begin{macrocode} +\def\tab@deepmagic#1{% + \csname NC@rewrite@\string#1\endcsname\NC@find\tab@@magic@@% +} +\def\NC@find#1\tab@@magic@@{} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Standard column types} +% +% First, make sure we're setting up the right columns. This also sets the +% default for the user. Other packages must not use the |\colset| command +% for defining columns -- they should use the stack operations defined above. +% +% \begin{macrocode} +\colset{tabular} +% \end{macrocode} +% +% Now do the simple alignment types. These are fairly simple. The +% mysterious kern in the \lit{l} type is to stop the |\col@sep| glue from +% vanishing due to the |\unskip| inserted by the standard |\tab@midtext| if +% the column contains no text. (Thanks for spotting this bug go to that +% nice Mr~Carlisle.) +% +% \begin{macrocode} +\coldef l{\tabcoltype{\kern\z@\tab@bgroup}{\tab@egroup\hfil}} +\coldef c{\tabcoltype{\hfil\tab@bgroup}{\tab@egroup\hfil}} +\coldef r{\tabcoltype{\hfil\tab@bgroup}{\tab@egroup}} +% \end{macrocode} +% +% Some extensions now. These are explicitly teextual or mathematical +% columns. Can be useful if you're providing column types for other people. +% I've inserted a kern here for exactly the same reason as for the \lit{l} +% column type above. +% +% \begin{macrocode} +\coldef T#1{\tab@aligncol{#1}{\tab@btext}{\tab@etext}} +\coldef M#1{\tab@aligncol{#1}{\tab@bmaths}{\tab@emaths}} +\def\tab@aligncol#1#2#3{% + \if#1l\tabcoltype{\kern\z@#2}{#3\hfil}\fi% + \if#1c\tabcoltype{\hfil#2}{#3\hfil}\fi% + \if#1r\tabcoltype{\hfil#2}{#3}\fi% +} +% \end{macrocode} +% +% Now for the default rules. +% +% \begin{macrocode} +\coldef |{\tabruletype{\vrule\@width\arrayrulewidth}} +\coldef !#1{\tabruletype{#1}} +% \end{macrocode} +% +% Deal with \lit{@} expressions. +% +% \begin{macrocode} +\coldef @#1{\tabspctype{#1}} +% \end{macrocode} +% +% And the paragraph types. I've added things to handle footnotes here. +% +% \begin{macrocode} +\coldef p#1{\tabcoltype% + {\savenotes\vtop\tab@bpar{#1}}% + {\tab@epar\spewnotes\hfil}} +\coldef m#1{\tabcoltype% + {\savenotes$\vcenter\tab@bpar{#1}}% + {\tab@epar$\spewnotes\hfil}} +\coldef b#1{\tabcoltype% + {\savenotes\vbox\tab@bpar{#1}}% + {\tab@epar\spewnotes\hfil}} +% \end{macrocode} +% +% Phew. Only a few more left now. The user text ones. +% +% \begin{macrocode} +\coldef >#1{\tabuserpretype{#1}} +\coldef <#1{\tabuserposttype{#1}} +% \end{macrocode} +% +% The strange column type. +% +% \begin{macrocode} +\coldef ##1#2{\tabcoltype{#1}{#2}} +% \end{macrocode} +% +% And \lit{*}, which repeats a preamble spec. This is really easy, and not +% at all like the original one. +% +% \begin{macrocode} +\coldef *#1#2{% + \count@#1% + \loop\ifnum\count@>0\relax% + \tab@doreadpream{#2}% + \advance\count@\m@ne% + \repeat% +} +% \end{macrocode} +% +% +% \subsection{Paragraph handling} +% +% First of all, starting new paragraphs: the vbox token is already there, and +% we have the width as an argument. +% +% \begin{macro}{\tab@bpar} +% +% There are some gymnastics to do here to support lists which form the +% complete text of the parbox. One of the odd things I'll do here is to +% not insert a strut on the first line: instead, I'll put the text into a +% box register so that I can inspect it later. So that I have access to +% the height of the first line, I'll use a |\vtop| -- I can get at the +% final depth by using |\prevdepth|, so this seems to be the most general +% solution. +% +% \begin{macrocode} +\def\tab@bpar#1{% + \bgroup% + \hsize#1\relax% + \@arrayparboxrestore% + \setbox\z@\vtop\bgroup + \global\@minipagetrue% + \everypar{% + \global\@minipagefalse% + \everypar{}% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@epar} +% +% To end the paragraph, close the box. That sounds easy, doesn't it? +% I need to space out the top and bottom of the box so that it looks as if +% struts have been applied. +% +% \begin{macrocode} +\def\tab@epar{% +% \end{macrocode} +% +% Anyway, I should end the current paragraph if I'm still in horizontal +% mode. A simple |\par| will do this nicely. I'll also remove any trailing +% vertical glue (which may be left there by a list environment), because +% things will look very strange otherwise. +% +% \begin{macrocode} + \ifhmode\@maybe@unskip\par\fi% + \unskip% +% \end{macrocode} +% +% Now I'll look at the depth of the last box: if it's less deep than my +% special strut, I'll cunningly backpedal by a bit, and add a box with the +% appropriate depth. Since this will lie on the previous baseline, it won't +% alter the effective height of the box. There's a snag here. |\prevdepth| +% may be wrong for example if the last thing inserted was a rule, or the +% box is just empty. Check for this specially. (Thanks to Rowland for +% spotting this.) +% +% \begin{macrocode} + \ifdim\prevdepth>-\@m\p@\ifdim\prevdepth<\dp\@arstrutbox% + \kern-\prevdepth% + \nointerlineskip% + \vtop to\dp\@arstrutbox{}% + \fi\fi% +% \end{macrocode} +% +% I've finished the bottom of the box now: I'll close it, and start work on +% the top again. +% +% \begin{macrocode} + \egroup% +% \end{macrocode} +% +% For top-alignment to work, the first item in the box must be another box. +% (This is why I couldn't just set |\prevdepth| at the beginning.) If the +% box isn't high enough, I'll add a box of the right height and then kern +% backwards so that the `real' first box ends up in the right place. +% +% \begin{macrocode} + \ifdim\ht\z@<\ht\@arstrutbox% + \vbox to\ht\@arstrutbox{}% + \kern-\ht\z@% + \fi% + \unvbox\z@% + \egroup% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Gentle persuasion} +% +% To persuade \package{longtable} to work, we emulate some features of +% the \package{array} way of doing things. It's a shame, but we have to do +% it, because \package{longtable} came first. +% +% Note the horribleness with the grouping here. In order to get everything +% expanded at the right time, |\@preamble| just replaces itself with the (not +% expanded!) preamble string, using |\the|. This means that the preamble +% string must be visible in the group just above us. Now, +% \package{longtable} (and \package{array} for that matter) does +% |\@mkpreamble| immediately after opening a new group. So all we need to do +% is close that group, do our stuff, and reopen the group again. (Evil +% laughter\dots) +% +% \begin{macrocode} +\def\@mkpream#1{% + \endgroup% + \colset{tabular}% + \tab@initread% + \def\tab@multicol{\@arstrut}% + \tab@preamble{\tab@multicol}% + \def\tab@midtext{\ignorespaces\@sharp\@sharp\@maybe@unskip}% + \tab@readpreamble{#1}% + \gdef\@preamble{\the\tab@preamble}% + \let\tab@bgroup\begingroup% + \let\tab@egroup\endgroup% + \begingroup% +} +% \end{macrocode} +% +% +% \subsection{Debugging} +% +% This macro just parses a preamble and displays it on the terminal. It +% means I can see whether the thing's working. +% +% \begin{macrocode} +\def\showpream#1{% + \tab@initread% + \tab@readpreamble{#1}% + \showthe\tab@preamble% + \showthe\tab@shortline% +} +% \end{macrocode} +% +% A quick macro for showing column types. +% +% \begin{macrocode} +\def\showcol#1{% + \expandafter\show\csname\tab@colset!col.\string#1\endcsname% +} +% \end{macrocode} +% +% +% \subsection{The \env{tabular} and \env{array} environments} +% +% This is where we define the actual environments which users play with. +% +% \subsubsection{The environment routines} +% +% The real work is done in the |\@array| macro later. We just set up lots +% (and I mean \emph{lots}) of parameters first, and then call |\@array|. +% +% \begin{macro}{\tab@array} +% +% The |\tab@array| macro does most of the common array things. +% +% \begin{macrocode} +\def\tab@array{% + \tab@width\z@% + \let\tab@bgroup\tab@bmaths% + \let\tab@egroup\tab@emaths% + \@tabarray% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@btext} +% \begin{macro}{\tab@bmaths} +% \begin{macro}{\tab@etext} +% \begin{macro}{\tab@emaths} +% +% These macros contain appropriate things to use when typesetting +% text or maths macros. They're all trivial. They're here only for +% later modification by funny things like the \env{smarray} environment. +% +% \begin{macrocode} +\def\tab@btext{\begingroup} +\def\tab@bmaths{$} +\def\tab@etext{\endgroup} +\def\tab@emaths{\m@th$} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{environment}{array} +% +% Now for the \env{array} environment. The `|$|' signs act as a group, so we +% don't need to do extra grouping this time. Closing the environment is +% easy. +% +% \begin{macrocode} +\def\array{% + \col@sep\arraycolsep% + \let\tab@extrasep\arrayextrasep% + \tab@normalstrut% + \tab@array% +} +\def\endarray{% + \crcr% + \egroup% + \tab@right% + \tab@restorehlstate% +} +% \end{macrocode} +% +% \end{environment} +% +% \begin{environment}{smarray} +% +% Now for something a little different. The \env{smarray} environment +% gives you an array with lots of small text. +% +% \begin{macrocode} +\def\smarray{% + \extrarowheight\z@% + \col@sep\smarraycolsep% + \let\tab@extrasep\smarrayextrasep% + \def\tab@bmaths{$\scriptstyle}% + \def\tab@btext{\begingroup\scriptsize}% + \setbox\z@\hbox{\scriptsize\strut}% + \dimen@\ht\z@\dimen\tw@\dp\z@\tab@setstrut% + \tab@array% +} +\let\endsmarray\endarray +% \end{macrocode} +% +% \end{environment} +% +% \begin{macro}{\tabstyle} +% +% This is a little hook that document designers can use to modify the +% appearance of tables throughout a document. For example, I've set it to +% make the text size |\small| in all tables in this document. Macro writers +% shouldn't try to use it as a hook for their own evilness, though. I've +% used |\providecommand| to avoid nobbling an existing definition. +% +% \begin{macrocode} +\providecommand\tabstyle{} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\@tabular} +% +% The two \env{tabular} environments share lots of common code, so we +% separate that out. (This needs to be done better.) All we really do here +% is set up the |\tab@bgroup| and |\tab@egroup| to localise things properly, +% and then go. +% +% \begin{macrocode} +\def\@tabular#1{% + \tabstyle% + \tab@width#1% + \let\tab@bgroup\tab@btext% + \let\tab@egroup\tab@etext% + \col@sep\tabcolsep% + \let\tab@extrasep\tabextrasep% + \tab@normalstrut% + \@tabarray% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{tabular} +% \begin{environment}{tabular*} +% +% These environments just call a macro which does all the common stuff. +% +% \begin{macrocode} +\def\tabular{\@tabular\z@} +\expandafter\let\csname tabular*\endcsname\@tabular +\let\endtabular\endarray +\expandafter\let\csname endtabular*\endcsname\endarray +% \end{macrocode} +% +% \end{environment} +% \end{environment} +% +% \subsubsection{Setting the strut height} +% +% \begin{macro}{\tab@setstrut} +% +% We use a magical strut, called |\@arstrut|, which keeps the table from +% collapsing around our heads. This is where we set it up. +% +% It bases the array strut size on the given values of |\dimen@| and +% |\dimen\tw@|, amended by various appropriate fiddle values added in by +% various people. +% +% \begin{macrocode} +\def\tab@setstrut{% + \setbox\@arstrutbox\hbox{% + \vrule% + \@height\arraystretch\dimen@% + \@depth\arraystretch\dimen\tw@% + \@width\z@% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@normalstrut} +% +% This sets the strut the normal way, from the size of |\strutbox|. +% +% \begin{macrocode} +\def\tab@normalstrut{% + \dimen@\ht\strutbox\advance\dimen@\extrarowheight% + \dimen\tw@\dp\strutbox% + \tab@setstrut% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Setting up the alignment} +% +% The following bits are mainly for other packages to hook themselves onto. +% +% \begin{macrocode} +\let\@arrayleft\relax% +\let\@arrayright\relax% +% \end{macrocode} +% +% \begin{macrocode} +\def\@tabarray{% + \let\@arrayleft\relax% + \let\@arrayright\relax% + \@ifnextchar[\@array{\@array[c]}% +} +% \end{macrocode} +% +% \begin{macro}{\@array} +% +% The |\@array| macro does most of the real work for the environments. The +% first job is to set up the row strut, which keeps the table rows at the +% right height. We just take the normal strut box, and extend its height by +% the |\extrarowheight| length parameter. +% +% \begin{macrocode} +\def\@array[#1]#2{% +% \end{macrocode} +% +% Sort out the hline state variable. We'll store the old value in a +% control sequence to avoid wasting any more count registers. +% +% \begin{macrocode} + \edef\tab@restorehlstate{% + \global\tab@endheight\the\tab@endheight% + \gdef\noexpand\tab@hlstate{\tab@hlstate}% + }% + \def\tab@hlstate{n}% +% \end{macrocode} +% +% Now we read the preamble. All the clever things we've already done are +% terribly useful here. +% +% The |\tab@setcr| sets up |\\| to be a newline even if users have changed it +% using something like |\raggedright|. +% +% \begin{macrocode} + \colset{tabular}% + \tab@initread% + \def\tab@midtext{\tab@setcr\ignorespaces####\@maybe@unskip}% + \def\tab@multicol{\@arstrut\tab@startrow}% + \tab@preamble{\tab@multicol\tabskip\z@skip}% + \tab@readpreamble{#2}% +% \end{macrocode} +% +% Set up the default tabskip glue. This is easy: there isn't any. +% +% \begin{macrocode} + \tab@leftskip\z@skip% + \tab@rightskip\z@skip% +% \end{macrocode} +% +% Now set up the positioning of the table. This is put into a separate macro +% because it's rather complicated. +% +% \begin{macrocode} + \tab@setposn{#1}% +% \end{macrocode} +% +% Now work out how to start the alignment. +% +% \begin{macrocode} + \ifdim\tab@width=\z@% + \def\tab@halign{}% + \else% + \def\tab@halign{to\tab@width}% + \fi% +% \end{macrocode} +% +% Finally, do all the normal things we need to do before an alignment. Note +% that we define |\tabularnewline| first, then set |\\| from that (using +% |\tab@setcr|). Since |\\| is reset in the |\tab@midtext| of every table +% cell, it becomes secondary to |\tabularnewline|. Doing things this way +% avoids the problems with declarations like |\raggedright| which redefine +% |\\| in their own (usually rather strange) way, so you don't need to mess +% about with things like the |\PreserveBackslash| command given in the +% \textit{\LaTeX\ Companion}. +% +% \begin{macrocode} + \lineskip\z@\baselineskip\z@% + \m@th% + \def\tabularnewline{\tab@arraycr\tab@penalty}% + \tab@setcr% + \let\par\@empty% + \everycr{}\tabskip\tab@leftskip% + \tab@left\halign\tab@halign\expandafter\bgroup% + \the\tab@preamble\tabskip\tab@rightskip\cr% +} +% \end{macrocode} +% +% \end{macro} +% +% You've no doubt noticed the |\tab@left| and |\tab@right| macros above. +% These are set up here and elsewhere to allow other things to gain control +% at various points of the table (they include and take the place of the +% |\@arrayleft| and |\@arrayright| hooks in \package{array}, put in for +% \package{delarray}'s use. +% +% \subsubsection{Positioning the table} +% +% \begin{macro}{\tab@setposn} +% +% This macro sets everything up for the table's positioning. It's rather +% long, but not all that complicated. Honest. +% +% First, we set up some defaults (for centring). If anything goes wrong, we +% just do the centring things. +% +% \begin{macrocode} +\def\tab@setposn#1{% + \def\tab@left{% + \savenotes% + \leavevmode\hbox\bgroup$\@arrayleft\vcenter\bgroup% + }% + \def\tab@right{% + \egroup% + \m@th\@arrayright$\egroup% + \spewnotes% + }% + \global\tab@endheight\z@% +% \end{macrocode} +% +% For the standard positioning things, we just do appropriate boxing things. +% Note that the dollar signs are important, since \package{delarray} might +% want to put its delimiters in here. +% +% The |\if@tempswa| switch it used to decide if we're doing an unboxed +% tabular. We'll set it if we find an unbox-type position code, and then +% check that everything's OK for this. +% +% \begin{macrocode} + \@tempswafalse% + \let\tab@penalty\relax% + \if#1t% + \def\tab@left{% + \savenotes% + \leavevmode\setbox\z@\hbox\bgroup$\@arrayleft\vtop\bgroup% + }% + \def\tab@right{% + \egroup% + \m@th\@arrayright$\egroup% + \tab@raisebase% + \spewnotes% + }% + \gdef\tab@hlstate{t}% + \global\tab@endheight\ht\@arstrutbox% + \else\if#1b% + \def\tab@left{% + \savenotes% + \leavevmode\setbox\z@\hbox\bgroup$\@arrayleft\vbox\bgroup% + }% + \def\tab@right{% + \egroup% + \m@th\@arrayright$\egroup% + \tab@lowerbase% + \spewnotes% + }% + \gdef\tab@hlstate{b}% + \else% + \if#1L\@tempswatrue\fi% + \if#1C\@tempswatrue\fi% + \if#1R\@tempswatrue\fi% + \fi\fi% +% \end{macrocode} +% +% Now for some tests to make sure we're allowed to do the unboxing. We text +% for |\@arrayleft| being defined, because people trying to hook us won't +% understand unboxed tabulars. +% +% \begin{macrocode} + \if@tempswa\ifhmode% + \ifinner\tab@err@unbrh\@tempswafalse\else\par\fi% + \fi\fi% + \if@tempswa\ifmmode\tab@err@unbmm\@tempswafalse\fi\fi% + \if@tempswa\ifx\@arrayleft\relax\else% + \tab@err@unbext\@tempswafalse% + \fi\fi% +% \end{macrocode} +% +% Finally, if we're still doing an unboxed alignment, we need to sort out the +% spacing. We know that no-one's tried to hook on to the environment, so we +% clear |\tab@left| and |\tab@right|. +% +% \begin{macrocode} + \if@tempswa% + \def\tab@left{\vskip\parskip\medskip}% + \def\tab@right{\par\@endpetrue\global\@ignoretrue}% +% \end{macrocode} +% +% Now we need to sort out the alignment. The only way we can do this is by +% playing with tabskip glue. There are two possiblities: +% +% \begin{itemize} +% +% \item If this is a straight \env{tabular} or an \env{array}, we just use +% infinite glue. This is reasonable, I think. +% +% \item If we have a width for the table, we calculate the fixed values of +% glue on either side. This is fairly easy, and forces the table to +% the required width. +% +% \end{itemize} +% +% First, set up the left and right glues to represent the prevailing +% margins set up by \env{list} environments. I think this is the right +% thing to do. +% +% \begin{macrocode} + \tab@leftskip\@totalleftmargin% + \tab@rightskip\hsize% + \advance\tab@rightskip-\linewidth% + \advance\tab@rightskip-\@totalleftmargin% +% \end{macrocode} +% +% First of all, deal with the simple case. I'm using 10000\,fill glue here, +% in an attempt to suppress |\extracolsep| glue from making the table the +% wrong width. It can always use filll glue if it really needs to, though. +% +% \begin{macrocode} + \ifdim\tab@width=\z@% + \if#1L\else\advance\tab@leftskip\z@\@plus10000fill\fi% + \if#1R\else\advance\tab@rightskip\z@\@plus10000fill\fi% +% \end{macrocode} +% +% Now for the fun bit. This isn't too hard really. The extra space I must +% add around the table adds up to $|\linewidth| - |\tab@width|$. I just +% need to add this onto the appropriate sides of the table. +% +% \begin{macrocode} + \else% + \dimen@\linewidth% + \advance\dimen@-\tab@width% + \if#1L\advance\tab@rightskip\dimen@\fi% + \if#1R\advance\tab@leftskip\dimen@\fi% + \if#1C% + \advance\tab@leftskip.5\dimen@% + \advance\tab@rightskip.5\dimen@% + \fi% + \fi% +% \end{macrocode} +% +% Don't allow page breaks. David Carlisle's wonderful \env{longtable} +% package does page breaks far better than I could possibly do here, and +% we're compatible with it (wahey!). +% +% \begin{macrocode} + \def\tab@penalty{\penalty\@M}% +% \end{macrocode} +% +% Finally, set the new width of the table, and leave. +% +% \begin{macrocode} + \tab@width\hsize% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Handling tops and bottoms} +% +% This is how the tops and bottoms of tables are made to line up with the +% text on the same line, in the presence of arbitrary rules and space. The +% old method, based on the way the \package{array} package worked, wasn't +% terribly good. This new version copes much better with almost anything +% that gets thrown at it. +% +% I'll keep a state in a macro (|\tab@hlstate|), which tells me what I'm +% meant to be doing. The possible values are \lit{n}, which means I don't +% have to do anything, \lit{t}, which means that I'm meant to be handling +% top-aligned tables, and \lit{b}, which means that I'm meant to be lining +% up the bottom. There are several other `substates' which have various +% magic meanings. +% +% \begin{macrocode} +\def\tab@hlstate{n} +% \end{macrocode} +% +% When all's said and done, I extract the box containing the table, and +% play with the height and depth to try and make it correct. +% +% \begin{macro}{\tab@addruleheight} +% +% This macro is called by `inter-row' things to add their height to our +% dimen register. +% +% Only do this if the state indicates that it's sensible. +% +% \begin{macrocode} +\def\tab@addruleheight#1{% + \if\tab@hlstate n\else% + \global\advance\tab@endheight#1\relax% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@startrow} +% +% This is called at the start of a row, from within the array preamble. +% Currently, this assumes that the rows aren't bigger than their struts: +% this is reasonable, although slightly limiting, and it could be done better +% if I was willing to rip the alignment apart and put it back together +% again. +% +% \begin{macrocode} +\def\tab@startrow{% + \if\tab@hlstate t% + \gdef\tab@hlstate{n}% + \else\if\tab@hlstate b% + \global\tab@endheight\dp\@arstrutbox% + \fi\fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@raisebase} +% +% This macro is called at the end of it all, to set the height and depth +% of the box correctly. It sets the height to |\tab@endheight|, and the +% depth to everything else. The box is in |\box|~0 currently. +% +% \begin{macrocode} +\def\tab@raisebase{% + \global\advance\tab@endheight-\ht\z@% + \raise\tab@endheight\box\z@% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@lowerbase} +% +% And, for symmetry's sake, here's how to set the bottom properly instead. +% +% \begin{macrocode} +\def\tab@lowerbase{% + \global\advance\tab@endheight-\dp\z@% + \lower\tab@endheight\box\z@% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Breaking tables into bits} +% +% Unboxed tables have a wonderful advantage over boxed ones: you can stop +% halfway through and do something else for a bit. Here's how: +% +% \begin{macro}{\tabpause} +% +% I'd like to avoid forbidding catcode changes here. I'll use |\doafter| +% now I've got it, to ensure that colour handling and things occur +% \emph{inside} the |\noalign| (otherwise they'll mess up the alignment +% very seriously). +% +% We have to be careful here to ensure that everything works correctly within +% lists. (The \package{amsmath} package had this problem in its +% |\intertext| macro, so I'm not alone here.) +% +% \begin{macrocode} +\def\tabpause#{% + \noalign{\ifnum0=`}\fi% + \@parboxrestore% + \tab@startpause% + \vskip-\parskip% + \parshape\@ne\@totalleftmargin\linewidth% + \noindent% + \doafter\tabpause@i% +} +\def\tabpause@i{% + \nobreak% + \tab@endpause% + \ifnum0=`{\fi}% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{The wonderful world of \cmd\multicolumn} +% +% \begin{macro}{\multicolumn} +% +% This is actually fantasitcally easy. Watch and learn. Make sure you +% notice the |\long|s here: remember that some table cells can contain +% paragraphs, so it seems sensible to allow |\par| into the argument. +% (As far as I know, most other |\multicolumn| commands don't do this, +% which seems a little silly. Then again, I forgot to do it the first +% time around.) +% +% \begin{macrocode} +\long\def\multicolumn#1#2#3{% + \multispan{#1}% + \begingroup% + \tab@multicol% + \tab@initread% + \tab@preamble{}% + \long\def\tab@midtext{#3}% + \let\tab@looped\tab@err@multi% + \tab@readpreamble{#2}% + \the\tab@preamble% + \endgroup% + \ignorespaces% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Interlude: range lists} +% +% For processing arguments to |\vgap| and |\cline|, we need to be able to +% do things with lists of column ranges. To save space, and to make my +% fingers do less typing, here's some routines which do range handling. +% +% \begin{macro}{\ranges} +% +% Given a macro name and a comma separated list of ranges and simple numbers, +% this macro will call the macro giving it each range in the list in turn. +% Single numbers~$n$ will be turned into ranges $n$--$n$. +% +% The first job is to read the macro to do (which may already have some +% arguments attached to it). We'll also start a group to make sure that +% our changes to temp registers don't affect anyone else. +% +% There's a space before the delimiting |\q@delim| to stop numbers being +% parsed to far and expanding our quark (which will stop \TeX\ dead in its +% tracks). Since we use |\@ifnextchar| to look ahead, spaces in range lists +% are perfectly all right. +% +% \begin{macrocode} +\def\ranges#1#2{% + \gdef\ranges@temp{#1}% + \begingroup% + \ranges@i#2 \q@delim% +} +% \end{macrocode} +% +% +% We're at the beginning of the list. We expect either the closing marker +% (if this is an empty list) or a number, which we can scoop up into a +% scratch register. +% +% \begin{macrocode} +\def\ranges@i{% + \@ifnextchar\q@delim\ranges@done{\afterassignment\ranges@ii\count@}% +} +% \end{macrocode} +% +% We've read the first number in the range. If there's another number, we'll +% expect a `|-|' sign to be next. If there is no `|-|', call the user's code +% with the number duplicated and then do the rest of the list. +% +% \begin{macrocode} +\def\ranges@ii{% + \@ifnextchar-\ranges@iii{\ranges@do\count@\count@\ranges@v}% +} +% \end{macrocode} +% +% Now we strip the `|-|' off and read the other number into a temporary +% register. +% +% \begin{macrocode} +\def\ranges@iii-{\afterassignment\ranges@iv\@tempcnta} +% \end{macrocode} +% +% We have both ends of the range now, so call the user's code, passing it +% both ends of the range. +% +% \begin{macrocode} +\def\ranges@iv{\ranges@do\count@\@tempcnta\ranges@v} +% \end{macrocode} +% +% We've finished doing an item now. If we have a `|,|' next, then start +% over with the next item. Otherwise, if we're at the end of the list, +% we can end happily. Finally, if we're totally confused, raise an +% error. +% +% \begin{macrocode} +\def\ranges@v{% + \@ifnextchar,% + \ranges@vi% + {% + \@ifnextchar\q@delim% + \ranges@done% + {\tab@err@range\ranges@vi,}% + }% +} +% \end{macrocode} +% +% We had a comma, so gobble it, read the next number, and go round again. +% +% \begin{macrocode} +\def\ranges@vi,{\afterassignment\ranges@ii\count@} +% \end{macrocode} +% +% Here's how we call the user's code, now. We close the group, so that the +% user's code doesn't have to do global things to remember its results, and +% we expand the two range ends from their count registers. We also ensure +% that the range is the right way round. +% +% \begin{macrocode} +\def\ranges@do#1#2{% + \ifnum#1>#2\else% + \expandafter\endgroup% + \expandafter\ranges@temp% + \expandafter{% + \the\expandafter#1% + \expandafter}% + \expandafter{% + \the#2% + }% + \begingroup% + \fi% +} +% \end{macrocode} +% +% And finishing the scan is really easy. We close the group after gobbling +% the close token. +% +% \begin{macrocode} +\def\ranges@done\q@delim{\endgroup} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\ifinrange} +% +% Something a little more useful, now. |\ifinrange| takes four arguments: +% a number, a range list (as above), and two token lists which I'll call +% \emph{then} and \emph{else}. If the number is in the list, I'll do +% \emph{then}, otherwise I'll do \emph{else}. +% +% \begin{macrocode} +\def\ifinrange#1#2{% + \@tempswafalse% + \count@#1% + \ranges\ifinrange@i{#2}% + \if@tempswa% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% +} +\def\ifinrange@i#1#2{% + \ifnum\count@<#1 \else\ifnum\count@>#2 \else\@tempswatrue\fi\fi% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Horizontal rules OK} +% +% This is where all the gubbins for |\vgap| and friends is kept, lest it +% contaminate fairly clean bits of code found elsewhere. +% +% \subsubsection{Drawing horizontal rules} +% +% \begin{macro}{\hline} +% +% Note the funny use of |\noalign| to allow \TeX\ stomach ops like +% |\futurelet| without starting a new table row. This lets us see if there's +% another |\hline| coming up, so we can see if we need to insert extra +% vertical space. +% +% \begin{macrocode} +\def\hline{% + \tab@dohline% + \noalign{\ifnum0=`}\fi% + \tab@penalty% + \futurelet\@let@token\hline@i% +} +% \end{macrocode} +% +% We check here for another |\hline| command, and insert glue if there is. +% This looks terrible, though, and |\hlx{hvh}| is much nicer. Still\dots +% +% \begin{macrocode} +\def\hline@i{% + \ifx\@let@token\hline% + \vskip\doublerulesep% + \tab@addruleheight\doublerulesep% + \fi% + \ifnum0=`{\fi}% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@dohline} +% +% This is where hlines actually get drawn. +% Drawing lines is more awkward than it used to be, particularly in unboxed +% tables. It used to be a case simply of saying |\noalign{\hrule}|. +% However, since unboxed tables are actually much wider than they look, this +% would make the rules stretch right across the page and look generally +% horrible. +% +% The solution is simple: we basically do a dirty big |\cline|. +% +% \begin{macrocode} +\def\tab@dohline{% + \multispan{\tab@columns}% + \leaders\hrule\@height\arrayrulewidth\hfil% + \tab@addruleheight\arrayrulewidth% + \cr% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Vertical rules} +% +% I couldn't fit these in anywhere else, so they'll have to go here. I'll +% provide a new optional argument which specifies the width of the rule; this +% gets rid of the problem described in the \emph{Companion}, where to get +% an unusually wide vertical rule, you have to play with things like +% \syntax{"\\vrule width" <dimen>} which really isn't too nice. +% +% \begin{macro}{\vline} +% +% The new |\vline| has an optional argument which gives the width of the +% rule. The |\relax| stops \TeX\ trying to parse a \<rule-specification> for +% too long, in case someone says something like `|\vline depthcharges|' or +% something equally unlikely. +% +% \begin{macrocode} +\renewcommand\vline[1][\arrayrulewidth]{\vrule\@width#1\relax} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Drawing bits of lines} +% +% Just for a bit of fun, here's an extended version of |\cline| which takes +% a list of columns to draw lines under, rather than just a single range. +% +% \begin{macro}{\cline} +% +% Not a single line of code written yet, and we already have a dilemma on +% our hands. Multiple consecutive |\cline| commands are meant to draw +% on the same vertical bit of table. But horizontal lines are meant to have +% thickness now. Oh, well [sigh], we'll skip back on it after all. +% +% Now the problem remains how best to do the job. The way I see it, there +% are three possibilities: +% +% \begin{itemize} +% +% \item We can start a table row, and then for each column of the table +% (as recorded in |\tab@columns|) we look to see if that column is +% listed in the range list and if so draw the rule. This requires +% lots of scanning of the range list. +% +% \item We can take each range in the list, and draw rules appropriately, +% just like the old |\cline| used to do, and starting a new table row +% for each. +% +% \item We can start a table row, and then for each range remember where we +% stopped drawing the last row, move to the start of the new one, and +% draw it. If we start moving backwards, we close the current row +% and open a new one. +% +% \end{itemize} +% +% The last option looks the most efficient, and the most difficult. This +% is therefore what I shall do |;-)|. +% +% The first thing to do is to add in a little negative space, and start a +% table row (omitting the first item). Then scan the range list, and finally +% close the table row and add some negative space again. +% +% We need a global count register to keep track of where we are. Mixing +% local and global assignments causes all sorts of tragedy, so I shall hijack +% |\tab@state|. +% +% \begin{macrocode} +\def\cline#1{% + \noalign{\kern-.5\arrayrulewidth\tab@penalty}% + \omit% + \global\tab@state\@ne% + \ranges\cline@i{#1}% + \cr% + \noalign{\kern-.5\arrayrulewidth\tab@penalty}% +} +% \end{macrocode} +% +% Now for the tricky bit. When we're given a range, we look to see if the +% first number is less than |\tab@state|. If so, we quickly close the +% current row, kern backwards and start again with an |\omit| and reset +% |\tab@state| to 1, and try again. +% +% \begin{macrocode} +\def\cline@i#1#2{% + \ifnum#1<\tab@state\relax% + \tab@@cr% + \noalign{\kern-\arrayrulewidth\tab@penalty}% + \omit% + \global\tab@state\@ne% + \fi% +% \end{macrocode} +% +% We are now either at or in front of the column position required. If +% we're too far back, we must |\hfil&\omit| our way over to the correct% +% column. +% +% \begin{macrocode} + \@whilenum\tab@state<#1\do{% + \hfil\tab@@tab@omit% + \global\advance\tab@state\@ne% + }% +% \end{macrocode} +% +% We've found the start correctly. We must deal with a tiny problem now: +% if this is not the first table cell, the left hand vertical rule is in the +% column to the left, so our horizontal rule won't match up properly. So +% we skip back by a bit to compensate. If there isn't actually a vertical +% rule to line up with, no-one will notice, because the rules are so thin. +% This adds a little touch of quality to the whole thing, which is after all +% the point of this whole exercise. +% +% \begin{macrocode} + \ifnum\tab@state>\@ne% + \kern-\arrayrulewidth% + \fi% +% \end{macrocode} +% +% Now we must stretch this table cell to the correct width. +% +% \begin{macrocode} + \@whilenum\tab@state<#2\do{% + \tab@@span@omit% + \global\advance\tab@state\@ne% + }% +% \end{macrocode} +% +% We're ready. Draw the rule. Note that this is |\hfill| glue, just in case +% we start putting in |\hfil| glue when we step onto the next cell. +% +% \begin{macrocode} + \leaders\hrule\@height\arrayrulewidth\hfill% +} +% \end{macrocode} +% +% Some alignment primitives are hidden inside macros so they don't get seen +% at the wrong time. This is what they look like: +% +% \begin{macrocode} +\def\tab@@cr{\cr} +\def\tab@@tab@omit{&\omit} +\def\tab@@span@omit{\span\omit} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Drawing short table rows} +% +% Before I start on a description of more code, I think I'll briefly discuss +% my reasons for leaving the |\vgap| command in its current state. There's a +% reasonable case for introducing an interface between |\vgap| and +% |\multicolumn|, to avoid all the tedious messing about with column +% ranges. There are good reasons why I'm not going to do this: +% +% \begin{itemize} +% +% \item It's very difficult to do: it requires either postprocessing of +% the table or delaying processing of each row until I know exactly +% what's in it; a |\multicolumn| in a row should be able to affect +% a |\vgap| before the row, which gets very nasty. This package is +% probably far too large already, and adding more complexity and +% running the risk of exhausting \TeX's frustratingly finite capacity +% for the sake of relieving the user of a fairly trivial job doesn't +% seem worthwhile. +% +% \item Perhaps more importantly, there are perfectly valid occasions when +% it's useful to have the current vgap behaviour. For example, the +% \texttt{MIX} word layout diagrams found in \emph{The Art of +% Computer Programming} use the little `stub lines' to show where +% data items cross byte boundaries: +% +% ^^A This actually looks terrifyingly similar to the original. +% ^^A The leading @{} is there to stop the table looking off-centre, +% ^^A because there's no left hand rule telling you where the table +% ^^A starts, like there is on the right, just the \tabcolsep glue. +% +% \begingroup +% \newcommand{\wide}[2]{\multicolumn{#1}{c|}{\ttfamily #2}} +% \begin{tabular}[C]{@{} r @{\qquad} | Mc | *{5}{c|}} \hlx{c{2-7} v} +% empty & - & 1 & 0 & 0 & 0 & 0 \\ \hlx{v c{2-7} v} +% occupied & + & \wide{2}{LINK} & \wide{3}{KEY} \\ \hlx{v c{2-7}} +% \end{tabular} +% \endgroup +% +% \end{itemize} +% +% That's my excuses out of the way; now I'll press on with the actual +% programming. +% +% \begin{macro}{\tab@checkrule} +% +% We have a range list in |\tab@xcols| and a number as an argument. If we +% find the number in the list, wejust space out the following group, +% otherwise we let it be. +% +% \begin{macrocode} +\def\tab@checkrule#1{% + \count@#1\relax% + \expandafter\ifinrange% + \expandafter\count@% + \expandafter{\tab@xcols}% + {\tab@checkrule@i}% + {}% +} +\def\tab@checkrule@i#1{\setbox\z@\hbox{#1}\hb@xt@\wd\z@{}} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\vgap} +% +% We must tread carefully here. A single misplaced stomach operation can +% cause error messages. We therefore start with an |\omit| so we can search +% for optional arguments. +% +% So that |\hlx| can get control after |\vgap| has finished, we provide a +% hook called |\vgap@after| which is expanded after |\vgap| has finished. +% Here we make it work like |\@empty|, which expands to nothing. (Note that +% |\relax| will start a new table row, so we can't use that.) There are +% some penalty items here to stick the |\vgap| row to the text row and +% |\hline| that are adjacent to it. The \package{longtable} package will +% split an |\hline| in half, so this is the correct thing to do. +% +% \begin{macrocode} +\def\vgap{% + \noalign{\nobreak}% + \omit% + \global\let\vgap@after\@empty% + \iffalse{\fi\ifnum0=`}\fi% + \@ifnextchar[\vgap@i\vgap@simple% +} +% \end{macrocode} +% +% We set up two different sorts of |\vgap| -- a simple one which allows all +% rules to be passed through, and a specific one which carefully vets each +% one (and is therefore slower). We decide which to so based on the presence +% of an optional argument. +% +% The optional argument handler just passes its argument to an interface +% routine which is used by |\hlx|. +% +% \begin{macrocode} +\def\vgap@i[#1]{\vgap@spec{#1}} +% \end{macrocode} +% +% Now we handle specified columns. Since we're in an omitted table cell, we +% must set things up globally. Assign the column spec to a macro, and set up +% vetting by the routine above. Then just go and do the job. +% +% \begin{macrocode} +\def\vgap@spec#1#2{% + \gdef\tab@xcols{#1}% + \global\let\tab@ckr\tab@checkrule% + \vgap@do{#2}% +} +% \end{macrocode} +% +% Handle all columns. Just gobble the column number for each rule, and let +% the drawing pass unharmed. Easy. +% +% \begin{macrocode} +\def\vgap@simple#1{% + \global\let\tab@ckr\@gobble% + \vgap@do{#1}% +} +% \end{macrocode} +% +% This is where stuff actually gets done. We set the |\vgap| flag on while +% we do the short row. Then just expand the token list we built while +% scanning the preamble. +% +% Note that the flag is cleared at the end of the last column, to allow other +% funny things like |\noalign| and |\omit| before a new row is started. +% +% \begin{macrocode} +\def\vgap@do#1{% + \ifnum0=`{}\fi% + \global\tab@vgaptrue% + \the\tab@shortline% + \vrule\@height#1\@width\z@% + \global\tab@vgapfalse + \tab@addruleheight{#1}% + \cr% + \noalign{\nobreak}% + \vgap@after% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Prettifying syntax} +% +% \begin{macro}{\hlx} +% +% This is like a poor cousin to the preamble parser. The whole loop is +% carefully written to take place \emph{only} in \TeX's mouth, so the +% alignment handling bits half way down the gullet don't see any of this. +% +% First, pass the string to another routine. +% +% \begin{macrocode} +\def\hlx#1{\hlx@loop#1\q@delim} +% \end{macrocode} +% +% Now peel off a token, and dispatch using |\csname|. We handle +% undefinedness of the command in a fairly messy way, although it probably +% works. Maybe. +% +% \begin{macrocode} +\def\hlx@loop#1{% + \ifx#1\q@delim\else% + \@ifundefined{hlx@cmd@\string#1}{% + \expandafter\hlx@loop% + }{% + \csname hlx@cmd@\string#1\expandafter\endcsname% + }% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\hlxdef} +% +% New |\hlx| commands can be defined using |\hlxdef|. This is a simple +% abbreviation. +% +% \begin{macrocode} +\def\hlxdef#1{\@namedef{hlx@cmd@#1}} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\hlx h} +% +% Handle an \lit{h} character. Just do an |\hline| and return to the loop. +% We look ahead to see if there's another \lit{h} coming up, and if so +% insert two |\hline| commands. This strange (and inefficient) behaviour +% keeps packages which redefine |\hline| happy. +% +% \begin{macrocode} +\hlxdef h#1{% + \noalign{% + \ifx#1h% + \def\@tempa{\hline\hline\hlx@loop}% + \else% + \def\@tempa{\hline\hlx@loop#1}% + \fi% + \expandafter + }% + \@tempa% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\hlx b} +% +% The \lit{b} character does a nifty backspace, for \package{longtable}'s +% benefit. +% +% \begin{macrocode} +\hlxdef b{\noalign{\kern-\arrayrulewidth}\hlx@loop} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\hlx /} +% +% The `"/"' character allows a page break at the current position. +% +% \begin{macrocode} +\hlxdef /{% + \noalign{\ifnum0=`}\fi% + \@ifnextchar[\hlx@cmd@break@i{\hlx@cmd@break@i[0]}% +} +\def\hlx@cmd@break@i[#1]{\ifnum0=`{\fi}\pagebreak[0]\hlx@loop} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\hlx v} +% +% Handle a \lit{v} character. This is rather like the |\vgap| code above, +% although there are syntactic differences. +% +% \begin{macrocode} +\hlxdef v{% + \noalign{\nobreak}% + \omit% + \iffalse{\fi\ifnum0=`}\fi% + \global\let\vgap@after\hlx@loop% + \@ifnextchar[\hlx@vgap@i{\hlx@vgap@ii\vgap@simple}% +} +\def\hlx@vgap@i[#1]{% + \ifx!#1!% + \def\@tempa{\hlx@vgap@ii\vgap@simple}% + \else% + \def\@tempa{\hlx@vgap@ii{\vgap@spec{#1}}}% + \fi% + \@tempa% +} +\def\hlx@vgap@ii#1{% + \@ifnextchar[{\hlx@vgap@iii{#1}}{\hlx@vgap@iii{#1}[\doublerulesep]}% +} +\def\hlx@vgap@iii#1[#2]{#1{#2}} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\hlx s} +% +% Allow the user to leave a small gap using the \lit{s} command. +% +% \begin{macrocode} +\hlxdef s{% + \noalign{\ifnum0=`}\fi% + \nobreak% + \@ifnextchar[\hlx@space@i{\hlx@space@i[\doublerulesep]}% +} +\def\hlx@space@i[#1]{% + \vskip#1% + \tab@addruleheight{#1}% + \ifnum0=`{\fi}% + \hlx@loop% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\hlx c} +% +% We might as well allow a \lit{c} command to do a |\cline|. +% +% \begin{macrocode} +\hlxdef c#1{\cline{#1}\hlx@loop} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\hlx .} +% +% The \lit{.} character forces a start of the new column. There's a little +% problem here. Since the \lit{.} character starts the next column, we need +% to gobble any spaces following the |\hlx| command before the cell contents +% actually starts. Unfortunately, |\ignorespaces| will start the column for +% us, so we can't put it in always. We'll handle it here, then. We'll take +% the rest of the `preamble' string, and warn if it's not empty. Then we'll +% |\ignorespaces| -- this will start the column for us, so we don't need to +% |\relax| any more. +% +% \begin{macrocode} +\hlxdef .#1\q@delim{% + \ifx @#1@\else% + \PackageWarning{mdwtab}{% + Ignoring \protect\hlx\space command characters following a + `.'\MessageBreak command% + }% + \fi% + \ignorespaces% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Starting new table rows} +% +% We take a break from careful mouthery at last, and start playing with +% newlines. The standard one allows pagebreaks in unboxed tables, which +% isn't really too desirable. +% +% Anyway, we'll try to make this macro rather more reusable than the standard +% one. Here goes. +% +% \begin{macro}{\@arraycr} +% +% We pass lots of information to a main parser macro, and expect it to cope. +% +% \begin{macrocode} +\def\@arraycr{\tab@arraycr{}} +\def\tab@arraycr#1{\tab@cr{\tab@tabcr{#1}}{}{}} +% \end{macrocode} +% +% Now to actually do the work. |\tab@cr| passes us the skip size, and the +% appropriate one of the two arguments given above (both of which are empty) +% depending on the presence of the $*$. +% +% \begin{macrocode} +\def\tab@tabcr#1#2{% +% \end{macrocode} +% +% If the total height I need to add between rows (from the optional argument +% and the `extrasep' parameter) is greater than zero, I'll handle this by +% extending the strut slightly. I'm not actually sure whether this is the +% right thing to do, to be honest, although it's easier than trying to +% to an automatic |\vgap|, because I need to know which columns to skip. +% If the space is less than zero, I'll just insert the vertical space with +% in a |\noalign|. +% +% First, to calculate how much space needs adding. +% +% \begin{macrocode} + \dimen@#2% + \advance\dimen@\tab@extrasep% +% \end{macrocode} +% +% If the height is greater than zero, I need to play with the strut. I must +% bear in mind that the current table cell (which I'm still in, remember) +% may be in vertical mode, and I may or may not be in a paragraph. +% +% If I am in vertical mode, I'll backpedal to the previous box and put the +% strut in an hbox superimposed on the previous baseline. Otherwise, I can +% just put the strut at the end of the text. (This works in either LR +% or paragraph mode as long as I'm not between paragraphs.) Again, Rowland's +% empty cell bug strikes. (See |\tab@epar| for details.) +% +% \begin{macrocode} + \ifdim\dimen@>\z@% + \ifvmode% + \unskip\ifdim\prevdepth>-\@m\p@\kern-\prevdepth\fi% + \nointerlineskip\expandafter\hbox% + \else% + \@maybe@unskip\expandafter\@firstofone% + \fi% + {\advance\dimen@\dp\@arstrutbox\vrule\@depth\dimen@\@width\z@}% + \fi% +% \end{macrocode} +% +% This table cell works as a group (which is annoying here). I'll copy the +% interrow gap into a global register so that I can use it in the |\noalign|. +% +% \begin{macrocode} + \global\dimen\@ne\dimen@% + \cr% + \noalign{% + #1% + \ifdim\dimen\@ne<\z@\vskip\dimen\@ne\relax\fi% + }% + \@gobble% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@setcr} +% +% To set the |\\| command correctly in each table cell, we make it a part of +% the preamble (in |\tab@midtext|) to call this routine. It's easy -- just +% saves the preamble from being huge. +% +% \begin{macrocode} +\def\tab@setcr{\let\\\tabularnewline} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\tab@cr} +% +% Now we do the parsing work. This is fun. Note the revenge of the funny +% braces here. Nothing to worry about, honest. The tricky bit is to keep +% track of which arguments are which. (Thanks to David Carlisle for pointing +% out that I'd missed out the |\relax| here.) +% +% \begin{macrocode} +\def\tab@cr#1#2#3{% + \relax% + \iffalse{\fi\ifnum0=`}\fi% + \@ifstar{\tab@cr@i{#1}{#3}}{\tab@cr@i{#1}{#2}}% +} +\def\tab@cr@i#1#2{% + \@ifnextchar[{\tab@cr@ii{#1}{#2}}{\tab@cr@ii{#1}{#2}[\z@]}% +} +\def\tab@cr@ii#1#2[#3]{% + \ifnum0=`{}\fi% + #1{#3}{#2}% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Gratuitous grotesquery} +% +% So far we've had an easy-ish ride (or should that be \emph{queasy}?). Now +% for something unexplainably evil. We convince \LaTeX\ that it's loaded the +% \package{array} package, so that packages which need it think they've got +% it. +% +% The bogus date is the same as the date for the \package{array} package I've +% got here -- this will raise a warning if Frank updates his package which +% should filter back to me telling me that there's something I need to +% know about. +% +% The messing with |\xdef| and the funny parsing ought to insert the current +% \package{mdwtab} version and date into the fake \package{array} version +% string, giving a visible clue to the user that this isn't the real +% \package{array} package. +% +% \begin{macrocode} +\begingroup +\catcode`.=11 +\def\@tempa#1 #2 #3\@@{#1 #2} +\xdef\ver@array.sty + {1995/11/19 [mdwtab.sty \expandafter\@tempa\ver@mdwtab.sty\@@]} +\endgroup +% \end{macrocode} +% +% +% \subsection{Error messages} +% +% I've put all the error messages together, where I can find them, translate +% them or whatever. +% +% First, some token-space saving (which also saves my fingers): +% +% \begin{macrocode} +\def\tab@error{\PackageError{mdwtab}} +% \end{macrocode} +% +% Now do the error messages. +% +% \begin{macrocode} +\def\tab@err@misscol{% + \tab@error{Missing column type}{% + I'm lost. I was expecting something describing^^J% + the type of the current column, but you seem to^^J% + have missed it out. I've inserted a type `l'^^J% + column here in the hope that this makes sense.% + }% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\tab@err@oddgroup{% + \tab@error{Misplaced group in table preamble}{% + I've found an open brace character in your preamble^^J% + when I was expecting a specifier character. I'm^^J% + going to gobble the whole group and carry on as if^^J% + I'd never seen it.% + }% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\tab@err@undef#1{% + \tab@error{Unknown `\tab@colset' preamble character `\string#1'}{% + I don't understand what you meant by typing this^^J% + character. Anyway, I'll ignore it this time around.^^J% + Just don't you do it again.% + }% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\tab@err@unbrh{% + \tab@error{Can't use unboxed tabular in LR mode}{% + You've asked for a tabular or array environment with^^J% + `L', `C' or `R' as the position specifier, but you're^^J% + in LR (restricted horizontal) mode, so it won't work.^^J% + I'll assume you really meant `c' and soldier on.% + }% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\tab@err@unbmm{% + \tab@error{Can't use unboxed tabular in maths mode}{% + You've asked for a tabular or array environment with^^J% + `L', `C' or `R' as the position specifier, but you're^^J% + in maths mode, so it won't work. I'll pretend that^^J% + you really typed `c', and that this is all a bad dream.% + }% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\tab@err@unbext{% + \tab@error{Can't extend unboxed tabulars}{% + You're trying to use kludgy extensions (e.g.,^^J% + `delarray') on an array or tabular with `L', `C'^^J% + or `R' as the position specifier. I'll assume you^^J% + subconsciously wanted a `c' type all along.% + }% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\tab@err@multi{% + \tab@error{More than one column in a \protect\multicolumn}{% + You've put more than one column into a \string\multicolumn^^J% + descriptor. It won't work. I have no idea what^^J% + will happen, although it won't be pleasant. Hold^^J% + on tight now...% + }% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\tab@err@range{% + \tab@error{Expected `,' or `<end>' in range list}{% + I was expecting either the end of the range list,^^J% + or a comma, followed by another range. I've^^J% + inserted a comma to try and get me back on track.^^J% + Good luck.% + }% +} +% \end{macrocode} +% +% That's it. No more. Move along please. +% +% \begin{macrocode} +%</mdwtab> +% \end{macrocode} +% +% +%^^A------------------------------------------------------------------------- +% \section{Implementation of \package{mathenv}} +% +% +% This is in a separate package, mainly to avoid wasting people's memory. +% +% \begin{macrocode} +%<*mathenv> +% \end{macrocode} +% +% +% \subsection{Options handling} +% +% We need to be able to cope with \textsf{fleqn} and \textsf{leqno} options. +% This will adjust our magic modified \env{eqnarray} environment +% appropriately. +% +% \begin{macrocode} +\newif\if@fleqn +\newif\if@leqno +\DeclareOption{fleqn}{\@fleqntrue} +\DeclareOption{leqno}{\@leqnotrue} +\ProcessOptions +% \end{macrocode} +% +% We use the \package{mdwtab} package for all its nice table handling things. +% (Oh, and to inflict it on users who want to do nice equations and don't +% care about our tables.) +% +% \begin{macrocode} +\RequirePackage{mdwtab} +% \end{macrocode} +% +% +% \subsection{Some useful registers} +% +% The old \LaTeX\ version puts the equation numbers in by keeping a count of +% where it is in the alignment. Since I don't know how may columns there are +% going to be, I'll just use a switch in the preamble to tell me to stop +% tabbing. +% +% \begin{macrocode} +\newif\if@eqalast +% \end{macrocode} +% +% Now define some useful length parameters. First allocate them: +% +% \begin{macrocode} +\newskip\eqaopenskip +\newskip\eqacloseskip +\newskip\eqacolskip +\newskip\eqainskip +\newskip\splitleft +\newskip\splitright +% \end{macrocode} +% +% Now assign some default values. Users can play with these if they really +% want although I can't see the point myself. +% +% \begin{macrocode} +\AtBeginDocument{% + \eqacloseskip\@centering% + \eqacolskip1.5em\@plus\@m\p@ + \eqainskip\z@% + \if@fleqn% + \eqaopenskip\mathindent% + \splitleft\mathindent\relax% + \splitright\mathindent\@minus\mathindent\relax% + \else% + \eqaopenskip\@centering% + \splitleft2.5em\@minus2.5em% + \splitright\splitleft% + \fi% + \relax% +} +% \end{macrocode} +% +% +% \subsection{A little display handling} +% +% I'm probably going a little far here, and invading territory already +% claimed by the \package{amsmath} stuff (and done a good deal better than +% I can be bothered to do), but just for completeness, this is how we handle +% attempts to put displays inside other displays without screwing up the +% spacing. +% +% \begin{macro}{\dsp@startouter} +% +% This is how we start an outermost display. It's fairly easy really. We +% make |\dsp@start| start an inner display, and make |\dsp@end| close the +% outer display. +% +% \begin{macrocode} +\def\dsp@startouter{% + \let\dsp@end\dsp@endouter% + $$% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\dsp@endouter} +% +% Ending the outer display is utterly trivial. +% +% \begin{macrocode} +\def\dsp@endouter{$$} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\dsp@startinner} +% +% Starting inner displays is done in a vbox (actually I choose |\vbox| or +% |\vtop| depending on the setting of \textsf{leqno} to put the equation +% number the right way round). +% +% \begin{macrocode} +\def\dsp@startinner{% + \let\dsp@end\dsp@endinner% + \if@fleqn\kern-\mathindent\fi% + \if@leqno\vtop\else\vtop\fi\bgroup% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\dsp@endinner} +% +% Ending an inner display is also really easy. +% +% \begin{macrocode} +\def\dsp@endinner{\egroup} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\dsp@start} +% +% This is what other bits of code uses to start displays. It's one of the +% start macros up above, and outer by default. +% +% \begin{macrocode} +\def\dsp@start{% + \ifmmode% + \ifinner\mth@err@mdsp\fi% + \expandafter\dsp@startinner% + \else% + \ifhmode\ifinner\mth@err@hdsp\fi\fi% + \expandafter\dsp@startouter% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\dsp@tabpause} +% +% This sets up the correct pre- and postambles for the |\tabpause| macro in +% maths displays. This is fairly simple stuff. +% +% \begin{macrocode} +\def\dsp@tabpause{% + \def\tab@startpause% + {\penalty\postdisplaypenalty\vskip\belowdisplayskip}% + \def\tab@endpause% + {\penalty\predisplaypenalty\vskip\abovedisplayskip}% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{The \env{eqnarray} environment} +% +% We allow the user to play with the style if this is really wanted. I dunno +% why, really. Maybe someone wants very small alignments. +% +% \begin{macrocode} +\let\eqastyle\displaystyle +% \end{macrocode} +% +% \subsubsection{The main environments} +% +% \begin{environment}{eqnarray} +% \begin{environment}{eqnarray*} +% +% We define the toplevel commands here. They just add in default arguments +% and then call |\@eqnarray| with a preamble string. We handle equation +% numbers by setting up a default (|\eqa@defnumber|) which is put into +% the final column. At the beginning of each row, we globally |\let| +% |\eqa@number| equal to |\eqa@defnumber|. The |\eqnumber| macro just +% changes |\eqa@number| as required. Since |\eqa@number| is changed globally +% we must save it in this environment. +% +% First, we must sort out the optional arguments and things. This is really +% easy. The only difference between the starred and non-starred environments +% is the default definition of |\eqa@defnumber|. +% +% \begin{macrocode} +\def\eqnarray{% + \eqnarray@i\eqa@eqcount% +} +\@namedef{eqnarray*}{\eqnarray@i{}} +\def\eqnarray@i#1{\@ifnextchar[{\eqnarray@ii{#1}}{\eqnarray@ii{#1}[rcl]}} +% \end{macrocode} +% +% Right. Now for the real work. The first argument is the default numbering +% tokens; the second is the preamble string. +% +% \begin{macrocode} +\def\eqnarray@ii#1[#2]{% +% \end{macrocode} +% +% Set up the equation counter and labels correctly. +% +% \medskip\par\noindent|\begin{rant}|\par +% The hacking with |\@currentlabel| is here because (in the author's opinion) +% \LaTeX's |\refstepcounter| macro is broken. It's currently defined as +% \begin{listing} +%\def\refstepcounter#1{% +% \stepcounter{#1}% +% \protected@edef\@currentlabel% +% {\csname p@#1\endcsname\csname the#1\endcsname}% +%} +% \end{listing} +% which means that the current label gets `frozen' as soon as you do the +% counter step. By redefining the macro as +% \begin{listing} +%\def\refstepcounter#1{% +% \stepcounter{#1}% +% \edef\@currentlabel{% +% \expandafter\noexpand\csname p@#1\endcsname% +% \expandafter\noexpand\csname the#1\endcsname% +% }% +%} +% \end{listing} +% these sorts of problems would be avoided, without any loss of functionality +% or compatibility that I can see. +% \par\noindent|\end{rant}|\par +% +% \begin{macrocode} + \stepcounter{equation}% + \def\@currentlabel{\p@equation\theequation}% +% \end{macrocode} +% +% The next step is to set up the numbering. I must save the old numbering +% so I can restore it later (once in the alignment, I must assign these +% things globally). +% +% \begin{macrocode} + \let\eqa@oldnumber\eqa@number% + \def\eqa@defnumber{#1}% + \global\let\eqa@number\eqa@defnumber% +% \end{macrocode} +% +% The |\if@eqalastfalse| switch is false everywhere except when we're in the +% final column. +% +% \begin{macrocode} + \@eqalastfalse% +% \end{macrocode} +% +% Remove the |\mathsurround| kerning, since it will look very odd inside +% the display. We have our own spacing parameters for configuring these +% things, so |\mathsurround| is unnecessary. +% +% \begin{macrocode} + \m@th% +% \end{macrocode} +% +% Time to parse the preamble string now. I must choose the correct column +% set, initialise the preamble parser and set up the various macros. The% +% extra `|@{\tabskip\eqacloseskip}|' item sets up the tabskip glue to centre +% the alignment properly. +% +% \begin{macrocode} + \colset{eqnarray}% + \tab@initread% + \def\tab@tabtext{&\tabskip\z@skip}% + \tab@preamble{\tabskip\z@skip}% + \tab@readpreamble{#2@{\tabskip\eqacloseskip}}% + \dsp@tabpause% +% \end{macrocode} +% +% Now for some final setting up. The column separation is set from the +% user's parameter, the |\everycr| tokens are cleared, and I set up the +% newline command appropriately. +% +% \begin{macrocode} + \col@sep.5\eqainskip% + \everycr{}% + \let\\\@eqncr% +% \end{macrocode} +% +% Now start a maths display and do the alignment. Set up the left hand +% tabskip glue to centre the alignment, and do the actual alignment. +% The preamble used is mainly that generated from the user's string, although +% the stuff at the end is how we set up the equation number -- it repeats +% appropriately so we can always find it. +% +% \begin{macrocode} + \dsp@start% + \tabskip\eqaopenskip% + \halign to\displaywidth\expandafter\bgroup% + \the\tab@preamble% + &&\eqa@lastcol\hb@xt@\z@{\hss##}\tabskip\z@\cr% +} +% \end{macrocode} +% +% Now for the end of the environment. This is really easy. Set the final +% equation number, close the |\halign|, tidy up the equation counter (it's +% been stepped once too many times) and close the display. +% +% \begin{macrocode} +\def\endeqnarray{% + \eqa@eqnum% + \egroup% + \dsp@end% + \global\let\eqa@number\eqa@oldnumber% + \global\@ignoretrue% + \global\advance\c@equation\m@ne% +} +\expandafter\let\csname endeqnarray*\endcsname\endeqnarray +% \end{macrocode} +% +% \end{environment} +% \end{environment} +% +% Now we can define the column types. +% +% \begin{macrocode} +\colpush{eqnarray} +% \end{macrocode} +% +% Note the positioning of ord atoms in the stuff below. This will space out +% relations and binops correctly when they occur at the edges of columns, and +% won't affect ord atoms at the edges, because ords pack closely. +% +% First the easy onces. Just stick |\hfil| in the right places and +% everything will be all right. +% +% \begin{macrocode} +\coldef r{\tabcoltype{\hfil$\eqastyle}{{}$}} +\coldef c{\tabcoltype{\hfil$\eqastyle{}}{{}$\hfil}} +\coldef l{\tabcoltype{$\eqastyle{}}{$\hfil}} +\coldef x{\tabcoltype{\if@fleqn\else\hfil\fi$\eqastyle}{$\hfil}} +% \end{macrocode} +% +% Now for the textual ones. This is also fairly easy. +% +% \begin{macrocode} +\collet T [tabular]T +% \end{macrocode} +% +% Sort of split types of equations. I mustn't use |\rlap| here, or +% everything goes wrong -- |\\| doesn't get noticed by \TeX\ in the same way +% as |\cr| does. +% +% \begin{macrocode} +\coldef L{\tabcoltype{\hb@xt@2em\bgroup$\eqastyle}{$\hss\egroup}} +% \end{macrocode} +% +% The \lit{:} column type is fairly simple. +% +% \begin{macrocode} +\coldef :{\tabspctype{\tabskip\eqacolskip}} +\coldef q{\tabspctype{\quad}} +% \end{macrocode} +% +% The other column types just insert given text in an appropriate way. +% +% \begin{macrocode} +\collet > [tabular]> +\collet < [tabular]< +\collet * [tabular]* +\collet @ [tabular]@ +% \end{macrocode} +% +% Finally, the magical `|\magic|' column type, which sets the equation +% number. We set up the |\tabskip| glue properly, tab on, and set the flag +% which marks the final column. The |\eqa@lastcol| command is there to +% raise an error if the user tabs over to this column. I'll temporarily +% redefine it to |\@eqalasttrue| when I enter this column legitimately. +% The extra magical bits here will make the final column repeat, so that we +% can find it if necessary. Well is this column type named. +% +% That's it. We can return to normal now. +% +% \begin{macrocode} +\colpop +% \end{macrocode} +% +% \subsubsection{Newline codes} +% +% Newline sequences (|\\|) get turned into calls of |\@eqncr|. The job is +% fairly simple, really. +% +% \begin{macrocode} +\def\@eqncr{\tab@cr\eqacr@i\interdisplaylinepenalty\@M}% +\def\eqacr@i#1#2{% + \eqa@eqnum% + \noalign{\penalty#2\vskip\jot\vskip#1}% +} +% \end{macrocode} +% +% \subsubsection{Setting equation numbers} +% +% \begin{macro}{\eqa@eqpos} +% +% Before we start, we need to generalise the flush-left number handling bits. +% The macro |\eqa@eqpos| will put its argument in the right place. +% +% \begin{macrocode} +\if@leqno + \def\eqa@eqpos#1{% + \hb@xt@.01\p@{}\rlap{\normalfont\normalcolor\hskip-\displaywidth#1}% + } +\else + \def\eqa@eqpos#1{\normalfont\normalcolor#1} +\fi +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\eqa@eqnum} +% +% Here we typeset an equation number in roughly the right place. First I'll +% redefine |\eqa@lastcol| so that it tells me I'm in the right place, and +% start a loop to find that place. +% +% \begin{macrocode} +\def\eqa@eqnum{% + \global\let\eqa@lastcol\@eqalasttrue% + \eqa@eqnum@i% +} +% \end{macrocode} +% +% Now for the loop. The |\relax| here is absolutely vital -- it starts the +% table column, inserting useful tokens like `|\eqa@lastcol|' which tell +% me where I am in the alignment. Then, if I've reached the end, I can +% typeset the equation number; otherwise I go off into another macro and +% step on to the next column. +% +% \begin{macrocode} +\def\eqa@eqnum@i{% + \relax% + \if@eqalast% + \expandafter\eqa@eqnum@ii% + \else% + \expandafter\eqa@eqnum@iii% + \fi% +} +\def\eqa@eqnum@ii{% + \eqa@eqpos\eqa@number% + \global\let\eqa@number\eqa@defnumber% + \global\let\eqa@lastcol\eqa@@lastcol% + \cr% +} +\def\eqa@eqnum@iii{&\eqa@eqnum@i} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\eqa@lastcol} +% +% This is used as a marker for the final column in an \env{eqnarray} +% environment. By default it informs the user that they've been very +% silly and swallows the contents of the column. I'll redefine it to +% something more useful at appropriate times, and then turn it back again. +% +% \begin{macrocode} +\def\eqa@@lastcol{\mth@err@number\setbox\z@} +\let\eqa@lastcol\eqa@@lastcol +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Numbering control} +% +% \begin{macro}{\eqnumber} +% +% The |\eqnumber| command sets the equation number on the current equation. +% This is really easy, actually. +% +% \begin{macrocode} +\newcommand\eqnumber[1][\eqa@eqcount]{\gdef\eqa@number{#1}} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\eqa@eqcount} +% +% This is how a standard equation number is set, stepping the counter and +% all. It's really easy and obvious. +% +% \begin{macrocode} +\def\eqa@eqcount{(\theequation)\global\advance\c@equation\@ne} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\nonumber} +% +% The \LaTeX\ |\nonumber| command could be defined by saying +% \begin{listing} +%\renewcommand{\nonumber}{\eqnumber[]} +% \end{listing} +% but I'll be slightly more efficient and redefine |\eqa@number| directly. +% +% \begin{macrocode} +\def\nonumber{\global\let\eqa@number\@empty} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{The \env{eqnalign} environment} +% +% As a sort of companion to \env{eqnarray}, here's an environment which does +% similar things inside a box, rather than taking up the whole display width. +% It uses the same column types that we've already created, so there should +% be no problems. +% +% \begin{environment}{eqnalign} +% +% First, sort out some simple things like optional arguments. +% +% \begin{macrocode} +\def\eqnalign{\@ifnextchar[\eqnalign@i{\eqnalign@i[rcl]}} +\def\eqnalign@i[#1]{% + \@ifnextchar[{\eqnalign@ii{#1}}{\eqnalign@ii{#1}[c]}% +} +% \end{macrocode} +% +% Now we actually do the environment. This is fairly easy, actually. +% +% \begin{macrocode} +\def\eqnalign@ii#1[#2]{% + \let\\\eqn@cr% + \colset{eqnarray}% + \tab@initread% + \def\tab@tabtext{&\tabskip\z@skip}% + \tabskip\z@skip% + \col@sep.5\eqainskip% + \tab@readpreamble{#1}% + \everycr{}% + \if#2t\vtop\else% + \if#2b\vbox\else% + \vcenter% + \fi% + \fi% + \bgroup% + \halign\expandafter\bgroup\the\tab@preamble\cr% +} +% \end{macrocode} +% +% Finishing the environment is even simpler. +% +% \begin{macrocode} +\def\endeqnalign{% + \crcr% + \egroup% + \egroup% +} +% \end{macrocode} +% +% \end{environment} +% +% \begin{macro}{\eqn@cr} +% +% Newlines are really easy here. +% +% \begin{macrocode} +\def\eqn@cr{\tab@cr\eqn@cr@i{}{}} +\def\eqn@cr@i#1{\cr\noalign{\vskip\jot\vskip#1}\@gobble} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Simple multiline equations} +% +% As a sort of example and abbreviation, here's a multiline display +% environment which just centres everything. +% +% \begin{environment}{eqlines} +% +% We just get |\eqnarray| to do everything for us. This is really easy. +% +% \begin{macrocode} +\def\eqlines{\eqnarray[x]} +\let\endeqlines\endeqnarray +% \end{macrocode} +% +% \end{environment} +% +% \begin{environment}{eqlines*} +% +% There's a $*$ version which omits numbers. This is easy too. Lots of +% hacking with expansion here to try and reduce the number of tokens being +% used. Is it worth it? +% +% \begin{macrocode} +\expandafter\edef\csname eqlines*\endcsname{% + \expandafter\noexpand\csname eqnarray*\endcsname[x]% +} +\expandafter\let\csname endeqlines*\expandafter\endcsname + \csname endeqnarray*\endcsname +% \end{macrocode} +% +% \end{environment} +% +% +% \subsection{Split equations} +% +% Based on an idea from \textit{The \TeX book}, we provide some simple +% environments for doing split equations. These's plenty of scope for +% improvement here, though. +% +% \begin{environment}{spliteqn} +% \begin{environment}{spliteqn*} +% +% The only difference between these two is that the $*$-version doesn't put +% in an equation number by default (although this behaviour can be +% changed by |\eqnumber|). +% +% The fun here mainly concerns putting in the equation number at the right +% place -- for |leqno| users, we need to put the number on the first line; +% otherwise we put it on the last line. +% +% The way we handle this is to have two macros, |\\| (which clearly does +% all the user line breaks) and |\seq@lastcr| which is used at the end of +% the environment to wrap everything up. The |\seq@eqnocr| macro puts an +% equation number on the current line and then does a normal |\\|. It also +% resets |\\| and |\seq@lastcr| so that they don't try to put another +% equation number in. This must be done globally, although anyone who tries +% to nest maths displays will get what they deserve. +% +% For the non-$*$ environment, then, we need to step the equation counter, +% and set |\\| to |\seq@cr| or |\seq@eqnocr| as appropriate for the setting +% of the |leqno| flag -- |\seq@lastcr| always gets set to put an equation +% number in (because it will be reset if the number actually gets done +% earlier -- this catches stupid users trying to put a single row into +% a split environment). +% +% \begin{macrocode} +\def\spliteqn{% + \let\eqa@oldnumber\eqa@number% + \global\let\eqa@number\eqa@eqcount% + \spliteqn@i% +} +% \end{macrocode} +% +% For the $*$ variant, we don't need to bother with equation numbering, so +% this is really easy. +% +% \begin{macrocode} +\@namedef{spliteqn*}{% + \let\eqa@oldnumber\eqa@number% + \gdef\eqa@number{}% + \spliteqn@i% +} +% \end{macrocode} +% +% Ending the environments is easy. Most of the stuff here will be described +% later. +% +% \begin{macrocode} +\def\endspliteqn{% + \hfilneg\seq@lastcr% + \egroup% + \dsp@end% + \global\let\eqa@number\eqa@oldnumber% + \global\advance\c@equation\m@ne% +} +\expandafter\let\csname endspliteqn*\endcsname\endspliteqn +% \end{macrocode} +% +% \end{environment} +% \end{environment} +% +% \begin{macro}{\spliteqn@i} +% +% Here we handle the full display splits. Start a maths display, and make +% each row of the alignment take up the full display width. +% +% The macro |\seq@dosplit| does most of the real work for us -- setting up +% the alignment and so forth. The template column is interesting. There +% are two items glue on both sides of the actual text: +% +% \begin{itemize} +% +% \item Some glue which can shrink. This keeps the display from the edges +% of the page unless we get a really wide item. +% +% \item An |\hfil| to do the alignment. By default, this centres the +% equations. On the first line, however, we put a leading |\hfilneg| +% which cancels the first |\hfil|, making the first row left aligned. +% Similarly, at the end, we put an |\hfilneg| after the last equation +% to right align the last line. +% +% \end{itemize} +% +% We pass this information on as an argument. It's easy really. +% +% \begin{macrocode} +\def\spliteqn@i{% +% \end{macrocode} +% +% First, set up equation numbering properly. See my rant about +% |\refstepcounter| above. +% +% \begin{macrocode} + \stepcounter{equation}% + \def\@currentlabel{\p@equation\theequation}% +% \end{macrocode} +% +% Right; now to sort out the numbering and newline handling. If the number's +% meant to be on the first line (for \textsf{leqno} users), then it gets +% typeset on the first like; otherwise we just do a normal newline on +% all lines except the first. Once |\seq@eqnocr| has done its stuff, it +% redefines all the newline handling not to insert another number. +% +% \begin{macrocode} + \if@leqno% + \global\let\seq@docr\seq@eqnocr% + \else% + \global\let\seq@docr\seq@cr% + \fi% + \global\let\seq@lastcr\seq@eqnocr% +% \end{macrocode} +% +% For my next trick, I'll do some display handling -- start a (possibly +% nested) maths display, set up the |\tabpause| macro appropriately, and +% set the newline command to do the right thing. +% +% \begin{macrocode} + \dsp@start% + \dsp@tabpause% + \def\\{\seq@docr}% +% \end{macrocode} +% +% Finally, call another macro to do the remaining bits of setting up. +% +% \begin{macrocode} + \seq@dosplit% + {\hb@xt@\displaywidth{% + \hskip\splitleft\hfil$\displaystyle##$% + \hfil\hskip\splitright}}% + {\hfilneg}% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{subsplit} +% +% For doing splits in the middle of equations, we provide a similar +% environment. Here, we make |\\| just start a new line. We also use +% a |\vcenter| rather than a full maths display. The glue items are also +% a bit different: we use plain double-quads on each side of the item, and +% we need to remove them by hand at the extremeties of the environment. +% +% \begin{macrocode} +\def\subsplit{% + \let\\\seq@cr% + \vcenter\bgroup% + \seq@dosplit{\hfil\qquad$##$\qquad\hfil}{\hfilneg\hskip-2em}% +} +% \end{macrocode} +% +% Ending the environment is fairly easy. We remove the final glue item, +% and close the alignment and the vbox. +% +% \begin{macrocode} +\def\endsubsplit{% + \hfilneg\hskip-2em\cr% + \egroup\egroup% +} +% \end{macrocode} +% +% \end{environment} +% +% \begin{macro}{\seq@dosplit} +% +% Here we do most of the real work. Actually, since the preamble is passed +% in as an argument, most of the work is already done. The only thing to +% really note is the template for subsequent columns. To stop users putting +% in extra columns (which is where we put the equation number) we raise an +% error and discard the input in a scratch box register. This template is +% repeated infinitely so as to allow us to put the equation number in nicely. +% However, the final negative glue item won't work properly, so the equation +% will look awful. +% +% \begin{macrocode} +\def\seq@dosplit#1#2{% + \halign\bgroup% + #1&&\mth@err@number\setbox\z@\hbox{##}\cr% + #2\relax% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\seq@eqnocr} +% +% Here's how we set equation numbers. Since the column provided raises +% errors as soon as a token finds its way into it, we start with a |&\omit|. +% Then we just put the equation number in a zero-width box. Finally, we +% reset the newline commands to avoid putting in more than one equation +% number, and do normal newline things. +% +% \begin{macrocode} +\def\seq@eqnocr{% + &\omit% + \hb@xt@\z@{\hss\eqa@eqpos\eqa@number}% + \global\let\seq@docr\seq@cr% + \global\let\seq@lastcr\seq@cr% + \seq@cr% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\seq@cr} +% +% Newlines are very easy. We add a |\jot| of extra space, since this is +% a nice thing to do. +% +% \begin{macrocode} +\def\seq@cr{\tab@cr\seq@cr@i\interdisplaylinepenalty\@M} +\def\seq@cr@i#1#2{\cr\noalign{\penalty#2\vskip\jot\vskip#1}} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Matrix handling} +% +% There's been a complete and total overhaul of the spacing calculations +% for matrices here. The vertical spacing now bears an uncanny similarity +% to the rules \TeX\ uses to space out |\atop|-like fractions, the difference +% being that you can have more than one column in a matrix. This has the +% interesting side-effect that we get an \package{amsmath}-style +% sub/superscript environment almost free of charge with the matrix handling +% (it just ends up being a script-size single-column matrix). +% +% What is rather gratifying is that our \env{matrix} environment looks +% rather nicer than \package{amsmath}'s (which is based directly on +% \env{array}, giving it nasty restrictions on the numbers of columns and +% so on); in particular, the version here gives the `correct' result for +% Knuth's exercise~18.42 (which states categorically that a |\smallskip| +% should be placed between the rows of the big matrix). +% +% The reason the interrow space doesn't come out in the AMS version is +% that \env{array} inserts extra vertical space by extending the depth of +% the final row using a strut: the big matrix already extends deeper than +% this, so the strut doesn't make any difference. If the space was added +% by |\hlx{s[\smallskipamount]}| instead of the |\\| command, things would +% be different. +% +% \begin{figure} +% +% ^^A This is essentially what amsmath (version 1.2b) does. The real +% ^^A implementation requires a counter MaxMatrixCols, and has fewer braces: +% ^^A that's all the difference. Oh, and I turn off \arrayextrasep here, +% ^^A since amsmath doesn't expect it to be there (accurate emulation, see?) +% ^^A and I've used \hspace instead of \hskip since everything else is +% ^^A `proper' LaTeX stuff. +% +% \newenvironment{ams-pmatrix}{^^A +% \setlength{\arrayextrasep}{0pt}^^A +% \left(^^A +% \hspace{-\arraycolsep}^^A +% \begin{array}{*{10}{c}}^^A +% }{^^A +% \end{array}^^A +% \hspace{-\arraycolsep}^^A +% \right)^^A +% } +% +% \begin{demo}{Exercise 18.42 from \emph{The \TeX book}} +%\newcommand{\domatrix}[1]{ +% \def\mat##1 +% {\begin{#1}##1\end{#1}} +% \[ \begin{#1} +% \mat{a & b \\ c & d} & +% \mat{e & f \\ g & h} +% \\[\smallskipamount] +% 0 & +% \mat{i & j \\ k & l} +% \end{#1} +% \] +%} +%\domatrix{pmatrix} +%\domatrix{ams-pmatrix} +% \end{demo} +% +% \end{figure} +% +% \begin{environment}{genmatrix} +% +% The first job is to store my maths style and font away, because I'll be +% needing it lots later. +% +% \begin{macrocode} +\def\genmatrix#1#2#3#4#5{% + \let\mat@style#1% + \ifx#2\scriptstyle% + \let\mat@font\scriptfont% + \else\ifx#2\scriptscriptstyle% + \let\mat@font\scriptscriptfont% + \else% + \let\mat@font\textfont% + \fi\fi% +% \end{macrocode} +% +% Now to cope with inserted text. This is easy. +% +% \begin{macrocode} + \ifx\mat@style\scriptstyle% + \let\mat@textsize\scriptsize% + \else\ifx\mat@style\scriptscriptstyle% + \let\mat@textsize\scriptscriptsize% + \else% + \let\mat@textsize\relax% + \fi\fi% +% \end{macrocode} +% +% Now for some fun. I'll remember how to start and end the matrix in a +% couple of macros |\mat@left| and |\mat@right|. I haven't yet worked out +% exactly what needs to be in |\mat@right| yet, though, so I'll build that +% up in a scratch token list while I'm making my mind up. +% +% Initially, I want to open a group (to trap the style changes), set the +% maths style (to get the right spacing), insert the left delimiter, insert +% some spacing around the matrix, and start a centred box. The ending just +% closes all the groups and delimiters I opened. +% +% \begin{macrocode} + \def\mat@left{\bgroup\mat@style\left#4#3\vcenter\bgroup}% + \toks@{\egroup#3\right#5\egroup}% +% \end{macrocode} +% +% Now comes a slightly trickier bit. If the maths style is script or +% scriptscript, then I need to raise the box by a little bit to make it look +% really good. The right amount is somewhere around \smallf 3/4\,pt, I +% think, so that's what I'll use. +% +% \begin{macrocode} + \@tempswatrue% + \ifx\mat@style\displaystyle\else\ifx\mat@style\textstyle\else% + \@tempswafalse% + \setbox\z@\hbox\bgroup$% + \toks@\expandafter{\the\toks@$\m@th\egroup\raise.75\p@\box\z@}% + \fi\fi% +% \end{macrocode} +% +% If I'm not in maths mode right now, then I should enter maths mode, and +% remember to leave it later. +% +% \begin{macrocode} + \if@tempswa\ifmmode\else% + $\m@th% + \toks@\expandafter{\the\toks@$}% + \fi\fi% +% \end{macrocode} +% +% Now I've sorted out how to end the environment properly, so I can set up +% the macro, using |\edef|. +% +% \begin{macrocode} + \edef\mat@right{\the\toks@}% +% \end{macrocode} +% +% Now see if there's an optional argument. If not, create lots of centred +% columns. +% +% \begin{macrocode} + \@ifnextchar[\genmatrix@i{\genmatrix@i[[c]}% +} +% \end{macrocode} +% +% Now to sort out everything else. +% +% \begin{macrocode} +\def\genmatrix@i[#1]{% +% \end{macrocode} +% +% Some initial setting up: choose the correct column set, and set up some +% variables for reading the preamble. +% +% \begin{macrocode} + \colset{matrix}% + \tab@initread% +% \end{macrocode} +% +% Now comes some of the tricky stuff. The space between columns should be +% 12\,mu (by trial and error). We put the space in a box so we can measure +% it in the correct mathstyle. +% +% \begin{macrocode} + \setbox\z@\hbox{$\mat@style\mskip12mu$}% + \edef\tab@tabtext{&\kern\the\wd\z@}% + \tab@readpreamble{#1}% +% \end{macrocode} +% +% Now we need to decide how to space out the rows. The code here is based +% on the information in appendix~G of \emph{The \TeX book}: I think it'd be +% nice if my matrices were spaced out in the same way as normal fractions +% (particularly |\choose|y things). The standard |\baselineskip| and +% |\lineskip| parameters come in really handy here. +% +% The parameters vary according to the size of the text, so I need to see +% if we have scriptsize or less, or not. The tricky |\if| sorts this out. +% +% \begin{macrocode} + \if1\ifx\mat@style\scriptstyle1\else% + \ifx\mat@style\scriptscriptstyle1\else0\fi\fi% + \baselineskip\fontdimen10\mat@font\tw@% + \advance\baselineskip\fontdimen12\mat@font\tw@% + \lineskip\thr@@\fontdimen8\mat@font\thr@@% + \else% + \baselineskip\fontdimen8\mat@font\tw@% + \advance\baselineskip\fontdimen11\mat@font\tw@% + \lineskip7\fontdimen8\mat@font\thr@@% + \fi% + \lineskiplimit\lineskip% +% \end{macrocode} +% +% Now actually set up for the alignment. Assign |\\| to the correct value. +% Set up the |\tabskip|. Do the appropriate |\mat@left| thing set up above. +% And then start the alignment. +% +% \begin{macrocode} + \let\\\mat@cr% + \tabskip\z@skip% + \col@sep\z@% + \mat@left% + \halign\expandafter\bgroup\the\tab@preamble\tabskip\z@skip\cr% +% \end{macrocode} +% +% Now for a little hack to make the spacing consistent between matrices of +% the same height. This comes directly from \PlainTeX. This appears to +% make the spacing \emph{exactly} the same as the \TeX\ primites, oddly +% enough. +% +% \begin{macrocode} + \ifx\mat@font\textfont% + \omit$\mat@style\mathstrut$\cr\noalign{\kern-\baselineskip}% + \fi% +} +% \end{macrocode} +% +% Finishing the environment is really easy. We do the spacing hack again +% at the bottom, close the alignment and then tidy whatever we started in +% |\mat@left|. +% +% \begin{macrocode} +\def\endgenmatrix{% + \crcr% + \ifx\mat@font\textfont% + \omit$\mat@style\mathstrut$\cr\noalign{\kern-\baselineskip}% + \fi% + \egroup% + \mat@right% +} +% \end{macrocode} +% +% \end{environment} +% +% \begin{macro}{\mat@cr} +% +% Newlines are really easy. The $*$-form means nothing here, so we ignore +% it. +% +% \begin{macrocode} +\def\mat@cr{\tab@cr\mat@cr@i{}{}} +\def\mat@cr@i#1{\cr\noalign{\vskip#1}\@gobble} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\newmatrix} +% +% This is how we define new matrix environments. It's simple fun with +% |\csname| and |\expandafter|. +% +% \begin{macrocode} +\def\newmatrix#1#2{% + \@namedef{#1}{\genmatrix#2}% + \expandafter\let\csname end#1\endcsname\endgenmatrix% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{matrix} +% \begin{environment}{pmatrix} +% \begin{environment}{dmatrix} +% \begin{environment}{smatrix} +% \begin{environment}{spmatrix} +% \begin{environment}{sdmatrix} +% \begin{environment}{smatrix*} +% \begin{environment}{spmatrix*} +% \begin{environment}{sdmatrix*} +% +% Now we define all the other environments we promised. This is easy. +% +% \begin{macrocode} +\newmatrix{matrix}{{\textstyle}{\textstyle}{\,}{.}{.}} +\newmatrix{pmatrix}{{\textstyle}{\textstyle}{\,}{(}{)}} +\newmatrix{dmatrix}{{\textstyle}{\textstyle}{\,}} +\newmatrix{smatrix}{{\scriptstyle}{\scriptstyle}{}{.}{.}} +\newmatrix{spmatrix}{{\scriptstyle}{\scriptstyle}{}{(}{)}} +\newmatrix{sdmatrix}{{\scriptstyle}{\scriptstyle}{}} +\newmatrix{smatrix*}{{\scriptstyle}{\textstyle}{}{.}{.}} +\newmatrix{spmatrix*}{{\scriptstyle}{\textstyle}{}{(}{)}} +\newmatrix{sdmatrix*}{{\scriptstyle}{\textstyle}{}} +% \end{macrocode} +% +% \end{environment} +% \end{environment} +% \end{environment} +% \end{environment} +% \end{environment} +% \end{environment} +% \end{environment} +% \end{environment} +% \end{environment} +% +% \begin{environment}{script} +% +% Now for superscripts and subscripts. This is fairly easy, because I +% took so much care over the matrix handling. +% +% \begin{macrocode} +\def\script{% + \let\mat@style\scriptstyle% + \def\mat@left{\vcenter\bgroup}% + \def\mat@right{\egroup}% + \let\mat@font\scriptfont% + \let\mat@textsize\scriptsize% + \@ifnextchar[\genmatrix@i{\genmatrix@i[c]}% +} +\let\endscript\endgenmatrix +% \end{macrocode} +% +% \end{environment} +% +% Now define the column types. +% +% \begin{macrocode} +\colpush{matrix} +\coldef l{\tabcoltype{\kern\z@$\mat@style}{\m@th$\hfil}} +\coldef c{\tabcoltype{\hfil$\mat@style}{\m@th$\hfil}} +\coldef r{\tabcoltype{\hfil$\mat@style}{\m@th$}} +\coldef T#1{\tab@aligncol{#1}{\begingroup\mat@textsize}{\endgroup}} +% \end{macrocode} +% +% The repeating type is more awkward. Things will go wrong if this is +% given before the first column, so we must do a whole repeat by hand. We +% can tell if we haven't contributed a column yet, since |\tab@column| will +% be zero. Otherwise, we fiddle the parser state to start a new column, and +% insert the |&| character to make \TeX\ repeat the preamble. +% +% \begin{macrocode} +\coldef {[}{% + \@firstoftwo{% + \ifnum\tab@columns=\z@% + \def\@tempa##1\q@delim{% + \tab@mkpreamble##1[##1\q@delim% + }% + \expandafter\@tempa% + \else% + \tab@setstate\tab@prestate% + \tab@append\tab@preamble{&}% + \expandafter\tab@mkpreamble% + \fi% + }% +} +% \end{macrocode} +% +% We're done defining columns now. +% +% \begin{macrocode} +\colpop +% \end{macrocode} +% +% +% \subsection{Dots\dots} +% +% Nothing whatsoever to do with alignments, although vertical and diagonal +% dots in small matrices look really silly. The following hacky definitions +% work rather better. +% +% \begin{macro}{\mdw@dots} +% +% First of all, here's some definitions common to both of the dots macros. +% The macro takes as an argument the actual code to draw the dots, passing +% it the scaled size of a point in the scratch register |\dimen@|; the +% register |\box 0| is set to contain a dot of the appropriate size. +% +% \begin{macrocode} +\def\mdw@dots#1{\ensuremath{\mathpalette\mdw@dots@i{#1}}} +\def\mdw@dots@i#1#2{% + \setbox\z@\hbox{$#1\mskip1.8mu$}% + \dimen@\wd\z@% + \setbox\z@\hbox{$#1.$}% + #2% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\vdots} +% +% I'll start with the easy one. This is a simple translation of the original +% implementation. +% +% \begin{macrocode} +\def\vdots{% + \mdw@dots{\vbox{% + \baselineskip4\dimen@% + \lineskiplimit\z@% + \kern6\dimen@% + \copy\z@\copy\z@\box\z@% + }}% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\ddots} +% +% And I'll end with the other easy one\dots +% +% \begin{macrocode} +\def\ddots{% + \mdw@dots{\mathinner{% + \mkern1mu% + \raise7\dimen@\vbox{\kern7\dimen@\copy\z@}% + \mkern2mu% + \raise4\dimen@\copy\z@% + \mkern2mu% + \raise\dimen@\box\z@% + \mkern1mu% + }}% +} +% \end{macrocode} +% +% \end{macro} +% +% +% \subsection{Lucky dip} +% +% Time to round off with some trivial environments, just to show how easy +% this stuff is. +% +% \begin{environment}{cases} +% \begin{environment}{smcases} +% +% These are totally and utterly trivial. +% +% \begin{macrocode} +\def\cases{\left\{\,\array{@{}lTl@{}}} +\def\endcases{\endarray\,\right.} +\def\smcases{\left\{\smarray{@{}lTl@{}}} +\def\endsmcases{\endsmarray\,\right.} +% \end{macrocode} +% +% \end{environment} +% \end{environment} +% +% \subsection{Error messages} +% +% Some token saving: +% +% \begin{macrocode} +\def\mth@error{\PackageError{mathenv}} +% \end{macrocode} +% +% Now for the error messages. +% +% \begin{macrocode} +\def\mth@err@number{% + \mth@error{Too many `&' characters found}{% + You've put too many `&' characters in an alignment^^J% + environment (like `eqnarray' or `spliteqn') and wandered^^J% + into trouble. I've gobbled the contents of that column^^J% + and hopefully I can recover fairly easily.% + }% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\mth@err@mdsp{% + \mth@error{Can't do displays in nondisplay maths mode}{% + You're trying to start a display environment, but you're^^J% + in nondisplay maths mode. The display will appear but^^J% + don't blame me when it looks horrible.% + }% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\mth@err@hdsp{% + \mth@error{Can't do displays in LR mode}{% + You're trying to start a display environment, but you're^^J% + in LR (restricted horizontal) mode. Everything will go^^J% + totally wrong, so your best bet is to type `X', fix the^^J% + mistake and start again.% + }% +} +% \end{macrocode} +% +% \vskip\parskip\vbox{ ^^A The best way I could find of keeping this lot +% ^^A together, I'm afraid. +% That's all there is. Byebye. +% +% \begin{macrocode} +%</mathenv> +% \end{macrocode} +% \nopagebreak +% +% \hfill Mark Wooding, \today +% } +% +% \Finale +% +\endinput diff --git a/Master/texmf-dist/source/latex/mdwtools/mdwtools.ins b/Master/texmf-dist/source/latex/mdwtools/mdwtools.ins new file mode 100644 index 00000000000..d44b1a2d791 --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/mdwtools.ins @@ -0,0 +1,79 @@ +% +% $Id: mdwtools.ins,v 1.3 1996/11/19 20:57:26 mdw Exp $ +% +% Installer for the mdwtools packages +% +% (c) 1996 Mark Wooding +% + +%----- Revision history ----------------------------------------------------- +% +% $Log: mdwtools.ins,v $ +% Revision 1.3 1996/11/19 20:57:26 mdw +% Entered into RCS +% + +% --- Licence note --- +% +% mdwtools installer +% Copyright (c) 1996 Mark Wooding +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +% --- Sort out how to do all this --- + +\def\batchfile{mdwtools.ins} +\input docstrip +\keepsilent + +\preamble + +IMPORTANT NOTICE +\endpreamble + +{ % --- This is a group so that docstrip \reads it all in one go --- + + \ifx\generate\mdwxxnotdef + \gdef\mdwgen#1{#1} + \gdef\mdwf#1#2{\generateFile{#1}{n}{#2}} + \gdef\needed#1{} + \else + \global\let\mdwgen\generate + \global\def\mdwf{\file} + \global\askforoverwritefalse + \fi + +} + +\mdwgen{\mdwf {at.sty} {\from {at.dtx} {package}} + \mdwf {mdwlist.sty} {\from {mdwlist.dtx} {package}} + \mdwf {mdwtab.sty} {\from {mdwtab.dtx} {mdwtab} + \needed{syntax.dtx} + \from {footnote.dtx} {macro} + \from {doafter.dtx} {macro}} + \mdwf {syntax.sty} {\from {syntax.dtx} {package} + \from {doafter.dtx} {macro}} + \mdwf {mathenv.sty} {\from {mdwtab.dtx} {mathenv}} + \mdwf {mdwmath.sty} {\from {mdwmath.dtx} {package}} + \mdwf {sverb.sty} {\from {sverb.dtx} {package}} + \mdwf {footnote.sty} {\from {footnote.dtx} {package}} + \mdwf {doafter.sty} {\from {doafter.dtx} {package,latex2e}} + \mdwf {doafter.tex} {\from {doafter.dtx} {package,plain}} + \mdwf {cmtt.sty} {\from {cmtt.dtx} {sty}} + \mdwf {mTTenc.def} {\from {cmtt.dtx} {def}} + \mdwf {mTTcmtt.fd} {\from {cmtt.dtx} {fd}} +} + +\Msg{Done!} diff --git a/Master/texmf-dist/source/latex/mdwtools/sverb.dtx b/Master/texmf-dist/source/latex/mdwtools/sverb.dtx new file mode 100644 index 00000000000..df12c8c1df8 --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/sverb.dtx @@ -0,0 +1,1186 @@ +% \begin{meta-comment} +% +% $Id: sverb.dtx,v 1.3 1996/11/19 21:01:18 mdw Exp $ +% +% Verbatim typesetting done properly (ahem) +% +% (c) 1996 Mark Wooding +% +%----- Revision history ----------------------------------------------------- +% +% $Log: sverb.dtx,v $ +% Revision 1.3 1996/11/19 21:01:18 mdw +% Entered into RCS +% +% +% \end{meta-comment} +% +% \begin{meta-comment} <general public licence> +%% +%% sverb package -- handling of verbatim text +%% Copyright (c) 1996 Mark Wooding +%% +%% This program is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation; either version 2 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program; if not, write to the Free Software +%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +%% +% \end{meta-comment} +% +% \begin{meta-comment} <Package preamble> +%<+package>\NeedsTeXFormat{LaTeX2e} +%<+package>\ProvidesPackage{sverb} +%<+package> [1996/05/08 1.3 Verbatim typesetting] +% \end{meta-comment} +% +% \CheckSum{651} +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%% +% +% \begin{meta-comment} +% +%<*driver> +\input{mdwtools} +\describespackage{sverb} +\mdwdoc +%</driver> +% +% \end{meta-comment} +% +% \section{User guide} +% +% The \package{sverb} package provides some useful commands and environments +% for doing things with verbatim text. I prefer this code to the standard +% \package{verbatim} package (by Rainer Sch\"opf et al.)\ although I'm +% biased. +% +% The package was written to fulfil a particular purpose: I wanted to be able +% to typeset ARM assembler code, 77~columns wide, on A5~paper, with the +% fields separated by \textit{tab} characters. It's grown up fairly +% organically from that, and I've tidied it when I've seen the code get too +% ugly. +% +% The current features are: +% +% \begin{itemize} +% +% \item A `listing' environment which typesets verbatim text nicely. +% +% \item A command to read verbatim text from an external file. +% +% \item Support for arbitrary-sized chunks of text without overflowing \TeX's +% memory. +% +% \item Support for \textit{tab} characters in the verbatim text. +% +% \item An environment for typesetting demonstrations of \LaTeX\ markup. +% +% \item It all works correctly with the \package{doc} system for documenting +% \LaTeX\ packages. +% +% \item A fairly hairy but quite powerful programmer interface to the yukky +% bits of the package. +% +% \end{itemize} +% +% The interface is described in its own section, so that more timid readers +% can avoid it. That said, some of the stuff in this section gets rather +% technical. +% +% Note that this package doesn't even try to do anything with short bits of +% verbatim text (as handled by the |\verb:...:| command). I have a separate +% package (\package{syntax}) which does all sorts of horrible things along +% those lines. +% +% \subsection{The \env{listing} environment} +% +% \DescribeEnv{listing} +% The main method for typesetting verbatim text is the \env{listing} +% environment. This works pretty much the same as the standard +% \env{verbatim} environment, with some exceptions, which are described +% below. +% +% So that you know exactly what you're getting, here are the rules by which +% \package{sverb} decides what the verbatim text actually is: +% +% \begin{itemize} +% +% \item If there's any text, other than spaces, on the same line as the +% `|\begin{listing}|', then the contents of the environment begins +% immediately after the closing brace (with all leading spaces +% preserved). Otherwise, the text begins on the following line. +% +% \item If there is any text, other than spaces, before the +% `|\end{listing}|', but on the same line, this is considered to be the +% last line of the text; otherwise the text is presumed to have ended +% at the end of the previous line. +% +% \item Any text following the |\end{listing}| on the same line is thrown +% away. There are good reasons for this, but they're technical. +% Essentially there's nothing I can do about it. +% +% \end{itemize} +% +% \begin{figure} +% \begin{demo}[w]{The \env{listing} environment} +%\dots in the following code: +% +%\begin{listing} +%init MOV R0,#200 ;Version 2.00 please +% LDR R1,=&4B534154 ;Magic number (`TASK') +% ADR R2,appName ;Find application name +% SWI Wimp_Initialise ;Register as a WIMP task +%\end{listing} +% +%The next step is to \dots +% \end{demo} +% \end{figure} +% +% Tab characters are supported within the environment: tab stops are set +% every eighth column, although this can be modified. +% +% \subsubsection{Configuring the \env{listing} environment} +% +% The text size used in the \env{listing} environment is set by the +% |\listingsize| command. By default, this is set to |\small|, although you +% can redefine it in the document preamble, or it can be set in the document +% class. +% +% The amount by which the listing text is indented is controlled by the +% |\listingindent| length parameter. This is a fixed length, whose default +% value is 1\,em. +% +% \subsubsection{Choosing a different end-text} +% +% \DescribeEnv{listing*} +% The \env{listing} environment is terminated by the exact character sequence +% `|\end{listing}|'. This isn't too much of a problem, unless you want to +% include this string in the text. This is achieved by the \env{listing$*$} +% environment, which allows you to specify the end-text to find as an +% argument. +% +% For example: +% +% \begin{demo}{The \env{listing$*$} environment} +%Type a listing as follows: +% +%\begin{listing*}{<end-listing*>} +%\begin{listing} +%This is a listing. Yes. +%\end{listing} +%<end-listing*> +%\end{demo} +% +% Don't include `special' characters in your chosen end-text unless you know +% what you're doing. +% +% \subsection{Writing text to a file} +% +% \DescribeEnv{verbwrite} +% You can write verbatim text to a file using the \env{verbwrite} +% environment. The syntax is fairly straightforward: +% +% \begin{quote} +% \syntax{"\\begin{verbwrite}{"<file-name>"}" \dots "\\end{verbwrite}"} +% \end{quote} +% +% The text of the environment is written to the named file. The rules about +% where the text actually starts and ends are the same as for the +% \env{listing} environment. +% +% There is also a $*$-variant, like \env{listing$*$}, which allows you to +% choose the end-text. The end-text is the first argument, the filename +% comes second. +% +% There is a restriction on the characters you can write to the file: they +% must all be considered `printable' by \TeX; otherwise they will be read +% back in as `\syntax{"^^"<chars>}' which isn't too good. Unfortunately, +% this includes tab characters, so you can't write them.\footnote{^^A +% Well, not without doing serious surgery on \TeX\ itself, anyway. } +% +% \iffalse [Example time... Ho hum. There is evilness here.] \fi +%\begin{verbwrite*}{<end-write>}{wrdemo1.tmp} +%\begin{verbwrite}{wrdemo.tmp} +%This is some text written to +%a file near the beginning of +%the file. +%\end{verbwrite} +%<end-write> +% +% For example: \verbinput{wrdemo1.tmp} +% +% \input{wrdemo1.tmp} \iffalse [Now build the file ;-) ] \fi +% +% \subsection{The \cmd\verbinput\ command} +% +% \DescribeMacro{\verbinput} +% You can input a pre-prepared text file exactly as it is in the input using +% the |\verbinput| command. The filename is given as an argument. For +% example: +% +% \begin{demo}{The \cmd\verbinput\ command} +%\verbinput{wrdemo.tmp} +% \end{demo} +% +% \subsection{The \env{demo} environment} +% +% Package authors need to document their packages, and it's common to want +% to display examples showing the original text and the output side-by-side +% (or, when space doesn't permit this, one above the other). Both the +% \LaTeX\ book and \textit{The \LaTeX\ Companion} contain such examples. +% +% The \env{demo} environment allows such displays to be created easily. The +% syntax of the environment is as follows: +% +% \begin{quote} +% \syntax{"\\begin{demo}["<shape>"]{"<title>"}" \dots "\\end{demo}"} +% \end{quote} +% +% The optional \synt{shape} argument can be either `|w|' (wide), or `|n|' +% (narrow). A `wide' shape places the input and output one above the other, +% while the `narrow' shape puts them side-by-side. The default shape is +% `narrow'. An attractive border is drawn around the display to finish it +% off nicely. +% +% An example: +% +%\begin{demo*}{<end-demo>}[w]{The \env{demo} environment} +%\begin{demo}{From the \textit{\TeX book}} +%\[ \sum_{p\;\rm prime} +% f(p) = \int_{t>1} +% f(t)\,{\rm d}\pi(t) \] +%\end{demo} +%<end-demo> +% +% \DescribeEnv{demo*} +% As with the other environments created by this package, there's a +% $*$-variant which takes the end-text as an argument. +% +% +% \section{Programmer interface} +% +% This section describes the publicly available routines provided by the +% \package{sverb} package. Routines not described here are libable to be +% changed or even removed without warning, so don't use them. +% +% \subsection{Environment hooks} +% +% Each of the environments created here works in the same way. For each +% environment \env{foo}, there's a main command responsible for doing the +% work, called |\sv@foo|. This is given all the arguments of the normal +% environment, and two more: +% +% \begin{itemize} +% +% \item The `end-text' to search for, which marks the end of the environment. +% +% \item Some actions to perform after the text has been read and processed. +% This allows the calling macro to do some extra actions, like closing +% boxes, etc. +% +% \end{itemize} +% +% All the environments do is call the main command with appropriate +% arguments. +% +% \subsection{Reading the verbatim text} +% +% \DescribeMacro{\sv@read} +% The main scanning routine is |\sv@read|. It is called with three +% arguments: +% +% \begin{itemize} +% +% \item The end-text marking the end of the environment. +% +% \item The name of a macro (which must be a single token) which is called +% with a line of text as its single argument. This is given each +% line of text which is read from the environment in turn. +% +% \item A macro, or other sort of action, which is to be done when the text +% has been read and processed. +% +% \end{itemize} +% +% The macro |\sv@read| assumes that the caller has already made some +% provision for removing the category codes of the following text, by either +% calling |\@verbatim| or using the construction +% \begin{listing} +%\let\do=\@makeother +%\dospecials +% \end{listing} +% +% \DescribeMacro{\sv@safespc} +% Note that any space characters you read using |\sv@read| will be catcoded +% as |\active|. Normally this is OK because |\obeyspaces| (or +% |\@vobeyspaces|) will be in effect. If you're doing something more exotic, +% like writing text to a file or building a command string, you can call +% |\sv@safespc| which defines the active-space character to be a normal +% whitespace-space when expanded. +% +% \implementation +% +% \section{Implementation} +% +% This section defines several macros and environments which allow verbatim +% typing, with a high degree of configurability. OK, so this sort of +% thing's been done so often before that it isn't true, but I don't really +% care. +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \subsection{Simple things} +% +% To help us build funny macros which involve strange and different category +% codes, I'll write some simple macros which I can use while building my +% complicated and clever ones. +% +% \begin{macro}{\@cspecials} +% +% This macro is used to assist the definition of some of the environments. +% It makes `|\|', `|{|' and `|}|' into `other' characters, and replaces them +% with `\verb"|"', `|<|' and `|>|' respectively. Note that `|[|' and `|]|' +% aren't used, because they make defining commands which take optional +% arguments awkward. Note that we open a group here. This should be closed +% using \verb"|endgroup" at the end of the special section. +% +% \begin{macrocode} +\def\@cspecials{% + \begingroup% + \catcode`|0% + \catcode`<1% + \catcode`>2% + \catcode`\{12% + \catcode`\}12% + \catcode`\\12% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sv@startlisting} +% +% This macro sets everything up nicely for a \env{listing}-type verbatim +% environment. +% +% \begin{macrocode} +\def\sv@startlisting{% + \def\par{\@@par\penalty\interlinepenalty}% + \@@par% + \leftskip\@totalleftmargin% + \obeylines% + \@noligs% + \let\do\@makeother\dospecials% + \verbatim@font% + \frenchspacing% + \@vobeyspaces% + \settabwidth% + \catcode9\active% + \lccode`\~9\lowercase{\let~\sv@vtab}% + \lccode`\~13\lowercase{\let~\vinput@cr}% + \interlinepenalty500% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsection{Tab character handling} +% +% One of the things we want to do here is handle tab characters properly. +% (Here, `properly' means `moving to the next column which is a multiple of +% eight', the way these things were always meant to.) +% +% \begin{macro}{\settabwidth} +% +% The tabs used by our tabbed verbatim environments are set up by this +% routine. It sets the tab width parameter |\svtab| to 8 times the width +% of a |\tt| space. If you really want, you can redefine this macro. +% +% \begin{macrocode} +\newdimen\svtab +\def\settabwidth{\setbox\z@\hbox{\texttt{\space}}\svtab8\wd\z@} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sv@vtab} +% +% Here we handle tabs inside verbatim environments. We expect each line to +% be typeset as a box, using something like +% +% \begin{listing} +%\setbox0\hbox{#1} +%\leavevmode +%\box0 +%\par +% \end{listing} +% +% The idea is that you make tab active, and set it to this macro. We stop +% the current box, stretch it to the right width, and start another one +% straight after, so nobody know the difference. The code here is straight +% from Appendix~D of \textit{The \TeX book}. +% +% \begin{macrocode} +\def\sv@vtab{% + \hfill\egroup% + \@tempdima\wd\z@% + \divide\@tempdima\svtab% + \multiply\@tempdima\svtab% + \advance\@tempdima\svtab% + \wd\z@\@tempdima% + \leavevmode\box\z@% + \setbox\z@\hbox\bgroup% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\verbinput} +% +% We allow input from a file, by the |\verbinput| command. We display the +% text pretty much the same as the \env{listing} environment below. +% +% We set tab and return active, and get them to do appropriate things. This +% isn't actually all that hard. +% +% \begin{macrocode} +\def\verbinput#1{% + \begin{listinglist}% + \listingsize% + \sv@startlisting% + \setbox\z@\hbox\bgroup% + \input{#1}% + \sv@stripspc% + \egroup% + \ifdim\wd\z@=\z@% + \ifhmode\par\fi% + \else% + \leavevmode\box\z@\par% + \fi% + \end{listinglist}% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\vinput@cr} +% +% This macro handles return characters while inputting text in |\verbinput|. +% We just output our current box, and start another. +% +% \begin{macrocode} +\def\vinput@cr{% + \egroup% + \leavevmode\box\z@% + \par% + \setbox\z@\hbox\bgroup% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsection{Reading verbatim text} +% +% The traditional way of reading verbatim text is to use a delimited +% argument, as described in the \textit{\TeX book}. This works well-ish if +% the text isn't very long. A better solution would be to pick out the text +% line-by-line and process it like that. So this is what we do. +% +% \begin{macro}{\matcher} +% +% For long verbatim environments, we need to be able to find the end text. +% This is rather tricky. The solution here is rather horrible. The +% environment picks out each line of the text at a time, as an argument, and +% tests to see if it contains the text we're after. We do the test in a +% particularly yukky way: we add the actual target text to the end of the +% line, and inspect the text following the match to see if the match is at +% the end. +% +% The |\matcher| macro creates a `matcher' which will test strings to see if +% they contain something interesting. +% +% To create a matcher, say +% \syntax{"\\matcher{"<cmd-name>"}{"<target>"}{"<process-cmd>"}"}. The +% command \synt{cmd-name} accepts a line of text as an argument and calls +% the \synt{process-cmd} with the text of the line before the match, or the +% whole lot. It also sets |\@ifmatched| appropriately. +% +% (Having spent ages coming up with this cruft myself, I found some very +% similar, but slightly better, code in Appendix~D. So I've changed mine to +% match Donald's. Anyway, credit where it's due: cheers Don.) +% +% \begin{macrocode} +\newif\if@matched +\def\matcher#1#2#3{% + \expandafter\def\csname\string#1$match\endcsname##1#2##2##3\end{% + \ifx##2\relax% + \@matchedfalse% + \else% + \@matchedtrue% + \fi% + #3{##1}% + }% + \expandafter\def\expandafter#1\expandafter##\expandafter1\expandafter{% + \csname\string#1$match\endcsname##1#2\relax\end% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sv@stripspc} +% +% This macro strips any trailing glue in the current horizontal list. This +% is fairly simple, actually: we just loop while glue is the last item. It's +% slightly complicated by penalties which \TeX\ puts into the list between +% the glue items, but we just remove them too. +% +% \begin{macrocode} +\def\sv@stripspc{% + \unpenalty% + \ifdim\lastskip=\z@\else% + \unskip\expandafter\sv@stripspc% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sv@percent} +% +% This macro strips a single leading percent character if there is one, and +% if the \env{doc} package is loaded. We store the possibly stripped text in +% |\@tempa|. +% +% \begin{macrocode} +\begingroup +\catcode`\%=12 +\gdef\sv@percent#1#2\relax + {\ifx\check@percent\@@undefined + \ifx#1\relax\def\@tempa{}\else + \def\@tempa{#1#2}\fi\else + \ifx#1\relax\def\@tempa{}\else + \ifx#1%\def\@tempa{#2}\else + \def\@tempa{#1#2}\fi\fi\fi} +\endgroup +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\@isspaces} +% +% We want to avoid writing the first and last lines of the environment to the +% file if there's nothing in them. To do this, we need to know whether a +% piece of text contains only space characters. This macro does this, in a +% rather nasty way. See the other macros below for details of how this +% works. +% +% We define |\sv@safespc| at the same time: this makes space active and +% expand to a space character which is not active. Neat, huh? +% +% \begin{macrocode} +\lccode`\~32 +\lccode`\!32 +\lowercase{% + \def\@isspaces#1{% + \ifx#1\relax% + \def\@tempb{\@tempswafalse}% + \else\ifx#1~% + \let\@tempb\@isspaces% + \else% + \def\@tempb##1\relax{}% + \fi\fi% + \@tempb% + } + \def\sv@safespc{% + \catcode32\active% + \def~{ }% + } +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sv@read} +% +% This macro does the main job of reading a chunk of verbatim text. You call +% it like this: +% +% \begin{quote} +% \syntax{"\\sv@read{"<end-text>"}{"<process-line-proc>"}{"<end-proc>"}"} +% \end{quote} +% +% The \synt{end-text} is the text to find at the end of the `environment': we +% stop when we find it. +% +% The \synt{process-line-proc} is a macro which is passed as an argument each +% line which we read from the text. +% +% The \synt{end-proc} is a macro to call once we've finished reading all of +% the text. This can tidy up an environment or close a file or whatever. +% +% We read the text by picking out newlines using a delimited macro. We have +% to be a little clever, because newlines are active in verbatim text. +% +% We will also strip `|%|' signs off the beginning if the \package{doc} +% package is here (\package{doc} tries to play with \LaTeX's verbatim stuff, +% and doesn't understand the way we do things). +% +% \begin{macrocode} +\def\sv@read#1#2#3{% +% \end{macrocode} +% +% This code does all sorts of evil things, so I'll start by opening a group. +% +% \begin{macrocode} + \begingroup% +% \end{macrocode} +% +% So that I can spot the end-text, I'll create a matcher macro. +% +% \begin{macrocode} + \matcher\@match{#1}\sv@read@ii% +% \end{macrocode} +% +% So that I can identify line ends, I'll make them active. I'll also make +% spaces active so that they can expand to whatever they ought to expand +% to (spaces in files, or funny \verb*" " characters or whatever. +% +% \begin{macrocode} + \catcode13\active% + \catcode32\active% +% \end{macrocode} +% +% I'll use the |\if@tempswa| flag to tell me whether I ought to output the +% current line. This is a little messy, so I'll describe it later. I'll +% initialise it to false because this is the correct thing to do. +% +% \begin{macrocode} + \@tempswafalse% +% \end{macrocode} +% +% Most of the job is done by two submacros. I'll define them in terms of +% my current arguments (to save lots of token munging). The first just +% extracts the next line (which ends at the next newline character) and +% tries to match it. +% +% \begin{macrocode} + \lccode`\~13\lowercase{% + \def\sv@read@i##1~{\@match{##1}}% + }% +% \end{macrocode} +% +% The results of the match get passed here, along with the text of the +% line up to the matched text. +% +% \begin{macrocode} + \def\sv@read@ii##1{% +% \end{macrocode} +% +% The first job to do is to maybe strip off percent signs from the beginning, +% to keep \package{doc} happy. +% +% \begin{macrocode} + \sv@percent##1\relax\relax% +% \end{macrocode} +% +% Now I need to decide whether I ought to output this line. The method goes +% like this: if this is the first line (|\if@tempswa| is false) or the last +% (|\if@matched| is true), \emph{and} the text consists only of spaces, then +% I'll ignore it. +% +% The first thing to do is to notice the last line -- if |\if@matched| is +% true, then I'll make |\if@tempswa| false to make the first-line and +% last-line cases work the same way. +% +% \begin{macrocode} + \if@matched\@tempswafalse\fi% +% \end{macrocode} +% +% Now if this is the first or last line, I'll examine it for spaces. This +% is done in a separate macro. It will set |\if@tempswa| false if the +% text contains only spaces. +% +% \begin{macrocode} + \if@tempswa\else\@tempswatrue\expandafter\@isspaces\@tempa\relax\fi% +% \end{macrocode} +% +% Now, if |\if@tempswa| is still true, perform the \<process-line-proc> on +% the line of text. I'll provide a group, so that it doesn't upset me +% too much. +% +% \begin{macrocode} + \if@tempswa% + \begingroup% + \expandafter#2\expandafter{\@tempa}% + \endgroup% + \fi% +% \end{macrocode} +% +% The next line won't be the first one, so I'll set the flag true in +% readiness. +% +% \begin{macrocode} + \@tempswatrue% +% \end{macrocode} +% +% Now, if that wasn't the last line, go round again; otherwise end the group +% I started ages ago, and do the user's \<end-proc>. +% +% \begin{macrocode} + \if@matched\def\@tempa{\endgroup#3}\else\let\@tempa\sv@read@i\fi% + \@tempa% + }% +% \end{macrocode} +% +% Now to start the thing up. I'll read the first line. +% +% \begin{macrocode} + \sv@read@i% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sv@readenv} +% +% This macro works out an appropriate end-text for the current environment. +% If you say \syntax{"\\sv@readenv{"<macro-name>"}"}, it will expand do +% \begin{listinglist} \listingsize \synshorts +% <macro-name>"{\\"$_{12}$"end{"$_{12}$<current-env-name>"}"$_{12}$"}"^^A +% "{\\end{"<current-env-name>"}}" +% \end{listinglist} +% Easy, no? +% +% This is all done with mirrors. No, err\dots\ it's done with +% |\expandafter|. +% +% \begin{macrocode} +\begingroup +\lccode`\<=`\{ +\lccode`\>=`\} +\lccode`\|=`\\ +\lowercase{\endgroup +\def\sv@readenv#1{% + \expandafter\expandafter\expandafter% + #1\expandafter\sv@readenv@i\@currenvir\@@% +} +\def\sv@readenv@i#1\@@{{|end<#1>}{\end{#1}}} +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sv@verbline} +% +% This macro typesets a line in a verbatim way, so you can construct a real +% verbatim environment from it. It's a bit tricky in the way that it catches +% the last line. Don't worry about this: it's easy really. Note the +% |\relax| after the |\par| -- this is because \package{doc} tries to do +% clever things with |\par| to strip `|%|' signs out. +% +% \begin{macrocode} +\def\sv@verbline#1{% + \setbox\z@\hbox{#1\sv@stripspc}% + \ifdim\wd\z@=\z@% + \if@matched\ifhmode\par\relax\fi\else\leavevmode\par\relax\fi% + \else% + \leavevmode\box\z@\par\relax% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsection{Listing environments} +% +% The \env{listing} environment is our equivalent of the standard +% \env{verbatim} environment. We do some slightly cleverer things, though, +% to make sure (for example) that even text which contains |\end{listing}| +% can be typeset. +% +% \begin{macro}{\listinglist} +% \begin{environment}{listinglist} +% +% This defines the layout for the \env{listing} environment. It starts a +% list with the appropriate shape. It's also made into an environment, so +% that the end-paragraph-environment bits work correctly. +% +% The |\listingindent| length parameter sets up the indentation of the +% listings. If there's a |\parindent| setting, I'll line listings up with +% that; otherwise I'll just choose something which looks right. +% +% \begin{macrocode} +\newdimen\listingindent +\AtBeginDocument{% + \ifdim\parindent=\z@\listingindent1em\else\listingindent\parindent\fi% +} +% \end{macrocode} +% +% Now to define a size hook for the environment. This is fairly simple +% stuff. +% +% \begin{macrocode} +\ifx\listingsize\@@undefined + \let\listingsize\small +\fi +% \end{macrocode} +% +% Now to define the environment itself. Suppress the indentation if we're +% first thing on a new list item, so that the listing lines up with +% everything else. +% +% \begin{macrocode} +\def\listinglist{% + \list{}{% + \if@inlabel% + \leftmargin\z@% + \else% + \leftmargin\listingindent% + \fi% + \rightmargin\z@% + \labelwidth\z@% + \labelsep\z@% + \itemindent\z@% + \listparindent\z@% + \let\makelabel\relax% + \parsep\z@skip% + }% + \parfillskip\@flushglue% + \item\relax% +} +\let\endlistinglist\endlist +% \end{macrocode} +% +% \end{environment} +% \end{macro} +% +% \begin{environment}{listing} +% +% The \env{listing} environment is the only real verbatim-like environment we +% create will all this kit, although it does the job very nicely. +% +% The environment indents its contents slightly, unlike \env{verbatim}, and +% uses a smaller typeface in an attempt to fit 77-column text on an A5~page. +% There is also a $*$-variant, which allows you to specify the terminating +% text. This enables you to include absolutely any text in the environment, +% including |\end{listing}|. +% +% First, we must define the |\listing| command. +% +% \begin{macrocode} +\def\listing{% + \listinglist% + \listingsize% + \sv@readenv\sv@listing% +} +% \end{macrocode} +% +% Now we define the |\@listing| command, which does most of the work. We +% base the \env{listing} environment on a \env{list}. +% +% \begin{macrocode} +\def\sv@listing#1#2{% + \sv@startlisting% + \sv@read{#1}\sv@verbline{\endlistinglist#2}% +} +% \end{macrocode} +% +% Now we define the starred version. The command name needs to include the +% `|*|' character, so we must use |\csname|. There's some hacking here to +% allow us to read the name using the appropriate catcodes for otherwise +% normal characters: \LaTeX\ activates some characters and makes them typeset +% themselves to suppress some ligaturing. +% +% \begin{macrocode} +\expandafter\def\csname listing*\endcsname{% + \listinglist% + \listingsize% + \begingroup% + \@noligs% + \def\@tempa##1{\endgroup\sv@listing{##1}{\end{listing*}}}% + \@tempa% +} +% \end{macrocode} +% +% \end{environment} +% +% \begin{environment}{ignore} +% +% The \env{ignore} environment entirely ignores its contents. Anything at +% all may be put into the environment: it is discarded utterly. +% +% We define some macros for defining ignoring environments, because this can +% be useful for version control, possibly. +% +% \begin{macrocode} +\def\sv@ignore#1#2{% + \@bsphack% + \let\do\@makeother\dospecials% + \sv@read{#1}\@gobble{\@esphack#2}% +} +\def\ignore{\sv@readenv\sv@ignore} +\def\ignoreenv#1{% + \expandafter\let\csname #1\endcsname\ignore% +} +\def\unignoreenv#1{% + \expandafter\def\csname #1\endcsname{\endgroup}% + \expandafter\def\csname end#1\endcsname% + {\begingroup\def\@currenvir{#1}}% +} +% \end{macrocode} +% +% \end{environment} +% +% \subsection{The \env{verbwrite} environment} +% +% The \env{verbwrite} environment allows text to be written to a file in a +% verbatim way. Note that tab characters don't work, because \TeX\ refuses +% to be nice. +% +% \begin{macro}{\sv@write} +% +% As seems to be traditional now, we first define a general hookable macro +% which allows a caller to specify the end-text and what to do afterwards. +% +% \begin{macrocode} +\newwrite\sv@writefile +\def\sv@write#1#2{% + \begingroup% + \@bsphack% + \let\do\@makeother\dospecials% + \sv@safespc% + \sv@read{#1}\sv@writeline{\sv@endwrite#2}% +} +\def\sv@writeline#1{% + \immediate\write\sv@writefile{#1}% +} +\def\sv@endwrite{% + \@esphack% + \endgroup% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{verbwrite} +% +% Now we can define the actual environment. We define a $*$-variant which +% allows the user to specify the end-text, just to make sure. +% +% \begin{macrocode} +\def\verbwrite#1{% + \immediate\openout\sv@writefile#1\relax% + \sv@readenv\sv@write% +} +\def\endverbwrite{\immediate\closeout\sv@writefile} +\expandafter\def\csname verbwrite*\endcsname#1#2{% + \immediate\openout\sv@writefile#2\relax% + \sv@write{#1}{\immediate\closeout\sv@writefile\end{verbwrite*}}% +} +% \end{macrocode} +% +% \end{environment} +% +% \subsection{The \env{demo} environment} +% +% By way of tying all of this together, I present an environment for +% displaying demonstrations of \LaTeX\ markup. We read the contents of the +% environment, write it to a temporary file, and read it back twice, +% typesetting it the first time and displaying it verbatim the second time. +% +% \begin{macro}{\sv@demoname} +% +% This macro expands to the filename to use for the temporary data. To +% allow the package documentation to demonstrate the \env{demo} environment +% itself, we need to keep a nesting count. This avoids too much hackery, +% which unfortunately appears to plague all of my \TeX\ code. +% +% \begin{macrocode} +\newcount\sv@nestcount +\def\sv@demoname{demo\number\sv@nestcount.tmp} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sv@demo} +% +% As for listing, we do all the business through a private macro. This is +% good because it means we can leave the main macro readable. The argument +% is the end-text to spot. +% +% \begin{macrocode} +\def\sv@demo#1#2{% + \@ifnextchar[{\sv@demo@i{#1}{#2}}{\sv@demo@i{#1}{#2}[n]}% +} +\def\sv@demo@i#1#2[#3]#4{% + \advance\sv@nestcount by\@ne% + \immediate\openout\sv@writefile\sv@demoname\relax% + \sv@write{#1}{% + \immediate\closeout\sv@writefile% + \sv@dodemo{#2}{#3}{#4}% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{demo} +% +% This is the real environment. We provide \env{demo$*$} too, to allow the +% user to choose the end-text. +% +% \begin{macrocode} +\def\demo{\sv@readenv\sv@demo} +\expandafter\def\csname demo*\endcsname#1{\sv@demo{#1}{\end{demo*}}} +% \end{macrocode} +% +% \end{environment} +% +% \begin{macro}{\sv@dodemo} +% +% First, let's define some common bits of code in the stuff below. The +% minipages used to typeset the material has some clever stuff to avoid +% strange spacing in the output. +% +% \begin{macrocode} +\def\sv@demosmp{% + \begin{minipage}[t]{\@tempdima}% + \vskip8\p@% + \hrule\@height\z@% + \raggedright% + \vbox\bgroup% +} +\def\sv@demoemp{% + \par\unpenalty\unskip% + \egroup% + \vskip8\p@% + \hrule\@height\z@% + \end{minipage}% +} +% \end{macrocode} +% +% This is the macro which actually typesets the demonstration. +% +% \begin{macrocode} +\def\sv@dodemo#1#2#3{% +% \end{macrocode} +% +% Now work out some values. We set |\hsize| to the line width leaving 2\,em +% of space on either side. The size of the minipages is calculated depending +% on the shape of the demonstration. This is all fairly simple. +% +% \begin{macrocode} + \begingroup% + \@tempdima\linewidth% + \advance\@tempdima-2em% + \hsize\@tempdima% + \if#2w% + \advance\@tempdima-2em% + \else% + \advance\@tempdima-3em% + \divide\@tempdima2% + \fi% +% \end{macrocode} +% +% Now we open a big vertical box, and put in a header to mark off the +% demonstration. +% +% \begin{macrocode} + \par% + \setbox\z@\hbox{\strut\enspace#3\enspace\strut}% + \@tempdimb.5\dp\z@% + \advance\@tempdimb-.5\ht\z@% + \ht\z@\@tempdimb\dp\z@\@tempdimb% + \noindent\hskip1em\vtop{% + \hb@xt@\hsize{% + \hrulefill% + \raise\@tempdimb\box\z@% + \hrulefill% + }% + \nointerlineskip% + \hb@xt@\hsize{\vrule\@height5\p@\hfil\vrule\@height5\p@}% + \nointerlineskip% +% \end{macrocode} +% +% Now we insert the output text in the first minipage. I'll force `|%|' +% to be a comment character, in case something like \package{doc} has had its +% wicked way. +% +% \begin{macrocode} + \vskip-\parskip% + \noindent\hbox{}\hskip1em% + \sv@demosmp% + \catcode`\%14\relax% + \input{\sv@demoname}% + \sv@demoemp% +% \end{macrocode} +% +% Insert some kind of separation between the two. In `wide' format, we start +% a new line, and put a ruleoff between the two. In `narrow' format, we just +% leave some space. +% +% \begin{macrocode} + \if#2w% + \vskip8\p@\hrule\vskip8\p@% + \noindent\hbox{}% + \fi% + \hskip1em% +% \end{macrocode} +% +% Now we put the verbatim copy of the text in the other minipage. +% +% \begin{macrocode} + \sv@demosmp% + \listingindent\z@% + \verbinput\sv@demoname% + \sv@demoemp% + \par% + \nointerlineskip% + \hb@xt@\hsize{\vrule\@height5\p@\hfil\vrule\@height5\p@}% + \hrule% + }% + \endgroup% + \par% + \vskip\baselineskip% + #1% +} +% \end{macrocode} +% +% \end{macro} +% +% That's all there is. Have fun. +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \hfill Mark Wooding, \today +% +% \Finale +% +\endinput diff --git a/Master/texmf-dist/source/latex/mdwtools/syntax.dtx b/Master/texmf-dist/source/latex/mdwtools/syntax.dtx new file mode 100644 index 00000000000..1f251b73634 --- /dev/null +++ b/Master/texmf-dist/source/latex/mdwtools/syntax.dtx @@ -0,0 +1,2823 @@ +% \begin{meta-comment} +% +% syntax.dtx +% +% Syntax typesetting package for LaTeX 2e +% +% (c) 1996 Mark Wooding +% +% \end{meta-comment} +% +% \begin{meta-comment} <general public licence> +%% +%% syntax package -- typesetting syntax descriptions +%% Copyright (c) 1996 Mark Wooding +%% +%% This program is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation; either version 2 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program; if not, write to the Free Software +%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +%% +% \end{meta-comment} +% +% \begin{meta-comment} <Package preamble> +%<+package>\NeedsTeXFormat{LaTeX2e} +%<+package>\ProvidesPackage{syntax} +%<+package> [1996/05/17 1.07 Syntax typesetting (MDW)] +% \end{meta-comment} +% +% \CheckSum{1439} +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +%% +% +% \begin{meta-comment} <driver> +% +%<*driver> +% +% This hacking will remember the old default underscore character. Even if +% T1 fonts are being used, it will get the grotty version. Why is it that +% all of the encoding handling ends up looking like this? +% +\expandafter\let\expandafter\oldus\csname?\string\textunderscore\endcsname +% +\input{mdwtools} +\describespackage{syntax} +\DeclareRobustCommand\syn{\package{syntax}} +\mdwdoc +%</driver> +% +% \end{meta-comment} +% +% \section{User guide} +% +% \subsection{Introduction} +% +% The \syn\ package provides a number of commands and environments which +% extend \LaTeX\ and allow you to typeset good expositions of syntax. +% +% The package provides several different types of features: probably not all +% of these will be required by every document which needs the package: +% \begin{itemize} +% \item A system of abbreviated forms for typesetting syntactic items. +% \item An environment for typesetting BNF-type grammars +% \item A collection of environments for building syntax diagrams. +% \end{itemize} +% +% The package also includes some other features which, while not necessarily +% syntax-related, will probably come in handy for similar types of document: +% \begin{itemize} +% \item An abbreviated notation for verbatim text, similar to the +% \package{shortvrb} package. +% \item A slightly different underscore character, which works as expected +% in text and maths modes. +% \end{itemize} +% +% \subsection{The abbreviated verbatim notation} +% +% In documents describing programming languages and libraries, it can become +% tedious to type "\verb|...|" every time. Like Frank Mittelbach's +% \package{shortvrb} package, \syn\ provides a way of setting up single-^^A +% character abbreviations. The only real difference between the two is that +% the declarations provided by \syn\ obey \LaTeX's normal scoping rules. +% +% \DescribeMacro\shortverb +% You can set up a character as a `verbatim shorthand' character using the +% |\shortverb| command. This takes a single argument, which should be a +% single-character control sequence containing the character you want to use. +% So, for example, the command +% \begin{listing} +%\shortverb{\|} +% \end{listing} +% would set up the `"|"' character to act as a verbatim delimiter. While a +% |\shortverb| declaration is in force, any text surrounded by (in this case) +% vertical bar characters will be typeset as if using the normal |\verb| +% command. +% +% \DescribeEnv{shortverb} +% Since \LaTeX\ allows any declaration to be used as an environment, you can +% use a \env{shortverb} environment to delimit the text over which your +% character is active: +% \begin{listing} +%Some text... +%\begin{shortverb}{\|} +%... +%\end{shortverb} +% \end{listing} +% +% \DescribeMacro\unverb +% If you want to disable a |\shortverb| character without ending the scope +% of other declarations, you can use the |\unverb| command, passing it +% a character as a control sequence, in the same way as above. +% +% The default \TeX/\LaTeX\ underscore character is rather too short for +% use in identifiers. For example: +% +% \begingroup \let\_=\oldus +% \begin{demo}{Old-style underscores} +%Typing long underscore-filled +%names, like big\_function\_name, +%is normally tedious. The normal +%positioning of the underscore +%is wrong, too. +% \end{demo} +% \endgroup +% +% The \syn\ package redefines the |\_| command to draw a more attractive +% underscore character. It also allows you to use the |_|~character +% directly to produce an underscore outside of maths mode: |_|~behaves +% as a subscript character as usual inside maths mode. +% +% \begin{demo}{New \syn\ underscores} +%You can use underscore-filled +%names, like big_function_name, +%simply and naturally. Of +%course, subscripts still work +%normally in maths mode, e.g., +%$x_i$. +% \end{demo} +% +% \subsection{Typesetting syntactic items} +% \begin{synshorts} +% +% The \syn\ package provides some simple commands for typesetting syntactic +% items. +% +% \DescribeMacro\synt +% Typing "\\synt{"<text>"}" typesets <text> as a \lq non-terminal', +% in italics and surrounded by angle brackets. If you use "\\synt" a lot, +% you can use the incantation +% \begin{listing} +%\def\<#1>{\synt{#1}} +% \end{listing} +% to allow you to type "\\<"<text>">" as an alternative to +% "\\synt{"<text>"}". +% +% \DescribeMacro\lit +% You can also display literal text, which the reader should type directly, +% using the "\\lit" command. +% +% \begin{demo}{Use of \cmd\lit} +%Type \lit{ls} to display a +%list of files. +% \end{demo} +% +% Note that the literal text appears in quotes. To suppress the quotes, +% use the `*' variant. +% +% The "\\lit" command produces slightly better output than "\\verb" for +% running text, since the spaces are somewhat narrower. However, "\\verb" +% allows you to type arbitrary characters, which are treated literally, +% whereas you must use commands such as "\\{" to use special characters +% within the argument to "\\lit". Of course, you can use "\\lit" anywhere +% in the document: "\\verb" mustn't be used inside a command argument. +% \end{synshorts} +% +% \subsection{Abbreviated forms for syntactic items} +% +% It would be very tedious to require the use of commands like |\synt| +% when building syntax descriptions like BNF grammars. It would also make +% your \LaTeX\ source hard to read. Therefore, \syn\ provides some +% abbreviated forms which make typesetting syntax quicker and easier. +% +% Since the abbreviated forms use several characters which you may want to +% use in normal text, they aren't enabled by default. They only work +% with special commands and environments provided by the \syn\ package. +% +% The abbreviated forms are shown in the table below: +% +% \begin{tab}[\synshorts]{ll} \hline +% \bf Input & \bf Output \\ \hline +% "<some text>" & <some text> \\ +% "`some text'" & `some text' \\ +% "\"some text\"" & "some text" \\ \hline +% \end{tab} +% +% Within one of these abbreviated forms, text is treated more-or-less +% verbatim: +% \begin{itemize} +% +% \item Any |$|, |%|, |^|, |&|, |{|, |}|, |~| or |#| characters are treated +% literally: their normal special meanings are ignored. +% +% \item Other special characters, with the exception of |\|, are also treated +% literally: this includes any characters made special by |\shortverb|. +% +% \end{itemize} +% +% However, the |\| character retains its meaning. Since the brace +% characters are not recognised, most commands can't be used within +% abbreviated forms. However, you can use special commands to type some +% of the remaining special characters: +% +% \begin{tab}[\synshorts]{ll} \hline +% \bf Command & \bf Result \\ \hline +% "\\\\" & A `\\' character \\ +% "\\>" & A `>' character \\ +% "\\'" & A `\'' character \\ +% "\\\"" & A `"' character \\ +% "\\\ " & A `\ ' character (not a space) \\ \hline +% \end{tab} +% +% Note that |\\|, |\>|, |\"| and \verb*|\ | are only useful in a |\tt| font, +% i.e., inside |`...'| and |"..."| forms, since the characters don't exist +% in normal fonts. The |\>|, |\"| and |\'| commands are only provided so +% you can use these characters within |<...>|, |"..."| and |`...'| forms +% respectively: in the other forms, there is no need to use the special +% command. +% +% In addition, when the above abbreviations are enabled, the character "|" +% is set to typeset a \syntax{|} symbol, which is conventionally used to +% separate alternatives in syntax descriptions. +% +% \DescribeMacro\syntax +% Normally, these abbreviated forms are enabled only within special +% environments, such as \env{grammar} and \env{syntdiag}. To use them +% in running text, use the |\syntax| command. The abbreviations are made +% active within the argument of the |\syntax| command.\footnote{^^A +% The argument of the \cmd\syntax\ command may contain commands such +% as \cmd\verb, which are normally not allowed within arguments. +% } Note that you cannot use the |\syntax| command within the argument +% of another command. +% +% \DescribeMacro\synshorts +% \DescribeEnv{synshorts} +% You can also enable the syntax shortcuts using the |\synshorts| declaration +% or the \env{synshorts} environment. This enables the syntax shortcuts +% until the scope of the declaration ends. +% +% \DescribeMacro\synshortsoff +% If syntax shortcuts are enabled, you can disable them using the +% |\synshortsoff| declaration. +% +% \subsection{The \env{grammar} environment} +% +% \DescribeEnv{grammar} +% For typesetting formal grammars, for example, of programming languages, +% the \syn\ package provides a \env{grammar} environment. Within this +% environment, the abbreviated forms described above are enabled. +% +% Within the environment, separate production rules should be separated by +% blank lines. You can use the normal |\\| command to perform line-breaking +% of a production rule. Note that a production rule must begin with a +% nonterminal name enclosed in angle brackets (|<| \dots |>|), followed by +% whitespace, then some kind of production operator (usually `::=') and then +% some more whitespace. You can control how this text is actually typeset, +% however. +% +% \DescribeMacro{\[[} +% \DescribeMacro{\]]} +% You can use syntax diagrams (see below) instead of a straight piece of BNF +% by enclosing it in a |\[[| \dots |\]]| pair. Note that you can't mix +% syntax diagrams and BNF in a production rule, and you will get something +% which looks very strange if you try. +% +% \DescribeMacro\alt +% In addition, a command |\alt| is provided for splitting long production +% rules over several lines: the |\alt| command starts a new line and places +% a \syntax{|} character slightly in the left margin. This is useful when +% a symbol has many alternative productions. +% +% \begin{demo}[w]{The \env{grammar} environment} +%\begin{grammar} +%<statement> ::= <ident> `=' <expr> +% \alt `for' <ident> `=' <expr> `to' <expr> `do' <statement> +% \alt `{' <stat-list> `}' +% \alt <empty> +% +%<stat-list> ::= <statement> `;' <stat-list> | <statement> +%\end{grammar} +% \end{demo} +% +% You can modify the appearance of grammars using three length parameters: +% +% \begin{description} \def\makelabel{\hskip\labelsep\cmd} +% +% \item [\grammarparsep] is the amount of space inserted between production +% rules. It is a rubber length whose default value is 8\,pt, with +% 1\,pt of stretch and shrink. +% +% \item [\grammarindent] is the amount by which the right hand side of a +% production rule is indented from the left margin. It is a rigid +% length. Its default value is 2\,em. +% +% \end{description} +% +% \DescribeMacro\grammarlabel +% You can also control how the `label' is typeset by redefining the +% |\grammarlabel| command. The command is given two arguments: the name of +% the nonterminal (which was enclosed in angle brackets), and the `production +% operator'. The command is expected to produce the label. By default, it +% typesets the nonterminal name using |\synt| and the operator at opposite +% ends of the label, separated by an |\hfill|. +% +% \subsection{Syntax diagrams} +% +% A full formal BNF grammar can be somewhat overwhelming for less technical +% readers. Documents aimed at such readers tend to display grammatical +% structures as \emph{syntax diagrams}. +% +% \DescribeEnv{syntdiag} +% A syntax diagram is always enclosed in a \env{syntdiag} environment. You +% should think of the environment as enclosing a new sort of \LaTeX\ mode: +% trying to type normal text into a syntax diagram will result in very ugly +% output. \LaTeX\ ignores spaces and return characters while in syntax +% diagram mode. +% +% The syntax of the environment is very simple: +% +% \begin{grammar} +% <synt-diag-env> ::= \[[ +% "\\begin{syntdiag}" +% \begin{stack} \\ "[" <decls> "]" \end{stack} +% <text> +% "\\end{syntdiag}" +% \]] +% \end{grammar} +% +% The \<decls> contain any declarations you want to insert, to control +% the environment. The parameters to tweak are described below. +% +% Within a syntax diagram, you can include syntactic items using the +% abbreviated forms described elsewhere. The output from these forms is +% modified slightly in syntax diagram mode so that the diagram looks +% right. +% +% I probably ought to point out now that the syntax diagram typesetting +% commands produce beautiful-looking diagrams with all the rules and curves +% accurately positioned. Some device drivers don't position these objects +% correctly in their output. I've had particular trouble with |dvips|. I'll +% say it again: it's not my fault! +% +% \DescribeEnv{syntdiag*} +% The \env{syntdiag} environment only works in paragraph mode, and it acts +% rather like a paragraph, splitting over several lines when appropriate. +% If you just want to typeset a snippet of a syntax diagram, you can +% use the starred environment \env{syntdiag$*$}. +% +% \begin{grammar} +% <synt-diag-star-env> ::= \[[ +% "\\begin{syntdiag*}" +% \begin{stack} \\ "[" <decls> "]" \end{stack} +% \begin{stack} \\ "[" <width> "]" \end{stack} +% <text> +% "\\end{syntdiag*}" +% \]] +% \end{grammar} +% +% When typesetting little demos like this, it's not normal to fully adorn +% the syntax diagram with the full double arrows +% (`\begin{syntdiag*}[\left{>>-}\right{-><}]\tok{$\cdots$}\end{syntdiag*}'). +% The two declarations \syntax{"\\left{"<arrow>"}" and "\\right{"<arrow>"}"} +% allow you to choose the arrows on each side of the syntax diagram snippet. +% The possible values of \<arrow> are shown in the table-ette below: +% +% ^^A Time to remember what I learned about tables while writing mdwtab. +% ^^A Just for the embarassment factor, here's the number of attempts I +% ^^A took to get the table below to look right: __6. Hmm... not as bad +% ^^A as I expected. Most of them were fine-tuning things. +% +% \medskip ^^A Leave a vertical gap +% \hbox to\columnwidth{\hfil\vbox{\tabskip=0pt ^^A Centre it horizontally +% \sdsize \csname sd@setsize\endcsname ^^A Position syntdiag arrows +% \halign to .5\columnwidth{ ^^A Set the table width +% &\ttfamily\ignorespaces#\unskip\hfil\tabskip=0pt ^^A Typeset the name +% &\quad\csname sd@arr@#\endcsname\hfil ^^A Typeset the arrow +% &\setbox0=\hbox{#}\tabskip=0pt plus 1fil\cr ^^A Stretch between columns +% >>-&>>-& &>-&>-& &->&->\cr +% -><&-><& &...&...& &-&-\cr +% }}\hfil} ^^A Close the boxing +% \medskip ^^A And leave another gap +% +% These declarations should be used only in the optional argument to the +% \env{syntdiag$*$} command. The second optional argument to the +% environment, if specified, fixes the width of the syntax diagram snippet; +% if you omit this argument, the diagram is made just wide enough to +% fit everything in. +% +% \begin{figure} +% \begin{demo}[w]{Example of \env{syntdiag$*$}} +%\newcommand{\bs}[2]{% +% \begin{minipage}{1.6in}% +% \begin{syntdiag*}[\left{#1}\right{#2}][1.6in]% +%} +%\newcommand{\es}{\end{syntdiag*}\end{minipage}} +% +%\begin{center} +%\begin{tabular}{cl} \\ \hline +%\bf Construction & \bf Meaning \\ \hline +%\bs {>>-} {...} \es & Start of syntax diagram \\ +%\bs {...} {-><} \es & End of syntax diagram \\ +%\bs {>-} {...} \es & Continued on next line \\ +%\bs {...} {->} \es & Continued from previous line \\ \hline +%\bs {...} {...} +% \begin{stack} <option-a> \\ <option-b> \\ <option-c> \end{stack} +%\es & Alternatives: choose any one \\ +%\bs {...} {...} +% \begin{rep} <repeat-me> \\ <separator> \end{rep} +%\es & One or more items, with separators \\ \hline +%\end{tabular} +%\end{center} +% \end{demo} +% \end{figure} +% +% \DescribeMacro\tok +% You can also include text using the |\tok| command. The argument of this +% command is typeset in \LaTeX's LR~mode and inserted into the diagram. +% Syntax abbreviations are allowed within the argument, so you can, for +% example, include textual descriptions like +% \begin{listing} +%\tok{any <char> except `"'} +% \end{listing} +% +% \DescribeEnv{stack} +% Within a syntax diagram, a choice between several different items is +% shown by stacking the alternatives vertically. In \LaTeX, this is done +% by enclosing the items in a \env{stack} environment. Each individual item +% is separated by |\\| commands, as in the \env{array} and \env{tabular} +% environments. Each row may contain any syntax diagram material, including +% |\tok| commands and other \env{stack} environments. +% +% Note if you end a \env{stack} environment with a |\\| command, a blank +% row is added to the bottom of the stack, indicating that none of the items +% need be specified. +% +% \DescribeEnv{rep} +% Text which can be repeated is enclosed in a \env{rep} environment: the +% text is displayed with a backwards pointing arrow drawn over it, showing +% that it may be repeated. Optionally, you can specify text to be +% displayed in the arrow, separating it from the main text with a |\\| +% command. +% +% Note that items on the backwards arrow of a \env{rep} construction should +% be displayed \emph{backwards}. You must put the individual items in +% reverse order when building this part of your diagrams. \syn\ will +% correctly reverse the arrows on \env{rep} structures, but apart from +% this, you must cope on your own. You are recommended to keep these parts +% of your diagrams as simple as possible to avoid confusing readers. +% +% \begin{demo}[w]{A syntax diagram} +%\begin{syntdiag} +%<ident> `(' +% \begin{rep} \begin{stack} \\ +% <type> \begin{stack} \\ <ident> \end{stack} +% \end{stack} \\ `,' \end{rep} +%\begin{stack} \\ `...' \end{stack} `)' +%\end{syntdiag} +% \end{demo} +% +% \subsubsection{Line breaking in syntax diagrams} +% +% Syntax diagrams are automatically broken over lines and across pages. +% Lines are only broken between items on the outermost level of the diagram: +% i.e., not within \env{stack} or \env{rep} environments. +% +% You can force a line break at a particular place by using the |\\| command +% as usual. This supports all the usual \LaTeX\ features: a `|*|' variant +% which prohibits page breaking, and an optional argument specifying the +% extra vertical space between lines. +% +% \subsubsection{Customising syntax diagrams} +% +% There are two basic styles of syntax diagrams supported: +% +% \begin{description} +% +% \item [square] Lines in the syntax diagram join at squared-off corners. +% This appears to be the standard way of displaying syntax diagrams +% in IBM manuals, and most other documents I've seen. +% +% \item [rounded] Lines curve around corners. Also, no arrows are drawn +% around repeating loops: the curving of the lines provides this +% information instead. This style is used in various texts on +% Pascal, and appears to be more popular in academic circles. +% +% \end{description} +% +% You can specify the style you want to use for syntax diagrams by giving +% the style name as an option on the |\usepackage| command. For example, +% to force rounded edges to be used, you could say +% +% \begin{listing} +%\usepackage[rounded]{syntax} +% \end{listing} +% +% \DescribeMacro\sdsize +% \DescribeMacro\sdlengths +% The \env{syntdiag} environment takes an option argument, which should +% contain declarations which are obeyed while the environment is set up. +% The default value of this argument is `|\sdsize\sdlengths|'. The +% |\sdsize| command sets the default type size for the environment: this is +% normally |\small|. |\sdlengths| sets the values of the length parameters +% used by the environment based on the current text size. These parameters +% are described below. +% +% For example, if you wanted to reduce the type size of the diagrams still +% further, you could use the command +% \begin{listing} +%\begin{syntdiag}[\tiny\sdlengths] +% \end{listing} +% +% The following length parameters may be altered: +% +% \begin{description} \def\makelabel{\hskip\labelsep\cmd} +% +% \item [\sdstartspace] The length of the rule between the arrows which +% begin each line of the syntax diagram and the first item on the line. +% Note that most objects have some space on either side of them as +% well. This is a rubber length. Its default value is 1\,em, although +% it can shrink by up to 10\,pt. +% +% \item [\sdendspace] The length of the rule between the last item on a +% line and the arrow at the very end. Note that the final line also +% has extra rubber space on the end. This is a rubber length. Its +% default value is 1\,em, although it will shrink by up to 10\,pt. +% +% \item [\sdmidskip] The length of the rule on either side of a large +% construction (either a \env{stack} or a \env{rep}). It is a rubber +% length. Its default value is \smallf 1/2\,em, with a very small +% amount of infinite stretch. +% +% \item [\sdtokskip] The length of the rule on either side of a |\tok| +% item or syntax abbreviation. It is a rubber length. Its default +% value is \smallf 1/4\,em, with a very small amount of inifnite +% stretch. +% +% \item [\sdfinalskip] The length of the rule which finishes the last line +% of a syntax diagram. It is a rubber length. Its default value is +% \smallf 1/2\,em, with 10000\,fil of stretch, which will left-align +% the items on the line.\footnote{^^A +% This is a little \TeX nical. The idea is that if a stray 1\,fil +% of stretch is added to the end of the line, it won't be noticed. +% However, the alignment of the text on the line can still be +% modified using \cmd{\sd@rule}\cmd{\hfill}, if you're feeling +% brave. +% } +% +% \item [\sdrulewidth] Half the width of the rules used in the diagram. +% It is a rigid length. Its default value is 0.2\,pt. +% +% \item [\sdcirclediam] The diameter of the circle from which the quadrants +% used in rounded-style diagrams are taken. This must be a multiple +% of 4\,pt, or else the lines on the diagram won't match up. +% +% \end{description} +% +% In addition, you should call |\sdsetstrut| passing it the total height +% (\({\rm height}+{\rm depth}\)) of a normal line of text at the current +% size. Normally, the value of |\baselineskip| will be appropriate. +% +% You can also alter the appearance of \env{stack}s and \env{rep}s by using +% their optional positioning arguments. By default, \env{stack}s descend +% below the main line of the diagram, and \env{rep}s extend above it. +% Specifying an optional argument of |[b]| for either environment reverses +% this, putting \env{stack}s above and \env{rep}s below the line. +% +% \subsection{Changing the presentation styles} +% +% You can change the way in which the syntax items are typeset by altering +% some simple commands (using |\renewcommand|). Each item (nonterminals, +% as typeset by |\synt|, and quoted and unquoted terminals, as typeset by +% |\lit| and |\lit*|) has two style commands associated with it, as shown +% in the table below. +% +% \begin{tab}{lll} \hline +% \bf Syntax item & \bf Left command & \bf Right command \\ \hline +% Nonterminals & |\syntleft| & |\syntright| \\ +% Quoted terminals & |\litleft| & |\litright| \\ +% Unquoted terminals & |\ulitleft| & |\ulitright| \\ \hline +% \end{tab} +% +% It's not too hard to see how this works. For example, if you look at +% the implementation for |\syntleft| and |\syntright| in the implementation +% section, you'll notice that they're defined like this: +% \begin{listing} +%\newcommand{\syntleft}{$\langle$\normalfont\itshape} +%\newcommand{\syntright}{$\rangle$} +% \end{listing} +% I think this is fairly simple, if you understand things like font changing. +% +% Note that changing these style commands alters the appearance of all syntax +% objects of the appropriate types, as created by the |\synt| and |\lit| +% commands, in \env{grammar} environments, and in syntax diagrams. +% +% +% \section{Change history} +% +% \subsection*{Version 1.07} +% +% \begin{itemize} +% \item Fixed problem with underscore hacking in a \env{tabbing} environment. +% \end{itemize} +% +% \subsection*{Version 1.06} +% +% \begin{itemize} +% \item Added style hooks for syntax items. +% \item Improved colour handling in syntax diagrams, thanks to the |\doafter| +% package. +% \item Fixed some nasty bugs in the \env{grammar} environment which confused +% other lists and ruined the spacing. The \env{grammar} handling is +% now much tidier in general. +% \end{itemize} +% +% \subsection*{Version 1.05} +% +% \begin{itemize} +% \item Fixed `the bug' in the syntax diagram typesetting. It now breaks +% lines almost psychically, and doesn't break in the wrong places. +% \item Almost rewrote the \env{grammar} environment. It now does lots of +% the list handling itself, to allow more versatile typesetting of the +% left hand sides. There's lots of evil in there now. +% \item Added some more configurability. In particular, two new settings +% have been added to control \env{grammar} environments, and a neat +% way of adding new syntax diagram structures has been introduced. +% \end{itemize} +% +% \subsection*{Version 1.04} +% +% \begin{itemize} +% \item Changed the vertical positioning of the rules, to make all the text +% line up properly. While the old version was elegant and simple, it +% had the drawback of looking nasty. +% \item Allow line breaks at underscores, but don't if there's another one +% afterwards. Also, prevent losing following space if underscore is +% written to a file. +% \end{itemize} +% +% \subsection*{Version 1.02} +% +% \begin{itemize} +% \item Added support for rounded corners in syntax diagrams. +% \item Changed lots of |\hskip| commands to |\kern|s, to prevent possible +% line breaks. +% \end{itemize} +% +% \subsection*{Version 1.01} +% +% \begin{itemize} +% \item Allowed disabling of underscore active character, to avoid messing +% up filenames. +% \item Added |\grammarparsep| and |\grammarindent| length parameters to +% control the appearance of grammars. +% \end{itemize} +% +% \implementation +% +% \section{Implementation of \syn} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \subsection{Options handling} +% +% We define all the options we know about, and then see what's been put +% on the usepackage line. +% +% The options we provide currently are as follows: +% +% \begin{description} +% \item [rounded] draws neatly rounded edges on the diagram. +% \item [square] draws squared-off edges on the diagram. This is the +% default. +% \item [nounderscore] disables the undescore active character, The |\_| +% command still produces the nice version created here. +% \end{description} +% +% \begin{macrocode} +\DeclareOption{rounded}{\sd@roundtrue} +\DeclareOption{square}{\sd@roundfalse} +\DeclareOption{nounderscore}{\@uscorefalse} +% \end{macrocode} +% +% Now process the options: +% +% \begin{macrocode} +\newif\ifsd@round +\newif\if@uscore\@uscoretrue +\ExecuteOptions{square} +\ProcessOptions +% \end{macrocode} +% +% \subsection{Special character handling} +% +% A lot of the \syn\ package requires the use special active characters. +% These must be added to two lists: |\dospecials|, which is used by |\verb| +% and friends, and |\@sanitize|, which is used by |\index|. The two macros +% here, |\addspecial| and |\remspecial|, provide these registration +% facilities. +% +% Two similar macros are found in Frank Mittelbach's \package{doc} package: +% these have the disadvantage of global operation. My macros here are based +% on Frank's, which in turn appear to be based on Donald Knuth's list +% handling code presented in Appendix~D of \textit{The \TeX book}. +% +% Both these macros take a single argument: a single-character control +% sequence containing the special character to be added to or removed from +% the lists. +% +% \begin{macro}{\addspecial} +% +% This is reasonably straightforward. We remove the sequence from the lists, +% in case it's already there, and add it in in the obvious way. This +% requires a little bit of fun with |\expandafter|. +% +% \begin{macrocode} +\def\addspecial#1{% + \remspecial{#1}% + \expandafter\def\expandafter\dospecials\expandafter{\dospecials\do#1}% + \expandafter\def\expandafter\@santize\expandafter{% + \@sanitize\@makeother#1}% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\remspecial} +% +% This is the difficult bit. Since |\dospecials| and |\@sanitize| have the +% form of list macros, we can redefine |\do| and |\@makeother| to do the +% job for us. We must be careful to put the old meaning of |\@makeother| +% back. The current implementation assumes it knows what |\@makeother| does. +% +% \begin{macrocode} +\def\remspecial#1{% + \def\do##1{\ifnum`#1=`##1 \else\noexpand\do\noexpand##1\fi}% + \edef\dospecials{\dospecials}% + \def\@makeother##1{\ifnum`#1=`##1 \else% + \noexpand\@makeother\noexpand##1\fi}% + \edef\@sanitize{\@sanitize}% + \def\@makeother##1{\catcode`##112}% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsection{Underscore handling} +% +% When typing a lot of identifiers, it can be irksome to have to escape +% all `|_|' characters in the manuscript. We make the underscore character +% active, so that it typesets an underscore in horizontal mode, and does +% its usual job as a subscript operator in maths mode. Underscore must +% already be in the special character lists, because of its use as a +% subscript character, so this doesn't cause us a problem. +% +% \begin{macro}{\underscore} +% +% The |\underscore| macro typesets an underline character, using a horizontal +% rule. This is positioned slightly below the baseline, and is also slightly +% wider than the default \TeX\ underscore. This code is based on a similar +% implementation found in the \package{lgrind} package. +% +% \begin{macrocode} +\def\underscore{% + \leavevmode% + \kern.06em% + \vbox{% + \hrule\@width.6em\@depth.4ex\@height-.34ex% + }% + \ifdim\fontdimen\@ne\font=\z@% + \kern.06em% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\@uscore} +% +% This macro is called by the `|_|' active character to sort out what to do. +% +% If this is maths mode, we use the |\sb| macro, which is already defined +% to do subscripting. Otherwise, we call |\textunderscore|, which picks the +% nicest underscore it can find. +% +% There's some extra cunningness here, because I'd like to be able to +% hyphenate after underscores usually, but not when there's another one +% following. And then, because \env{tabbing} redefines |\_|, there's some +% more yukkiness to handle that: the usual |\@tabacckludge| mechanism doesn't +% cope with this particular case. +% +% \begin{macrocode} +\let\usc@builtindischyphen\- +\def\@uscore.{% + \ifmmode% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + \sb% + {\textunderscore\@ifnextchar_{}{\usc@builtindischyphen}}% +} +% \end{macrocode} +% +% \end{macro} +% +% Now we set up the active character. Note the |\protect|, which makes +% underscores work reasonably well in moving arguments. Note also the way +% we end with a some funny stuff to prevent spaces being lost if this is +% written to a file. +% +% \begin{macrocode} +\if@uscore + \AtBeginDocument{% + \catcode`\_\active% + \begingroup% + \lccode`\~`\_% + \lowercase{\endgroup\def~{\protect\@uscore.}}% + } +\fi +% \end{macrocode} +% +% Finally, we redefine the |\_| macro to use our own |\underscore|, because +% it's prettier. Actually, we don't: we just redefine the +% |\?\textunderscore| command (funny name, isn't it?). +% +% \begin{macrocode} +\expandafter\let\csname?\string\textunderscore\endcsname\underscore +% \end{macrocode} +% +% \subsection{Abbreviated verbatim notation} +% +% In similar style to the \package{doc} package, we allow the user to set up +% characters which delimit verbatim text. Unlike \package{doc}, we make +% such changes local to the current group. This is performed through the +% |\shortverb| and |\unverb| commands. +% +% The implementations of these commands are based upon the |\MakeShortVerb| +% and |\DeleteShortVerb| commands of the \package{doc} package, although +% these versions have effect local to the current grouping level. This +% prevents their redefinition of |\dospecials| from interfering with the +% grammar shortcuts, which require local changes only. +% +% The command |\shortverb| takes a single argument: a single-character +% control sequence defining which character to make into the verbatim text +% delimiter. We store the old meaning of the active character in a control +% sequence called |\mn@\|\<char>. Note that this control sequence +% contains a backslash character, which is a little odd. We also define a +% command |\cc@\|\<char> which will return everything to normal. This +% is used by the |\unverb| command. +% +% \begin{macro}{\shortverb} +% +% Here we build the control sequences we need to make everything work nicely. +% The active character is defined via |\lowercase|, using the |~| character: +% this is already made active by \TeX\@. +% +% The actual code requires lots of fiddling with |\expandafter| and friends. +% +% \begin{macrocode} +\def\shortverb#1{% +% \end{macrocode} +% +% First, we check to see if the command |\cc@\|\<char> has been defined. +% +% \begin{macrocode} + \@ifundefined{cc@\string#1}{% +% \end{macrocode} +% +% If it hasn't been defined, we add the character to the specials list. +% +% \begin{macrocode} + \addspecial#1% +% \end{macrocode} +% +% Now we set our character to be the lowercase version of |~|, which allows +% us to use it, even though we don't know what it is. +% +% \begin{macrocode} + \begingroup% + \lccode`\~`#1% +% \end{macrocode} +% +% Finally, we reach the tricky bit. All of this is lowercased, so any +% occurrences of |~| are replaced by the user's special character. +% +% \begin{macrocode} + \lowercase{% + \endgroup% +% \end{macrocode} +% +% We remember the current meaning of the character, in case it has one. We +% have to use |\csname| to build the rather strange name we use for this. +% +% \begin{macrocode} + \expandafter\let\csname mn@\string#1\endcsname~% +% \end{macrocode} +% +% Now we build |\cc@\|\<char>. This is done with |\edef|, since more +% of this needs to be expanded now than not. In this way, the actual macros +% we create end up being very short. +% +% \begin{macrocode} + \expandafter\edef\csname cc@\string#1\endcsname{% +% \end{macrocode} +% +% First, add a command to restore the character's old catcode. +% +% \begin{macrocode} + \catcode`\noexpand#1\the\catcode`#1% +% \end{macrocode} +% +% Now we restore the character's old meaning, using the version we saved +% earlier. +% +% \begin{macrocode} + \let\noexpand~\expandafter\noexpand% + \csname mn@\string#1\endcsname% +% \end{macrocode} +% +% Now we remove the character from the specials lists. +% +% \begin{macrocode} + \noexpand\remspecial\noexpand#1% +% \end{macrocode} +% +% Finally, we delete this macro, so that |\unverb| will generate a warning +% if the character is |\unverb|ed again. +% +% \begin{macrocode} + \let\csname cc@\string#1\endcsname\relax% + }% +% \end{macrocode} +% +% All of that's over now. We set up the new definition of the character, +% in terms of |\verb|, and make the character active. The nasty |\syn@ttspace| +% is there to make the spacing come out right. It's all right really. Honest. +% +% \begin{macrocode} + \def~{\verb~\syn@ttspace}% + }% + \catcode`#1\active% +% \end{macrocode} +% +% If our magic control sequence already existed, we can assume that the +% character is already a verbatim delimiter, and raise a warning. +% +% \begin{macrocode} + }{% + \PackageWarning{syntax}{Character `\expandafter\@gobble\string#1' + is already a verbatim\MessageBreak + delimiter}% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\unverb} +% +% This is actually terribly easy: we just use the |\cc@\|\<char> command +% we definied earlier, after making sure that it's been defined. +% +% \begin{macrocode} +\def\unverb#1{% + \@ifundefined{cc@\string#1}{% + \PackageWarning{syntax}{Character `\expandafter\@gobble\string#1' + is not a verbatim\MessageBreak + delimiter}% + }{% + \csname cc@\string#1\endcsname% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsection{Style hooks for syntax forms} +% +% To allow the appearance of syntax things to be configured, we provide some +% redefinable bits. +% +% The three types of objects (nonterminal symbols, and quoted and unquoted +% terminals) each have two macros associated with them: one which does the +% `left' bit of the typesetting, and one which does the `right' bit. The +% items are typeset as LR~boxes. I'll be extra good while defining these +% hooks, so that it's obvious what's going on; macho \TeX\ hacker things +% resume after this section. +% +% \begin{macro}{\syntleft} +% \begin{macro}{\syntright} +% +% I can't see why anyone would want to change the typesetting of +% nonterminals, although I'll provide the hooks for symmetry's sake. +% +% \begin{macrocode} +\newcommand{\syntleft}{$\langle$\normalfont\itshape} +\newcommand{\syntright}{$\rangle$} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% +% \begin{macro}{\ulitleft} +% \begin{macro}{\ulitright} +% \begin{macro}{\litleft} +% \begin{macro}{\litright} +% +% Now we can define the left and right parts of quoted and unquoted +% terminals. US~readers may want to put double quotes around the quoted +% terminals, for example. +% +% \begin{macrocode} +\newcommand{\ulitleft}{\normalfont\ttfamily\syn@ttspace\frenchspacing} +\newcommand{\ulitright}{} +\newcommand{\litleft}{`\bgroup\ulitleft} +\newcommand{\litright}{\ulitright\egroup'} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Simple syntax typesetting} +% +% In general text, we allow access to our typesetting conventions through +% standard \LaTeX\ commands. +% +% \begin{macro}{\synt} +% +% The |\synt| macro typesets its argument as a syntactic quantity. It puts +% the text of the argument in italics, and sets angle brackets around it. +% Breaking of a |\synt| object across lines is forbidden. +% +% \begin{macrocode} +\def\synt#1{\mbox{\syntleft{#1\/}\syntright}} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\lit} +% +% The |\lit| macro typesets its argument as literal text, to be typed in. +% Normally, this means setting the text in |\tt| font, and putting quotes +% around it, although the quotes can be suppressed by using the $*$-variant. +% +% The |\syn@ttspace| macro sets up the spacing for the text nicely: |\tt| +% spaces tend to be a little wide. +% +% \begin{macrocode} +\def\lit{\@ifstar{\lit@i\ulitleft\ulitright}{\lit@i\litleft\litright}} +\def\lit@i#1#2#3{\mbox{#1{#3\/}#2}} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\syn@ttspace} +% +% This sets up the |\spaceskip| value for |\tt| text. +% +% \begin{macrocode} +\def\syn@ttspace@{\spaceskip.35em\@plus.2em\@minus.15em\relax} +% \end{macrocode} +% +% However, this isn't always the right thing to do. +% +% \begin{macrocode} +\def\ttthinspace{\let\syn@ttspace\syn@ttspace@} +\def\ttthickspace{\let\syn@ttspace\@empty} +% \end{macrocode} +% +% I know what I like thoough. +% +% \begin{macrocode} +\ttthinspace +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{The shortcuts} +% +% The easy part is over now. The next job is to set up the `grammar +% shortcuts' which allow easy changing of styles. +% +% We support four shortcuts: +% \begin{itemize} +% \item |`literal text'| typesets \syntax{`literal text'} +% \item |<non-terminal>| typesets \syntax{<non-terminal>} +% \item |"unquoted text"| typesets \syntax{"unquoted text"} +% \item \verb"|" typesets a \syntax{|} character +% \end{itemize} +% These are all implemented through active characters, which are enabled +% using the |\syntaxShortcuts| macro, described below. +% +% \begin{macro}{\readupto} +% +% \syntax{"\\readupto{"<char>"}{"<decls>"}{"<command>"}"} will read all +% characters up until the next occurrence of \<char>. Normally, all +% special characters will be deactivated. However, you can reactivate some +% characters, using the \<decls> argument, which is processed before the +% text is read. +% +% The code is borrowed fairly obviously from the \LaTeXe\ source for the +% |\verb| command. +% +% \begin{macrocode} +\def\readupto#1#2#3{% + \bgroup% + \verb@eol@error% + \let\do\@makeother\dospecials% + #2% + \catcode`#1\active% + \lccode`\~`#1% + \gdef\verb@balance@group{\verb@egroup% + \@latex@error{\noexpand\verb illegal in command argument}\@ehc}% + \def\@vhook{\verb@egroup#3}% + \aftergroup\verb@balance@group% + \lowercase{\let~\@vhook}% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\syn@assist} +% +% The |\syn@assist| macro is used for defining three of the shortcuts. It +% is called as +% +% \begin{quote} +% \syntax{"\\syn@assist{"<left-decls>"}{"<actives>"}{"<delimeter>"}" \\ +% \null \quad "{"<right-decls>"}{"<end-cmd>"}"} +% \end{quote} +% +% It creates an hbox, sets up the escape sequences for quoting our magic +% characters, and then typesets a box containing +% +% \begin{quote} +% \syntax{<left-decls>"{"<delimited-text>"\\/}"<right-decls>} +% \end{quote} +% +% The \<left-decls> and \<right-decls> can be |\relax| if they're not +% required. +% +% The \<actives> argument is passed to |\readupto|, to allow some special +% characters through. By default, we re-enable |\|, and make `\verb*" "' +% typeset some space glue, rather than a space character. A macro +% `\verb*"\ "' is defined to actually print a space character, which yield +% `\verb*" "' in the `|\tt|' font. +% +% Finally, it defines a |\ch| command, which, given a single-character +% control sequence as its argument, typesets the character. This is useful, +% since |`| has been made active when we set up these calls, so the +% direct |\char`\|\<char> doesn't work. +% +% \begin{macrocode} +\def\syn@assist#1#2#3#4#5{% +% \end{macrocode} +% +% First, we start the box, and open a group. We use |\mbox| because it +% does all the messing with |\leavevmode| which is needed. +% +% \begin{macrocode} + \mbox\bgroup% +% \end{macrocode} +% +% Next job is to set up the escape sequences. +% +% \begin{macrocode} + \chardef\\`\\% + \chardef\>`\>% + \chardef\'`\'% + \chardef\"`\"% + \chardef\ `\ % +% \end{macrocode} +% +% Now to define |\ch|. This is done the obvious way. +% +% \begin{macrocode} + \def\ch##1{\char`##1}% +% \end{macrocode} +% +% For active characters, we do some fiddling with |\lccode|s. +% +% \begin{macrocode} + \def\act##1{% + \catcode`##1\active% + \begingroup% + \lccode`\~`##1% + \lowercase{\endgroup\def~}% + }% +% \end{macrocode} +% +% Finally, we do the real work of setting the text. We use |\readupto| to +% actually find the text we want. +% +% \begin{macrocode} + #1% + \begingroup% + \readupto#3{% + \catcode`\\0% + \catcode`\ 10% + #2% + }{% + \/\endgroup#4\egroup#5% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\syn@shorts} +% +% This macro actually defines the expansions for the active characters. +% We have to do this separately because |`| must be active when we use it +% in the |\def|, but we can't do that and use |\catcode| at the same time. +% The arguments are commands to do before and after the actual command. +% These are passed up from |\syntaxShortcuts|. +% +% All of the characters use |\syn@assist| in the obvious way except for +% \verb"|", which drops into maths mode instead. +% +% Note that when changing the catcodes, we must save |`| until last. +% +% \begin{macrocode} +\begingroup +\catcode`\<\active +\catcode`\|\active +\catcode`\"\active +\catcode`\`\active +% +\gdef\syn@shorts#1#2{% +% \end{macrocode} +% +% The `|<|' character must typeset its argument in italics. We make `|_|' +% do the same as the `|\_|' command. +% +% \begin{macrocode} + \def<{% + #1% + \syn@assist% + \syntleft% + {\act_{\@uscore.}}% + >% + \syntright% + {#2}% + }% +% \end{macrocode} +% +% The `|`|' and `|"|' characters should print its argument in |\tt| font. +% We change the `|\tt|' space glue to provide nicer spacing on the line. +% +% \begin{macrocode} + \def`{% + #1% + \syn@assist% + \litleft% + \relax% + '% + \litright% + {#2}% + }% + \def"{% + #1% + \syn@assist% + \ulitleft% + \relax% + "% + \ulitright% + {#2}% + }% +% \end{macrocode} +% +% Finally, the `\verb"|"' character is typeset by using the mysterious +% |\textbar| command. +% +% \begin{macrocode} + \def|{\textbar}% +% \end{macrocode} +% +% We're finished here now. +% +% \begin{macrocode} +} +% +\endgroup +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\syntaxShortcuts} +% +% This is a user-level command which enables the use of our shortcuts in the +% current group. It uses |\addspecial|, defined below, to register the +% active characters, sets up their definitions and activates them. +% +% The two arguments are commands to be performed before and after the +% handling of the abbreviation. In this way, you can further process the +% output. +% +% This command is not intended to be used directly by users: it should be +% used by other macros and packages which wish to take advantage of the +% facilities offered by this package. We provide a |\synshorts| declaration +% (which may be used as an environment, of course) which is more `user +% palatable'. +% +% \begin{macrocode} +\def\syntaxShortcuts#1#2{% + \syn@shorts{#1}{#2}% + \addspecial\`% + \addspecial\<% + \addspecial\|% + \addspecial\"% + \catcode`\|\active% + \catcode`\<\active% + \catcode`\"\active% + \catcode`\`\active% +} +% +\def\synshorts{\syntaxShortcuts\relax\relax} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\synshortsoff} +% +% This macro can be useful occasionally: it disables the syntax shortcuts, +% so you can type normal text for a while. +% +% \begin{macrocode} +\def\synshortsoff{% + \catcode`\|12% + \catcode`\<12% + \catcode`\"12% + \catcode`\`12% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\syntax} +% +% The |\syntax| macro typesets its argument, allowing the use of our +% shortcuts within the argument. +% +% Actually, we go to some trouble to ensure that the argument to |\syntax| +% \emph{isn't} a real argument so we can change catcodes as we go. We +% use the |\let\@let@token=| trick from \PlainTeX\ to do this. +% +% \begin{macrocode} +\def\syntax#{\bgroup\syntaxShortcuts\relax\relax\let\@let@token} +% \end{macrocode} +% +% \end{macro} +% +% \begin{environment}{grammar} +% +% The \env{grammar} environment is the final object we have to define. It +% allows typesetting of beautiful BNF grammars. +% +% First, we define the length parameters we need: +% +% \begin{macrocode} +\newskip\grammarparsep + \grammarparsep8\p@\@plus\p@\@minus\p@ +\newdimen\grammarindent + \grammarindent2em +% \end{macrocode} +% +% Now define the default label typesetting. This macro is designed to be +% replaced by a user, so we'll be extra-well-behaved and use genuine \LaTeX\ +% commands. Well, almost \dots +% +% \begin{macrocode} +\newcommand{\grammarlabel}[2]{% + \synt{#1} \hfill#2% +} +% \end{macrocode} +% +% Now for a bit of hacking to make the item stuff work properly. This gets +% done for every new paragraph that's started without an |\item| command. +% +% First, store the left hand side of the production in a box. Then I'll +% end the paragraph, and insert some nasty glue to take up all the space, +% so no-one will ever notice that there was a paragraph break there. The +% strut just makes sure that I know exactly how high the line is. +% +% \begin{macrocode} +\def\gr@implitem<#1> #2 {% + \sbox\z@{\hskip\labelsep\grammarlabel{#1}{#2}}% + \strut\@@par% + \vskip-\parskip% + \vskip-\baselineskip% +% \end{macrocode} +% +% The |\item| command will notice that I've inserted these funny glues and +% try to remove them: I'll stymie its efforts by inserting an invisible +% rule. Then I'll insert the label using |\item| in the normal way. +% +% \begin{macrocode} + \hrule\@height\z@\@depth\z@\relax% + \item[\unhbox\z@]% +% \end{macrocode} +% +% Just before I go, I'll make \lit{<} back into an active character. +% +% \begin{macrocode} + \catcode`\<\active% +} +% \end{macrocode} +% +% Now for the environment proper. Deep down, it's a list environment, with +% some nasty tricks to stop anyone from noticing. +% +% The first job is to set up the list from the parameters I'm given. +% +% \begin{macrocode} +\newenvironment{grammar}{% + \list{}{% + \labelwidth\grammarindent% + \leftmargin\grammarindent% + \advance\grammarindent\labelsep + \itemindent\z@% + \listparindent\z@% + \parsep\grammarparsep% + }% +% \end{macrocode} +% +% We have major problems in |\raggedright| layouts, which try to use |\par| +% to start new lines. We go back to normal |\\| newlines to try and bodge +% our way around these problems. +% +% \begin{macrocode} + \let\\\@normalcr +% \end{macrocode} +% +% Now to enable the shortcuts. +% +% \begin{macrocode} + \syntaxShortcuts\relax\relax% +% \end{macrocode} +% +% Now a little bit of magic. The |\alt| macro moves us to a new line, and +% typesets a vertical bar in the margin. This allows typesetting of +% multiline alternative productions in a pretty way. +% +% \begin{macrocode} + \def\alt{\\\llap{\textbar\quad}}% +% \end{macrocode} +% +% Now for another bit of magic. We set up some |\par| cleverness to spot +% the start of each production rule and format it in some cunning and +% user-defined way. +% +% \begin{macrocode} + \def\gr@setpar{% + \def\par{% + \parshape\@ne\@totalleftmargin\linewidth% + \@@par% + \catcode`\<12% + \everypar{% + \everypar{}% + \catcode`\<\active% + \gr@implitem% + }% + }% + }% + \gr@setpar% + \par% +% \end{macrocode} +% +% Now set up the |\[[| and |\]]| commands to do the right thing. We have +% to check the next character to see if it's correct, otherwise we'll +% open a maths display as usual. +% +% \begin{macrocode} + \let\gr@leftsq\[% + \let\gr@rightsq\]% + \def\gr@endsyntdiag]{\end{syntdiag}\gr@setpar\par}% + \def\[{\@ifnextchar[{\begin{syntdiag}\@gobble}\gr@leftsq}% + \def\]{\@ifnextchar]\gr@endsyntdiag\gr@rightsq}% +% \end{macrocode} +% +% Well, that's it for this side of the environment. +% +% \begin{macrocode} +}{% +% \end{macrocode} +% +% Closing the environment is a simple matter of tidying away the list. +% +% \begin{macrocode} + \@newlistfalse% + \everypar{}% + \endlist% +} +% \end{macrocode} +% +% \end{environment} +% +% \subsection{Syntax diagrams} +% +% Now we come to the final and most complicated part of the package. +% +% Syntax diagrams are drawn using arrow characters from \LaTeX's line font, +% used in the \env{picture} environment, and rules. The horizontal rules +% of the diagram are drawn along the baselines of the lines in which they +% are placed. The text items in the diagram are placed in boxes and lowered +% below the main baseline. Struts are added throughout to keep the vertical +% spacing consistent. +% +% The vertical structures (stacks and loops) are all implemented with \TeX's +% primitive |\halign| command. +% +% \subsubsection{User-configurable parameters} +% +% First, we allocate the \<dimen> and \<skip> arguments needed. Fixed +% lengths, as the \LaTeX book calls them, are allocated as \<dimen>s, to +% take some of the load off of all the \<skip> registers. +% +% \begin{macrocode} +\newskip\sdstartspace +\newskip\sdendspace +\newskip\sdmidskip +\newskip\sdtokskip +\newskip\sdfinalskip +\newdimen\sdrulewidth +\newdimen\sdcirclediam +\newdimen\sdindent +% \end{macrocode} +% +% We need some \TeX\ \<dimen>s for our own purposes, to get everything in +% the right places. We use labels for the `temporary' \TeX\ parameters +% which we use, to avoid wasting registers. +% +% \begin{macrocode} +\dimendef\sd@lower\z@ +\dimendef\sd@upper\tw@ +\dimendef\sd@mid4 +\dimendef\sd@topcirc6 +\dimendef\sd@botcirc8 +% \end{macrocode} +% +% \begin{macro}{\sd@setsize} +% When the text size for syntax diagrams changes, it's necessary to work out +% the height for various rules in the diagram. +% +% \begin{macrocode} +\def\sd@setsize{% + \sd@mid\ht\strutbox% + \advance\sd@mid-\dp\strutbox% + \sd@mid.5\sd@mid% + \sd@upper\sdrulewidth% + \advance\sd@upper\sd@mid% + \sd@lower\sdrulewidth% + \advance\sd@lower-\sd@mid% + \sd@topcirc-.5\sdcirclediam% + \advance\sd@topcirc\sd@mid% + \sd@botcirc-.5\sdcirclediam% + \advance\sd@botcirc-\sd@mid% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sdsize} +% +% You can set the default type size used by syntax diagrams by redefining +% the |\sdsize| command, using the |\renewcommand| command. +% +% By default, syntax diagrams are set slightly smaller than the main body +% text.\footnote{^^A +% I've used pure \LaTeX\ commands for this and the \cmd\sdlengths\ macro, +% to try and illustrate how these values might be changed by a user. The +% rest of the code is almost obfuscted in its use of raw \TeX\ features, +% in an attempt to dissuade more na\"\i ve users from fiddling with it. +% I suppose this is what you get when you let assembler hackers loose with +% something like \LaTeX. +% } +% +% \begin{macrocode} +\newcommand{\sdsize}{% + \small% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sdlengths} +% +% Finally, the default length parameters are set in the |\sdlengths| command. +% You can redefine the command using |\renewcommand|. +% +% We set up the length parameters here. +% +% \begin{macrocode} +\newcommand{\sdlengths}{% + \setlength{\sdstartspace}{1em minus 10pt}% + \setlength{\sdendspace}{1em minus 10pt}% + \setlength{\sdmidskip}{0.5em plus 0.0001fil}% + \setlength{\sdtokskip}{0.25em plus 0.0001fil}% + \setlength{\sdfinalskip}{0.5em plus 10000fil}% + \setlength{\sdrulewidth}{0.2pt}% + \setlength{\sdcirclediam}{8pt}% + \setlength{\sdindent}{0pt}% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Other declarations} +% +% We define four switches. The table shows what they're used for. +% +% \begin{table} +% \begin{tab}{lp{3in}} \hline +% +% \bf Switch & \bf Meaning \\ \hline +% +% |\ifsd@base| & We are at `base level' in the diagram: +% i.e., not in any other sorts of +% constructions. This is used to decide +% whether to allow line breaking. \\[2pt] +% +% |\ifsd@top| & The current loop construct is being +% typeset with the loop arrow above the +% baseline. \\[2pt] +% +% |\ifsd@toplayer| & We are typesetting the top layer of +% a stack. This is used to ensure that +% the vertical rules on either side are +% typeset at the right height. \\[2pt] +% +% |\ifsd@backwards| & We're typesetting backwards, because +% we're in the middle of a loop arrow. +% the only difference this makes is that +% any subloops have the arrow on the +% side. \\ \hline +% +% \end{tab} +% \caption{Syntax diagram switches} +% \end{table} +% +% \begin{macrocode} +\newif\ifsd@base +\newif\ifsd@top +\newif\ifsd@toplayer +\newif\ifsd@backwards +% \end{macrocode} +% +% \begin{macro}{\sd@err} +% +% We output our errors through this macro, which saves a little typing. +% +% \begin{macrocode} +\def\sd@err{\PackageError{syntax}} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Arrow-drawing} +% +% We need to draw some arrows. \LaTeX\ tries to make this as awkward as +% possible, so we have to start moving the arrows around in boxes quite a +% lot. +% +% The left and right pointing arrows are fairly simple: we just add some +% horizontal spacing to prevent the width of the arrow looking odd. +% +% \begin{macrocode} +\def\sd@arrow{% + \ht\tw@\z@% + \dp\tw@\z@% + \raise\sd@mid\box\tw@% + \egroup% +} +\def\sd@rightarr{% + \bgroup% + \setbox\tw@\hbox{\kern-6\p@\@linefnt\char'55}% + \sd@arrow% +} +\def\sd@leftarr{% + \bgroup% + \raise\sd@mid\hbox{\@linefnt\char'33\kern-6\p@}% + \sd@arrow% +} +% \end{macrocode} +% +% The up arrow is very strange. We need to bring the arrow down to base +% level, and smash its height. +% +% \begin{macrocode} +\def\sd@uparr{% + \bgroup% + \setbox\tw@\hb@xt@\z@{\kern-\sdrulewidth\@linefnt\char'66\hss}% + \setbox\tw@\hbox{\lower10\p@\box\tw@}% + \sd@arrow% +} +% \end{macrocode} +% +% The down arrow is similar, although it's already at the right height. +% Thus, we can just smash the box. +% +% \begin{macrocode} +\def\sd@downarr{% + \bgroup% + \setbox\tw@\hb@xt@\z@{\kern-\sdrulewidth\@linefnt\char'77\hss}% + \sd@arrow% +} +% \end{macrocode} +% +% \subsubsection{Drawing curves} +% +% If the user has selected curved edges, we use the \LaTeX\ features provided +% to obtain the curves. These are drawn slightly oddly to make it easier +% to fit them into the diagram. +% +% Some explanation about the \LaTeX\ circle font is probably called for +% before we go any further. The font consists of sets of four quadrants +% of a particular size (and some other characters, which aren't important +% at the moment). Each collection of quadrants fit together to form a +% perfect circle of a given diameter. The individual quadrant characters +% have strange bounding boxes, as described in the files \textit{lcircle.mf} +% and \textit{ltpict.dtx}, and also in Appendix~D of \textit{The \TeX book}. +% Our job here is to make these quadrants useful in the context of +% drawing syntax diagrams. +% +% \begin{macro}{\sd@circ} +% First, we define |\sd@circ|, which performs the common parts of the four +% routines. Since the characters in the circle font are grouped together, +% we can pick out a particular corner piece by specifying its index into +% the group for the required size. The |\sd@circ| routine will pick out +% the required character, given this index as an argument, and put it in +% box~2, after fiddling with the sizes a little: +% \begin{itemize} +% +% \item We clear the width to zero. The individual routines then add a kern +% of the correct amount, so that the quadrant appears in the right +% place. +% +% \item The piece is lowered by half the rule width. This positions the +% top and bottom pieces of the circle to be half way over the baseline, +% which is the correct position for the rest of the diagram. +% +% \end{itemize} +% +% Finally, we make sure we're in horizontal mode: horrific results occur +% if this is not the case. I'm sure I don't need to explain this any more +% graphically. +% +% \begin{macrocode} +\def\sd@circ#1{% + \@getcirc\sdcirclediam% + \advance\@tempcnta#1% + \setbox\tw@\hbox{\lower\sdrulewidth% + \hbox{\@circlefnt\char\@tempcnta}}% + \wd\tw@\z@% + \leavevmode% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sd@tlcirc} +% \begin{macro}{\sd@trcirc} +% \begin{macro}{\sd@blcirc} +% \begin{macro}{\sd@brcirc} +% +% These are the macros which actually draw quadrants of circles. They all +% call |\sd@circ|, passing an appropriate index, and then fiddle with the +% box sizes and apply kerning specific to the quadrant positioning. +% +% The exact requirements for positioning are as follows: +% +% \begin{itemize} +% +% \item The horizontal parts of the arcs must lie along the baseline (i.e., +% half the line must be above the baseline, and half must be below). +% This is consistent with the horizontal rules used in the diagram. +% +% \item The vertical parts must overlap vertical rules on either side, so +% that a |\vrule\sd@|\textit{xx}|circ| makes the arc appear to be +% a real curve in the line. The requirements are actually somewhat +% inconsistent; for example, the \env{stack} environment uses curves +% \emph{before} the |\vrule|s. Special requirements like this are +% handled as special cases later. +% +% \item The height and width of the arc are at least roughly correct. +% +% \end{itemize} +% +% \begin{macrocode} +\def\sd@tlcirc{{% + \sd@circ3% + \ht\tw@\sdrulewidth% + \dp\tw@.5\sdcirclediam% + \kern-\tw@\sdrulewidth% + \raise\sd@mid\box\tw@% + \kern.5\sdcirclediam% +}} +% \end{macrocode} +% +% \begin{macrocode} +\def\sd@trcirc{{% + \sd@circ0% + \ht\tw@\sdrulewidth% + \dp\tw@.5\sdcirclediam% + \kern.5\sdcirclediam% + \raise\sd@mid\box\tw@% +}} +% \end{macrocode} +% +% \begin{macrocode} +\def\sd@blcirc{{% + \sd@circ2% + \ht\tw@.5\sdcirclediam% + \dp\tw@\sdrulewidth% + \kern-\tw@\sdrulewidth% + \raise\sd@mid\box\tw@% + \kern.5\sdcirclediam% +}} +% \end{macrocode} +% +% \begin{macrocode} +\def\sd@brcirc{{% + \sd@circ1% + \ht\tw@.5\sdcirclediam% + \dp\tw@\sdrulewidth% + \kern.5\sdcirclediam% + \raise\sd@mid\box\tw@% +}} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\sd@llc} +% \begin{macro}{\sd@rlc} +% +% In the \env{rep} environment, we need to be able to draw arcs with +% horizontal lines running through them. The two macros here do the job +% nicely. |\sd@llc| (which is short for left overlapping circle) is +% analogous to |\llap|: it puts its argument in a box of zero width, sticking +% out to the left. However, it also draws a rule along the baseline. This +% is important, as it prevents text from overprinting the arc. |\sd@rlc| +% is very similar, just the other way around. +% +% \begin{macrocode} +\def\sd@llc#1{% + \hb@xt@.5\sdcirclediam{% + \sd@rule\hskip.5\sdcirclediam% + \hss% + #1% + }% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\sd@rlc#1{% + \hb@xt@.5\sdcirclediam{% + #1% + \hss% + \sd@rule\hskip.5\sdcirclediam% + }% +} +% \end{macrocode} +% +% \end{macro} +% \end{macro} +% +% \subsubsection{Drawing rules} +% +% It's important to draw the rules \emph{along} the baseline, rather than +% above it: hence, the depth of the rule must be equal to the height. +% +% \begin{macro}{\sd@rule} +% +% We use rule leaders instead of glue through most of the syntax diagrams. +% The command \syntax{"\\sd@rule"<skip>} draws a rule of the correct +% dimensions, which has the behaviour of an \syntax{"\\hskip"<skip>}. +% +% \begin{macrocode} +\def\sd@rule{\leaders\hrule\@height\sd@upper\@depth\sd@lower} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sd@gap} +% +% The gap between elements is added using this macro. It will allow a +% line break if we're at the top level of the diagram, using a rather +% strange discretionary. +% +% This is called as \syntax{"\\sd@gap{"<skip-register>"}"}. +% +% \begin{macrocode} +\def\sd@gap#1{% +% \end{macrocode} +% +% First, we see if we're at the top level. Within constructs, we avoid the +% overhead of a |\discretionary|. We put half of the width of the skip on +% each side of the discretionary break. +% +% \begin{macrocode} + \ifsd@base% + \skip@#1% + \divide\skip\z@\tw@% + \nobreak\sd@rule\hskip\skip@% + \discretionary{% + \sd@qarrow{->}% + }{% + \hbox{% + \sd@qarrow{>-}% + \sd@rule\hskip\sdstartspace% + \sd@rule\hskip3.5\p@% + }% + }{% + }% + \nobreak\sd@rule\hskip\skip@% +% \end{macrocode} +% +% If we're not at the base level, we just put in a rule of the correct +% width. +% +% \begin{macrocode} + \else% + \sd@rule\hskip#1% + \fi% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{The \protect\env{syntdiag} environment} +% +% All syntax diagrams are contained within a \env{syntdiag} environment. +% +% \begin{environment}{syntdiag} +% +% The only argument is a collection of declarations, which by +% default is +% +% \begin{listing} +%\sdsize\sdlengths +% \end{listing} +% +% However, if the optional argument is not specified, \TeX\ reads the first +% character of the environment, which may not be catcoded correctly. We set +% up the catcodes first, using the |\syntaxShortcuts| command, and then read +% the argument. We don't use |\newcommand|, because that would involve +% creating yet \emph{another} macro. Time to fiddle with |\@ifnextchar| +% \dots +% +% \begin{macrocode} +\def\syntdiag{% + \syntaxShortcuts\sd@tok@i\sd@tok@ii% + \@ifnextchar[\syntdiag@i{\syntdiag@i[]}% +} +% \end{macrocode} +% +% Now we actually do the job we're meant to. +% +% \begin{macrocode} +\def\syntdiag@i[#1]{% +% \end{macrocode} +% +% The first thing to do is execute the user's declarations. We then set +% up things for the font size. +% +% \begin{macrocode} + \sdsize\sdlengths% + #1% + \sd@setsize% +% \end{macrocode} +% +% Next, we start a list, to change the text layout. +% +% \begin{macrocode} + \list{}{% + \leftmargin\sdindent% + \rightmargin\leftmargin% + \labelsep\z@% + \labelwidth\z@% + }% + \item[]% +% \end{macrocode} +% +% We reconfigure the paragraph format quite a lot now. We clear +% |\parfillskip| to avoid any justification at the end of the paragraph. +% We also turn off paragraph indentation. +% +% \begin{macrocode} + \parfillskip\z@% + \noindent% +% \end{macrocode} +% +% Next, we add in the arrows on the beginning of the line, and a bit of +% glue. +% +% \begin{macrocode} + \sd@qarrow{>>-}% + \nobreak\sd@rule\hskip\sdstartspace% +% \end{macrocode} +% +% This is the base level of the diagram, so we enable line breaking. +% +% \begin{macrocode} + \sd@basetrue% +% \end{macrocode} +% +% Since the objects being broken are rather large, we enable sloppy line +% breaking. We also try to avoid page breaks in mid-diagram, by upping the +% |\interlinepenalty|. +% +% \begin{macrocode} + \sloppy% + \interlinepenalty100% + \hyphenpenalty0% +% \end{macrocode} +% +% We handle all the spacing within the environment, so we make \TeX\ ignore +% spaces and newlines. +% +% \begin{macrocode} + \catcode`\ 9% + \catcode`\^^M9% +% \end{macrocode} +% +% We now have to change the behaviour of |\\| to line-break syntax diagrams. +% +% \begin{macrocode} + \let\\\sd@newline% + \ignorespaces% +} +% \end{macrocode} +% +% When we end the diagram, we just have to add in the final fillskip, and +% double arrow. +% +% \begin{macrocode} +\def\endsyntdiag{% + \unskip% + \nobreak\sd@rule\hskip\sdmidskip% + \sd@rule\hskip\sdfinalskip% + \sd@qarrow{-><}% + \endlist% +} +% \end{macrocode} +% +% \end{environment} +% +% \begin{environment}{syntdiag*} +% +% The starred form of \env{syntdiag} typesets a syntax diagram in LR-mode; +% this is useful if you're describing parts of syntax diagrams, for example. +% +% This is in fact really easy. The first bit which checks for an optional +% argument is almost identical to the non-$*$ version. +% +% \begin{macrocode} +\@namedef{syntdiag*}{% + \syntaxShortcuts\sd@tok@i\sd@tok@ii% + \@ifnextchar[\syntdiag@s@i{\syntdiag@s@i[]}% +} +% \end{macrocode} +% +% Handle another optional argument giving the width of the box to fill. +% +% \begin{macrocode} +\def\syntdiag@s@i[#1]{% + \@ifnextchar[{\syntdiag@s@ii{#1}}{\syntdiag@s@iii{#1}{\hbox}}% +} +\def\syntdiag@s@ii#1[#2]{\syntdiag@s@iii{#1}{\hb@xt@#2}} +% \end{macrocode} +% +% Now to actually start the display. This is mostly simple. Just to make +% sure about the LR-ness of the typesetting, I'll put everything in an hbox. +% +% \begin{macrocode} +\def\syntdiag@s@iii#1#2{% + \leavevmode% + #2\bgroup% +% \end{macrocode} +% +% Now configure the typesetting according to the user's wishes. +% +% \begin{macrocode} + \let\@@left\left% + \let\@@right\right% + \def\left##1{\def\sd@startarr{##1}}% + \def\right##1{\def\sd@endarr{##1}}% + \left{>-}\right{->}% + \sdsize\sdlengths% + #1% + \sd@setsize% + \let\left\@@left% + \let\right\@@right% +% \end{macrocode} +% +% Put in the initial double-arrow. +% +% \begin{macrocode} + \sd@qarrow\sd@startarr% + \sd@rule\hskip\sdmidskip% +% \end{macrocode} +% +% We're in horizontal mode, so don't bother with linebreaking. +% +% \begin{macrocode} + \sd@basefalse% +% \end{macrocode} +% +% Finally, disable spaces and things. +% +% \begin{macrocode} + \catcode`\ 9% + \catcode`\^^M9% + \ignorespaces% +} +% \end{macrocode} +% +% Ending the environment is very similar. +% +% \begin{macrocode} +\@namedef{endsyntdiag*}{% + \unskip% + \sd@rule\hskip\sdmidskip% + \sd@rule\hskip\sdfinalskip% + \sd@qarrow\sd@endarr% + \egroup% +} +% \end{macrocode} +% +% \end{environment} +% +% \begin{macro}{\sd@qarrow} +% +% This typesets the various left and right arrows required in syntax +% diagrams. The argument is one of \syntax{`>>-', `->', `>-' or `-><'}. +% +% \begin{macrocode} +\def\sd@qarrow#1{% + \begingroup% + \lccode`\~=`\<\lowercase{\def~{<}}% + \hbox{\csname sd@arr@#1\endcsname}% + \endgroup% +} +\@namedef{sd@arr@>>-}{\sd@rightarr\kern-.5\p@\sd@rightarr\kern-\p@} +\@namedef{sd@arr@>-}{\sd@rightarr\kern-\p@} +\@namedef{sd@arr@->}{\sd@rightarr} +\@namedef{sd@arr@-><}{\sd@rightarr\kern-\p@\sd@leftarr} +\@namedef{sd@arr@...}{$\cdots$} +\@namedef{sd@arr@-}{} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sd@newline} +% +% The line breaking within a syntax diagram is controlled by the +% |\sd@newline| command, to which |\\| is assigned. +% +% We support all the standard \LaTeX\ features here. The line breaking +% involves adding a fill skip and arrow, moving to the next line, adding +% an arrow and a rule, and continuing. +% +% \begin{macrocode} +\def\sd@newline{\@ifstar{\vadjust{\penalty\@M}\sd@nl@i}\sd@nl@i} +\def\sd@nl@i{\@ifnextchar[\sd@nl@ii\sd@nl@iii} +\def\sd@nl@ii[#1]{\vspace{#1}\sd@nl@iii} +\def\sd@nl@iii{% + \nobreak\sd@rule\hskip\sdmidskip% + \sd@rule\hskip\sdfinalskip% + \kern-3\p@% + \sd@rightarr% + \newline% + \sd@rightarr% + \nobreak\sd@rule\hskip\sdstartspace% + \sd@rule\hskip3.5\p@% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Putting things in the right place} +% +% Syntax diagrams have fairly stiff requirements on the positioning of text +% relative to the diagram's rules. To help people (and me) to write +% extensions to the syntax diagram typesetting which automatically put things +% in the right place, I provide some simple macros. +% +% \begin{environment}{sdbox} +% +% By placing some text in the \env{sdbox} environment, it will be read into a +% box and then output at the correct height for the syntax diagram. Note +% that stuff in the box is set in horizontal (LR) mode, so you'll have to use +% a \env{minipage} if you want formatted text. The macro also supplies rules +% on either side of the box, with a length given in the environment's +% argument. +% +% Macro writers are given explicit permission to use this environment through +% the |\sdbox| and |\endsdbox| commands if this makes life easier. +% +% The calculation in the |\endsdbox| macro works out how to centre the box +% vertically over the baseline. If the box's height is~$h$, and its depth +% is~$d$, then its centre-line is $(h+d)/2$ from the bottom of the box. +% Since the baseline is already $d$ from the bottom, we need to lower the box +% by $(h+d)/2 - d$, or $h/2-d/2$. +% +% \begin{macrocode} +\def\sdbox#1{% + \@tempskipa#1\relax% + \sd@gap\@tempskipa% + \setbox\z@\hbox\bgroup% + \begingroup% + \catcode`\ 10% + \catcode`\^^M5% + \synshortsoff% +} +\def\endsdbox{% + \endgroup% + \egroup% + \@tempdima\ht\z@% + \advance\@tempdima-\dp\z@% + \advance\@tempdima-\tw@\sd@mid% + \lower.5\@tempdima\box\z@% + \sd@gap\@tempskipa% +} +% \end{macrocode} +% +% \end{environment} +% +% \subsubsection{Typesetting syntactic items} +% +% Using the hooks built into the syntax abbreviations above, we typeset +% the text into a box, and write it out, centred over the baseline. A strut +% helps to keep the actual text baselines level for short pieces of text. +% +% \begin{macro}{\sd@tok@i} +% +% The preamble for a syntax abbreviation. We start a box, and set the +% space and return characters to work again. A strut is added to the box to +% ensure correct vertical spacing for normal text. +% +% \begin{macrocode} +\def\sd@tok@i{% + \sdbox\sdtokskip% + \strut% + \space% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sd@tok@ii} +% +% \begin{macrocode} +\def\sd@tok@ii{% + \space% + \endsdbox% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{Inserting other pieces of text} +% +% Arbitrary text may be put into a syntax diagram through the use of the +% |\tok| macro. Its `argument' is typeset in the same way as a syntactic +% item (centred over the baseline). The implementation goes to some effort +% to ensure that the text is not actually an argument, to allow category +% codes to change while the text is being typeset. +% +% \begin{macro}{\tok} +% +% We start a box, and make space and return do their normal jobs. We use +% |\aftergroup| to regain control once the box is finished. |\doafter| is +% used to get control after the group finishes. +% +% \begin{macrocode} +\def\tok#{% + \sdbox\sdtokskip% + \strut% + \enspace% + \syntaxShortcuts\relax\relax% + \doafter\sd@tok% +} +% \end{macrocode} +% +% The |\sd@tok| macro is similar to |\sd@tok@ii| above. +% +% \begin{macrocode} +\def\sd@tok{% + \enspace% + \endsdbox% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{The \protect\env{stack} environment} +% +% The \env{stack} environment is used to present alternatives in a syntax +% diagram. The alternatives are separated by |\\| commands. +% +% \begin{macro}{\stack} +% +% The optional positioning argument is handled using \LaTeX's |\newcommand| +% mechanism. +% +% \begin{macrocode} +\newcommand\stack[1][t]{% +% \end{macrocode} +% +% First, we add some horizontal space. +% +% \begin{macrocode} + \sd@gap\sdmidskip% +% \end{macrocode} +% +% We're within a complex construction, so we need to clear the |\ifsd@base| +% flag. +% +% \begin{macrocode} + \begingroup\sd@basefalse% +% \end{macrocode} +% +% The top and bottom rows of the stack are different to the others, since +% the vertical rules mustn't extend all the way up the side of the item. +% The bottom row is handled separately by |\endstack| below. The top row +% must be handled via a flag, |\ifsd@toplayer|. +% +% Initially, the flag must be set true. +% +% \begin{macrocode} + \sd@toplayertrue% +% \end{macrocode} +% +% We set the |\\| command to separate the items in the |\halign|. +% +% \begin{macrocode} + \let\\\sd@stackcr% +% \end{macrocode} +% +% The actual structure must be set in vertical mode, so we must place it +% in a box. The position argument determines whether this must be a +% |\vbox| or a |\vtop|. We also insert a bit of rounding if the options say +% we must. +% +% \begin{macrocode} + \if#1t% + \let\@tempa\vtop% + \sd@toptrue% + \ifsd@round\llap{\sd@trcirc\kern\tw@\sdrulewidth}\fi% + \else\if#1b% + \let\@tempa\vbox% + \sd@topfalse% + \ifsd@round\llap{\sd@brcirc\kern\tw@\sdrulewidth}\fi% + \else% + \sd@err{Bad position argument passed to stack}% + {The positioning argument must be one of `t' or `b'. I% + have^^Jassumed you meant to type `t'.}% + \let\@tempa\vtop% + \fi\fi% +% \end{macrocode} +% +% Now we start the box, which we will complete at the end of the environment. +% +% \begin{macrocode} + \@tempa\bgroup% +% \end{macrocode} +% +% We must remove any extra space between rows of the table, since the rules +% will not join up correctly. We can use |\offinterlineskip| safely, since +% each individual row contains a strut. +% +% \begin{macrocode} + \offinterlineskip% +% \end{macrocode} +% +% Now we can start the alignment. We actually use \PlainTeX's |\ialign| +% macro, which also clears |\tabskip| for us. +% +% \begin{macrocode} + \ialign\bgroup% +% \end{macrocode} +% +% The preamble is trivial, since we must do all of the work ourselves +% +% \begin{macrocode} + ##\cr% +% \end{macrocode} +% +% We can now start putting the text into a box ready for typesetting later. +% The strut makes the vertical spacing correct. +% +% \begin{macrocode} + \setbox\z@\hbox\bgroup% + \strut% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\endstack} +% +% The first part of this is similar to the |\sd@stackcr| macro below, except +% that the vertical rules are different. We don't support rounded edges +% on single-row stacks, although this isn't a great loss to humanity. +% +% \begin{macrocode} +\def\endstack{% + \egroup% + \ifsd@toplayer% + \sd@dostack\sd@upper\sd@lower\relax\relax% + \else% + \ifsd@round% + \ifsd@top% + \sd@dostack{\ht\z@}\sd@botcirc\sd@blcirc\sd@brcirc% + \else% + \sd@dostack{\ht\z@}\sd@botcirc\relax\relax% + \fi% + \else% + \sd@dostack{\ht\z@}\sd@lower\relax\relax% + \fi% + \fi% +% \end{macrocode} +% +% We now close the |\halign| and the vbox we created. +% +% \begin{macrocode} + \egroup% + \egroup% +% \end{macrocode} +% +% Deal with any rounding we started off. +% +% \begin{macrocode} + \ifsd@round% + \ifsd@top + \rlap{\kern\tw@\sdrulewidth\sd@tlcirc}% + \else% + \rlap{\kern\tw@\sdrulewidth\sd@blcirc}% + \fi% + \fi% +% \end{macrocode} +% +% Finally, we add some horizontal glue to space the diagram out. +% +% \begin{macrocode} + \endgroup\sd@gap\sdmidskip% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sd@stackcr} +% +% The |\\| command is set to this macro during a \env{stack} environment. +% +% \begin{macrocode} +\def\sd@stackcr{% +% \end{macrocode} +% +% The first job is to close the box containing the previous item. +% +% \begin{macrocode} + \egroup% +% \end{macrocode} +% +% Now we typeset the vertical rules differently depending on whether this is +% the first item in the stack. This looks quite terrifying initially, but +% it's just an enumeration of the possible cases for the different values +% of |\ifsd@toplayer|, |\ifsd@top| and |\ifsd@round|, putting in appropriate +% rules and arcs in the right places. +% +% \begin{macrocode} + \ifsd@toplayer% + \ifsd@round% + \ifsd@top% + \sd@dostack\sd@topcirc{\dp\z@}\relax\relax% + \else% + \sd@dostack\sd@topcirc{\dp\z@}\sd@tlcirc\sd@trcirc% + \fi% + \else% + \sd@dostack\sd@upper{\dp\z@}\relax\relax% + \fi% + \else% + \ifsd@round% + \ifsd@top% + \sd@dostack{\ht\z@}{\dp\z@}\sd@blcirc\sd@brcirc% + \else% + \sd@dostack{\ht\z@}{\dp\z@}\sd@tlcirc\sd@trcirc% + \fi% + \else% + \sd@dostack{\ht\z@}{\dp\z@}\relax\relax% + \fi% + \fi% +% \end{macrocode} +% +% The next item won't be the first, so we clear the flag. +% +% \begin{macrocode} + \sd@toplayerfalse% +% \end{macrocode} +% +% Now we have to set up the next cell. We put the text into a box again. +% +% \begin{macrocode} + \setbox\z@\hbox\bgroup% + \strut% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sd@dostack} +% +% Actually typesetting the text in a cell is performed here. The macro is +% called as +% \begin{quote}\synshorts +% "\\sd@dostack{"<height>"}{"<depth>"}{"<left-arc>"}{"<right-arc>"}" +% \end{quote} +% where \<height> and \<depth> are the height and depth of the vertical +% rules to put around the item, and \<left-arc> and \<right-arc> are +% commands to draw rounded edges on the left and right hand sides of the +% item. +% +% The values for the height and depth are quite often going to be the height +% and depth of box~0. Since we empty box~0 in the course of typesetting the +% row, we need to cache the sizes on entry. +% +% \begin{macrocode} +\def\sd@dostack#1#2#3#4{% + \@tempdima#1% + \@tempdimb#2% + \kern-\tw@\sdrulewidth% + \vrule\@height\@tempdima\@depth\@tempdimb\@width\tw@\sdrulewidth% + #3% + \sd@rule\hfill% + \sd@gap\sdtokskip% + \unhbox\z@% + \sd@gap\sdtokskip% + \sd@rule\hfill% + #4% + \vrule\@height\@tempdima\@depth\@tempdimb\@width\tw@\sdrulewidth% + \kern-\tw@\sdrulewidth% + \cr% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsubsection{The \protect\env{rep} environment} +% +% The \env{rep} environment is used for typesetting loops in the diagram. +% Again, we use |\halign| for the typesetting. Loops are simpler than +% stacks, however, since there are always two rows. We store both rows in +% box registers, and build the loop at the end. +% +% \begin{macro}{\rep} +% +% Again, we use |\newcommand| to process the optional argument. +% +% \begin{macrocode} +\newcommand\rep[1][t]{% +% \end{macrocode} +% +% First, leave a gap on the left side. +% +% \begin{macrocode} + \sd@gap\sdmidskip% +% \end{macrocode} +% +% We're not at base level any more, so disable linebreaking. +% +% \begin{macrocode} + \begingroup\sd@basefalse% +% \end{macrocode} +% +% Remember we're going backwards now. +% +% \begin{macrocode} + \ifsd@backwards\sd@backwardsfalse\else\sd@backwardstrue\fi% +% \end{macrocode} +% +% Define |\\| to separate the two parts of the loop. +% +% \begin{macrocode} + \let\\\sd@loop% +% \end{macrocode} +% +% Now check the argument, and use the appropriate type of box. In addition +% to changing the typesetting, we must remember which way up to typeset the +% loop, since the end code must always put the first argument on the +% baseline, with the loop either above or below. +% +% \begin{macrocode} + \if#1t% + \let\@tempa\vbox% + \sd@toptrue% + \else\if#1b% + \let\@tempa\vtop% + \sd@topfalse% + \else% + \sd@err{Bad position argument passed to loop}% + {The positioning argument must be `t' or `b'. I have^^J% + assumed you meant to type `t'.}% + \let\@tempa\vbox% + \sd@toptrue% + \fi\fi% +% \end{macrocode} +% +% Now we start the box. +% +% \begin{macrocode} + \@tempa\bgroup% +% \end{macrocode} +% +% The loop is by default empty, apart from a strut. This is put into box~1. +% +% \begin{macrocode} + \setbox\tw@\copy\strutbox% +% \end{macrocode} +% +% Now start typesetting the main text in box~0. +% +% \begin{macrocode} + \setbox\z@\hbox\bgroup\strut% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\endrep} +% +% The final code must first close whatever box was open. +% +% \begin{macrocode} +\def\endrep{% + \egroup% +% \end{macrocode} +% +% Now we typeset the loop, depending on which way up it was meant to be. +% Again, this terrifying piece of code is a simple list of possibile values +% of our various flags. +% +% \begin{macrocode} + \ifsd@top% + \ifsd@round% + \sd@doloop\tw@\z@\relax\relax% + \sd@tlcirc\sd@trcirc{\sd@rlc\sd@blcirc}{\sd@llc\sd@brcirc}% + \else% + \sd@doloop\tw@\z@\relax\sd@downarr\relax\relax\relax\relax% + \fi% + \else% + \ifsd@round% + \sd@doloop\z@\tw@\relax\relax% + {\sd@rlc\sd@tlcirc}{\sd@llc\sd@trcirc}\sd@blcirc\sd@brcirc% + \else% + \sd@doloop\z@\tw@\sd@uparr\relax\relax\relax\relax\relax% + \fi% + \fi% +% \end{macrocode} +% +% Close the vbox we opened. +% +% \begin{macrocode} + \egroup% +% \end{macrocode} +% +% Finally, we leave a gap before the next structure. +% +% \begin{macrocode} + \endgroup\sd@gap\sdmidskip% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sd@loop} +% +% This macro handles the |\\| command within a loop environment. We close +% the current box, and start filling in box~1. We also redefine |\\| to +% raise an error when the |\\| command is used again. +% +% \begin{macrocode} +\def\sd@loop{% + \egroup% + \def\\{\sd@err{Too many \string\\\space commands in loop}\@ehc}% + \setbox\tw@\hbox\bgroup\strut% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sd@doloop} +% +% This is the macro which actually creates the |\halign| for the loop. It +% is called with four arguments, as: +% \begin{quote}\synshorts +% "\\sd@doloop{"<top-box>"}{"<bottom-box>"}"^^A +% "{"<top-arrow>"}{"<btm-arrow>"}" \\ +% \hbox{}\quad "{"<top-left-arc>"}{"<top-right-arc>"}"^^A +% "{"<bottom-left-arc>"}{"<btm-right-arc>"}"^^A +% \kern-1in ^^A It may be overfull, but it looks OK to me ;-) +% \end{quote} +% +% The two \<box> arguments give the numbers of boxes to extract in the top +% and bottom rows of the alignment. The \<arrow> arguments specify +% characters to typeset at the end of the top and bottom rows for arrows. +% The various \<arc> arguments are commands which typeset arcs around the +% various parts of the items. +% +% We calculate the height and depth of the two boxes, and store them in +% \<dimen> registers, because the boxes are emptied before the right-hand +% rules are typeset. +% +% Actually, the two rows of the alignment are typeset in a different macro: +% we just pass the correct information on. +% +% \begin{macrocode} +\def\sd@doloop#1#2#3#4#5#6#7#8{% + \@tempdima\dp#1\relax% + \@tempdimb\ht#2\relax% + \offinterlineskip% + \ialign{% + ##\cr% + \ifsd@round% + \sd@doloop@i#1#3\sd@topcirc\@tempdima{#5}{#6}% + \sd@doloop@i#2#4\@tempdimb\sd@botcirc{#7}{#8}% + \else% + \sd@doloop@i#1#3\sd@upper\@tempdima{#5}{#6}% + \sd@doloop@i#2#4\@tempdimb\sd@lower{#7}{#8}% + \fi% + }% +} +% \end{macrocode} +% +% \end{macro} +% +% \begin{macro}{\sd@doloop@i} +% +% Here we do the actual job of typesetting the rows of a loop alignment. +% The four arguments are: +% \begin{quote}\synshorts +% "\\sd@doloop@i{"<box>"}{"<arrow>"}"^^A +% "{"<rule-height>"}{"<rule-depth>"}" \\ +% \hbox{}\quad "{"<left-arc>"}{"<right-arc>"}"^^A +% \end{quote} +% +% The arrow position is determined by the |\ifsd@backwards| flag. The rest +% is fairly simple. +% +% \begin{macrocode} +\def\sd@doloop@i#1#2#3#4#5#6{% + \ifsd@backwards#2\fi% + \kern-\tw@\sdrulewidth% + \vrule\@height#3\@depth#4\@width\tw@\sdrulewidth% + #5% + \sd@rule\hfill% + \sd@gap\sdtokskip% + \unhbox#1% + \sd@gap\sdtokskip% + \sd@rule\hfill% + #6% + \vrule\@height#3\@depth#4\@width\tw@\sdrulewidth% + \ifsd@backwards\else#2\fi% + \kern-\tw@\sdrulewidth% + \cr% +} +% \end{macrocode} +% +% \end{macro} +% +% \subsection{The end} +% +% Phew! That's all of it completed. I hope this collection of commands +% and environments is of some help to someone. +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \hfill Mark Wooding, \today +% +% \Finale +% +\endinput |