mdwtab.dtx 170 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447
  1. % \begin{meta-comment}
  2. %
  3. % $Id$
  4. %
  5. % Another rewrite of the tabular environment, and maths alignments
  6. %
  7. % (c) 1996 Mark Wooding
  8. %
  9. %----- Revision history -----------------------------------------------------
  10. %
  11. % $Log$
  12. % Revision 1.1 2000-07-13 09:10:21 michael
  13. % + Initial import
  14. %
  15. % Revision 1.1 1998/09/21 10:19:01 michael
  16. % Initial implementation
  17. %
  18. % Revision 1.8 1996/12/09 23:20:42 mdw
  19. % (\tab@setstrut): Fixed so that it uses \dimen\tw@ for the strut depth,
  20. % as advertised.
  21. %
  22. % Revision 1.7 1996/11/29 21:59:16 mdw
  23. % Fixed a little formatting mistake in a syntax diagram, and switched over
  24. % to the new syntax diagram commands on the grounds that they're slightly
  25. % less messy. Maybe.
  26. %
  27. % Revision 1.6 1996/11/19 20:54:33 mdw
  28. % Entered into RCS
  29. %
  30. %
  31. % \end{meta-comment}
  32. %
  33. % \begin{meta-comment} <general public licence>
  34. %%
  35. %% mdwtab package -- another rewrite of the tabular environment, etc.
  36. %% Copyright (c) 1996 Mark Wooding
  37. %%
  38. %% This program is free software; you can redistribute it and/or modify
  39. %% it under the terms of the GNU General Public License as published by
  40. %% the Free Software Foundation; either version 2 of the License, or
  41. %% (at your option) any later version.
  42. %%
  43. %% This program is distributed in the hope that it will be useful,
  44. %% but WITHOUT ANY WARRANTY; without even the implied warranty of
  45. %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  46. %% GNU General Public License for more details.
  47. %%
  48. %% You should have received a copy of the GNU General Public License
  49. %% along with this program; if not, write to the Free Software
  50. %% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  51. %%
  52. % \end{meta-comment}
  53. %
  54. % \begin{meta-comment} <Package preambles>
  55. %<+mdwtab>\NeedsTeXFormat{LaTeX2e}
  56. %<+mdwtab>\ProvidesPackage{mdwtab}
  57. %<+mdwtab> [1998/04/28 1.9 Table typesetting with style]
  58. %<+mathenv>\NeedsTeXFormat{LaTeX2e}
  59. %<+mathenv>\ProvidesPackage{mathenv}
  60. %<+mathenv> [1998/04/28 1.9 Various maths environments]
  61. % \end{meta-comment}
  62. %
  63. % \CheckSum{2758}
  64. %% \CharacterTable
  65. %% {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
  66. %% 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
  67. %% Digits \0\1\2\3\4\5\6\7\8\9
  68. %% Exclamation \! Double quote \" Hash (number) \#
  69. %% Dollar \$ Percent \% Ampersand \&
  70. %% Acute accent \' Left paren \( Right paren \)
  71. %% Asterisk \* Plus \+ Comma \,
  72. %% Minus \- Point \. Solidus \/
  73. %% Colon \: Semicolon \; Less than \<
  74. %% Equals \= Greater than \> Question mark \?
  75. %% Commercial at \@ Left bracket \[ Backslash \\
  76. %% Right bracket \] Circumflex \^ Underscore \_
  77. %% Grave accent \` Left brace \{ Vertical bar \|
  78. %% Right brace \} Tilde \~}
  79. %%
  80. %
  81. % \begin{meta-comment}
  82. %
  83. %<*driver>
  84. \input{mdwtools}
  85. \describespackage{mdwtab}
  86. \describespackage{mathenv}
  87. \addcontents{lot}{\listoftables}
  88. \mdwdoc
  89. %</driver>
  90. %
  91. % \end{meta-comment}
  92. %
  93. %^^A-------------------------------------------------------------------------
  94. % \renewcommand{\tabstyle}{\small}
  95. %
  96. % \section{User guide}
  97. %
  98. %
  99. % The \package{mdwtab} package contains a reimplementation of the standard
  100. % \LaTeX\ \env{tabular} and \env{array} environments. This is not just an
  101. % upgraded version: it's a complete rewrite. It has several advantages over
  102. % the official \package{array} package (not raw \LaTeX's, which is even less
  103. % nice), and it's more-or-less compatible. Most of these are rather
  104. % technical, I'll admit.
  105. %
  106. % \begin{itemize}
  107. %
  108. % \item The newcolumn system is properly and perfectly integrated into the
  109. % system. There are now \emph{no} `primitive' column types -- all the
  110. % standard types are created as user-defined columns.
  111. %
  112. % \item You can define entirely different table-like environments using the
  113. % equipment here. It's still hard work, although less so than before.
  114. % I'll do an example of this some time.
  115. %
  116. % \item Construction of the preamble is generally much tidier. I've used
  117. % token registers rather than |\edef|, and it's all done very nicely.
  118. %
  119. % \item Fine spacing before and after rules (described by DEK as `a mark of
  120. % quality') is now utterly trivial, since the preamble-generator will
  121. % store the appropriate information.
  122. %
  123. % \item You can use \env{array} in LR and paragraph modes without having
  124. % to surround it with `|$|' signs.
  125. %
  126. % \item Usually you don't want tables in the middle of paragraphs. For these
  127. % cases, I've provided a simpler way to position the table
  128. % horizontally.
  129. %
  130. % \item Footnotes work properly inside \env{tabular} environments (hoorah!).
  131. % You can `catch' footnotes using the \env{minipage} environment if
  132. % you like. (It uses an internal version of the \package{footnote}
  133. % package to handle footnotes, which doesn't provide extra goodies like
  134. % the \env{footnote} environment; you'll need to load the full package
  135. % explicitly to get them.)
  136. %
  137. % \item Standard \LaTeX\ tabular environments have a problem with lining up
  138. % ruled tables. The |\firsthline| command given in the \textit{\LaTeX\
  139. % Companion} helps a bit, but it's not really good enough, and besides,
  140. % it doesn't \emph{actually} line the text up right after all. The
  141. % \package{mdwtab} package does the job properly to begin with, so you
  142. % don't need to worry.
  143. %
  144. % \end{itemize}
  145. %
  146. % I've tested the following packages with \package{mdwtab}, and they all
  147. % work. Some of the contortions required to make them work weren't pleasant,
  148. % but you don't need to know about them. By a strange coincidence, all the
  149. % packages were written by David Carlisle. Anyway, here's the list:
  150. % \begin{itemize}
  151. % \item The quite nice \package{dcolumn} package.
  152. % \item The more useful \package{delarray} package.
  153. % \item The rather spiffy \package{hhline} package.
  154. % \item The truly wonderful \package{tabularx} package.
  155. % \item The utterly magnificent \package{longtable} package.
  156. % \end{itemize}
  157. %
  158. % Note that I've looked at \package{supertabular} as well: it won't work, so
  159. % use \package{longtable} instead, 'cos it's much better.
  160. %
  161. %
  162. % \subsection{The downside}
  163. %
  164. % There's no such thing as a free lunch. The \package{mdwtab} environment
  165. % is not 100\% compatible with the \env{tabular} environment found in
  166. % \LaTeXe\ or the \package{array} package.
  167. %
  168. % The differences between \package{mdwtab} and \LaTeXe's \env{tabular}
  169. % environment are as follows:
  170. %
  171. % \begin{itemize} \synshorts \let\`=\lq
  172. %
  173. % \item The vertical spacing in \env{array} environments is different to
  174. % that in \env{tabular} environments. This produces more attractive
  175. % results in most mathematical uses of \env{array}s, in the author's
  176. % opinion. The spacing can be modified by playing with length
  177. % parameters.
  178. %
  179. % \item The presence of horizontal and vertical rules will alter the spacing
  180. % of the table (so a pair of columns separated by a `|' is wider than
  181. % a pair with no separation by "\\arrayrulewidth". This does mean that
  182. % horizontal and vertical rules match up properly -- the usual \LaTeX\
  183. % environment makes the horizontal rules stop just short of the edge
  184. % of the table, making an ugly mess (check out the \textit{\LaTeX\
  185. % book} if you don't believe me -- page~62 provides a good example).
  186. % The \package{array} package handles rules in the same way as
  187. % \package{mdwtab}.
  188. %
  189. % \setbox0=\hbox{\footnotesize`\\def\\xcs{\\tabskip=\\fill}'}
  190. % \setbox2=\hbox{\footnotesize`...@{\\span\\xcs}...'}
  191. % \item In common with the \package{array} package, there are some
  192. % restrictions on the use of the "\\extracolsep" command in preambles:
  193. % you may use at most one "\\extracolsep" command in each `@' or `!'
  194. % expression. Also, you can't say
  195. % \begin{listing}
  196. %\newcommand{\xcs}{\extracolsep{\fill}}
  197. % \end{listing}
  198. % and then expect something like `...@{\\xcs}...' to actually work --
  199. % the "\\extracolsep" mustn't be hidden inside any other
  200. % commands. Because things like `@' expressions aren't expanded at
  201. % the time, "\\extracolsep" has to be searched and processed
  202. % \`by hand'.\footnote{^^A
  203. % All \cs{extracolsep} does is modify the \cs{tabskip} glue, so
  204. % if you were an evil \TeX\ hacker like me, you could just say
  205. % \unhbox0\ and put \unhbox2\ in your preamble. That'd work nicely.
  206. % It also works with the \package{array} package.}
  207. %
  208. % \item Control sequences (commands) in a table's preamble aren't expanded
  209. % before the preamble is read. In fact, commands in the preamble are
  210. % considered to be column types, and their names are entirely
  211. % independent of normal \LaTeX\ commands. No column types of this
  212. % nature have yet been defined\footnote{^^A
  213. % There used to be an internal \cs{@magic} type used by
  214. % \env{eqnarray}, but you're not supposed to know about that.
  215. % Besides, it's not there any more.}
  216. % but the possibility's always there. Use the "\\newcolumntype" or
  217. % "\\coldef" commands to define new column types.
  218. %
  219. % \item The preamble parsing works in a completely different way. There is
  220. % a certain amount of compatibility provided, although it's heavily
  221. % geared towards keeping \package{longtable} happy and probably won't
  222. % work with other packages.
  223. %
  224. % \item Obscure constructs which were allowed by the old preamble parser but
  225. % violate the syntax shown in the next section (e.g., `|@{}|' to
  226. % suppress the "\\doublerulesep" space between two vertical rules,
  227. % described in \textit{The \LaTeX\ Companion} as \`a misuse of the
  228. % `@{...}' qualifier') are now properly outlawed. You will be given
  229. % an error message if you attempt to use such a construction.
  230. %
  231. % \item The `*' forms (which repeat column types) are now expanded at a
  232. % different time. Previously, preambles like `c@*{4}{{:}@}{--}c'
  233. % were considered valid (the example would expand to
  234. % `c@{:}@{:}@{:}@{:}@{--}c'), because `*'s were expanded before the
  235. % preamble was actually parsed. In the new system, `*' is treated
  236. % just like any other preamble character (it just has a rather odd
  237. % action), and preambles like this will result in an error (and
  238. % probably a rather confusing one).
  239. %
  240. % \end{itemize}
  241. %
  242. % There are also several incompatibilities between \package{mdwtab} and
  243. % \package{array}:
  244. %
  245. % \begin{itemize} \synshorts \let\`=\lq
  246. %
  247. % \item Because of the way "\\newcolumntype" works in the \package{array}
  248. % package, a horrid construction like
  249. % \begin{listing}
  250. %\newcolumntype{x}{{:}}
  251. %\begin{tabular}{|c!xc|}
  252. % \end{listing}
  253. % is considered to be valid, and is interpreted as `|c!{:}c|'. My
  254. % reading of pages~54 and~55 of the \textit{\LaTeX\ book} tells me
  255. % that this sort of thing is forbidden in normal \LaTeX\ commands.
  256. % The \package{mdwtab} preamble parser now treats column type letters
  257. % much more like commands with the result that the hacking above won't
  258. % work any more. The construction above would actually be interpreted
  259. % as `|c!{x}c|' (i.e., the `x' column type wouldn't be expanded to
  260. % `{:}' because the parser noticed that it was the argument to the
  261. % `!' modifier\footnote{^^A
  262. % This is a direct result of the way \TeX\ treats undelimited
  263. % arguments. See chapters~5 and~20 of \textit{The \TeX book} for
  264. % more information about how grouping affects argument reading.}).
  265. %
  266. % \item Most of the points above, particularly those relating to the
  267. % handling of the preamble, also apply to the \package{array} package.
  268. % it's not such an advance over the \LaTeXe\ version as everyone said
  269. % it was.
  270. %
  271. % \end{itemize}
  272. %
  273. %
  274. % \subsection{Syntax}
  275. %
  276. % \DescribeEnv{tabular}
  277. % \DescribeEnv{tabular*}
  278. % \DescribeEnv{array}
  279. % So that everyone knows where I stand, here's a complete syntax for my
  280. % version of the \env{tabular} environment, and friends
  281. %
  282. % \begin{grammar}
  283. %
  284. % <tabular-env> ::= \[[
  285. % "\\begin"
  286. % \begin{stack}
  287. % "{tabular}" \\ "{tabular*}" "{" <length> "}" \\
  288. % "{array}" \\ "{smarray}"
  289. % \end{stack}
  290. % \[ "[" <position-arg> "]" \]
  291. % "{" <preamble> "}" <text>
  292. % "\\end"
  293. % \( "{tabular}" \\ "{tabular*}" \\ "{array}" \\ "{smarray}" \)
  294. % \]]
  295. %
  296. % <position-arg> ::= (see below)
  297. %
  298. % <preamble> ::= \[[
  299. % <first-column>
  300. % \[ \< <column> \> \]
  301. % \]]
  302. %
  303. % <first-column> ::= \[[ \[ <rule> \] <column> \]]
  304. %
  305. % <column> ::= \[[
  306. % \[ <spacing> \] \[ \< <user-pre-text> \> \] <column-type>
  307. % \[ \< <user-post-text> \> \] \[ <spacing> \] \[ <rule> \]
  308. % \]]
  309. %
  310. % <spacing> ::= \[[ "@" "{" <text> "}" \]]
  311. %
  312. % <user-pre-text> ::= \[[ ">" "{" <text> "}" \]]
  313. %
  314. % <column-type> ::= \[[
  315. % \begin{stack}
  316. % \[ "T" \\ "M" \] \( "l" \\ "c" \\ "r" \) \\
  317. % \( "p" \\ "m" \\ "b" \) "{" <length> "}" \\
  318. % "#" "{" <raw-pre-text> "}" "{" <raw-post-text> "}"
  319. % \end{stack}
  320. % \]]
  321. %
  322. % <user-post-text> ::= \[[ "<" "{" <text> "}" \]]
  323. %
  324. % <rule> ::= \[[ \( "|" \\ "!" "{" <text> "}" \) \]]
  325. %
  326. % \end{grammar}
  327. %
  328. % If you examine the above very carefully, you'll notice a slight deviation
  329. % from the original -- an |@|-expression \emph{following} a rule is
  330. % considered to be part of the \emph{next} column, not the current one. This
  331. % is, I think, an almost insignificant change, and essential for some of the
  332. % new features. You'll also notice the new |#| column type form, which
  333. % allows you to define new real column types instead of just modifying
  334. % existing ones. It's not intended for direct use in preambles -- it's
  335. % there mainly for the benefit of people who know what they're doing and
  336. % insist on using |\newcolumntype| anyway.
  337. %%
  338. % The actual column types are shown in table~\ref{tbl:columns}.
  339. %
  340. % \begin{table}
  341. % \begin{tabular}[C]{| >{\synshorts} c | m{3in} |} \hlx{hv[1]}
  342. %
  343. % \multicolumn{2}{|c|}{\bf Column types} \\ \hlx{v[1]hv}
  344. % \bf Name & \bf Meaning \\ \hlx{vhv.}
  345. % "l" & Left aligned text (\env{tabular}) or
  346. % equation (\env{array}). \\ \hlx{.}
  347. % "c" & Centred text (\env{tabular}) or
  348. % equation (\env{array}). \\ \hlx{.}
  349. % "r" & Right aligned text (\env{tabular}) or
  350. % equation (\env{array}). \\ \hlx{vhv.}
  351. % "Ml", "Mc" and "Mr" & Left, centre and right aligned
  352. % equations.* \\ \hlx{.}
  353. % "Tl", "Tc" and "Tr" & Left, centre and right aligned
  354. % text.* \\ \hlx{vhv.}
  355. % "p{"<width>"}" & Top aligned paragraph with the given
  356. % width. \\ \hlx{.}
  357. % "m{"<width>"}" & Vertically centred paragraph with
  358. % the given width. \\ \hlx{.}
  359. % "b{"<width>"}" & Bottom aligned paragraph with the
  360. % given width. \\ \hlx{vhv.}
  361. % "#{"<pre>"}{"<post>"}" & User defined column type:
  362. % \<pre> is inserted before the
  363. % cell entry, \<post> is inserted
  364. % afterwards.* \\ \hlx{vhhv[1]}
  365. %
  366. % \multicolumn{2}{|c|}{\bf Other modifier characters} \\ \hlx{v[1]hv}
  367. % \bf Name & \bf Meaning \\ \hlx{vhv.}
  368. % "|" & Inserts a vertical rule between
  369. % columns. \\ \hlx{.}
  370. % "!{"<text>"}" & Inserts \<text> between columns,
  371. % treating it as a vertical rule. \\ \hlx{vhv.}
  372. % "@{"<text>"}" & Inserts \<text> instead of the
  373. % usual intercolumn space. \\ \hlx{vhv.}
  374. % ">{"<text>"}" & Inserts \<text> just before the
  375. % actual column entry. \\ \hlx{.}
  376. % "<{"<text>"}" & Inserts \<text> just after the
  377. % actual column entry. \\ \hlx{vhv.}
  378. % "*{"<count>"}{"<chars>"}" & Inserts \<count>
  379. % copies of the \<chars> into the
  380. % preamble. \\ \hlx{vhs}
  381. %
  382. % \multicolumn{2}{@{}l}{* This column type is a new feature}
  383. % \end{tabular}
  384. %
  385. % \caption{\package{array} and \package{tabular} column types and modifiers}
  386. % \label{tbl:columns}
  387. % \end{table}
  388. %
  389. % Now that's sorted everything out, there shouldn't be any arguments at all
  390. % about what a column means.
  391. %
  392. % The lowercase \<position-arg>s \lit{t}, \lit{c} and \lit{b} do exactly
  393. % what they did before: control the vertical positioning of the table. The
  394. % uppercase ones control the \emph{horizontal} positioning -- this is how you
  395. % create \emph{unboxed} tables. You can only create unboxed tables in
  396. % paragraph mode.
  397. %
  398. % Note that unboxed tables still can't be broken across pages. Use
  399. % the \package{longtable} package for this, because it already does an
  400. % excellent job.
  401. %
  402. % \DescribeMacro{\tabpause}
  403. % One thing you can to with unboxed tables, however, is to `interrupt' them,
  404. % do some normal typesetting, and then continue. This is achieved by the
  405. % |\tabpause| command: its argument is written out in paragraph mode, and
  406. % the table is continued after the argument finishes.
  407. % Note that it isn't a real argument as far as commands like |\verb| are
  408. % concerned -- they'll work inside |\tabpause| without any problems.
  409. %
  410. % \DescribeMacro{\vline}
  411. % The |\vline| command draws a vertical rule the height of the current table
  412. % cell (unless the current cell is being typeset in paragraph mode -- it
  413. % only works in the simple LR-mode table cells, or in \lit{@} or \lit{!}
  414. % modifiers). It's now been given an optional argument which gives the
  415. % width of the rule to draw:
  416. %
  417. % { \let\tabstyle=\relax
  418. % \begin{demo}{An example of \cmd\vline}
  419. %\large
  420. %\begin{tabular}
  421. % {| c !{\vline[2pt]} c | c |}
  422. % \hlx{hv}
  423. % \bf A & \it B & \sf C \\
  424. % \hlx{vhv}
  425. % \bf D & \it E & \sf F \\
  426. % \hlx{vh}
  427. %\end{tabular}
  428. % \end{demo}
  429. % }
  430. %
  431. % \DescribeMacro{smarray}
  432. % You've probably noticed that there's an unfamiliar environment mentioned
  433. % in the syntax shown above. The \env{smarray} environment produces a
  434. % `small' array, with script size cells rather than the normal full text
  435. % size cells. I've seen examples of this sort of construction\footnote{^^A
  436. % There's a nasty use of \env{smallmatrix} in the |testmath.tex| file which
  437. % comes with the \package{amslatex} distribution. It's actually there to
  438. % simulate a `smallcases' environment, which the \package{mathenv} package
  439. % includes, based around \env{smarray}.}
  440. % being implemented by totally unsuitable commands. Someone may find it
  441. % handy.
  442. %
  443. %
  444. % \subsection{An updated \cs{cline} command}
  445. %
  446. % \DescribeMacro{\cline}
  447. % The standard \LaTeX\ |\cline| command has been updated. As well as just
  448. % passing a range of columns to draw lines through, you can now pass a comma
  449. % separated list of column numbers and ranges:
  450. %
  451. % \begin{grammar}
  452. % <cline-cmd> ::= \[[
  453. % "\\cline" "{" \< <number> \[ "-" <number> \] \\ "," \> "}"
  454. % \]]
  455. % \end{grammar}
  456. %
  457. % The positioning of the horizontal lines has also been improved a bit, so
  458. % that they meet up with the vertical lines properly. Displays like the one
  459. % in the example below don't look good unless this has been done properly.
  460. %
  461. % {\let\tabstyle\relax
  462. % \begin{demo}[w]{A \cs{cline} example}
  463. %\newcommand{\mc}{\multicolumn{1}}
  464. %\begin{tabular}[C]{|c|c|c|c|} \cline{2,4}
  465. % \mc{c|}{one} & two & three & four \\ \hline
  466. % five & six & seven & \mc{c}{eight} \\ \cline{1,3}
  467. %\end{tabular}
  468. % \end{demo}
  469. % }
  470. %
  471. % \subsection{Spacing control}
  472. %
  473. % One of the most irritating things about \LaTeX's tables is that there isn't
  474. % enough space around horizontal rules. Donald Knuth, in \textit{The
  475. % \TeX book}, describes addition of some extra vertical space here as `a mark
  476. % of quality', and since \TeX\ was designed to produce `beautiful documents'
  477. % it seems a shame that \LaTeX\ doesn't allow this to be done nicely. Well,
  478. % it does now.
  479. %
  480. % \DescribeMacro{\vgap}
  481. % The extra vertical space is added using a command |\vgap|, with the
  482. % following syntax:
  483. %
  484. % \begin{grammar}
  485. %
  486. % <vgap-cmd> ::= \[[
  487. % "\\vgap" \[ "[" <which-cols> "]" \] "{" <length> "}"
  488. % \]]
  489. %
  490. % <which-cols> ::= \[[ \< <number> \[ "-" <number> \] \\ "," \> \]]
  491. %
  492. % \end{grammar}
  493. %
  494. % This command must appear either immediately after the beginning of the
  495. % table or immediately after the |\\| which ends a row. (Actually, there are
  496. % other commands which also have this requirement -- you can specify a
  497. % collection of them wherever you're allowed to give any one.) It adds some
  498. % vertical space (the amount is given by the \<length>) to the table,
  499. % making sure that the vertical rules of the table are extended correctly.
  500. %
  501. % The |\vgap| command relies on information stored while your table preamble
  502. % is being examined. However, it's possible that you might not want some
  503. % of the rules drawn (e.g., if you've used |\multicolumn|). The optional
  504. % \<which-cols> argument allows you to specify which rules are \emph{not}
  505. % to be drawn. You can specify either single column numbers or ranges. The
  506. % rule at the very left hand side is given the number~0; the rules at the
  507. % end of column~$n$ are numbered~$n$. It's easy really.
  508. %
  509. % \DescribeMacro{\hlx}
  510. % Using |\vgap| is all very well, but it's a bit cumbersome, and takes up a
  511. % lot of typing, especially when combined with |\hline| commands. The |\hlx|
  512. % command tries to tidy things.
  513. %
  514. % The syntax is simple:
  515. % \begin{grammar}
  516. %
  517. % <hlx-cmd> ::= \[[
  518. % "\\hlx" "{"
  519. % \begin{rep}
  520. % \begin{stack}
  521. % "h" \\
  522. % \tok{"v["<which-cols>"]["<length>"]"} \\
  523. % \tok{"s["<length>"]"} \\
  524. % \tok{"c{"<which-cols>"}"} \\
  525. % "b" \\
  526. % \tok{"/["<number>"]"} \\
  527. % "."
  528. % \end{stack}
  529. % \end{rep}
  530. % "}"
  531. % \]]
  532. %
  533. % \end{grammar}
  534. % The argument works a bit like a table preamble, really. Each letter is a
  535. % command. The following are supported:
  536. %
  537. % \begin{description}
  538. %
  539. % \item [\lit*{h}] Works just like |\hline|. If you put two adjacent to each
  540. % other, a gap will be put between them.
  541. %
  542. % \item [\lit*{v[}\<which-cols>\lit*{][}\<length>\lit*{]}] Works
  543. % like \syntax{"\\vgap["<which-cols>"]{"<length>"}"}. If the
  544. % \<length> is omitted, the value of |\doublerulesep| is used.
  545. % This usually looks right.
  546. %
  547. % \item [\lit*{s[}\<length>\lit*{]}] Leaves a vertical gap with the
  548. % given size. If you omit the \<length> then |\doublerulesep| is
  549. % used. This is usually right.
  550. %
  551. % \item [\lit*{c\char`\{}\<which-cols>\lit*{\char`\}}] Works just like
  552. % |\cline|.
  553. %
  554. % \item [\lit*{b}] Inserts a backspace the width of a rule. This is useful
  555. % when doing \package{longtable}s.
  556. %
  557. % \item [\lit*{/[}\<number>\lit*{]}] Allows a page break in a table. Don't
  558. % use this except in a \env{longtable} environment. The \<number>
  559. % works exactly the same as it does in the |\pagebreak| command,
  560. % except that the default is 0, which just permits a break without
  561. % forcing it.
  562. %
  563. % \item [\lit*{.}] (That's a dot) Starts the next row of the table. No
  564. % more characters may follow the dot, and no |\hline|, |\hlx|, |\vgap|
  565. % or |\multicolumn| commands may be used after it. You don't have to
  566. % include it, and most of the time it's totally useless. It can be
  567. % handy for some macros, though. I used it in (and in fact added it
  568. % especially for) the table of column types.
  569. %
  570. % \end{description}
  571. %
  572. % An example of the use of |\hlx| is given, so you can see what's going on.
  573. %
  574. % \begin{figure}
  575. % \let\tabstyle\relax
  576. % \begin{demo}[w]{Beautiful table example}
  577. %\newcommand{\zerowidth}[1]{\hbox to 0pt{\hss#1\hss}}
  578. %\setlength{\tabcolsep}{1.5em}
  579. %\begin{tabular}[C]{| r | c | r |} \hlx{hv[1,2]}
  580. % \multicolumn{3}{|c|}{\bf AT\&T Common Stock} \\ \hlx{v[1,2]hv}
  581. % \multicolumn{1}{|c|}{\zerowidth{\bf Year}} &
  582. % \multicolumn{1}{c|}{\zerowidth{\bf Price}} &
  583. % \multicolumn{1}{c|}{\zerowidth{\bf Dividend}} \\ \hlx{vhv}
  584. % 1971 & 41--54 & \$2.60 \\
  585. % 2 & 41--54 & 2.70 \\
  586. % 3 & 46--55 & 2.87 \\
  587. % 4 & 40--53 & 3.24 \\
  588. % 5 & 45--52 & 3.40 \\
  589. % 6 & 51--59 & .95\rlap{*} \\ \hlx{vhs}
  590. % \multicolumn{3}{@{}l}{* (first quarter only)}
  591. %\end{tabular}
  592. % \end{demo}
  593. % \end{figure}
  594. %
  595. %
  596. % \subsection{Creating beautiful long tables}
  597. %
  598. % You can use the |\vgap| and |\hlx| commands with David Carlisle's
  599. % stunning \package{longtable} package. However, there are some things you
  600. % should be away of to ensure that your tables always come out looking
  601. % lovely.
  602. %
  603. % The \package{longtable} package will break a table at an |\hline| command,
  604. % leaving a rule at the bottom of the page and another at the top of the
  605. % next page. This means that a constructions like |\hlx{vhv}| will be
  606. % broken into something like |\hlx{vh}| at the bottom of the page and
  607. % |\hlx{hv}| at the top of the next. You need to design the table headers
  608. % and footers with this in mind.
  609. %
  610. % However, there appears to be a slight problem:\footnote
  611. % {You might very well call it a bug. I couldn't possibly comment.}
  612. % if the footer starts with an |\hline|, and a page is broken at an |\hline|,
  613. % then you get an extra thick rule at the bottom of the page. This is a bit
  614. % of a problem, because if the rule isn't there in the footer and you get
  615. % a break between two rows \emph{without} a rule between them, then the page
  616. % looks very odd.
  617. %
  618. % If you want to do ruled longtables, I'd recommend that you proceed as
  619. % follows:
  620. % \begin{itemize}
  621. % \item End header sections with an |\hlx{vh}|.
  622. % \item Begin footer sections with an |\hlx{bh}|.
  623. % \item Begin the main table with |\hlx{v}|.
  624. % \item Insert |\hlx{vhv}| commands in the main table body as usual.
  625. % \end{itemize}
  626. % If \package{longtable} gets modified appropriately, the use of the \lit{b}
  627. % command won't be necessary.
  628. %
  629. % Here's an example of the sort of thing you'd type.
  630. %
  631. % \begin{listinglist} \listingsize
  632. % \verb"\begin{longtable}[c]{|c|l|} \hlx{hv}" \\
  633. % \verb"\bf Heading & \bf Also heading \\ \hlx{vh}" \\
  634. % \verb"\endhead" \\
  635. % \verb"\hlx{bh}" \\
  636. % \verb"\endfoot" \\
  637. % \verb"\hlx{v}" \\
  638. % \verb"First main & table line \\ \hlx{vhv}" \\
  639. % \verb"Lots of text & like this \\ \hlx{vhv}" \\
  640. % \null\quad\vdots \\
  641. % \verb"Lots of text & like this \\ \hlx{vhv}" \\
  642. % \verb"Last main & table line \\ \hlx{vh}" \\
  643. % \verb"\end{longtable}"
  644. % \end{listinglist}
  645. %
  646. %
  647. % \subsection{Rules and vertical positioning}
  648. %
  649. % In the \LaTeXe\ and \package{array.sty} versions of \env{tabular}, you run
  650. % into problems if you try to use ruled tables together with the \lit{[t]} or
  651. % \lit{[b]} position specifiers -- the top or bottom rule ends up being
  652. % nicely lined up with the text baseline, giving you an effect which is
  653. % nothing like the one you expected. The \textit{\LaTeX\ Companion} gives
  654. % two commands |\firsthline| and |\lasthline| which are supposed to help with
  655. % this problem. (These commands have since migrated into the \package{array}
  656. % package.) Unfortunately, |\firsthline| doesn't do its job properly --
  657. % it gets the text position wrong by exactly the width of the table rules.
  658. %
  659. % The \package{mdwtab} package makes all of this automatic. It gets the
  660. % baseline positions exactly right, whether or not you use rules. Earlier
  661. % versions of this package required that you play with a length parameter
  662. % called |\rulefudge|; this is no longer necessary (or even possible -- the
  663. % length parameter no longer exists). The package now correctly compensates
  664. % for all sorts of rules and |\vgap|s at the top and bottom of a table and
  665. % it gets the positioning right all by itself. You've never had it so good.
  666. %
  667. %
  668. % \subsection{User serviceable parts}
  669. %
  670. % There are a lot of parameters which you can modify in order to make arrays
  671. % and tables look nicer. They are all listed in table~\ref{tbl:config}.
  672. %
  673. % \begin{table}
  674. % \begin{tabular}[C]{| l | m{3in} |} \hlx{hv}
  675. % \bf Parameter & \bf Meaning \\ \hlx{vhv}
  676. % |\tabstyle| & A command executed at the beginning of
  677. % a \env{tabular} or \env{tabular$*$}
  678. % environment. By default does nothing.
  679. % Change using |\renewcommand|. \\ \hlx{vhv}
  680. % |\extrarowheight| & A length added to the height of every
  681. % row, used to stop table rules
  682. % overprinting ascenders. Default 0\,pt.
  683. % Usage is deprecated now: use |\hlx|
  684. % instead. \\ \hlx{vhv}
  685. % |\tabextrasep| & Extra space added between rows in a
  686. % \env{tabular} or \env{tabular$*$}
  687. % environment (added \emph{before} any
  688. % following |\hline|). Default 0\,pt. \\
  689. % |\arrayextrasep| & Analogous to |\tabextrasep|, but for
  690. % \env{array} environments. Default
  691. % 1\,jot (3\,pt). \\
  692. % |\smarrayextrasep| & Analogous to |\tabextrasep|, but for
  693. % \env{smarray} environments. Default
  694. % 1\,pt. \\ \hlx{vhv}
  695. % |\tabcolsep| & Space added by default on each side of
  696. % a table cell (unless suppressed by an
  697. % \lit{@}-expression) in \env{tabular}
  698. % environments. Default is defined by
  699. % your document class. \\
  700. % |\arraycolsep| & Analogous to |\tabcolsep|, but for
  701. % \env{array} environments. Default is
  702. % defined by your document class. \\
  703. % |\smarraycolsep| & Analogous to |\tabcolsep|, but for
  704. % \env{smarray} environments. Default
  705. % is 3\,pt. \\ \hlx{vhv}
  706. % |\arrayrulewidth| & The width of horizontal and vertical
  707. % rules in tables. \\
  708. % |\doublerulesep| & Space added between two adjacent
  709. % vertical or horizontal rules. Also
  710. % used by |\hlx{v}|. \\ \hlx{vhv}
  711. % |\arraystretch| & Command containing a factor to
  712. % multiply the default row height.
  713. % Default is defined by your document
  714. % class (usually 1). \\ \hlx{vh}
  715. % \end{tabular}
  716. %
  717. % \caption{Parameters for configuring table environments}
  718. % \label{tbl:config}
  719. %
  720. % \end{table}
  721. %
  722. %
  723. % \subsection{Defining column types}
  724. %
  725. % \DescribeMacro{\newcolumntype}
  726. % The easy way to define new column types is using |\newcolumntype|. It
  727. % works in more or less the same way as |\newcommand|:
  728. %
  729. % \begin{grammar}
  730. %
  731. % <new-col-type-cmd> ::= \[[
  732. % "\\newcolumntype"
  733. % "{" <column-name> "}"
  734. % \[ "[" <num-args> "]" \]
  735. % \[ "[" <default-arg> "]" \]
  736. % "{" <first-column> \[ \< <column> \> \] "}"
  737. % \]]
  738. %
  739. % \end{grammar}
  740. %
  741. % (The \env{array.sty} implementation doesn't accept the \<default-arg>
  742. % argument. I've no idea why not, 'cos it was very easy to implement.)
  743. %
  744. % \DescribeMacro{\colset}
  745. % This implementation allows you to define lots of different sets of columns.
  746. % You can change the current set using the |\colset| declaration:
  747. % \begin{grammar}
  748. % <colset-cmd> ::= \[[ "\\colset" "{" <set-name> "}" \]]
  749. % \end{grammar}
  750. % This leaves a problem, though: at any particular moment, the current
  751. % column set could be anything, since other macros and packages can change
  752. % it.
  753. %
  754. % \DescribeMacro{\colpush}
  755. % \DescribeMacro{\colpop}
  756. % What actually happens is that a stack of column sets is maintained. The
  757. % |\colset| command just replaces the item at the top of the stack. The
  758. % command |\colpush| pushes its argument onto the top of the stack, making
  759. % it the new current set. The corresponding |\colpop| macro (which doesn't
  760. % take any arguments) removes the top item from the stack, reinstating the
  761. % previous current column set.
  762. %
  763. % \begin{grammar}
  764. % <colpush-cmd> ::= \[[ "\\colpush" "{" <set-name> "}" \]]
  765. % <colpop-cmd> ::= \[[ "\\colpop" \]]
  766. % \end{grammar}
  767. %
  768. % The macros which manipulate the column set stack work \emph{locally}.
  769. % The contents of the stack are saved when you open a new group.
  770. %
  771. % To make sure everyone behaves themselves properly, these are the rules for
  772. % using the column set stack:
  773. %
  774. % \begin{itemize}
  775. %
  776. % \item Packages defining column types must ensure that they preserve the
  777. % current column set. Either they must push their own column type
  778. % and pop it off when they're finished defining columns, or they must
  779. % avoid changing the stack at all, and use the optional arguments to
  780. % |\coldef| and |\collet|.
  781. %
  782. % \item Packages must not assume that any particular column set is current
  783. % unless they have made sure of it themselves.
  784. %
  785. % \item Packages must ensure that they pop exactly as much as they push.
  786. % There isn't much policing of this (perhaps there should be more),
  787. % so authors are encouraged to behave responsibly.
  788. %
  789. % \item Packages must change the current column set (using |\colset|) when
  790. % they start up their table environment. This will be restored when
  791. % the environment closes.
  792. %
  793. % \end{itemize}
  794. %
  795. % \DescribeMacro{\coldef}
  796. % |\newcolumntype| is probably enough for most purposes. However, Real
  797. % \TeX nicians, and people writing new table-generating environments, require
  798. % something lower-level.
  799. %
  800. % \begin{grammar}
  801. % <coldef-cmd> ::= \[[
  802. % "\\coldef"
  803. % \[ "[" <set-name> "]" \]
  804. % <col-name> <arg-template> "{" <replacement-text> "}"
  805. % \]]
  806. % \end{grammar}
  807. %
  808. % Note that this defines a column type in the current colset. It works
  809. % almost exactly the same way as \TeX's primitive |\def|. There is a
  810. % potential gotcha here: a |\tab@mkpream| token is inserted at the end of
  811. % your replacement text. If you need to read an optional argument or
  812. % something, you'll need to gobble this token before you carry on. The
  813. % |\@firstoftwo| macro could be handy here:
  814. % \begin{listing}
  815. %\coldef x{\@firstoftwo{\@ifnextchar[\@xcolumn@i\@xcolumn@ii}}}
  816. % \end{listing}
  817. % This isn't a terribly pretty state of affairs, and I ought to do something
  818. % about it. I've not seen any use for an optional argument yet, though.
  819. % Note that if you do gobble the |\tab@mkpream|, it's your responsibility to
  820. % insert another one at the very end of your macro's expansion (so that
  821. % further preamble characters can be read).
  822. %
  823. % The replacement text is inserted directly. It's normal to insert preamble
  824. % elements here. There are several to choose from:
  825. %
  826. % \begin{description}
  827. %
  828. % \item [Column items] provide the main `meat' of a column. You insert a
  829. % column element by saying
  830. % \syntax{"\\tabcoltype{"<pre-text>"}{"<post-text>"}"}.
  831. % The user's text gets inserted between these two. (So do user pre-
  832. % and post-texts. Bear this in mind.)
  833. %
  834. % \item [User pre-text items] work like the \lit{>} preamble command. You
  835. % use the \syntax{"\\tabuserpretype{"<text>"}"} command to insert it.
  836. % User pre-texts are written in \emph{reverse} order between the
  837. % pre-text of the column item and the text from the table cell.
  838. %
  839. % \item [User post-text items] work like the \lit{<} preamble command. You
  840. % use the \syntax{"\\tabuserposttype{"<text>"}"} command to insert it.
  841. % Like user pre-texts, user post-texts are written in reverse order,
  842. % between the table cell text and the column item post-text.
  843. %
  844. % \item [Space items] work like the \lit{@} preamble command. They're
  845. % inserted with the \syntax{"\\tabspctype{"<text>"}"} command.
  846. %
  847. % \item [Rule items] work like the `\verb"|"' and \lit{!} commands. You
  848. % insert them with the \syntax{"\\tabruletype{"<text>"}"} command.
  849. % Note that the text is inserted by |\vgap| too, so it should contain
  850. % things which adjust their vertical size nicely. If you really need
  851. % to, you can test |\iftab@vgap| to see if you're in a |\vgap|.
  852. %
  853. % \end{description}
  854. %
  855. % \DescribeMacro{\collet}
  856. % As well as defining columns, you can copy definitions (rather like |\let|
  857. % allows you to copy macros). The syntax is like this:
  858. %
  859. % \begin{grammar}
  860. %
  861. % <collet-cmd> ::= \[[
  862. % \[ "[" <set-name> "]" \] <col-name> \[ "=" \] \[ "[" <set-name> "]" \]
  863. % <col-name>
  864. % \]]
  865. %
  866. % \end{grammar}
  867. %
  868. % (In other words, you can copy defintions from other column sets.)
  869. %
  870. %
  871. % \subsection{Defining new table-generating environments}
  872. %
  873. % Quite a few routines are provided specifically to help you to define new
  874. % environments which do alignment in a nice way.
  875. %
  876. % \subsubsection{Reading preambles}
  877. %
  878. % The main tricky bit in doing table-like environments is parsing preambles.
  879. % No longer.
  880. %
  881. % \DescribeMacro{\tab@readpreamble}
  882. % \DescribeMacro{\tab@doreadpream}
  883. % The main parser routine is called |\tab@doreadpream|. Given a user
  884. % preamble string as an argument, it will build an |\halign| preamble to
  885. % return to you. However, the preamble produced won't be complete. This is
  886. % because you can actually make multiple calls to |\tab@doreadpream| with
  887. % bits of user preambles. The |\newcolumntype| system uses this mechanism,
  888. % as does the \lit{*} (repeating) modifier. When there really is no more
  889. % preamble to read, you need to \emph{commit} the heldover tokens to the
  890. % output. The |\tab@readpreamble| routine will do this for you -- given a
  891. % user preamble, it builds a complete output from it.
  892. %
  893. % A token register |\tab@preamble| is used to store the generated preamble.
  894. % Before starting, you must iniitialise this token list to whatever you want.
  895. % There's another token register, |\tab@shortline|, which is used to store
  896. % tokens used by |\vgap|. For each column in the table, the list contains
  897. % an |\omit| (to override the standard preamble) and an |\hfil| space taking
  898. % up most of the column. Finally, for each rule item in the user preamble,
  899. % the shortline list contains an entry of the form:
  900. % \begin{quote} \synshorts
  901. % "\\tab@ckr{"<column-number>"}{"<rule-text>"}"
  902. % \end{quote}
  903. % This is used to decide whether to print the rule or an empty thing of the
  904. % same width. You probably ought to know that the very first column does
  905. % \emph{not} have a leading |\omit| -- this is supplied by |\vgap| so that
  906. % it can then look for optional arguments.
  907. %
  908. % \DescribeMacro{\tab@initread}
  909. % As well as initialising |\tab@preamble| and emptying |\tab@shortline|,
  910. % there are several other operations required to initialise a preamble read.
  911. % These are all performed by the |\tab@initread| macro, although you may want
  912. % to change some of the values for your specific application. For reference,
  913. % the actions performed are:
  914. % \begin{itemize}
  915. % \item initialising the parser state by setting $|\tab@state| =
  916. % |\tab@startstate|$;
  917. % \item clearing the token lists |\tab@preamble| and |\tab@shortlist|;
  918. % \item initialising the macros |\tab@tabtext|, |\tab@midtext|, and
  919. % |\tab@multicol| to their default values of `|&|',
  920. % `|\ignorespaces#\unskip|' and the empty token list respectively.^^A
  921. % \footnote{^^A
  922. % These are macros rather than token lists to avoid hogging all
  923. % the token list registers. Actually, the package only allocates
  924. % two, although it does use almost all of the temporary registers as
  925. % well. Also, there's a lie: \cs{unskip} is too hamfisted to remove
  926. % trailing spaces properly; I really use a macro called
  927. % \cs{@maybe@unskip}}
  928. % \item clearing the internal token list registers |\tab@pretext|,
  929. % |tab@userpretext| and |\tab@posttext|;
  930. % \item clearing the column counter |\tab@columns| to zero;
  931. % \item clearing the action performed when a new column is started (by making
  932. % the |\tab@looped| macro equal to |\relax|; this is used to make
  933. % |\multicolumn| macro raise an error if you try to do more than one
  934. % column); and
  935. % \item setting up some other switches used by the parser (|\iftab@rule|,
  936. % |\iftab@initrule| and |\iftab@firstcol|, all of which are set to be
  937. % |true|).
  938. % \end{itemize}
  939. %
  940. % The macro |\tab@multicol| is used by the |\multicolumn| command to insert
  941. % any necessary items (e.g., struts) before the actual column text. If you
  942. % set this to something non-empty, you should probably consider adding a
  943. % call to the macro to the beginning of |\tab@preamble|.
  944. %
  945. % When parsing is finally done, the count register |\tab@columns| contains
  946. % the number of columns in the alignment. Don't corrupt this value, because
  947. % it's used for handling |\hline| commands.
  948. %
  949. % \subsubsection{Starting new lines}
  950. %
  951. % The other messy bit required by table environments is the newline command
  952. % |\\|. There are nasty complications involved with starting new lines, some
  953. % of which can be handled by this package, and some on which I can only give
  954. % advice.
  955. %
  956. % \DescribeMacro{\tab@cr}
  957. % The optional arguments and star-forms etc. can be read fairly painlessly
  958. % using the |\tab@cr| command:
  959. %
  960. % \begin{grammar}
  961. % <tabcr-cmd> ::= \[[
  962. % "\\tab@cr" <command> "{" <non-star-text> "}" "{" <star-text> "}"
  963. % \]]
  964. % \end{grammar}
  965. %
  966. % This will call your \<command> with two arguments. The first is the
  967. % contents of the optional argument, or `|\z@|' if there wasn't one. The
  968. % second is either \<star-text> or \<non-star-text> depending on
  969. % whether the user wrote the $*$-form or not.
  970. %
  971. % Somewhere in your \<command>, you'll have to use the |\cr| primitive to
  972. % end the table row. After you've done this, you \emph{must} ensure that you
  973. % don't do anything that gets past \TeX's mouth without protecting it --
  974. % otherwise |\hline| and co.\ won't work. I usually wrap things up in a
  975. % |\noalign| to protect them, although there are other methods. Maybe.
  976. %
  977. % You might like to have a look at the \env{eqnarray} implementation provided
  978. % to see how all this gets put into practice.
  979. %
  980. %
  981. % \subsection{The \env{mathenv} package alignment environments}
  982. %
  983. % The \env{mathenv} package provides several environments for aligning
  984. % equations in various ways. They're mainly provided as a demonstration of
  985. % the table handling macros in \package{mdwtab}, so don't expect great
  986. % things. If you want truly beautiful mathematics, use
  987. % \package{amsmath}.\footnote{^^A
  988. % Particularly since nice commands like \cmd\over\ are being reactivated
  989. % in a later release of \package{amsmath}.}
  990. % However, the various environments do nest in an approximately useful way.
  991. % I also think that the \env{matrix} and \env{script} environments provided
  992. % here give better results than their \package{amsmath} equivalents, and
  993. % they are certainly more versatile.
  994. %
  995. % \subsubsection{The new \env{eqnarray} environment}
  996. %
  997. % \DescribeEnv{eqnarray}
  998. % \DescribeEnv{eqnarray*}
  999. % As an example of the new column defining features, and because the original
  1000. % isn't terribly good, I've included a rewritten version of the
  1001. % \env{eqnarray} environment. The new implementation closes the gap between
  1002. % \env{eqnarray} and \AmSTeX\ alignment features. It's in a separate,
  1003. % package called \package{mathenv}, to avoid wasting your memory.
  1004. %
  1005. % \begin{grammar}
  1006. %
  1007. % <eqnarray-env> ::= \[[
  1008. % <begin-eqnarray> \< <row> \\ "\\\\" \> <end-eqnarray>
  1009. % \]]
  1010. %
  1011. % <begin-eqnarray> ::= \[[
  1012. % "\\begin" \( "{eqnarray}" \\ "{eqnarray*}" \)
  1013. % \[ "[" \< <eqa-column> \> "]" \]
  1014. % \]]
  1015. %
  1016. % <eqa-column> ::= \[[
  1017. % \[ "q" \\ ":" \]
  1018. % \[ \< ">" "{" <pre-text> "}" \> \]
  1019. % \begin{stack}
  1020. % \[ "T" \] \( "r" \\ "c" \\ "l" \) \\
  1021. % "L" \\
  1022. % "x"
  1023. % \end{stack}
  1024. % \[ \< "<" "{" <post-text> "}" \> \]
  1025. % \]]
  1026. %
  1027. % <end-eqnarray> ::= \[[
  1028. % "\\end" \begin{stack} "{eqnarray}" \\ "{eqnarray*}" \end{stack}
  1029. % \]]
  1030. %
  1031. % \end{grammar}
  1032. %
  1033. % Descriptions of the various column types are given in
  1034. % table~\ref{tbl:eqnarray}.
  1035. %
  1036. % \begin{table}
  1037. % \begin{tabular}[C]{| >{\synshorts} c | m{3in} |} \hlx{hv[1]}
  1038. %
  1039. % \multicolumn{2}{|c|}{\bf Column types} \\ \hlx{v[1]hv}
  1040. % \bf Name & \bf Meaning \\ \hlx{vhv.}
  1041. % "l" & Left aligned piece of equation. \\ \hlx{.}
  1042. % "c" & Centred piece of equation. \\ \hlx{.}
  1043. % "x" & Centred or flush-left whole equation
  1044. % (depending on \textsf{fleqn} option). \\ \hlx{.}
  1045. % "r" & Right aligned piece of equation. \\ \hlx{vhv.}
  1046. % "L" & Left aligned piece of equation whose
  1047. % width is considered to be 2\,em. \\ \hlx{vhv.}
  1048. % "Tl", "Tc" and "Tr" & Left, centre and right aligned
  1049. % text. \\ \hlx{vhhv[1]}
  1050. %
  1051. % \multicolumn{2}{|c|}{\bf Other modifier characters} \\ \hlx{v[1]hv}
  1052. % \bf Name & \bf Meaning \\ \hlx{vhv.}
  1053. % ":" & Leaves a big gap between equations.
  1054. % By default, the `chunks' separated by
  1055. % \lit{:}s are equally spaced on the
  1056. % line. \\ \hlx{.}
  1057. % "q" & Inserts 1\,em of space \\ \hlx{vhv.}
  1058. % ">{"<text>"}" & Inserts \<text> just before the
  1059. % actual column entry. \\ \hlx{.}
  1060. % "<{"<text>"}" & Inserts \<text> just after the
  1061. % actual column entry. \\ \hlx{vhv.}
  1062. % "*{"<count>"}{"<chars>"}" & Inserts \<count>
  1063. % copies of the \<chars> into the
  1064. % preamble. \\ \hlx{vh}
  1065. % \end{tabular}
  1066. %
  1067. % \caption{\package{eqnarray} column types and modifiers}
  1068. % \label{tbl:eqnarray}
  1069. % \end{table}
  1070. %
  1071. % The default preamble, if you don't supply one of your own, is \lit{rcl}.
  1072. % Most of the time, \lit{rl} is sufficient, although compatibility is more
  1073. % important to me.
  1074. %
  1075. % By default, there is no space between columns, which makes formul\ae\ in an
  1076. % \env{eqnarray} environment look just like formul\ae\ typeset on their own,
  1077. % except that things get aligned in columns. This is where the default
  1078. % \env{eqnarray} falls down: it leaves |\arraycolsep| space between each
  1079. % column making the thing look horrible.
  1080. %
  1081. % An example would be good here, I think. This one's from exercise 22.9 of
  1082. % the \textit{\TeX book}.
  1083. %
  1084. % \begin{demo}[w]{Simultaneous equations}
  1085. %\begin{eqnarray}[*3{rc}rl]
  1086. % 10w & + & 3x & + & 3y & + & 18z & = 1 \\
  1087. % 6w & - & 17x & & & - & 5z & = 2
  1088. %\end{eqnarray}
  1089. % \end{demo}
  1090. %
  1091. % Choosing a more up-to-date example, here's some examples from the
  1092. % \textit{\LaTeX\ Companion}.
  1093. %
  1094. % \begin{demo}[w]{Lots of equations}
  1095. %\begin{eqnarray}[rl:rl:lq]
  1096. % V_i &= v_i - q_i v_j, & X_i &= x_i - q_i x_j, &
  1097. % U_i = u_i, \qquad \mbox{for $i \ne j$} \\
  1098. % V_j &= v_j, & X_j &= x_j &
  1099. % U_j u_j + \sum_{i \ne j} q_i u_i. \label{eq:A}
  1100. %\end{eqnarray}
  1101. % \end{demo}
  1102. %
  1103. % \begin{figure}
  1104. % \begin{demo}[w]{Plain text column and \cs{tabpause}}
  1105. %\begin{eqnarray}[rlqqTl]
  1106. % x &= y & by (\ref{eq:A}) \\
  1107. % x' &= y' & by definition \\
  1108. %\tabpause{and}
  1109. % x + x' &= y + y' & by Axiom~1
  1110. %\end{eqnarray}
  1111. % \end{demo}
  1112. % \end{figure}
  1113. %
  1114. % The new features also mean that you don't need to mess about with
  1115. % |\lefteqn| any more. This is handled by the \lit{L} column type:
  1116. %
  1117. % \begin{demo}{Splitting example}
  1118. %\begin{eqnarray*}[Ll]
  1119. % w+x+y+z = \\
  1120. % & a+b+c+d+e+ \\
  1121. % & f+g+h+i+j
  1122. %\end{eqnarray*}
  1123. % \end{demo}
  1124. %
  1125. % Finally, just to prove that the spacing's right at last, here's another one
  1126. % from the \textit{Companion}.
  1127. %
  1128. % \begin{demo}{Spacing demonstration}
  1129. %\begin{equation}
  1130. % x^2 + y^2 = z^2
  1131. %\end{equation}
  1132. %\begin{eqnarray}[rl]
  1133. % x^2 + y^2 &= z^2 \\
  1134. % y^2 &< z^2
  1135. %\end{eqnarray}
  1136. % \end{demo}
  1137. %
  1138. % Well, that was easy enough. Now on to numbering. As you've noticed, the
  1139. % equations above are numbered. You can use the \env{eqnarray$*$}
  1140. % environment to turn off the numbering in the whole environment, or say
  1141. % |\nonumber| on a line to suppress numbering of that one in particular.
  1142. %
  1143. % \DescribeMacro{\eqnumber}
  1144. % More excitingly, you can say |\eqnumber| to enable numbering for a
  1145. % particular equation, or \syntax{"\\eqnumber["<text>"]"} to choose what to
  1146. % show instead of the line number. This works for both starred and unstarred
  1147. % versions of the environment. Now |\nonumber| becomes merely a synonym for
  1148. % `|\eqnumber[]|'.
  1149. %
  1150. % A note for cheats: you can use the sparkly new \env{eqnarray} for simple
  1151. % equations by specifying \lit{x} as the column description. Who needs
  1152. % \AmSTeX?\ |;-)|
  1153. %
  1154. % \DescribeEnv{eqlines}
  1155. % \DescribeEnv{eqlines*}
  1156. % In fact, there's a separate environment \env{eqlines}, which is equivalent
  1157. % to \env{eqnarray} with a single \lit{x} column; the result is that you can
  1158. % insert a collection of displayed equations separated by |\\| commands. If
  1159. % you don't like numbering, use \env{eqlines$*$} insead.
  1160. %
  1161. % \subsubsection{The \env{eqnalign} environment}
  1162. %
  1163. % \DescribeEnv{eqnalign}
  1164. % There's a new environment, \env{eqnalign}, which does almost the same
  1165. % thing as \env{eqnarray} but not quite. It doesn't do equation numbers,
  1166. % and it wraps its contents up in a box. The result of this is that:
  1167. %
  1168. % \begin{itemize}
  1169. %
  1170. % \item You can use \env{eqnalign} for just a part of a formula.
  1171. % The \env{eqnarray} environment must take up the whole display.
  1172. %
  1173. % \item You can use \env{eqnalign} within \env{eqnarray} for extra fine
  1174. % alignment of subsidiary bits.
  1175. %
  1176. % \item You can break off from doing an \env{eqnarray} using the |\tabpause|
  1177. % command. You can't use |\tabpause| inside
  1178. % \env{eqnalign}.\footnote{^^A
  1179. % Well, technically speaking there's nothing to stop you. However,
  1180. % the results won't be pretty.}
  1181. %
  1182. % \end{itemize}
  1183. %
  1184. % The \env{eqnalign} environment works like this:
  1185. %
  1186. % \begin{grammar}
  1187. %
  1188. % <eqnalign-env> ::= \[[
  1189. % <begin-eqnalign> <contents> <end-eqnalign>
  1190. % \]]
  1191. %
  1192. % <begin-eqnalign> ::= \[[
  1193. % "\\begin" "{eqnalign}"
  1194. % \[ "[" \< <eqa-column> \> "]" \]
  1195. % \[ "[" \( "t" \\ "c" \\ "b" \) "]" \]
  1196. % \]]
  1197. %
  1198. % <end-eqnalign> ::= \[[ "\\end" "{eqnalign}" \]]
  1199. %
  1200. % \end{grammar}
  1201. %
  1202. % As the syntax suggests, the preamble for the \env{eqnalign} environment
  1203. % works exactly the same way as for \env{eqnarray}. Example time: another
  1204. % one from the \textit{\TeX book}.
  1205. %
  1206. % \begin{figure}
  1207. % \begin{demo}[w]{Example of \env{eqnalign}}
  1208. %\[
  1209. % \left\{ \begin{eqnalign}[rl]
  1210. % \alpha &= f(z) \\ \beta &= f(z^2) \\
  1211. % \gamma &= f(z^3)
  1212. % \end{eqnalign} \right\}
  1213. % \qquad
  1214. % \left\{ \begin{eqnalign}[rl]
  1215. % x &= \alpha^2 - \beta \\ y &= 2\gamma
  1216. % \end{eqnalign} \right\}.
  1217. %\]
  1218. % \end{demo}
  1219. % \end{figure}
  1220. %
  1221. % \DescribeMacro{\multicolumn}
  1222. % The |\multicolumn| command works correctly in both the \env{eqnarray} and
  1223. % \env{eqnalign} environments, although you should bear in mind that you
  1224. % should give \env{eqnarray} column types, not \env{array} ones.
  1225. %
  1226. % \subsubsection{A note on spacing in alignment environments}
  1227. %
  1228. % Most of the time, equations in \env{eqnarray} and \env{eqnalign}
  1229. % environments will be beautiful. However, there are some things you should
  1230. % bear in mind when you produce beautiful equations.
  1231. %
  1232. % The main problem with spacing is making sure that binary relations and
  1233. % binary operators have the correct amount of space on each side of them.
  1234. % The alignment environments insert `hidden' objects at the ends of table
  1235. % cells to assist with the spacing: \lit{l} column types have a hidden object
  1236. % on the left, \lit{r} types have a hidden object on the right, and \lit{c}
  1237. % types have a hidden object on \emph{both} ends. These hidden objects add
  1238. % the correct space when there's a binary operator or relation next to them.
  1239. % If some other sort of object is lurking there, no space is added. So far,
  1240. % so good.
  1241. %
  1242. % The only problem comes when you have something like this:
  1243. %
  1244. % \begin{demo}{How not to do an \env{eqnarray}}
  1245. %\begin{eqnarray*}[rcl]
  1246. % x + y & = & 12 \\
  1247. % 2x - 5y & = & -6
  1248. %\end{eqnarray*}
  1249. % \end{demo}
  1250. %
  1251. % The `$-$' sign in the second equation has been treated as a binary operator
  1252. % when really it should be a unary prefix operator, but \TeX\ isn't clever
  1253. % enough to know the difference. (Can you see the difference in the spacing
  1254. % between $-6$~and~${}-6$?) There are two possible solutions to the
  1255. % problem. You could wrap the `|-6|' up in a group (`|{-6}|'), or just the
  1256. % $-$ sign (`|{-}6|'). A better plan, though, is to get rid of the middle
  1257. % column altogether:
  1258. %
  1259. % \begin{demo}{How to do an \env{eqnarray}}
  1260. %\begin{eqnarray*}[rl]
  1261. % x + y & = 12 \\
  1262. % 2x - 5y & = -6
  1263. %\end{eqnarray*}
  1264. % \end{demo}
  1265. %
  1266. % Since the things in the middle column were the same width, it's not
  1267. % actually doing any good. Also, now that \TeX\ can see that the thing on
  1268. % the left of the `$-$' sign is a relation (the `$=$' sign), it will space
  1269. % the formula correctly.
  1270. %
  1271. % In this case, it might be even better to add some extra columns, and line
  1272. % up the $x$ and $y$ terms in the left hand side:
  1273. %
  1274. % \begin{demo}{Extra beautiful \env{eqnarray}}
  1275. %\begin{eqnarray*}[rrl]
  1276. % x + & y & = 12 \\
  1277. % 2x - & 5y & = -6
  1278. %\end{eqnarray*}
  1279. % \end{demo}
  1280. %
  1281. % ^^A Some hacking now to display box sizes.
  1282. %
  1283. % {
  1284. % \catcode`p=12 \catcode`t=12
  1285. % \gdef\magni#1pt{#1}
  1286. % }
  1287. %
  1288. % \newcommand{\widthof}[1]{^^A
  1289. % \settowidth{\dimen0 }{#1}^^A
  1290. % \expandafter\magni\the\dimen0\,pt^^A
  1291. % }
  1292. %
  1293. % ^^A The text below makes an assumption which looks correct to me (I asked
  1294. % ^^A TeX, and it agreed with me), although in case anything changes, I want
  1295. % ^^A to be informed.
  1296. %
  1297. % \sbox0{$+$} \sbox2{$-$} \ifdim\wd0=\wd2\else%
  1298. % \errmessage{Assertion failed: `+' and `-' are different widths!}
  1299. % \fi
  1300. %
  1301. % There's no need to put the `$+$' and `$-$' operators in their own column
  1302. % here, because they're both \widthof{$+$} wide, even though they don't
  1303. % look it.
  1304. %
  1305. % \subsubsection{Configuring the alignment environments}
  1306. %
  1307. % There are a collection of parameters you can use to make the equation
  1308. % alignment environments (\env{eqnarray} and \env{eqnalign}) look the way
  1309. % you like them. These are all shown in table~\ref{tbl:eqnparms}.
  1310. %
  1311. % \begin{table}
  1312. % \begin{tabular}[C]{| l | p{3in} |} \hlx{hv}
  1313. % \bf Parameter & \bf Use \\ \hlx{vhv}
  1314. % |\eqaopenskip| & Length put on the left of an
  1315. % \env{eqnarray} environment. By
  1316. % default, this is |\@centering| (to
  1317. % centre the alignment) or |\mathindent|
  1318. % (to left align) depending on whether
  1319. % you're using the \textsf{fleqn}
  1320. % document class option. \\
  1321. % |\eqacloseskip| & Length put on the right of an
  1322. % \env{eqnarray} environment. By
  1323. % default, this is |\@centering|, to
  1324. % align the environment correctly. \\ \hlx{vhv}
  1325. % |\eqacolskip| & Space added by the \lit{:} column
  1326. % modifier. This should be a rubber
  1327. % length, although it only stretches in
  1328. % \env{eqnarray}, not in \env{eqnalign}.
  1329. % The default value is 1\smallf1/2\,em
  1330. % with 1000\,pt of stretch. \\
  1331. % |\eqainskip| & Space added at each side of a normal
  1332. % column. By default this is 0\,pt. \\ \hlx{vhv}
  1333. % |\eqastyle| & The maths style used in the alignment.
  1334. % By default, this is |\textstyle|,
  1335. % and you probably won't want to change
  1336. % it. \\ \hlx{vh}
  1337. % \end{tabular}
  1338. %
  1339. % \caption{Parameters for the \env{eqnarray} and \env{eqnalign} environments}
  1340. % \label{tbl:eqnparms}
  1341. % \end{table}
  1342. %
  1343. %
  1344. % \subsection{Other multiline equations}
  1345. %
  1346. % Sometimes there's no sensible alignment point for splitting equations. The
  1347. % normal thing to do under these circumstances is to put the first line way
  1348. % over to the left of the page, and the last line over to the right. (If
  1349. % there are more lines, I imagine we put them in the middle.)
  1350. %
  1351. % \DescribeEnv{spliteqn}
  1352. % \DescribeEnv{spliteqn*}
  1353. % The \env{spliteqn} environment allows you to do such splitting of
  1354. % equations. Rather than tediously describe it, I'll just give an example,
  1355. % because it's really easy. The $*$-version works the same, except it
  1356. % doesn't put an equation number in.
  1357. %
  1358. % \begin{figure}
  1359. % \begin{demo}[w]{A split equation}
  1360. %\begin{spliteqn}
  1361. % \sum_{1\le j\le n}
  1362. % \frac {1} { (x_j - x_1) \ldots (x_j - x_{j-1})
  1363. % (x - x_j) (x_j - x_{j+1}) \ldots (x_j - x_n) }
  1364. % \\
  1365. % = \frac {1} { (x - x_1) \ldots (x - x_n) }.
  1366. %\end{spliteqn}
  1367. % \end{demo}
  1368. % \end{figure}
  1369. %
  1370. % \DescribeEnv{subsplit}
  1371. % If you have a very badly behaved equation, you might want to split a part
  1372. % of it (say, a bit of a fraction), particularly if you're doing things in
  1373. % narrow columns.
  1374. %
  1375. % \begin{figure}
  1376. % \begin{demo}[w]{A \env{subsplit} environment}
  1377. %\begin{equation}
  1378. % \frac{
  1379. % \begin{subsplit}
  1380. % q^{\frac{1}{2} n(n+1)}(ea; q^2)_\infty (eq/a; q^2)_\infty \\
  1381. % (caq/e; q^2)_\infty (cq^2/ae; q^2)_\infty
  1382. % \end{subsplit}
  1383. % }{
  1384. % (e; q)_\infty (cq/e; q)_\infty
  1385. % }
  1386. %\end{equation}
  1387. % \end{demo}
  1388. % \end{figure}
  1389. %
  1390. % \subsection{Matrices}
  1391. %
  1392. % Also included in the \package{mathenv} package is a collection of things
  1393. % for typesetting matrices. The standard \env{array} doesn't (in my opinion)
  1394. % provide the right sort of spacing for matrices. \PlainTeX\ provides some
  1395. % quite nice matrix handling macros, but they don't work in the appropriate
  1396. % \LaTeX\ way.
  1397. %
  1398. % \textbf{Warning:} These definitions will make old versions of
  1399. % \package{plain.sty} unhappy; newer versions correctly restore the
  1400. % Plain~\TeX\ macros |\matrix| and |\pmatrix|.
  1401. %
  1402. % \DescribeEnv{matrix}
  1403. % The simple way to do matrices is with the \env{matrix} environment.
  1404. %
  1405. % \begin{grammar}
  1406. %
  1407. % <matrix-env> ::= \[[ <begin-matrix> <contents> <end-matrix> \]]
  1408. %
  1409. % <begin-matrix> ::= \[[ "\\begin{matrix}" \[ "[" <matrix-cols> "]" \] \]]
  1410. %
  1411. % <matrix-cols> ::= \[[
  1412. % \< \[ "[" \] \[ "T" \] \( "l" \\ "c" \\ "r" \) \>
  1413. % \]]
  1414. %
  1415. % <end-matrix> ::= \[[ "\\end{stack}" \]]
  1416. %
  1417. % \end{grammar}
  1418. %
  1419. % The \lit{l}, \lit{c} and \lit{r} columns are fairly obvious -- they align
  1420. % their contents in the appropriate way. The \lit{[} character is more
  1421. % complicated. It means `repeat the remaining column types forever', so a
  1422. % preamble of \lit{cc[lr} means `two centred columns, then alternating left-
  1423. % and right-aligned columns for as often as needed'. The default preamble,
  1424. % if you don't specify one, is \lit{[c} -- `any number of centred columns'.
  1425. %
  1426. % \DescribeMacro{\multicolumn}
  1427. % The |\multicolumn| command works correctly in matrices, although you should
  1428. % bear in mind that you should give \env{matrix} column types, not
  1429. % \env{array} ones.
  1430. %
  1431. % \DescribeEnv{pmatrix}
  1432. % The standard \env{matrix} environment doesn't put any delimiters around the
  1433. % matrix. You can use the standard |\left| and |\right| commands, although
  1434. % this is a bit nasty. The \env{pmatrix} environment will put parentheses
  1435. % around the matrix it creates; it's otherwise exactly the same as
  1436. % \env{matrix}.
  1437. %
  1438. % \DescribeEnv{dmatrix}
  1439. % A \env{dmatrix} environment is also provided. It takes two extra
  1440. % arguments: the left and right delimiter characters (without |\left| or
  1441. % |\right|).
  1442. %
  1443. % \begin{figure}
  1444. % \begin{demo}[w]{Various \env{matrix} environments}
  1445. %\[ \begin{matrix} 1 & 0 \\ 0 & -1 \end{matrix} \quad
  1446. % \begin{pmatrix}
  1447. % \cos\theta & \sin\theta \\
  1448. % -\sin\theta & \cos\theta
  1449. % \end{pmatrix} \quad
  1450. % \begin{dmatrix}[] 0 & -i \\ i & 0 \end{dmatrix}
  1451. %\]
  1452. % \end{demo}
  1453. % \end{figure}
  1454. %
  1455. % \DescribeEnv{smatrix}
  1456. % Normal matrices always come out the same size; they don't change size
  1457. % according to the surrounding context (unfortunately). However, it can be
  1458. % occasionally useful to put matrices in running text, so you can talk about
  1459. % $A$ being $\bigl( \begin{smatrix} a & b \\ b & c \end{smatrix} \bigr)$
  1460. % being its own transpose (i.e., $A = A^T$). This is accomplished using the
  1461. % \env{smatrix} (the `s' stands for `small' -- I thought that `smallmatrix'
  1462. % was too big to type inline). As well as inline text, the \env{smatrix}
  1463. % can be useful in displays, if the matrix is deep in a subformula. I can't
  1464. % think of any examples offhand, though.
  1465. %
  1466. % \DescribeEnv{spmatrix}
  1467. % \DescribeEnv{sdmatrix}
  1468. % The \env{smatrix} environment doesn't supply any delimiters, like
  1469. % \env{matrix}. There are \env{spmatrix} and \env{sdmatrix} environments
  1470. % which do, though. Note that delimiters have a tendency to get too big and
  1471. % mess up the line spacing -- I had to use explicitly |\big| delimiters
  1472. % in the above example.
  1473. %
  1474. % \DescribeEnv{pmatrix*}
  1475. % \DescribeEnv{spmatrix*}
  1476. % \DescribeEnv{sdmatrix*}
  1477. % All the small matrix environments have starred versions, which are more
  1478. % suitable for use in displays, since they have more space between the rows.
  1479. % They're intended for typesetting really big matrices in displays.
  1480. %
  1481. % \DescribeMacro{\ddots}
  1482. % \DescribeMacro{\vdots}
  1483. % The standard |\vdots| and |\ddots| commands don't produce anything at all
  1484. % nice in small matrices, so this package redefines them so that they scale
  1485. % properly to smaller sizes.
  1486. %
  1487. % \DescribeEnv{genmatrix}
  1488. % Actually, all these environments are special cases of one: \env{genmatrix}.
  1489. % This takes oodles of arguments:
  1490. % \begin{quote} \synshorts
  1491. % "\\begin{genmatrix}{"<matrix-style>"}{"<outer-style>"}" \\
  1492. % \null \qquad "{"<spacing>"}{"<left-delim>"}{"<right-delim>"}" \\
  1493. % \null \quad\vdots \\
  1494. % "\\end{genmatrix}"
  1495. % \end{quote}
  1496. % The two `style' arguments should be things like |\textstyle| or
  1497. % |\scriptstyle|; the first, \<matrix-style>, is the style to use for the
  1498. % matrix elements, and the second, \<outer-style>, is the style to assume
  1499. % for the surrounding text (this affects the spacing within the matrix; it
  1500. % should usually be the same as \<matrix-style>). The \<spacing> is inserted
  1501. % between the matrix and the delimiters, on each side of the matrix. It's
  1502. % usually `|\,|' in full-size matrices, and blank for small ones. The
  1503. % delimiters are inserted around the matrices, and sized appropriately.
  1504. %
  1505. % \DescribeEnv{newmatrix}
  1506. % You can create your own matrix environments if you like, using the
  1507. % |\newmatrix| command. It takes two arguments, although they're a bit
  1508. % odd. The first is the name of the environment, and the second contains
  1509. % the arguments to pass to \env{genmatrix}. For example, the \env{pmatrix}
  1510. % environment was defined by saying
  1511. %
  1512. % \begin{listing}
  1513. %\newmatrix{pmatrix}{{\textstyle}{\textstyle}{\,}{(}{)}}
  1514. % \end{listing}
  1515. %
  1516. % If you don't pass all three arguments, then you end up requiring the
  1517. % user to specify the remaining ones. This is how \env{dmatrix} works.
  1518. %
  1519. % \DescribeEnv{script}
  1520. % Finally, although it's not really a matrix, stacked super- and subscripts
  1521. % follow much the same sorts of spacing rules. The \env{script} environment
  1522. % allows you to do this sort of thing very easily. It essentially provides
  1523. % a `matrix' with the right sort of spacing. The default preamble string is
  1524. % \lit{c}, giving you centred scripts, although you can say
  1525. % |\begin{script}[l]| for left-aligned scripts, which is better if the
  1526. % script is being placed to the right of its operator. If you're really
  1527. % odd, you can have more than one column.
  1528. %
  1529. % \begin{demo}{Example of \env{script}}
  1530. %\[ \mathop{{\sum}'}_{x \in A}
  1531. % f(x)
  1532. % \stackrel{\mathrm{def}}{=}
  1533. % \sum_{\begin{script}
  1534. % x \in A \\ x \ne 0
  1535. % \end{script}} f(x)
  1536. %\]
  1537. % \end{demo}
  1538. %
  1539. %
  1540. % \subsection{Other \package{mathenv} environments}
  1541. %
  1542. % The \package{mathenv} package contains some other environments which may
  1543. % be useful, based on the enhanced \env{tabular} and \env{array}
  1544. % environments.
  1545. %
  1546. % \DescribeEnv{cases}
  1547. % The \env{cases} environment lets you say things like the following:
  1548. %
  1549. % \begin{demo}[w]{Example of \env{cases}}
  1550. %\[ P_{r-j} = \begin{cases}
  1551. % 0 & if $r-j$ is odd \\
  1552. % r!\,(-1)^{(r-j)/2} & if $r-j$ is even
  1553. % \end{cases}
  1554. %\]
  1555. % \end{demo}
  1556. %
  1557. % The spacing required for this is a bit messy, so providing an environment
  1558. % for it is quite handy.
  1559. %
  1560. % \DescribeEnv{smcases}
  1561. % The \env{smcases} environment works the same way as \env{cases}, but with
  1562. % scriptsize lettering.
  1563. %
  1564. % \implementation
  1565. %
  1566. %
  1567. %^^A-------------------------------------------------------------------------
  1568. % \section{Implementation of table handling}
  1569. %
  1570. %
  1571. % Here we go. It starts horrid and gets worse. However, it does stay nicer
  1572. % than the original, IMHO.
  1573. %
  1574. % \begin{macrocode}
  1575. %<*mdwtab>
  1576. % \end{macrocode}
  1577. %
  1578. %
  1579. % \subsection{Registers, switches and things}
  1580. %
  1581. % We need lots of these. It's great fun.
  1582. %
  1583. % The two count registers are simple enough:
  1584. %
  1585. % \begin{description}
  1586. % \item [\cs{tab@state}] contains the current parser state. Since we
  1587. % probably won't be parsing preambles recursively, this is a global
  1588. % variable.
  1589. % \item [\cs{tab@columns}] contains the number of the current column.
  1590. % \item [\cs{tab@hlstate}] contains the state required for hline management.
  1591. % \end{description}
  1592. %
  1593. % \begin{macrocode}
  1594. \newcount\tab@state
  1595. \newcount\tab@columns
  1596. % \end{macrocode}
  1597. %
  1598. % We need \emph{lots} of token registers. Fortunately, most of them are only
  1599. % used during parsing. We'll use \PlainTeX's scratch tokens for this. Note
  1600. % that |\toks\tw@| isn't used here. It, and |\toks@|, are free for use by
  1601. % column commands.
  1602. %
  1603. % \begin{macrocode}
  1604. \newtoks\tab@preamble
  1605. \newtoks\tab@shortline
  1606. \toksdef\tab@pretext 4
  1607. \toksdef\tab@posttext 6
  1608. \toksdef\tab@userpretext 8
  1609. % \end{macrocode}
  1610. %
  1611. % The dimens are fairly straightforward. The inclusion of |\col@sep| is a
  1612. % sacrifice to compatibility -- judicious use of |\let| in \package{array}
  1613. % would have saved a register.
  1614. %
  1615. % \begin{macrocode}
  1616. \newdimen\extrarowheight
  1617. \newdimen\tabextrasep
  1618. \newdimen\arrayextrasep
  1619. \newdimen\smarraycolsep
  1620. \newdimen\smarrayextrasep
  1621. \newdimen\tab@width
  1622. \newdimen\col@sep
  1623. \newdimen\tab@endheight
  1624. % \end{macrocode}
  1625. %
  1626. % Some skip registers too. Phew.
  1627. %
  1628. % \begin{macrocode}
  1629. \newskip\tab@leftskip
  1630. \newskip\tab@rightskip
  1631. % \end{macrocode}
  1632. %
  1633. % And some switches. The first three are for the parser.
  1634. %
  1635. % \begin{macrocode}
  1636. \newif\iftab@firstcol
  1637. \newif\iftab@initrule
  1638. \newif\iftab@rule
  1639. \newif\iftab@vgap
  1640. % \end{macrocode}
  1641. %
  1642. % Now assign some default values to new dimen parameters. These definitions
  1643. % are essentially the equivalent of an |\openup 1\jot| in \env{array}, but
  1644. % not in \env{tabular}. This looks nice, I think.
  1645. %
  1646. % \begin{macrocode}
  1647. \tabextrasep\z@
  1648. \arrayextrasep\jot
  1649. \smarraycolsep\thr@@\p@
  1650. \smarrayextrasep\z@
  1651. % \end{macrocode}
  1652. %
  1653. % Set some things up for alien table environments.
  1654. %
  1655. % \begin{macrocode}
  1656. \let\tab@extrasep\tabextrasep
  1657. \let\tab@penalty\relax
  1658. % \end{macrocode}
  1659. %
  1660. %
  1661. % \subsection{Some little details}
  1662. %
  1663. % \begin{macro}{\@maybe@unskip}
  1664. %
  1665. % This macro solves a little problem. In an alignment (and in other places)
  1666. % it's desirable to suppress trailing space. The usual method, to say
  1667. % |\unskip|, is a little hamfisted, because it removes perfectly reasonable
  1668. % aligning spaces like |\hfil|s. While as a package writer I can deal with
  1669. % this sort of thing by saying |\kern\z@| in appropriate places, it can
  1670. % annoy users who are trying to use |\hfill| to override alignment in funny
  1671. % places.
  1672. %
  1673. % My current solution seems to be acceptable. I'll remove the natural width
  1674. % of the last glue item, so that it can still stretch and shrink if
  1675. % necessary. The implementation makes use of the fact that multiplying
  1676. % a \<skip> by a \<number> kills off the stretch. (Bug fix: don't do this
  1677. % when we're in vertical mode.)
  1678. %
  1679. % \begin{macrocode}
  1680. \def\@maybe@unskip{\ifhmode\hskip\m@ne\lastskip\relax\fi}
  1681. % \end{macrocode}
  1682. %
  1683. % \end{macro}
  1684. %
  1685. % \begin{macro}{\q@delim}
  1686. %
  1687. % Finally, for the sake of niceness, here's a delimiter token I can use
  1688. % for various things. It's a `quark', for what it's worth (i.e., it expands
  1689. % to itself) although I'm not really sure why this is a good thing. As far
  1690. % as I'm concerned, it's important that it has a unique meaning (i.e., that
  1691. % it won't be |\ifx|-equal to other things, or something undefined) and that
  1692. % it won't be used where I don't expect it to be used. \TeX\ will loop
  1693. % horridly if it tries to expand this, so I don't think that quarks are
  1694. % wonderfully clever thing to use. (Maybe it should really expand to
  1695. % something like `\syntax{<quark>"."}', which will rapdly fill \TeX's memory
  1696. % if it gets accidentally expanded. Still, I'll leave it as it is until
  1697. % such time as I understand the idea more.)
  1698. %
  1699. % \begin{macrocode}
  1700. \def\q@delim{\q@delim}
  1701. % \end{macrocode}
  1702. %
  1703. % \end{macro}
  1704. %
  1705. %
  1706. % \subsection{Parser states}
  1707. %
  1708. % Now we start on the parser. It's really simple, deep down. We progress
  1709. % from state to state, extracing tokens from the preamble and building
  1710. % command names from them. Each command calls one of the element-building
  1711. % routines, which works out which state it should be in. We go through each
  1712. % of the states in between (see later) doing default things for the ones we
  1713. % missed out.
  1714. %
  1715. % Anyway, here's some symbolic names for the states. It makes my life
  1716. % easier.
  1717. %
  1718. % \begin{macrocode}
  1719. \chardef\tab@startstate 0
  1720. \chardef\tab@loopstate 1
  1721. \chardef\tab@rulestate 1
  1722. \chardef\tab@prespcstate 2
  1723. \chardef\tab@prestate 3
  1724. \chardef\tab@colstate 4
  1725. \chardef\tab@poststate 5
  1726. \chardef\tab@postspcstate 6
  1727. \chardef\tab@limitstate 7
  1728. % \end{macrocode}
  1729. %
  1730. %
  1731. % \subsection{Adding things to token lists}
  1732. %
  1733. % Define some macros for adding stuff to the beginning and end of token
  1734. % lists. This is really easy, actually. Here we go.
  1735. %
  1736. % \begin{macrocode}
  1737. \def\tab@append#1#2{#1\expandafter{\the#1#2}}
  1738. \def\tab@prepend#1#2{%
  1739. \toks@{#2}#1\expandafter{\the\expandafter\toks@\the#1}%
  1740. }
  1741. % \end{macrocode}%
  1742. %
  1743. %
  1744. % \subsection{Committing a column to the preamble}
  1745. %
  1746. % Each time we pass the `rule' state, we `commit' the tokens we've gathered
  1747. % so far to the main preamble token list. This is how we do it. Note the
  1748. % icky use of |\expandafter|.
  1749. %
  1750. % \begin{macrocode}
  1751. \def\tab@commit{%
  1752. % \end{macrocode}
  1753. %
  1754. % If this isn't the first column, then we need to put in a column separator.
  1755. %
  1756. % \begin{macrocode}
  1757. \iftab@firstcol\else%
  1758. \expandafter\tab@append\expandafter\tab@preamble%
  1759. \expandafter{\tab@tabtext}%
  1760. \fi%
  1761. % \end{macrocode}
  1762. %
  1763. % Now we spill the token registers into the main list in a funny order (which
  1764. % is why we're doing it in this strange way in the first place.
  1765. %
  1766. % \begin{macrocode}
  1767. \toks@\expandafter{\tab@midtext}%
  1768. \tab@preamble\expandafter{%
  1769. \the\expandafter\tab@preamble%
  1770. \the\expandafter\tab@pretext%
  1771. \the\expandafter\tab@userpretext%
  1772. \the\expandafter\toks@%
  1773. \the\tab@posttext%
  1774. }%
  1775. % \end{macrocode}
  1776. %
  1777. % Now reset token lists and things for the next go round.
  1778. %
  1779. % \begin{macrocode}
  1780. \tab@firstcolfalse%
  1781. \tab@pretext{}%
  1782. \tab@userpretext{}%
  1783. \tab@posttext{}%
  1784. }
  1785. % \end{macrocode}
  1786. %
  1787. %
  1788. % \subsection{Playing with parser states}
  1789. %
  1790. % \begin{macro}{\tab@setstate}
  1791. %
  1792. % This is how we set new states. The algorithm is fairly simple, really.
  1793. %
  1794. % ^^A Let's see how good my TeX really is... ;-)
  1795. % ^^A Actually, it doesn't seem to have worked out too badly. Maybe I should
  1796. % ^^A write a package to do this automatically. It's rather tricky, though.
  1797. %
  1798. % \def\qq{\mbox{\quad}}
  1799. % \sbox{0}{\itshape\textunderscore}\def\_{\usebox{0}}
  1800. %
  1801. % \begin{quote}
  1802. % {\bf while} $\it tab\_state \ne s$ {\bf do} \\
  1803. % \qq $\mathit{tab\_state = tab\_state}+1$; \\
  1804. % \qq {\bf if} $\it tab\_state = tab\_limitState$ {\bf then}
  1805. % $\it tab\_state=tab\_loopState$; \\
  1806. % \qq {\bf if} $\it tab\_state = tab\_preSpcState$ {\bf then} \\
  1807. % \qq \qq {\bf if} $\it tab\_initRule$ {\bf then} \\
  1808. % \qq \qq \qq $\it tab\_initRule = {\bf false}$; \\
  1809. % \qq \qq {\bf else} \\
  1810. % \qq \qq \qq {\bf if} $\it tab\_inMultiCol$ {\bf then moan}; \\
  1811. % \qq \qq \qq $\it commit$; \\
  1812. % \qq \qq \qq $\it append(tab\_shortLine,\hbox{`|&\omit|')}$; \\
  1813. % \qq \qq {\bf end\,if}; \\
  1814. % \qq {\bf end\,if}; \\
  1815. % \qq {\bf if} $\it tab\_state \ne s$ {\bf then}
  1816. % $\it do\_default(tab\_state)$; \\
  1817. % {\bf end\,while};
  1818. % \end{quote}
  1819. %
  1820. % First we decide if there's anything to do. If so, we call another macro to
  1821. % do it for us.
  1822. %
  1823. % \begin{macrocode}
  1824. \def\tab@setstate#1{%
  1825. \ifnum#1=\tab@state\else%
  1826. \def\@tempa{\tab@setstate@i{#1}}%
  1827. \@tempa%
  1828. \fi%
  1829. }
  1830. % \end{macrocode}
  1831. %
  1832. % This is where the fun is. First we bump the state by one, and loop back
  1833. % if we fall off the end.
  1834. %
  1835. % \begin{macrocode}
  1836. \def\tab@setstate@i#1{%
  1837. \global\advance\tab@state\@ne%
  1838. \ifnum\tab@state>\tab@limitstate%
  1839. \global\tab@state\tab@loopstate%
  1840. \fi%
  1841. % \end{macrocode}
  1842. %
  1843. % Now, if we've just passed the ruleoff state, we commit the current text
  1844. % \emph{unless} this was the strange initial rule at the very beginning. We
  1845. % provide a little hook here so that |\multicolumn| can moan if you try and
  1846. % give more than one column there. We also add another tab/omit pair to the
  1847. % list we use for |\vgap|.
  1848. %
  1849. % \begin{macrocode}
  1850. \ifnum\tab@state=\tab@prespcstate%
  1851. \iftab@initrule%
  1852. \tab@initrulefalse%
  1853. \else%
  1854. \tab@looped%
  1855. \tab@commit%
  1856. \tab@append\tab@shortline{&\omit}%
  1857. \fi%
  1858. \fi%
  1859. % \end{macrocode}
  1860. %
  1861. % Now we decide whether to go round again. If not, we do the default thing
  1862. % for this state. This is mainly here so that we can put the |\tabcolsep| or
  1863. % whatever in if the user didn't give an \lit{@} expression.
  1864. %
  1865. % \begin{macrocode}
  1866. \ifnum#1=\tab@state%
  1867. \let\@tempa\relax%
  1868. \else%
  1869. \csname tab@default@\number\tab@state\endcsname%
  1870. \fi%
  1871. \@tempa%
  1872. }
  1873. % \end{macrocode}
  1874. %
  1875. % \end{macro}
  1876. %
  1877. % Now we set up the default actions for the various states.
  1878. %
  1879. % In state~2 (pre-space) we add in the default gap if either we didn't have
  1880. % an \lit{@} expression in the post-space state or there was an explicit
  1881. % intervening rule.
  1882. %
  1883. % \begin{macrocode}
  1884. \@namedef{tab@default@2}{%
  1885. \iftab@rule%
  1886. \tab@append\tab@pretext{\hskip\col@sep}%
  1887. \fi%
  1888. }
  1889. % \end{macrocode}
  1890. %
  1891. % If the user omits the column type, we insert an `l'-type column and moan
  1892. % a lot.
  1893. %
  1894. % \begin{macrocode}
  1895. \@namedef{tab@default@4}{%
  1896. \tab@err@misscol%
  1897. \tab@append\tab@pretext{\tab@bgroup\relax}%
  1898. \tab@append\tab@posttext{\relax\tab@egroup\hfil}%
  1899. \tab@append\tab@shortline{\hfil}%
  1900. \advance\tab@columns\@ne%
  1901. }
  1902. % \end{macrocode}
  1903. %
  1904. % Finally we deal with the post-space state. We set a marker so that we
  1905. % put in the default space in the pre-space state later too.
  1906. %
  1907. % \begin{macrocode}
  1908. \@namedef{tab@default@6}{%
  1909. \tab@append\tab@posttext{\hskip\col@sep}%
  1910. \tab@ruletrue%
  1911. }
  1912. % \end{macrocode}
  1913. %
  1914. %
  1915. % \subsection{Declaring token types}
  1916. %
  1917. % \begin{macro}{\tab@extracol}
  1918. %
  1919. % Before we start, we need to handle |\extracolsep|. This is a right pain,
  1920. % because the original version of \env{tabular} worked on total expansion,
  1921. % which is a Bad Thing. On the other hand, turning |\extracolsep| into a
  1922. % |\tabskip| is also a major pain.
  1923. %
  1924. % \begin{macrocode}
  1925. \def\tab@extracol#1#2{\tab@extracol@i#1#2\extracolsep{}\extracolsep\end}
  1926. \def\tab@extracol@i#1#2\extracolsep#3#4\extracolsep#5\end{%
  1927. \ifx @#3@%
  1928. \def\@tempa{#1{#2}}%
  1929. \else%
  1930. \def\@tempa{#1{#2\tabskip#3\relax#4}}%
  1931. \fi%
  1932. \@tempa%
  1933. }
  1934. % \end{macrocode}
  1935. %
  1936. % \end{macro}
  1937. %
  1938. % This is where we do the work for inserting preamble elements.
  1939. %
  1940. % \begin{macro}{\tabruletype}
  1941. %
  1942. % Inserting rules is interesting, because we have to decide where to put
  1943. % them. If this is the funny initial rule, it goes in the pre-text list,
  1944. % otherwise it goes in the post-text list. We work out what to do first
  1945. % thing:
  1946. %
  1947. % \begin{macrocode}
  1948. \def\tabruletype#1{\tab@extracol\tabruletype@i{#1}}%
  1949. \def\tabruletype@i#1{%
  1950. \iftab@initrule%
  1951. \let\tab@tok\tab@pretext%
  1952. \else%
  1953. \let\tab@tok\tab@posttext%
  1954. \fi%
  1955. % \end{macrocode}
  1956. %
  1957. % Now if we're already in the rule state, we must have just done a rule.
  1958. % This means we must put in the |\doublerulesep| space, both here and in the
  1959. % shortline list. Otherwise we just stick the rule in.
  1960. %
  1961. % This is complicated, because |\vgap| needs to be able to remove some bits
  1962. % of rule. We pass each one to a macro |\tab@ckr|, together with the column
  1963. % number, which is carefully bumped at the right times, and this macro will
  1964. % vet the rules and output the appropriate ones. There's lots of extreme
  1965. % |\expandafter| nastiness as a result. Amazingly, this actually works.
  1966. %
  1967. % \begin{macrocode}
  1968. \ifnum\tab@state=\tab@rulestate%
  1969. \tab@append\tab@tok{\hskip\doublerulesep\begingroup#1\endgroup}%
  1970. \expandafter\tab@append\expandafter\tab@shortline\expandafter{%
  1971. \expandafter\hskip\expandafter\doublerulesep%
  1972. \expandafter\tab@ckr\expandafter{\the\tab@columns}%
  1973. {\begingroup#1\endgroup}%
  1974. }%
  1975. \else%
  1976. \tab@setstate\tab@rulestate%
  1977. \tab@append\tab@tok{\begingroup#1\endgroup}%
  1978. \expandafter\tab@append\expandafter\tab@shortline\expandafter{%
  1979. \expandafter\tab@ckr\expandafter{\the\tab@columns}%
  1980. {\begingroup#1\endgroup}%
  1981. }%
  1982. \fi%
  1983. % \end{macrocode}
  1984. %
  1985. % Finally, we say there was a rule here, so that default space gets put in
  1986. % after this. Otherwise we lose lots of generality.
  1987. %
  1988. % \begin{macrocode}
  1989. \tab@ruletrue%
  1990. }
  1991. % \end{macrocode}
  1992. %
  1993. % \end{macro}
  1994. %
  1995. % \begin{macro}{\tabspctype}
  1996. %
  1997. % We need to work out which space-state we should be in. Then we just put
  1998. % the text in. Easy, really.
  1999. %
  2000. % \begin{macrocode}
  2001. \def\tabspctype#1{\tab@extracol\tabspctype@i{#1}}%
  2002. \def\tabspctype@i#1{%
  2003. \tab@rulefalse%
  2004. \ifnum\tab@state>\tab@prespcstate%
  2005. \tab@setstate\tab@postspcstate%
  2006. \let\tab@tok\tab@posttext%
  2007. \else%
  2008. \tab@setstate\tab@prespcstate%
  2009. \let\tab@tok\tab@pretext%
  2010. \fi%
  2011. \tab@append\tab@tok{\begingroup#1\endgroup}%
  2012. }
  2013. % \end{macrocode}
  2014. %
  2015. % \end{macro}
  2016. %
  2017. % \begin{macro}{\tabcoltype}
  2018. %
  2019. % If we're already in the column state, we bump the state and loop round
  2020. % again, to get all the appropriate default behaviour. We bump the column
  2021. % counter, and add the bits of text we were given to appropriate token lists.
  2022. % We also add the |\hfil| glue to the shortline list, to space out the rules
  2023. % properly.
  2024. %
  2025. % \begin{macrocode}
  2026. \def\tabcoltype#1#2{%
  2027. \ifnum\tab@state=\tab@colstate%
  2028. \global\advance\tab@state\@ne%
  2029. \fi%
  2030. \advance\tab@columns\@ne%
  2031. \tab@setstate\tab@colstate%
  2032. \tab@append\tab@pretext{#1}%
  2033. \tab@append\tab@posttext{#2}%
  2034. \tab@append\tab@shortline{\hfil}%
  2035. }
  2036. % \end{macrocode}
  2037. %
  2038. % \end{macro}
  2039. %
  2040. % \begin{macro}{\tabuserpretype}
  2041. % \begin{macro}{\tabuserposttype}
  2042. %
  2043. % These are both utterly trivial.
  2044. %
  2045. % \begin{macrocode}
  2046. \def\tabuserpretype#1{%
  2047. \tab@setstate\tab@prestate%
  2048. \tab@prepend\tab@userpretext{#1}%
  2049. }
  2050. % \end{macrocode}
  2051. %
  2052. % \begin{macrocode}
  2053. \def\tabuserposttype#1{%
  2054. \tab@setstate\tab@poststate%
  2055. \tab@prepend\tab@posttext{#1}%
  2056. }
  2057. % \end{macrocode}
  2058. %
  2059. % \end{macro}
  2060. % \end{macro}
  2061. %
  2062. %
  2063. % \subsection{The colset stack}
  2064. %
  2065. % Let's start with something fairly easy. We'll keep a stack of column sets
  2066. % so that users don't get confused by package authors changing the current
  2067. % column set. This is fairly easy, really.
  2068. %
  2069. % \begin{macro}{\tab@push}
  2070. % \begin{macro}{\tab@pop}
  2071. % \begin{macro}{\tab@head}
  2072. %
  2073. % These are the stack management routines. The only important thing to note
  2074. % is that |\tab@head| must take place \emph{only} in \TeX's mouth, so we can
  2075. % use it in |\csname|\dots|\endcsname| constructions.
  2076. %
  2077. % \begin{macrocode}
  2078. \def\tab@push#1#2{%
  2079. \toks@{{#2}}%
  2080. \expandafter\def\expandafter#1\expandafter{\the\expandafter\toks@#1}%
  2081. }
  2082. \def\tab@pop#1{\expandafter\def\expandafter#1\expandafter{\@gobble#1}}
  2083. \def\tab@head#1{\expandafter\tab@head@i#1\relax}
  2084. \def\tab@head@i#1#2\relax{#1}
  2085. % \end{macrocode}
  2086. %
  2087. % \end{macro}
  2088. % \end{macro}
  2089. % \end{macro}
  2090. %
  2091. % \begin{macro}{\colset}
  2092. % \begin{macro}{\colpush}
  2093. % \begin{macro}{\colpop}
  2094. %
  2095. % Now we can define the user macros.
  2096. %
  2097. % \begin{macrocode}
  2098. \def\tab@colstack{{tabular}}
  2099. \def\colset{\colpop\colpush}
  2100. \def\colpush{\tab@push\tab@colstack}
  2101. \def\colpop{\tab@pop\tab@colstack}
  2102. % \end{macrocode}
  2103. %
  2104. % \end{macro}
  2105. % \end{macro}
  2106. % \end{macro}
  2107. %
  2108. % \begin{macro}{\tab@colset}
  2109. %
  2110. % Now we define a shortcut for reading the top item off the stack.
  2111. %
  2112. % \begin{macrocode}
  2113. \def\tab@colset{\tab@head\tab@colstack}
  2114. % \end{macrocode}
  2115. %
  2116. % \end{macro}
  2117. %
  2118. %
  2119. % \subsection{The main parser routine}
  2120. %
  2121. % \begin{macro}{\tab@initread}
  2122. %
  2123. % This macro sets up lots of variables to their normal states prior to
  2124. % parsing a preamble. Some things may need changing, but not many.
  2125. %
  2126. % \begin{macrocode}
  2127. \def\tab@initread{%
  2128. % \end{macrocode}
  2129. %
  2130. % First, reset the parser state to the start state.
  2131. %
  2132. % \begin{macrocode}
  2133. \global\tab@state\tab@startstate%
  2134. % \end{macrocode}
  2135. %
  2136. % We clear the token lists to sensible values, mostly. The midtext macro
  2137. % contains what to put in the very middle of each template -- |\multicolumn|
  2138. % will insert its argument here.
  2139. %
  2140. % \begin{macrocode}
  2141. \tab@preamble{}%
  2142. \tab@shortline{}%
  2143. \def\tab@tabtext{&}%
  2144. \def\tab@midtext{\ignorespaces####\@maybe@unskip}%
  2145. \tab@pretext{}%
  2146. \tab@userpretext{}%
  2147. \tab@posttext{}%
  2148. \let\tab@multicol\@empty%
  2149. \def\tab@startpause{\penalty\postdisplaypenalty\medskip}%
  2150. \def\tab@endpause{\penalty\predisplaypenalty\medskip}%
  2151. % \end{macrocode}
  2152. %
  2153. % Finally, reset the column counter, don't raise errors when we loop, and set
  2154. % some parser flags to their appropriate values.
  2155. %
  2156. % \begin{macrocode}
  2157. \tab@columns\z@%
  2158. \let\tab@looped\relax%
  2159. \tab@ruletrue%
  2160. \tab@initruletrue%
  2161. \tab@firstcoltrue%
  2162. }
  2163. % \end{macrocode}
  2164. %
  2165. % \end{macro}
  2166. %
  2167. % \begin{macro}{\tab@readpreamble}
  2168. %
  2169. % This is the main macro for preamble handling. Actually, all it does is
  2170. % gobble its argument's leading brace and call another macro, but it does it
  2171. % with style.
  2172. %
  2173. % \begin{macrocode}
  2174. \def\tab@readpreamble#1{%
  2175. \tab@doreadpream{#1}%
  2176. \iftab@initrule\global\tab@state\tab@prespcstate\fi%
  2177. \tab@setstate\tab@rulestate%
  2178. \tab@commit%
  2179. }
  2180. % \end{macrocode}
  2181. %
  2182. % \end{macro}
  2183. %
  2184. % \begin{macro}{\tab@doreadpream}
  2185. %
  2186. % The preamble is in an argument. Previous versions used a nasty trick using
  2187. % |\let| and |\afterassignment|. Now we use an explicit end token, to allow
  2188. % dodgy column type handlers to scoop up the remaining preamble tokens
  2189. % and process them. Not that anyone would want to do that, oh no (see
  2190. % the \lit{[} type in the \env{eqnarray} environment |;-)|).
  2191. %
  2192. % \begin{macrocode}
  2193. \def\tab@doreadpream#1{\tab@mkpreamble#1\q@delim}
  2194. % \end{macrocode}
  2195. %
  2196. % \end{macro}
  2197. %
  2198. % \begin{macro}{\tab@mkpreamble}
  2199. %
  2200. % This is the main parser routine. It takes each token in turn, scrutinises
  2201. % it carefully, and does the appropriate thing with it.
  2202. %
  2203. % The preamble was given as an argument to |\tab@doreadpream|, and that has
  2204. % helpfully stripped off the initial |{| character. We need to pick off the
  2205. % next token (whatever it is) so we can examine it. We'll use |\futurelet|
  2206. % so we can detect groups and things in funny places.
  2207. %
  2208. % \begin{macrocode}
  2209. \def\tab@mkpreamble{\futurelet\@let@token\tab@mkpreamble@i}
  2210. % \end{macrocode}
  2211. %
  2212. % If we find a space token, we'll go off and do something a bit special,
  2213. % since spaces are sort of hard to handle. Otherwise we'll do it in the old
  2214. % fashioned way.
  2215. %
  2216. % \begin{macrocode}
  2217. \def\tab@mkpreamble@i{%
  2218. \ifx\@let@token\@sptoken%
  2219. \expandafter\tab@mkpreamble@spc%
  2220. \else%
  2221. \expandafter\tab@mkpreamble@ii%
  2222. \fi%
  2223. }
  2224. % \end{macrocode}
  2225. %
  2226. % If we find a |\@@endpreamble| token, that's it and we're finished. We just
  2227. % gobble it and return. Otherwise, if it's an open group character, we'll
  2228. % complain because someone's probably tried to put an argument in the wrong
  2229. % place. Finally, if none of the other things apply, we'll deal with the
  2230. % character below.
  2231. %
  2232. % \begin{macrocode}
  2233. \def\tab@mkpreamble@ii{%
  2234. \ifx\@let@token\q@delim%
  2235. \def\@tempa{\let\@let@token}%
  2236. \else%
  2237. \ifcat\bgroup\noexpand\@let@token%
  2238. \tab@err@oddgroup%
  2239. \def\@tempa##1{\tab@mkpreamble}%
  2240. \else%
  2241. \let\@tempa\tab@mkpreamble@iii%
  2242. \fi%
  2243. \fi%
  2244. \@tempa%
  2245. }
  2246. % \end{macrocode}
  2247. %
  2248. % Handle a character. This involves checking to see if it's actually
  2249. % defined, and then doing it. Doing things this way means we won't get
  2250. % stranded in mid-preamble unless a package author has blown it.
  2251. %
  2252. % \begin{macrocode}
  2253. \def\tab@mkpreamble@iii#1{%
  2254. \@ifundefined{\tab@colset!col.\string#1}{%
  2255. \tab@err@undef{#1}\tab@mkpreamble%
  2256. }{%
  2257. \@nameuse{\tab@colset!col.\string#1}%
  2258. }%
  2259. }
  2260. % \end{macrocode}
  2261. %
  2262. % If we get given a space character, we'll look up the command name as
  2263. % before. If no-one's defined the column type we'll just skip it silently,
  2264. % which lets users do pretty formatting if they like.
  2265. %
  2266. % \begin{macrocode}
  2267. \@namedef{tab@mkpreamble@spc} {%
  2268. \@ifundefined{\tab@colset!col. }{%
  2269. \tab@mkpreamble%
  2270. }{%
  2271. \@nameuse{\tab@colset!col. }%
  2272. }%
  2273. }
  2274. % \end{macrocode}
  2275. %
  2276. % \end{macro}
  2277. %
  2278. % \begin{macro}{\coldef}
  2279. %
  2280. % Here's how to define column types the nice way. Some dexterity is required
  2281. % to make everything work right, but it's simple really.
  2282. %
  2283. % \begin{macrocode}
  2284. \def\coldef{\@ifnextchar[\coldef@i{\coldef@i[\tab@colset]}}
  2285. \def\coldef@i[#1]#2#3#{\coldef@ii[#1]{#2}{#3}}
  2286. \def\coldef@ii[#1]#2#3#4{%
  2287. \expandafter\def\csname#1!col.\string#2\endcsname#3{%
  2288. #4\tab@mkpreamble%
  2289. }%
  2290. }
  2291. % \end{macrocode}
  2292. %
  2293. % \end{macro}
  2294. %
  2295. % \begin{macro}{\collet}
  2296. %
  2297. % We'd like to let people copy column types from other places. This is how
  2298. % to do it.
  2299. %
  2300. % \begin{macrocode}
  2301. \def\collet{\@ifnextchar[\collet@i{\collet@i[\tab@colset]}}
  2302. \def\collet@i[#1]#2{%
  2303. \@ifnextchar=%
  2304. {\collet@ii[#1]{#2}}%
  2305. {\collet@ii[#1]{#2}=}%
  2306. }
  2307. \def\collet@ii[#1]#2={%
  2308. \@ifnextchar[%
  2309. {\collet@iii[#1]{#2}}%
  2310. {\collet@iii[#1]{#2}[\tab@colset]}%
  2311. }
  2312. \def\collet@iii[#1]#2[#3]#4{%
  2313. \expandafter\let\csname#1!col.\string#2\expandafter\endcsname%
  2314. \csname#3!col.\string#4\endcsname%
  2315. }
  2316. % \end{macrocode}
  2317. %
  2318. % \end{macro}
  2319. %
  2320. % \begin{macro}{\newcolumntype}
  2321. %
  2322. % We just bundle the text off to |\newcommand| and expect it to cope. It
  2323. % ought to. The column type code inserts the user's tokens directly, rather
  2324. % than calling |\tab@doreadpream| recursively. The magic control sequence
  2325. % is the one looked up by the parser.
  2326. %
  2327. % There's some additional magic here for compatiblity with the obscure way
  2328. % that \package{array} works.
  2329. %
  2330. % \begin{macrocode}
  2331. \def\newcolumntype#1{\@ifnextchar[{\nct@i{#1}}{\nct@i#1[0]}}
  2332. \def\nct@i#1[#2]{\@ifnextchar[{\nct@ii{#1}[#2]}{\nct@iii{#1}{[#2]}}}
  2333. \def\nct@ii#1[#2][#3]{\nct@iii{#1}{[#2][#3]}}
  2334. \def\nct@iii#1#2#3{%
  2335. \expandafter\let\csname\tab@colset!col.\string#1\endcsname\relax%
  2336. \expandafter\newcommand\csname\tab@colset!col.\string#1\endcsname#2{%
  2337. \tab@deepmagic{#1}%
  2338. \tab@mkpreamble%
  2339. #3%
  2340. }%
  2341. }
  2342. % \end{macrocode}
  2343. %
  2344. % Now for some hacking for compatibility with \package{tabularx}.
  2345. %
  2346. % \begin{macrocode}
  2347. \def\newcol@#1[#2]{\nct@iii{#1}{[#2]}}
  2348. % \end{macrocode}
  2349. %
  2350. % And now some more. This is seriously deep magic. Hence the name.
  2351. %
  2352. % \begin{macrocode}
  2353. \def\tab@deepmagic#1{%
  2354. \csname NC@rewrite@\string#1\endcsname\NC@find\tab@@magic@@%
  2355. }
  2356. \def\NC@find#1\tab@@magic@@{}
  2357. % \end{macrocode}
  2358. %
  2359. % \end{macro}
  2360. %
  2361. %
  2362. % \subsection{Standard column types}
  2363. %
  2364. % First, make sure we're setting up the right columns. This also sets the
  2365. % default for the user. Other packages must not use the |\colset| command
  2366. % for defining columns -- they should use the stack operations defined above.
  2367. %
  2368. % \begin{macrocode}
  2369. \colset{tabular}
  2370. % \end{macrocode}
  2371. %
  2372. % Now do the simple alignment types. These are fairly simple. The
  2373. % mysterious kern in the \lit{l} type is to stop the |\col@sep| glue from
  2374. % vanishing due to the |\unskip| inserted by the standard |\tab@midtext| if
  2375. % the column contains no text. (Thanks for spotting this bug go to that
  2376. % nice Mr~Carlisle.)
  2377. %
  2378. % \begin{macrocode}
  2379. \coldef l{\tabcoltype{\kern\z@\tab@bgroup}{\tab@egroup\hfil}}
  2380. \coldef c{\tabcoltype{\hfil\tab@bgroup}{\tab@egroup\hfil}}
  2381. \coldef r{\tabcoltype{\hfil\tab@bgroup}{\tab@egroup}}
  2382. % \end{macrocode}
  2383. %
  2384. % Some extensions now. These are explicitly teextual or mathematical
  2385. % columns. Can be useful if you're providing column types for other people.
  2386. % I've inserted a kern here for exactly the same reason as for the \lit{l}
  2387. % column type above.
  2388. %
  2389. % \begin{macrocode}
  2390. \coldef T#1{\tab@aligncol{#1}{\tab@btext}{\tab@etext}}
  2391. \coldef M#1{\tab@aligncol{#1}{\tab@bmaths}{\tab@emaths}}
  2392. \def\tab@aligncol#1#2#3{%
  2393. \if#1l\tabcoltype{\kern\z@#2}{#3\hfil}\fi%
  2394. \if#1c\tabcoltype{\hfil#2}{#3\hfil}\fi%
  2395. \if#1r\tabcoltype{\hfil#2}{#3}\fi%
  2396. }
  2397. % \end{macrocode}
  2398. %
  2399. % Now for the default rules.
  2400. %
  2401. % \begin{macrocode}
  2402. \coldef |{\tabruletype{\vrule\@width\arrayrulewidth}}
  2403. \coldef !#1{\tabruletype{#1}}
  2404. % \end{macrocode}
  2405. %
  2406. % Deal with \lit{@} expressions.
  2407. %
  2408. % \begin{macrocode}
  2409. \coldef @#1{\tabspctype{#1}}
  2410. % \end{macrocode}
  2411. %
  2412. % And the paragraph types. I've added things to handle footnotes here.
  2413. %
  2414. % \begin{macrocode}
  2415. \coldef p#1{\tabcoltype%
  2416. {\savenotes\vtop\tab@bpar{#1}}%
  2417. {\tab@epar\spewnotes\hfil}}
  2418. \coldef m#1{\tabcoltype%
  2419. {\savenotes$\vcenter\tab@bpar{#1}}%
  2420. {\tab@epar$\spewnotes\hfil}}
  2421. \coldef b#1{\tabcoltype%
  2422. {\savenotes\vbox\tab@bpar{#1}}%
  2423. {\tab@epar\spewnotes\hfil}}
  2424. % \end{macrocode}
  2425. %
  2426. % Phew. Only a few more left now. The user text ones.
  2427. %
  2428. % \begin{macrocode}
  2429. \coldef >#1{\tabuserpretype{#1}}
  2430. \coldef <#1{\tabuserposttype{#1}}
  2431. % \end{macrocode}
  2432. %
  2433. % The strange column type.
  2434. %
  2435. % \begin{macrocode}
  2436. \coldef ##1#2{\tabcoltype{#1}{#2}}
  2437. % \end{macrocode}
  2438. %
  2439. % And \lit{*}, which repeats a preamble spec. This is really easy, and not
  2440. % at all like the original one.
  2441. %
  2442. % \begin{macrocode}
  2443. \coldef *#1#2{%
  2444. \count@#1%
  2445. \loop\ifnum\count@>0\relax%
  2446. \tab@doreadpream{#2}%
  2447. \advance\count@\m@ne%
  2448. \repeat%
  2449. }
  2450. % \end{macrocode}
  2451. %
  2452. %
  2453. % \subsection{Paragraph handling}
  2454. %
  2455. % First of all, starting new paragraphs: the vbox token is already there, and
  2456. % we have the width as an argument.
  2457. %
  2458. % \begin{macro}{\tab@bpar}
  2459. %
  2460. % There are some gymnastics to do here to support lists which form the
  2461. % complete text of the parbox. One of the odd things I'll do here is to
  2462. % not insert a strut on the first line: instead, I'll put the text into a
  2463. % box register so that I can inspect it later. So that I have access to
  2464. % the height of the first line, I'll use a |\vtop| -- I can get at the
  2465. % final depth by using |\prevdepth|, so this seems to be the most general
  2466. % solution.
  2467. %
  2468. % \begin{macrocode}
  2469. \def\tab@bpar#1{%
  2470. \bgroup%
  2471. \hsize#1\relax%
  2472. \@arrayparboxrestore%
  2473. \setbox\z@\vtop\bgroup
  2474. \global\@minipagetrue%
  2475. \everypar{%
  2476. \global\@minipagefalse%
  2477. \everypar{}%
  2478. }%
  2479. }
  2480. % \end{macrocode}
  2481. %
  2482. % \end{macro}
  2483. %
  2484. % \begin{macro}{\tab@epar}
  2485. %
  2486. % To end the paragraph, close the box. That sounds easy, doesn't it?
  2487. % I need to space out the top and bottom of the box so that it looks as if
  2488. % struts have been applied.
  2489. %
  2490. % \begin{macrocode}
  2491. \def\tab@epar{%
  2492. % \end{macrocode}
  2493. %
  2494. % Anyway, I should end the current paragraph if I'm still in horizontal
  2495. % mode. A simple |\par| will do this nicely. I'll also remove any trailing
  2496. % vertical glue (which may be left there by a list environment), because
  2497. % things will look very strange otherwise.
  2498. %
  2499. % \begin{macrocode}
  2500. \ifhmode\@maybe@unskip\par\fi%
  2501. \unskip%
  2502. % \end{macrocode}
  2503. %
  2504. % Now I'll look at the depth of the last box: if it's less deep than my
  2505. % special strut, I'll cunningly backpedal by a bit, and add a box with the
  2506. % appropriate depth. Since this will lie on the previous baseline, it won't
  2507. % alter the effective height of the box. There's a snag here. |\prevdepth|
  2508. % may be wrong for example if the last thing inserted was a rule, or the
  2509. % box is just empty. Check for this specially. (Thanks to Rowland for
  2510. % spotting this.)
  2511. %
  2512. % \begin{macrocode}
  2513. \ifdim\prevdepth>-\@m\p@\ifdim\prevdepth<\dp\@arstrutbox%
  2514. \kern-\prevdepth%
  2515. \nointerlineskip%
  2516. \vtop to\dp\@arstrutbox{}%
  2517. \fi\fi%
  2518. % \end{macrocode}
  2519. %
  2520. % I've finished the bottom of the box now: I'll close it, and start work on
  2521. % the top again.
  2522. %
  2523. % \begin{macrocode}
  2524. \egroup%
  2525. % \end{macrocode}
  2526. %
  2527. % For top-alignment to work, the first item in the box must be another box.
  2528. % (This is why I couldn't just set |\prevdepth| at the beginning.) If the
  2529. % box isn't high enough, I'll add a box of the right height and then kern
  2530. % backwards so that the `real' first box ends up in the right place.
  2531. %
  2532. % \begin{macrocode}
  2533. \ifdim\ht\z@<\ht\@arstrutbox%
  2534. \vbox to\ht\@arstrutbox{}%
  2535. \kern-\ht\z@%
  2536. \fi%
  2537. \unvbox\z@%
  2538. \egroup%
  2539. }
  2540. % \end{macrocode}
  2541. %
  2542. % \end{macro}
  2543. %
  2544. %
  2545. % \subsection{Gentle persuasion}
  2546. %
  2547. % To persuade \package{longtable} to work, we emulate some features of
  2548. % the \package{array} way of doing things. It's a shame, but we have to do
  2549. % it, because \package{longtable} came first.
  2550. %
  2551. % Note the horribleness with the grouping here. In order to get everything
  2552. % expanded at the right time, |\@preamble| just replaces itself with the (not
  2553. % expanded!) preamble string, using |\the|. This means that the preamble
  2554. % string must be visible in the group just above us. Now,
  2555. % \package{longtable} (and \package{array} for that matter) does
  2556. % |\@mkpreamble| immediately after opening a new group. So all we need to do
  2557. % is close that group, do our stuff, and reopen the group again. (Evil
  2558. % laughter\dots)
  2559. %
  2560. % \begin{macrocode}
  2561. \def\@mkpream#1{%
  2562. \endgroup%
  2563. \colset{tabular}%
  2564. \tab@initread%
  2565. \def\tab@multicol{\@arstrut}%
  2566. \tab@preamble{\tab@multicol}%
  2567. \def\tab@midtext{\ignorespaces\@sharp\@sharp\@maybe@unskip}%
  2568. \tab@readpreamble{#1}%
  2569. \gdef\@preamble{\the\tab@preamble}%
  2570. \let\tab@bgroup\begingroup%
  2571. \let\tab@egroup\endgroup%
  2572. \begingroup%
  2573. }
  2574. % \end{macrocode}
  2575. %
  2576. %
  2577. % \subsection{Debugging}
  2578. %
  2579. % This macro just parses a preamble and displays it on the terminal. It
  2580. % means I can see whether the thing's working.
  2581. %
  2582. % \begin{macrocode}
  2583. \def\showpream#1{%
  2584. \tab@initread%
  2585. \tab@readpreamble{#1}%
  2586. \showthe\tab@preamble%
  2587. \showthe\tab@shortline%
  2588. }
  2589. % \end{macrocode}
  2590. %
  2591. % A quick macro for showing column types.
  2592. %
  2593. % \begin{macrocode}
  2594. \def\showcol#1{%
  2595. \expandafter\show\csname\tab@colset!col.\string#1\endcsname%
  2596. }
  2597. % \end{macrocode}
  2598. %
  2599. %
  2600. % \subsection{The \env{tabular} and \env{array} environments}
  2601. %
  2602. % This is where we define the actual environments which users play with.
  2603. %
  2604. % \subsubsection{The environment routines}
  2605. %
  2606. % The real work is done in the |\@array| macro later. We just set up lots
  2607. % (and I mean \emph{lots}) of parameters first, and then call |\@array|.
  2608. %
  2609. % \begin{macro}{\tab@array}
  2610. %
  2611. % The |\tab@array| macro does most of the common array things.
  2612. %
  2613. % \begin{macrocode}
  2614. \def\tab@array{%
  2615. \tab@width\z@%
  2616. \let\tab@bgroup\tab@bmaths%
  2617. \let\tab@egroup\tab@emaths%
  2618. \@tabarray%
  2619. }
  2620. % \end{macrocode}
  2621. %
  2622. % \end{macro}
  2623. %
  2624. % \begin{macro}{\tab@btext}
  2625. % \begin{macro}{\tab@bmaths}
  2626. % \begin{macro}{\tab@etext}
  2627. % \begin{macro}{\tab@emaths}
  2628. %
  2629. % These macros contain appropriate things to use when typesetting
  2630. % text or maths macros. They're all trivial. They're here only for
  2631. % later modification by funny things like the \env{smarray} environment.
  2632. %
  2633. % \begin{macrocode}
  2634. \def\tab@btext{\begingroup}
  2635. \def\tab@bmaths{$}
  2636. \def\tab@etext{\endgroup}
  2637. \def\tab@emaths{\m@th$}
  2638. % \end{macrocode}
  2639. %
  2640. % \end{macro}
  2641. % \end{macro}
  2642. % \end{macro}
  2643. % \end{macro}
  2644. %
  2645. % \begin{environment}{array}
  2646. %
  2647. % Now for the \env{array} environment. The `|$|' signs act as a group, so we
  2648. % don't need to do extra grouping this time. Closing the environment is
  2649. % easy.
  2650. %
  2651. % \begin{macrocode}
  2652. \def\array{%
  2653. \col@sep\arraycolsep%
  2654. \let\tab@extrasep\arrayextrasep%
  2655. \tab@normalstrut%
  2656. \tab@array%
  2657. }
  2658. \def\endarray{%
  2659. \crcr%
  2660. \egroup%
  2661. \tab@right%
  2662. \tab@restorehlstate%
  2663. }
  2664. % \end{macrocode}
  2665. %
  2666. % \end{environment}
  2667. %
  2668. % \begin{environment}{smarray}
  2669. %
  2670. % Now for something a little different. The \env{smarray} environment
  2671. % gives you an array with lots of small text.
  2672. %
  2673. % \begin{macrocode}
  2674. \def\smarray{%
  2675. \extrarowheight\z@%
  2676. \col@sep\smarraycolsep%
  2677. \let\tab@extrasep\smarrayextrasep%
  2678. \def\tab@bmaths{$\scriptstyle}%
  2679. \def\tab@btext{\begingroup\scriptsize}%
  2680. \setbox\z@\hbox{\scriptsize\strut}%
  2681. \dimen@\ht\z@\dimen\tw@\dp\z@\tab@setstrut%
  2682. \tab@array%
  2683. }
  2684. \let\endsmarray\endarray
  2685. % \end{macrocode}
  2686. %
  2687. % \end{environment}
  2688. %
  2689. % \begin{macro}{\tabstyle}
  2690. %
  2691. % This is a little hook that document designers can use to modify the
  2692. % appearance of tables throughout a document. For example, I've set it to
  2693. % make the text size |\small| in all tables in this document. Macro writers
  2694. % shouldn't try to use it as a hook for their own evilness, though. I've
  2695. % used |\providecommand| to avoid nobbling an existing definition.
  2696. %
  2697. % \begin{macrocode}
  2698. \providecommand\tabstyle{}
  2699. % \end{macrocode}
  2700. %
  2701. % \end{macro}
  2702. %
  2703. % \begin{macro}{\@tabular}
  2704. %
  2705. % The two \env{tabular} environments share lots of common code, so we
  2706. % separate that out. (This needs to be done better.) All we really do here
  2707. % is set up the |\tab@bgroup| and |\tab@egroup| to localise things properly,
  2708. % and then go.
  2709. %
  2710. % \begin{macrocode}
  2711. \def\@tabular#1{%
  2712. \tabstyle%
  2713. \tab@width#1%
  2714. \let\tab@bgroup\tab@btext%
  2715. \let\tab@egroup\tab@etext%
  2716. \col@sep\tabcolsep%
  2717. \let\tab@extrasep\tabextrasep%
  2718. \tab@normalstrut%
  2719. \@tabarray%
  2720. }
  2721. % \end{macrocode}
  2722. %
  2723. % \end{macro}
  2724. %
  2725. % \begin{environment}{tabular}
  2726. % \begin{environment}{tabular*}
  2727. %
  2728. % These environments just call a macro which does all the common stuff.
  2729. %
  2730. % \begin{macrocode}
  2731. \def\tabular{\@tabular\z@}
  2732. \expandafter\let\csname tabular*\endcsname\@tabular
  2733. \let\endtabular\endarray
  2734. \expandafter\let\csname endtabular*\endcsname\endarray
  2735. % \end{macrocode}
  2736. %
  2737. % \end{environment}
  2738. % \end{environment}
  2739. %
  2740. % \subsubsection{Setting the strut height}
  2741. %
  2742. % \begin{macro}{\tab@setstrut}
  2743. %
  2744. % We use a magical strut, called |\@arstrut|, which keeps the table from
  2745. % collapsing around our heads. This is where we set it up.
  2746. %
  2747. % It bases the array strut size on the given values of |\dimen@| and
  2748. % |\dimen\tw@|, amended by various appropriate fiddle values added in by
  2749. % various people.
  2750. %
  2751. % \begin{macrocode}
  2752. \def\tab@setstrut{%
  2753. \setbox\@arstrutbox\hbox{%
  2754. \vrule%
  2755. \@height\arraystretch\dimen@%
  2756. \@depth\arraystretch\dimen\tw@%
  2757. \@width\z@%
  2758. }%
  2759. }
  2760. % \end{macrocode}
  2761. %
  2762. % \end{macro}
  2763. %
  2764. % \begin{macro}{\tab@normalstrut}
  2765. %
  2766. % This sets the strut the normal way, from the size of |\strutbox|.
  2767. %
  2768. % \begin{macrocode}
  2769. \def\tab@normalstrut{%
  2770. \dimen@\ht\strutbox\advance\dimen@\extrarowheight%
  2771. \dimen\tw@\dp\strutbox%
  2772. \tab@setstrut%
  2773. }
  2774. % \end{macrocode}
  2775. %
  2776. % \end{macro}
  2777. %
  2778. % \subsubsection{Setting up the alignment}
  2779. %
  2780. % The following bits are mainly for other packages to hook themselves onto.
  2781. %
  2782. % \begin{macrocode}
  2783. \let\@arrayleft\relax%
  2784. \let\@arrayright\relax%
  2785. % \end{macrocode}
  2786. %
  2787. % \begin{macrocode}
  2788. \def\@tabarray{%
  2789. \let\@arrayleft\relax%
  2790. \let\@arrayright\relax%
  2791. \@ifnextchar[\@array{\@array[c]}%
  2792. }
  2793. % \end{macrocode}
  2794. %
  2795. % \begin{macro}{\@array}
  2796. %
  2797. % The |\@array| macro does most of the real work for the environments. The
  2798. % first job is to set up the row strut, which keeps the table rows at the
  2799. % right height. We just take the normal strut box, and extend its height by
  2800. % the |\extrarowheight| length parameter.
  2801. %
  2802. % \begin{macrocode}
  2803. \def\@array[#1]#2{%
  2804. % \end{macrocode}
  2805. %
  2806. % Sort out the hline state variable. We'll store the old value in a
  2807. % control sequence to avoid wasting any more count registers.
  2808. %
  2809. % \begin{macrocode}
  2810. \edef\tab@restorehlstate{%
  2811. \global\tab@endheight\the\tab@endheight%
  2812. \gdef\noexpand\tab@hlstate{\tab@hlstate}%
  2813. }%
  2814. \def\tab@hlstate{n}%
  2815. % \end{macrocode}
  2816. %
  2817. % Now we read the preamble. All the clever things we've already done are
  2818. % terribly useful here.
  2819. %
  2820. % The |\tab@setcr| sets up |\\| to be a newline even if users have changed it
  2821. % using something like |\raggedright|.
  2822. %
  2823. % \begin{macrocode}
  2824. \colset{tabular}%
  2825. \tab@initread%
  2826. \def\tab@midtext{\tab@setcr\ignorespaces####\@maybe@unskip}%
  2827. \def\tab@multicol{\@arstrut\tab@startrow}%
  2828. \tab@preamble{\tab@multicol\tabskip\z@skip}%
  2829. \tab@readpreamble{#2}%
  2830. % \end{macrocode}
  2831. %
  2832. % Set up the default tabskip glue. This is easy: there isn't any.
  2833. %
  2834. % \begin{macrocode}
  2835. \tab@leftskip\z@skip%
  2836. \tab@rightskip\z@skip%
  2837. % \end{macrocode}
  2838. %
  2839. % Now set up the positioning of the table. This is put into a separate macro
  2840. % because it's rather complicated.
  2841. %
  2842. % \begin{macrocode}
  2843. \tab@setposn{#1}%
  2844. % \end{macrocode}
  2845. %
  2846. % Now work out how to start the alignment.
  2847. %
  2848. % \begin{macrocode}
  2849. \ifdim\tab@width=\z@%
  2850. \def\tab@halign{}%
  2851. \else%
  2852. \def\tab@halign{to\tab@width}%
  2853. \fi%
  2854. % \end{macrocode}
  2855. %
  2856. % Finally, do all the normal things we need to do before an alignment. Note
  2857. % that we define |\tabularnewline| first, then set |\\| from that (using
  2858. % |\tab@setcr|). Since |\\| is reset in the |\tab@midtext| of every table
  2859. % cell, it becomes secondary to |\tabularnewline|. Doing things this way
  2860. % avoids the problems with declarations like |\raggedright| which redefine
  2861. % |\\| in their own (usually rather strange) way, so you don't need to mess
  2862. % about with things like the |\PreserveBackslash| command given in the
  2863. % \textit{\LaTeX\ Companion}.
  2864. %
  2865. % \begin{macrocode}
  2866. \lineskip\z@\baselineskip\z@%
  2867. \m@th%
  2868. \def\tabularnewline{\tab@arraycr\tab@penalty}%
  2869. \tab@setcr%
  2870. \let\par\@empty%
  2871. \everycr{}\tabskip\tab@leftskip%
  2872. \tab@left\halign\tab@halign\expandafter\bgroup%
  2873. \the\tab@preamble\tabskip\tab@rightskip\cr%
  2874. }
  2875. % \end{macrocode}
  2876. %
  2877. % \end{macro}
  2878. %
  2879. % You've no doubt noticed the |\tab@left| and |\tab@right| macros above.
  2880. % These are set up here and elsewhere to allow other things to gain control
  2881. % at various points of the table (they include and take the place of the
  2882. % |\@arrayleft| and |\@arrayright| hooks in \package{array}, put in for
  2883. % \package{delarray}'s use.
  2884. %
  2885. % \subsubsection{Positioning the table}
  2886. %
  2887. % \begin{macro}{\tab@setposn}
  2888. %
  2889. % This macro sets everything up for the table's positioning. It's rather
  2890. % long, but not all that complicated. Honest.
  2891. %
  2892. % First, we set up some defaults (for centring). If anything goes wrong, we
  2893. % just do the centring things.
  2894. %
  2895. % \begin{macrocode}
  2896. \def\tab@setposn#1{%
  2897. \def\tab@left{%
  2898. \savenotes%
  2899. \leavevmode\hbox\bgroup$\@arrayleft\vcenter\bgroup%
  2900. }%
  2901. \def\tab@right{%
  2902. \egroup%
  2903. \m@th\@arrayright$\egroup%
  2904. \spewnotes%
  2905. }%
  2906. \global\tab@endheight\z@%
  2907. % \end{macrocode}
  2908. %
  2909. % For the standard positioning things, we just do appropriate boxing things.
  2910. % Note that the dollar signs are important, since \package{delarray} might
  2911. % want to put its delimiters in here.
  2912. %
  2913. % The |\if@tempswa| switch it used to decide if we're doing an unboxed
  2914. % tabular. We'll set it if we find an unbox-type position code, and then
  2915. % check that everything's OK for this.
  2916. %
  2917. % \begin{macrocode}
  2918. \@tempswafalse%
  2919. \let\tab@penalty\relax%
  2920. \if#1t%
  2921. \def\tab@left{%
  2922. \savenotes%
  2923. \leavevmode\setbox\z@\hbox\bgroup$\@arrayleft\vtop\bgroup%
  2924. }%
  2925. \def\tab@right{%
  2926. \egroup%
  2927. \m@th\@arrayright$\egroup%
  2928. \tab@raisebase%
  2929. \spewnotes%
  2930. }%
  2931. \gdef\tab@hlstate{t}%
  2932. \global\tab@endheight\ht\@arstrutbox%
  2933. \else\if#1b%
  2934. \def\tab@left{%
  2935. \savenotes%
  2936. \leavevmode\setbox\z@\hbox\bgroup$\@arrayleft\vbox\bgroup%
  2937. }%
  2938. \def\tab@right{%
  2939. \egroup%
  2940. \m@th\@arrayright$\egroup%
  2941. \tab@lowerbase%
  2942. \spewnotes%
  2943. }%
  2944. \gdef\tab@hlstate{b}%
  2945. \else%
  2946. \if#1L\@tempswatrue\fi%
  2947. \if#1C\@tempswatrue\fi%
  2948. \if#1R\@tempswatrue\fi%
  2949. \fi\fi%
  2950. % \end{macrocode}
  2951. %
  2952. % Now for some tests to make sure we're allowed to do the unboxing. We text
  2953. % for |\@arrayleft| being defined, because people trying to hook us won't
  2954. % understand unboxed tabulars.
  2955. %
  2956. % \begin{macrocode}
  2957. \if@tempswa\ifhmode%
  2958. \ifinner\tab@err@unbrh\@tempswafalse\else\par\fi%
  2959. \fi\fi%
  2960. \if@tempswa\ifmmode\tab@err@unbmm\@tempswafalse\fi\fi%
  2961. \if@tempswa\ifx\@arrayleft\relax\else%
  2962. \tab@err@unbext\@tempswafalse%
  2963. \fi\fi%
  2964. % \end{macrocode}
  2965. %
  2966. % Finally, if we're still doing an unboxed alignment, we need to sort out the
  2967. % spacing. We know that no-one's tried to hook on to the environment, so we
  2968. % clear |\tab@left| and |\tab@right|.
  2969. %
  2970. % \begin{macrocode}
  2971. \if@tempswa%
  2972. \def\tab@left{\vskip\parskip\medskip}%
  2973. \def\tab@right{\par\@endpetrue\global\@ignoretrue}%
  2974. % \end{macrocode}
  2975. %
  2976. % Now we need to sort out the alignment. The only way we can do this is by
  2977. % playing with tabskip glue. There are two possiblities:
  2978. %
  2979. % \begin{itemize}
  2980. %
  2981. % \item If this is a straight \env{tabular} or an \env{array}, we just use
  2982. % infinite glue. This is reasonable, I think.
  2983. %
  2984. % \item If we have a width for the table, we calculate the fixed values of
  2985. % glue on either side. This is fairly easy, and forces the table to
  2986. % the required width.
  2987. %
  2988. % \end{itemize}
  2989. %
  2990. % First, set up the left and right glues to represent the prevailing
  2991. % margins set up by \env{list} environments. I think this is the right
  2992. % thing to do.
  2993. %
  2994. % \begin{macrocode}
  2995. \tab@leftskip\@totalleftmargin%
  2996. \tab@rightskip\hsize%
  2997. \advance\tab@rightskip-\linewidth%
  2998. \advance\tab@rightskip-\@totalleftmargin%
  2999. % \end{macrocode}
  3000. %
  3001. % First of all, deal with the simple case. I'm using 10000\,fill glue here,
  3002. % in an attempt to suppress |\extracolsep| glue from making the table the
  3003. % wrong width. It can always use filll glue if it really needs to, though.
  3004. %
  3005. % \begin{macrocode}
  3006. \ifdim\tab@width=\z@%
  3007. \if#1L\else\advance\tab@leftskip\z@\@plus10000fill\fi%
  3008. \if#1R\else\advance\tab@rightskip\z@\@plus10000fill\fi%
  3009. % \end{macrocode}
  3010. %
  3011. % Now for the fun bit. This isn't too hard really. The extra space I must
  3012. % add around the table adds up to $|\linewidth| - |\tab@width|$. I just
  3013. % need to add this onto the appropriate sides of the table.
  3014. %
  3015. % \begin{macrocode}
  3016. \else%
  3017. \dimen@\linewidth%
  3018. \advance\dimen@-\tab@width%
  3019. \if#1L\advance\tab@rightskip\dimen@\fi%
  3020. \if#1R\advance\tab@leftskip\dimen@\fi%
  3021. \if#1C%
  3022. \advance\[email protected]\dimen@%
  3023. \advance\[email protected]\dimen@%
  3024. \fi%
  3025. \fi%
  3026. % \end{macrocode}
  3027. %
  3028. % Don't allow page breaks. David Carlisle's wonderful \env{longtable}
  3029. % package does page breaks far better than I could possibly do here, and
  3030. % we're compatible with it (wahey!).
  3031. %
  3032. % \begin{macrocode}
  3033. \def\tab@penalty{\penalty\@M}%
  3034. % \end{macrocode}
  3035. %
  3036. % Finally, set the new width of the table, and leave.
  3037. %
  3038. % \begin{macrocode}
  3039. \tab@width\hsize%
  3040. \fi%
  3041. }
  3042. % \end{macrocode}
  3043. %
  3044. % \end{macro}
  3045. %
  3046. % \subsubsection{Handling tops and bottoms}
  3047. %
  3048. % This is how the tops and bottoms of tables are made to line up with the
  3049. % text on the same line, in the presence of arbitrary rules and space. The
  3050. % old method, based on the way the \package{array} package worked, wasn't
  3051. % terribly good. This new version copes much better with almost anything
  3052. % that gets thrown at it.
  3053. %
  3054. % I'll keep a state in a macro (|\tab@hlstate|), which tells me what I'm
  3055. % meant to be doing. The possible values are \lit{n}, which means I don't
  3056. % have to do anything, \lit{t}, which means that I'm meant to be handling
  3057. % top-aligned tables, and \lit{b}, which means that I'm meant to be lining
  3058. % up the bottom. There are several other `substates' which have various
  3059. % magic meanings.
  3060. %
  3061. % \begin{macrocode}
  3062. \def\tab@hlstate{n}
  3063. % \end{macrocode}
  3064. %
  3065. % When all's said and done, I extract the box containing the table, and
  3066. % play with the height and depth to try and make it correct.
  3067. %
  3068. % \begin{macro}{\tab@addruleheight}
  3069. %
  3070. % This macro is called by `inter-row' things to add their height to our
  3071. % dimen register.
  3072. %
  3073. % Only do this if the state indicates that it's sensible.
  3074. %
  3075. % \begin{macrocode}
  3076. \def\tab@addruleheight#1{%
  3077. \if\tab@hlstate n\else%
  3078. \global\advance\tab@endheight#1\relax%
  3079. \fi%
  3080. }
  3081. % \end{macrocode}
  3082. %
  3083. % \end{macro}
  3084. %
  3085. % \begin{macro}{\tab@startrow}
  3086. %
  3087. % This is called at the start of a row, from within the array preamble.
  3088. % Currently, this assumes that the rows aren't bigger than their struts:
  3089. % this is reasonable, although slightly limiting, and it could be done better
  3090. % if I was willing to rip the alignment apart and put it back together
  3091. % again.
  3092. %
  3093. % \begin{macrocode}
  3094. \def\tab@startrow{%
  3095. \if\tab@hlstate t%
  3096. \gdef\tab@hlstate{n}%
  3097. \else\if\tab@hlstate b%
  3098. \global\tab@endheight\dp\@arstrutbox%
  3099. \fi\fi%
  3100. }
  3101. % \end{macrocode}
  3102. %
  3103. % \end{macro}
  3104. %
  3105. % \begin{macro}{\tab@raisebase}
  3106. %
  3107. % This macro is called at the end of it all, to set the height and depth
  3108. % of the box correctly. It sets the height to |\tab@endheight|, and the
  3109. % depth to everything else. The box is in |\box|~0 currently.
  3110. %
  3111. % \begin{macrocode}
  3112. \def\tab@raisebase{%
  3113. \global\advance\tab@endheight-\ht\z@%
  3114. \raise\tab@endheight\box\z@%
  3115. }
  3116. % \end{macrocode}
  3117. %
  3118. % \end{macro}
  3119. %
  3120. % \begin{macro}{\tab@lowerbase}
  3121. %
  3122. % And, for symmetry's sake, here's how to set the bottom properly instead.
  3123. %
  3124. % \begin{macrocode}
  3125. \def\tab@lowerbase{%
  3126. \global\advance\tab@endheight-\dp\z@%
  3127. \lower\tab@endheight\box\z@%
  3128. }
  3129. % \end{macrocode}
  3130. %
  3131. % \end{macro}
  3132. %
  3133. %
  3134. % \subsection{Breaking tables into bits}
  3135. %
  3136. % Unboxed tables have a wonderful advantage over boxed ones: you can stop
  3137. % halfway through and do something else for a bit. Here's how:
  3138. %
  3139. % \begin{macro}{\tabpause}
  3140. %
  3141. % I'd like to avoid forbidding catcode changes here. I'll use |\doafter|
  3142. % now I've got it, to ensure that colour handling and things occur
  3143. % \emph{inside} the |\noalign| (otherwise they'll mess up the alignment
  3144. % very seriously).
  3145. %
  3146. % We have to be careful here to ensure that everything works correctly within
  3147. % lists. (The \package{amsmath} package had this problem in its
  3148. % |\intertext| macro, so I'm not alone here.)
  3149. %
  3150. % \begin{macrocode}
  3151. \def\tabpause#{%
  3152. \noalign{\ifnum0=`}\fi%
  3153. \@parboxrestore%
  3154. \tab@startpause%
  3155. \vskip-\parskip%
  3156. \parshape\@ne\@totalleftmargin\linewidth%
  3157. \noindent%
  3158. \doafter\tabpause@i%
  3159. }
  3160. \def\tabpause@i{%
  3161. \nobreak%
  3162. \tab@endpause%
  3163. \ifnum0=`{\fi}%
  3164. }
  3165. % \end{macrocode}
  3166. %
  3167. % \end{macro}
  3168. %
  3169. %
  3170. % \subsection{The wonderful world of \cmd\multicolumn}
  3171. %
  3172. % \begin{macro}{\multicolumn}
  3173. %
  3174. % This is actually fantasitcally easy. Watch and learn. Make sure you
  3175. % notice the |\long|s here: remember that some table cells can contain
  3176. % paragraphs, so it seems sensible to allow |\par| into the argument.
  3177. % (As far as I know, most other |\multicolumn| commands don't do this,
  3178. % which seems a little silly. Then again, I forgot to do it the first
  3179. % time around.)
  3180. %
  3181. % \begin{macrocode}
  3182. \long\def\multicolumn#1#2#3{%
  3183. \multispan{#1}%
  3184. \begingroup%
  3185. \tab@multicol%
  3186. \tab@initread%
  3187. \tab@preamble{}%
  3188. \long\def\tab@midtext{#3}%
  3189. \let\tab@looped\tab@err@multi%
  3190. \tab@readpreamble{#2}%
  3191. \the\tab@preamble%
  3192. \endgroup%
  3193. \ignorespaces%
  3194. }
  3195. % \end{macrocode}
  3196. %
  3197. % \end{macro}
  3198. %
  3199. %
  3200. % \subsection{Interlude: range lists}
  3201. %
  3202. % For processing arguments to |\vgap| and |\cline|, we need to be able to
  3203. % do things with lists of column ranges. To save space, and to make my
  3204. % fingers do less typing, here's some routines which do range handling.
  3205. %
  3206. % \begin{macro}{\ranges}
  3207. %
  3208. % Given a macro name and a comma separated list of ranges and simple numbers,
  3209. % this macro will call the macro giving it each range in the list in turn.
  3210. % Single numbers~$n$ will be turned into ranges $n$--$n$.
  3211. %
  3212. % The first job is to read the macro to do (which may already have some
  3213. % arguments attached to it). We'll also start a group to make sure that
  3214. % our changes to temp registers don't affect anyone else.
  3215. %
  3216. % There's a space before the delimiting |\q@delim| to stop numbers being
  3217. % parsed to far and expanding our quark (which will stop \TeX\ dead in its
  3218. % tracks). Since we use |\@ifnextchar| to look ahead, spaces in range lists
  3219. % are perfectly all right.
  3220. %
  3221. % \begin{macrocode}
  3222. \def\ranges#1#2{%
  3223. \gdef\ranges@temp{#1}%
  3224. \begingroup%
  3225. \ranges@i#2 \q@delim%
  3226. }
  3227. % \end{macrocode}
  3228. %
  3229. %
  3230. % We're at the beginning of the list. We expect either the closing marker
  3231. % (if this is an empty list) or a number, which we can scoop up into a
  3232. % scratch register.
  3233. %
  3234. % \begin{macrocode}
  3235. \def\ranges@i{%
  3236. \@ifnextchar\q@delim\ranges@done{\afterassignment\ranges@ii\count@}%
  3237. }
  3238. % \end{macrocode}
  3239. %
  3240. % We've read the first number in the range. If there's another number, we'll
  3241. % expect a `|-|' sign to be next. If there is no `|-|', call the user's code
  3242. % with the number duplicated and then do the rest of the list.
  3243. %
  3244. % \begin{macrocode}
  3245. \def\ranges@ii{%
  3246. \@ifnextchar-\ranges@iii{\ranges@do\count@\count@\ranges@v}%
  3247. }
  3248. % \end{macrocode}
  3249. %
  3250. % Now we strip the `|-|' off and read the other number into a temporary
  3251. % register.
  3252. %
  3253. % \begin{macrocode}
  3254. \def\ranges@iii-{\afterassignment\ranges@iv\@tempcnta}
  3255. % \end{macrocode}
  3256. %
  3257. % We have both ends of the range now, so call the user's code, passing it
  3258. % both ends of the range.
  3259. %
  3260. % \begin{macrocode}
  3261. \def\ranges@iv{\ranges@do\count@\@tempcnta\ranges@v}
  3262. % \end{macrocode}
  3263. %
  3264. % We've finished doing an item now. If we have a `|,|' next, then start
  3265. % over with the next item. Otherwise, if we're at the end of the list,
  3266. % we can end happily. Finally, if we're totally confused, raise an
  3267. % error.
  3268. %
  3269. % \begin{macrocode}
  3270. \def\ranges@v{%
  3271. \@ifnextchar,%
  3272. \ranges@vi%
  3273. {%
  3274. \@ifnextchar\q@delim%
  3275. \ranges@done%
  3276. {\tab@err@range\ranges@vi,}%
  3277. }%
  3278. }
  3279. % \end{macrocode}
  3280. %
  3281. % We had a comma, so gobble it, read the next number, and go round again.
  3282. %
  3283. % \begin{macrocode}
  3284. \def\ranges@vi,{\afterassignment\ranges@ii\count@}
  3285. % \end{macrocode}
  3286. %
  3287. % Here's how we call the user's code, now. We close the group, so that the
  3288. % user's code doesn't have to do global things to remember its results, and
  3289. % we expand the two range ends from their count registers. We also ensure
  3290. % that the range is the right way round.
  3291. %
  3292. % \begin{macrocode}
  3293. \def\ranges@do#1#2{%
  3294. \ifnum#1>#2\else%
  3295. \expandafter\endgroup%
  3296. \expandafter\ranges@temp%
  3297. \expandafter{%
  3298. \the\expandafter#1%
  3299. \expandafter}%
  3300. \expandafter{%
  3301. \the#2%
  3302. }%
  3303. \begingroup%
  3304. \fi%
  3305. }
  3306. % \end{macrocode}
  3307. %
  3308. % And finishing the scan is really easy. We close the group after gobbling
  3309. % the close token.
  3310. %
  3311. % \begin{macrocode}
  3312. \def\ranges@done\q@delim{\endgroup}
  3313. % \end{macrocode}
  3314. %
  3315. % \end{macro}
  3316. %
  3317. % \begin{macro}{\ifinrange}
  3318. %
  3319. % Something a little more useful, now. |\ifinrange| takes four arguments:
  3320. % a number, a range list (as above), and two token lists which I'll call
  3321. % \emph{then} and \emph{else}. If the number is in the list, I'll do
  3322. % \emph{then}, otherwise I'll do \emph{else}.
  3323. %
  3324. % \begin{macrocode}
  3325. \def\ifinrange#1#2{%
  3326. \@tempswafalse%
  3327. \count@#1%
  3328. \ranges\ifinrange@i{#2}%
  3329. \if@tempswa%
  3330. \expandafter\@firstoftwo%
  3331. \else%
  3332. \expandafter\@secondoftwo%
  3333. \fi%
  3334. }
  3335. \def\ifinrange@i#1#2{%
  3336. \ifnum\count@<#1 \else\ifnum\count@>#2 \else\@tempswatrue\fi\fi%
  3337. }
  3338. % \end{macrocode}
  3339. %
  3340. % \end{macro}
  3341. %
  3342. %
  3343. % \subsection{Horizontal rules OK}
  3344. %
  3345. % This is where all the gubbins for |\vgap| and friends is kept, lest it
  3346. % contaminate fairly clean bits of code found elsewhere.
  3347. %
  3348. % \subsubsection{Drawing horizontal rules}
  3349. %
  3350. % \begin{macro}{\hline}
  3351. %
  3352. % Note the funny use of |\noalign| to allow \TeX\ stomach ops like
  3353. % |\futurelet| without starting a new table row. This lets us see if there's
  3354. % another |\hline| coming up, so we can see if we need to insert extra
  3355. % vertical space.
  3356. %
  3357. % \begin{macrocode}
  3358. \def\hline{%
  3359. \tab@dohline%
  3360. \noalign{\ifnum0=`}\fi%
  3361. \tab@penalty%
  3362. \futurelet\@let@token\hline@i%
  3363. }
  3364. % \end{macrocode}
  3365. %
  3366. % We check here for another |\hline| command, and insert glue if there is.
  3367. % This looks terrible, though, and |\hlx{hvh}| is much nicer. Still\dots
  3368. %
  3369. % \begin{macrocode}
  3370. \def\hline@i{%
  3371. \ifx\@let@token\hline%
  3372. \vskip\doublerulesep%
  3373. \tab@addruleheight\doublerulesep%
  3374. \fi%
  3375. \ifnum0=`{\fi}%
  3376. }
  3377. % \end{macrocode}
  3378. %
  3379. % \end{macro}
  3380. %
  3381. % \begin{macro}{\tab@dohline}
  3382. %
  3383. % This is where hlines actually get drawn.
  3384. % Drawing lines is more awkward than it used to be, particularly in unboxed
  3385. % tables. It used to be a case simply of saying |\noalign{\hrule}|.
  3386. % However, since unboxed tables are actually much wider than they look, this
  3387. % would make the rules stretch right across the page and look generally
  3388. % horrible.
  3389. %
  3390. % The solution is simple: we basically do a dirty big |\cline|.
  3391. %
  3392. % \begin{macrocode}
  3393. \def\tab@dohline{%
  3394. \multispan{\tab@columns}%
  3395. \leaders\hrule\@height\arrayrulewidth\hfil%
  3396. \tab@addruleheight\arrayrulewidth%
  3397. \cr%
  3398. }
  3399. % \end{macrocode}
  3400. %
  3401. % \end{macro}
  3402. %
  3403. % \subsubsection{Vertical rules}
  3404. %
  3405. % I couldn't fit these in anywhere else, so they'll have to go here. I'll
  3406. % provide a new optional argument which specifies the width of the rule; this
  3407. % gets rid of the problem described in the \emph{Companion}, where to get
  3408. % an unusually wide vertical rule, you have to play with things like
  3409. % \syntax{"\\vrule width" <dimen>} which really isn't too nice.
  3410. %
  3411. % \begin{macro}{\vline}
  3412. %
  3413. % The new |\vline| has an optional argument which gives the width of the
  3414. % rule. The |\relax| stops \TeX\ trying to parse a \<rule-specification> for
  3415. % too long, in case someone says something like `|\vline depthcharges|' or
  3416. % something equally unlikely.
  3417. %
  3418. % \begin{macrocode}
  3419. \renewcommand\vline[1][\arrayrulewidth]{\vrule\@width#1\relax}
  3420. % \end{macrocode}
  3421. %
  3422. % \end{macro}
  3423. %
  3424. % \subsubsection{Drawing bits of lines}
  3425. %
  3426. % Just for a bit of fun, here's an extended version of |\cline| which takes
  3427. % a list of columns to draw lines under, rather than just a single range.
  3428. %
  3429. % \begin{macro}{\cline}
  3430. %
  3431. % Not a single line of code written yet, and we already have a dilemma on
  3432. % our hands. Multiple consecutive |\cline| commands are meant to draw
  3433. % on the same vertical bit of table. But horizontal lines are meant to have
  3434. % thickness now. Oh, well [sigh], we'll skip back on it after all.
  3435. %
  3436. % Now the problem remains how best to do the job. The way I see it, there
  3437. % are three possibilities:
  3438. %
  3439. % \begin{itemize}
  3440. %
  3441. % \item We can start a table row, and then for each column of the table
  3442. % (as recorded in |\tab@columns|) we look to see if that column is
  3443. % listed in the range list and if so draw the rule. This requires
  3444. % lots of scanning of the range list.
  3445. %
  3446. % \item We can take each range in the list, and draw rules appropriately,
  3447. % just like the old |\cline| used to do, and starting a new table row
  3448. % for each.
  3449. %
  3450. % \item We can start a table row, and then for each range remember where we
  3451. % stopped drawing the last row, move to the start of the new one, and
  3452. % draw it. If we start moving backwards, we close the current row
  3453. % and open a new one.
  3454. %
  3455. % \end{itemize}
  3456. %
  3457. % The last option looks the most efficient, and the most difficult. This
  3458. % is therefore what I shall do |;-)|.
  3459. %
  3460. % The first thing to do is to add in a little negative space, and start a
  3461. % table row (omitting the first item). Then scan the range list, and finally
  3462. % close the table row and add some negative space again.
  3463. %
  3464. % We need a global count register to keep track of where we are. Mixing
  3465. % local and global assignments causes all sorts of tragedy, so I shall hijack
  3466. % |\tab@state|.
  3467. %
  3468. % \begin{macrocode}
  3469. \def\cline#1{%
  3470. \noalign{\kern-.5\arrayrulewidth\tab@penalty}%
  3471. \omit%
  3472. \global\tab@state\@ne%
  3473. \ranges\cline@i{#1}%
  3474. \cr%
  3475. \noalign{\kern-.5\arrayrulewidth\tab@penalty}%
  3476. }
  3477. % \end{macrocode}
  3478. %
  3479. % Now for the tricky bit. When we're given a range, we look to see if the
  3480. % first number is less than |\tab@state|. If so, we quickly close the
  3481. % current row, kern backwards and start again with an |\omit| and reset
  3482. % |\tab@state| to 1, and try again.
  3483. %
  3484. % \begin{macrocode}
  3485. \def\cline@i#1#2{%
  3486. \ifnum#1<\tab@state\relax%
  3487. \tab@@cr%
  3488. \noalign{\kern-\arrayrulewidth\tab@penalty}%
  3489. \omit%
  3490. \global\tab@state\@ne%
  3491. \fi%
  3492. % \end{macrocode}
  3493. %
  3494. % We are now either at or in front of the column position required. If
  3495. % we're too far back, we must |\hfil&\omit| our way over to the correct%
  3496. % column.
  3497. %
  3498. % \begin{macrocode}
  3499. \@whilenum\tab@state<#1\do{%
  3500. \hfil\tab@@tab@omit%
  3501. \global\advance\tab@state\@ne%
  3502. }%
  3503. % \end{macrocode}
  3504. %
  3505. % We've found the start correctly. We must deal with a tiny problem now:
  3506. % if this is not the first table cell, the left hand vertical rule is in the
  3507. % column to the left, so our horizontal rule won't match up properly. So
  3508. % we skip back by a bit to compensate. If there isn't actually a vertical
  3509. % rule to line up with, no-one will notice, because the rules are so thin.
  3510. % This adds a little touch of quality to the whole thing, which is after all
  3511. % the point of this whole exercise.
  3512. %
  3513. % \begin{macrocode}
  3514. \ifnum\tab@state>\@ne%
  3515. \kern-\arrayrulewidth%
  3516. \fi%
  3517. % \end{macrocode}
  3518. %
  3519. % Now we must stretch this table cell to the correct width.
  3520. %
  3521. % \begin{macrocode}
  3522. \@whilenum\tab@state<#2\do{%
  3523. \tab@@span@omit%
  3524. \global\advance\tab@state\@ne%
  3525. }%
  3526. % \end{macrocode}
  3527. %
  3528. % We're ready. Draw the rule. Note that this is |\hfill| glue, just in case
  3529. % we start putting in |\hfil| glue when we step onto the next cell.
  3530. %
  3531. % \begin{macrocode}
  3532. \leaders\hrule\@height\arrayrulewidth\hfill%
  3533. }
  3534. % \end{macrocode}
  3535. %
  3536. % Some alignment primitives are hidden inside macros so they don't get seen
  3537. % at the wrong time. This is what they look like:
  3538. %
  3539. % \begin{macrocode}
  3540. \def\tab@@cr{\cr}
  3541. \def\tab@@tab@omit{&\omit}
  3542. \def\tab@@span@omit{\span\omit}
  3543. % \end{macrocode}
  3544. %
  3545. % \end{macro}
  3546. %
  3547. % \subsubsection{Drawing short table rows}
  3548. %
  3549. % Before I start on a description of more code, I think I'll briefly discuss
  3550. % my reasons for leaving the |\vgap| command in its current state. There's a
  3551. % reasonable case for introducing an interface between |\vgap| and
  3552. % |\multicolumn|, to avoid all the tedious messing about with column
  3553. % ranges. There are good reasons why I'm not going to do this:
  3554. %
  3555. % \begin{itemize}
  3556. %
  3557. % \item It's very difficult to do: it requires either postprocessing of
  3558. % the table or delaying processing of each row until I know exactly
  3559. % what's in it; a |\multicolumn| in a row should be able to affect
  3560. % a |\vgap| before the row, which gets very nasty. This package is
  3561. % probably far too large already, and adding more complexity and
  3562. % running the risk of exhausting \TeX's frustratingly finite capacity
  3563. % for the sake of relieving the user of a fairly trivial job doesn't
  3564. % seem worthwhile.
  3565. %
  3566. % \item Perhaps more importantly, there are perfectly valid occasions when
  3567. % it's useful to have the current vgap behaviour. For example, the
  3568. % \texttt{MIX} word layout diagrams found in \emph{The Art of
  3569. % Computer Programming} use the little `stub lines' to show where
  3570. % data items cross byte boundaries:
  3571. %
  3572. % ^^A This actually looks terrifyingly similar to the original.
  3573. % ^^A The leading @{} is there to stop the table looking off-centre,
  3574. % ^^A because there's no left hand rule telling you where the table
  3575. % ^^A starts, like there is on the right, just the \tabcolsep glue.
  3576. %
  3577. % \begingroup
  3578. % \newcommand{\wide}[2]{\multicolumn{#1}{c|}{\ttfamily #2}}
  3579. % \begin{tabular}[C]{@{} r @{\qquad} | Mc | *{5}{c|}} \hlx{c{2-7} v}
  3580. % empty & - & 1 & 0 & 0 & 0 & 0 \\ \hlx{v c{2-7} v}
  3581. % occupied & + & \wide{2}{LINK} & \wide{3}{KEY} \\ \hlx{v c{2-7}}
  3582. % \end{tabular}
  3583. % \endgroup
  3584. %
  3585. % \end{itemize}
  3586. %
  3587. % That's my excuses out of the way; now I'll press on with the actual
  3588. % programming.
  3589. %
  3590. % \begin{macro}{\tab@checkrule}
  3591. %
  3592. % We have a range list in |\tab@xcols| and a number as an argument. If we
  3593. % find the number in the list, wejust space out the following group,
  3594. % otherwise we let it be.
  3595. %
  3596. % \begin{macrocode}
  3597. \def\tab@checkrule#1{%
  3598. \count@#1\relax%
  3599. \expandafter\ifinrange%
  3600. \expandafter\count@%
  3601. \expandafter{\tab@xcols}%
  3602. {\tab@checkrule@i}%
  3603. {}%
  3604. }
  3605. \def\tab@checkrule@i#1{\setbox\z@\hbox{#1}\hb@xt@\wd\z@{}}
  3606. % \end{macrocode}
  3607. %
  3608. % \end{macro}
  3609. %
  3610. % \begin{macro}{\vgap}
  3611. %
  3612. % We must tread carefully here. A single misplaced stomach operation can
  3613. % cause error messages. We therefore start with an |\omit| so we can search
  3614. % for optional arguments.
  3615. %
  3616. % So that |\hlx| can get control after |\vgap| has finished, we provide a
  3617. % hook called |\vgap@after| which is expanded after |\vgap| has finished.
  3618. % Here we make it work like |\@empty|, which expands to nothing. (Note that
  3619. % |\relax| will start a new table row, so we can't use that.) There are
  3620. % some penalty items here to stick the |\vgap| row to the text row and
  3621. % |\hline| that are adjacent to it. The \package{longtable} package will
  3622. % split an |\hline| in half, so this is the correct thing to do.
  3623. %
  3624. % \begin{macrocode}
  3625. \def\vgap{%
  3626. \noalign{\nobreak}%
  3627. \omit%
  3628. \global\let\vgap@after\@empty%
  3629. \iffalse{\fi\ifnum0=`}\fi%
  3630. \@ifnextchar[\vgap@i\vgap@simple%
  3631. }
  3632. % \end{macrocode}
  3633. %
  3634. % We set up two different sorts of |\vgap| -- a simple one which allows all
  3635. % rules to be passed through, and a specific one which carefully vets each
  3636. % one (and is therefore slower). We decide which to so based on the presence
  3637. % of an optional argument.
  3638. %
  3639. % The optional argument handler just passes its argument to an interface
  3640. % routine which is used by |\hlx|.
  3641. %
  3642. % \begin{macrocode}
  3643. \def\vgap@i[#1]{\vgap@spec{#1}}
  3644. % \end{macrocode}
  3645. %
  3646. % Now we handle specified columns. Since we're in an omitted table cell, we
  3647. % must set things up globally. Assign the column spec to a macro, and set up
  3648. % vetting by the routine above. Then just go and do the job.
  3649. %
  3650. % \begin{macrocode}
  3651. \def\vgap@spec#1#2{%
  3652. \gdef\tab@xcols{#1}%
  3653. \global\let\tab@ckr\tab@checkrule%
  3654. \vgap@do{#2}%
  3655. }
  3656. % \end{macrocode}
  3657. %
  3658. % Handle all columns. Just gobble the column number for each rule, and let
  3659. % the drawing pass unharmed. Easy.
  3660. %
  3661. % \begin{macrocode}
  3662. \def\vgap@simple#1{%
  3663. \global\let\tab@ckr\@gobble%
  3664. \vgap@do{#1}%
  3665. }
  3666. % \end{macrocode}
  3667. %
  3668. % This is where stuff actually gets done. We set the |\vgap| flag on while
  3669. % we do the short row. Then just expand the token list we built while
  3670. % scanning the preamble.
  3671. %
  3672. % Note that the flag is cleared at the end of the last column, to allow other
  3673. % funny things like |\noalign| and |\omit| before a new row is started.
  3674. %
  3675. % \begin{macrocode}
  3676. \def\vgap@do#1{%
  3677. \ifnum0=`{}\fi%
  3678. \global\tab@vgaptrue%
  3679. \the\tab@shortline%
  3680. \vrule\@height#1\@width\z@%
  3681. \global\tab@vgapfalse
  3682. \tab@addruleheight{#1}%
  3683. \cr%
  3684. \noalign{\nobreak}%
  3685. \vgap@after%
  3686. }
  3687. % \end{macrocode}
  3688. %
  3689. % \end{macro}
  3690. %
  3691. % \subsubsection{Prettifying syntax}
  3692. %
  3693. % \begin{macro}{\hlx}
  3694. %
  3695. % This is like a poor cousin to the preamble parser. The whole loop is
  3696. % carefully written to take place \emph{only} in \TeX's mouth, so the
  3697. % alignment handling bits half way down the gullet don't see any of this.
  3698. %
  3699. % First, pass the string to another routine.
  3700. %
  3701. % \begin{macrocode}
  3702. \def\hlx#1{\hlx@loop#1\q@delim}
  3703. % \end{macrocode}
  3704. %
  3705. % Now peel off a token, and dispatch using |\csname|. We handle
  3706. % undefinedness of the command in a fairly messy way, although it probably
  3707. % works. Maybe.
  3708. %
  3709. % \begin{macrocode}
  3710. \def\hlx@loop#1{%
  3711. \ifx#1\q@delim\else%
  3712. \@ifundefined{hlx@cmd@\string#1}{%
  3713. \expandafter\hlx@loop%
  3714. }{%
  3715. \csname hlx@cmd@\string#1\expandafter\endcsname%
  3716. }%
  3717. \fi%
  3718. }
  3719. % \end{macrocode}
  3720. %
  3721. % \end{macro}
  3722. %
  3723. % \begin{macro}{\hlxdef}
  3724. %
  3725. % New |\hlx| commands can be defined using |\hlxdef|. This is a simple
  3726. % abbreviation.
  3727. %
  3728. % \begin{macrocode}
  3729. \def\hlxdef#1{\@namedef{hlx@cmd@#1}}
  3730. % \end{macrocode}
  3731. %
  3732. % \end{macro}
  3733. %
  3734. % \begin{macro}{\hlx h}
  3735. %
  3736. % Handle an \lit{h} character. Just do an |\hline| and return to the loop.
  3737. % We look ahead to see if there's another \lit{h} coming up, and if so
  3738. % insert two |\hline| commands. This strange (and inefficient) behaviour
  3739. % keeps packages which redefine |\hline| happy.
  3740. %
  3741. % \begin{macrocode}
  3742. \hlxdef h#1{%
  3743. \noalign{%
  3744. \ifx#1h%
  3745. \def\@tempa{\hline\hline\hlx@loop}%
  3746. \else%
  3747. \def\@tempa{\hline\hlx@loop#1}%
  3748. \fi%
  3749. \expandafter
  3750. }%
  3751. \@tempa%
  3752. }
  3753. % \end{macrocode}
  3754. %
  3755. % \end{macro}
  3756. %
  3757. % \begin{macro}{\hlx b}
  3758. %
  3759. % The \lit{b} character does a nifty backspace, for \package{longtable}'s
  3760. % benefit.
  3761. %
  3762. % \begin{macrocode}
  3763. \hlxdef b{\noalign{\kern-\arrayrulewidth}\hlx@loop}
  3764. % \end{macrocode}
  3765. %
  3766. % \end{macro}
  3767. %
  3768. % \begin{macro}{\hlx /}
  3769. %
  3770. % The `"/"' character allows a page break at the current position.
  3771. %
  3772. % \begin{macrocode}
  3773. \hlxdef /{%
  3774. \noalign{\ifnum0=`}\fi%
  3775. \@ifnextchar[\hlx@cmd@break@i{\hlx@cmd@break@i[0]}%
  3776. }
  3777. \def\hlx@cmd@break@i[#1]{\ifnum0=`{\fi}\pagebreak[0]\hlx@loop}
  3778. % \end{macrocode}
  3779. %
  3780. % \end{macro}
  3781. %
  3782. % \begin{macro}{\hlx v}
  3783. %
  3784. % Handle a \lit{v} character. This is rather like the |\vgap| code above,
  3785. % although there are syntactic differences.
  3786. %
  3787. % \begin{macrocode}
  3788. \hlxdef v{%
  3789. \noalign{\nobreak}%
  3790. \omit%
  3791. \iffalse{\fi\ifnum0=`}\fi%
  3792. \global\let\vgap@after\hlx@loop%
  3793. \@ifnextchar[\hlx@vgap@i{\hlx@vgap@ii\vgap@simple}%
  3794. }
  3795. \def\hlx@vgap@i[#1]{%
  3796. \ifx!#1!%
  3797. \def\@tempa{\hlx@vgap@ii\vgap@simple}%
  3798. \else%
  3799. \def\@tempa{\hlx@vgap@ii{\vgap@spec{#1}}}%
  3800. \fi%
  3801. \@tempa%
  3802. }
  3803. \def\hlx@vgap@ii#1{%
  3804. \@ifnextchar[{\hlx@vgap@iii{#1}}{\hlx@vgap@iii{#1}[\doublerulesep]}%
  3805. }
  3806. \def\hlx@vgap@iii#1[#2]{#1{#2}}
  3807. % \end{macrocode}
  3808. %
  3809. % \end{macro}
  3810. %
  3811. % \begin{macro}{\hlx s}
  3812. %
  3813. % Allow the user to leave a small gap using the \lit{s} command.
  3814. %
  3815. % \begin{macrocode}
  3816. \hlxdef s{%
  3817. \noalign{\ifnum0=`}\fi%
  3818. \nobreak%
  3819. \@ifnextchar[\hlx@space@i{\hlx@space@i[\doublerulesep]}%
  3820. }
  3821. \def\hlx@space@i[#1]{%
  3822. \vskip#1%
  3823. \tab@addruleheight{#1}%
  3824. \ifnum0=`{\fi}%
  3825. \hlx@loop%
  3826. }
  3827. % \end{macrocode}
  3828. %
  3829. % \end{macro}
  3830. %
  3831. % \begin{macro}{\hlx c}
  3832. %
  3833. % We might as well allow a \lit{c} command to do a |\cline|.
  3834. %
  3835. % \begin{macrocode}
  3836. \hlxdef c#1{\cline{#1}\hlx@loop}
  3837. % \end{macrocode}
  3838. %
  3839. % \end{macro}
  3840. %
  3841. % \begin{macro}{\hlx .}
  3842. %
  3843. % The \lit{.} character forces a start of the new column. There's a little
  3844. % problem here. Since the \lit{.} character starts the next column, we need
  3845. % to gobble any spaces following the |\hlx| command before the cell contents
  3846. % actually starts. Unfortunately, |\ignorespaces| will start the column for
  3847. % us, so we can't put it in always. We'll handle it here, then. We'll take
  3848. % the rest of the `preamble' string, and warn if it's not empty. Then we'll
  3849. % |\ignorespaces| -- this will start the column for us, so we don't need to
  3850. % |\relax| any more.
  3851. %
  3852. % \begin{macrocode}
  3853. \hlxdef .#1\q@delim{%
  3854. \ifx @#1@\else%
  3855. \PackageWarning{mdwtab}{%
  3856. Ignoring \protect\hlx\space command characters following a
  3857. `.'\MessageBreak command%
  3858. }%
  3859. \fi%
  3860. \ignorespaces%
  3861. }
  3862. % \end{macrocode}
  3863. %
  3864. % \end{macro}
  3865. %
  3866. %
  3867. % \subsection{Starting new table rows}
  3868. %
  3869. % We take a break from careful mouthery at last, and start playing with
  3870. % newlines. The standard one allows pagebreaks in unboxed tables, which
  3871. % isn't really too desirable.
  3872. %
  3873. % Anyway, we'll try to make this macro rather more reusable than the standard
  3874. % one. Here goes.
  3875. %
  3876. % \begin{macro}{\@arraycr}
  3877. %
  3878. % We pass lots of information to a main parser macro, and expect it to cope.
  3879. %
  3880. % \begin{macrocode}
  3881. \def\@arraycr{\tab@arraycr{}}
  3882. \def\tab@arraycr#1{\tab@cr{\tab@tabcr{#1}}{}{}}
  3883. % \end{macrocode}
  3884. %
  3885. % Now to actually do the work. |\tab@cr| passes us the skip size, and the
  3886. % appropriate one of the two arguments given above (both of which are empty)
  3887. % depending on the presence of the $*$.
  3888. %
  3889. % \begin{macrocode}
  3890. \def\tab@tabcr#1#2{%
  3891. % \end{macrocode}
  3892. %
  3893. % If the total height I need to add between rows (from the optional argument
  3894. % and the `extrasep' parameter) is greater than zero, I'll handle this by
  3895. % extending the strut slightly. I'm not actually sure whether this is the
  3896. % right thing to do, to be honest, although it's easier than trying to
  3897. % to an automatic |\vgap|, because I need to know which columns to skip.
  3898. % If the space is less than zero, I'll just insert the vertical space with
  3899. % in a |\noalign|.
  3900. %
  3901. % First, to calculate how much space needs adding.
  3902. %
  3903. % \begin{macrocode}
  3904. \dimen@#2%
  3905. \advance\dimen@\tab@extrasep%
  3906. % \end{macrocode}
  3907. %
  3908. % If the height is greater than zero, I need to play with the strut. I must
  3909. % bear in mind that the current table cell (which I'm still in, remember)
  3910. % may be in vertical mode, and I may or may not be in a paragraph.
  3911. %
  3912. % If I am in vertical mode, I'll backpedal to the previous box and put the
  3913. % strut in an hbox superimposed on the previous baseline. Otherwise, I can
  3914. % just put the strut at the end of the text. (This works in either LR
  3915. % or paragraph mode as long as I'm not between paragraphs.) Again, Rowland's
  3916. % empty cell bug strikes. (See |\tab@epar| for details.)
  3917. %
  3918. % \begin{macrocode}
  3919. \ifdim\dimen@>\z@%
  3920. \ifvmode%
  3921. \unskip\ifdim\prevdepth>-\@m\p@\kern-\prevdepth\fi%
  3922. \nointerlineskip\expandafter\hbox%
  3923. \else%
  3924. \@maybe@unskip\expandafter\@firstofone%
  3925. \fi%
  3926. {\advance\dimen@\dp\@arstrutbox\vrule\@depth\dimen@\@width\z@}%
  3927. \fi%
  3928. % \end{macrocode}
  3929. %
  3930. % This table cell works as a group (which is annoying here). I'll copy the
  3931. % interrow gap into a global register so that I can use it in the |\noalign|.
  3932. %
  3933. % \begin{macrocode}
  3934. \global\dimen\@ne\dimen@%
  3935. \cr%
  3936. \noalign{%
  3937. #1%
  3938. \ifdim\dimen\@ne<\z@\vskip\dimen\@ne\relax\fi%
  3939. }%
  3940. \@gobble%
  3941. }
  3942. % \end{macrocode}
  3943. %
  3944. % \end{macro}
  3945. %
  3946. % \begin{macro}{\tab@setcr}
  3947. %
  3948. % To set the |\\| command correctly in each table cell, we make it a part of
  3949. % the preamble (in |\tab@midtext|) to call this routine. It's easy -- just
  3950. % saves the preamble from being huge.
  3951. %
  3952. % \begin{macrocode}
  3953. \def\tab@setcr{\let\\\tabularnewline}
  3954. % \end{macrocode}
  3955. %
  3956. % \end{macro}
  3957. %
  3958. % \begin{macro}{\tab@cr}
  3959. %
  3960. % Now we do the parsing work. This is fun. Note the revenge of the funny
  3961. % braces here. Nothing to worry about, honest. The tricky bit is to keep
  3962. % track of which arguments are which. (Thanks to David Carlisle for pointing
  3963. % out that I'd missed out the |\relax| here.)
  3964. %
  3965. % \begin{macrocode}
  3966. \def\tab@cr#1#2#3{%
  3967. \relax%
  3968. \iffalse{\fi\ifnum0=`}\fi%
  3969. \@ifstar{\tab@cr@i{#1}{#3}}{\tab@cr@i{#1}{#2}}%
  3970. }
  3971. \def\tab@cr@i#1#2{%
  3972. \@ifnextchar[{\tab@cr@ii{#1}{#2}}{\tab@cr@ii{#1}{#2}[\z@]}%
  3973. }
  3974. \def\tab@cr@ii#1#2[#3]{%
  3975. \ifnum0=`{}\fi%
  3976. #1{#3}{#2}%
  3977. }
  3978. % \end{macrocode}
  3979. %
  3980. % \end{macro}
  3981. %
  3982. %
  3983. % \subsection{Gratuitous grotesquery}
  3984. %
  3985. % So far we've had an easy-ish ride (or should that be \emph{queasy}?). Now
  3986. % for something unexplainably evil. We convince \LaTeX\ that it's loaded the
  3987. % \package{array} package, so that packages which need it think they've got
  3988. % it.
  3989. %
  3990. % The bogus date is the same as the date for the \package{array} package I've
  3991. % got here -- this will raise a warning if Frank updates his package which
  3992. % should filter back to me telling me that there's something I need to
  3993. % know about.
  3994. %
  3995. % The messing with |\xdef| and the funny parsing ought to insert the current
  3996. % \package{mdwtab} version and date into the fake \package{array} version
  3997. % string, giving a visible clue to the user that this isn't the real
  3998. % \package{array} package.
  3999. %
  4000. % \begin{macrocode}
  4001. \begingroup
  4002. \catcode`.=11
  4003. \def\@tempa#1 #2 #3\@@{#1 #2}
  4004. \xdef\[email protected]
  4005. {1995/11/19 [mdwtab.sty \expandafter\@tempa\[email protected]\@@]}
  4006. \endgroup
  4007. % \end{macrocode}
  4008. %
  4009. %
  4010. % \subsection{Error messages}
  4011. %
  4012. % I've put all the error messages together, where I can find them, translate
  4013. % them or whatever.
  4014. %
  4015. % First, some token-space saving (which also saves my fingers):
  4016. %
  4017. % \begin{macrocode}
  4018. \def\tab@error{\PackageError{mdwtab}}
  4019. % \end{macrocode}
  4020. %
  4021. % Now do the error messages.
  4022. %
  4023. % \begin{macrocode}
  4024. \def\tab@err@misscol{%
  4025. \tab@error{Missing column type}{%
  4026. I'm lost. I was expecting something describing^^J%
  4027. the type of the current column, but you seem to^^J%
  4028. have missed it out. I've inserted a type `l'^^J%
  4029. column here in the hope that this makes sense.%
  4030. }%
  4031. }
  4032. % \end{macrocode}
  4033. %
  4034. % \begin{macrocode}
  4035. \def\tab@err@oddgroup{%
  4036. \tab@error{Misplaced group in table preamble}{%
  4037. I've found an open brace character in your preamble^^J%
  4038. when I was expecting a specifier character. I'm^^J%
  4039. going to gobble the whole group and carry on as if^^J%
  4040. I'd never seen it.%
  4041. }%
  4042. }
  4043. % \end{macrocode}
  4044. %
  4045. % \begin{macrocode}
  4046. \def\tab@err@undef#1{%
  4047. \tab@error{Unknown `\tab@colset' preamble character `\string#1'}{%
  4048. I don't understand what you meant by typing this^^J%
  4049. character. Anyway, I'll ignore it this time around.^^J%
  4050. Just don't you do it again.%
  4051. }%
  4052. }
  4053. % \end{macrocode}
  4054. %
  4055. % \begin{macrocode}
  4056. \def\tab@err@unbrh{%
  4057. \tab@error{Can't use unboxed tabular in LR mode}{%
  4058. You've asked for a tabular or array environment with^^J%
  4059. `L', `C' or `R' as the position specifier, but you're^^J%
  4060. in LR (restricted horizontal) mode, so it won't work.^^J%
  4061. I'll assume you really meant `c' and soldier on.%
  4062. }%
  4063. }
  4064. % \end{macrocode}
  4065. %
  4066. % \begin{macrocode}
  4067. \def\tab@err@unbmm{%
  4068. \tab@error{Can't use unboxed tabular in maths mode}{%
  4069. You've asked for a tabular or array environment with^^J%
  4070. `L', `C' or `R' as the position specifier, but you're^^J%
  4071. in maths mode, so it won't work. I'll pretend that^^J%
  4072. you really typed `c', and that this is all a bad dream.%
  4073. }%
  4074. }
  4075. % \end{macrocode}
  4076. %
  4077. % \begin{macrocode}
  4078. \def\tab@err@unbext{%
  4079. \tab@error{Can't extend unboxed tabulars}{%
  4080. You're trying to use kludgy extensions (e.g.,^^J%
  4081. `delarray') on an array or tabular with `L', `C'^^J%
  4082. or `R' as the position specifier. I'll assume you^^J%
  4083. subconsciously wanted a `c' type all along.%
  4084. }%
  4085. }
  4086. % \end{macrocode}
  4087. %
  4088. % \begin{macrocode}
  4089. \def\tab@err@multi{%
  4090. \tab@error{More than one column in a \protect\multicolumn}{%
  4091. You've put more than one column into a \string\multicolumn^^J%
  4092. descriptor. It won't work. I have no idea what^^J%
  4093. will happen, although it won't be pleasant. Hold^^J%
  4094. on tight now...%
  4095. }%
  4096. }
  4097. % \end{macrocode}
  4098. %
  4099. % \begin{macrocode}
  4100. \def\tab@err@range{%
  4101. \tab@error{Expected `,' or `<end>' in range list}{%
  4102. I was expecting either the end of the range list,^^J%
  4103. or a comma, followed by another range. I've^^J%
  4104. inserted a comma to try and get me back on track.^^J%
  4105. Good luck.%
  4106. }%
  4107. }
  4108. % \end{macrocode}
  4109. %
  4110. % That's it. No more. Move along please.
  4111. %
  4112. % \begin{macrocode}
  4113. %</mdwtab>
  4114. % \end{macrocode}
  4115. %
  4116. %
  4117. %^^A-------------------------------------------------------------------------
  4118. % \section{Implementation of \package{mathenv}}
  4119. %
  4120. %
  4121. % This is in a separate package, mainly to avoid wasting people's memory.
  4122. %
  4123. % \begin{macrocode}
  4124. %<*mathenv>
  4125. % \end{macrocode}
  4126. %
  4127. %
  4128. % \subsection{Options handling}
  4129. %
  4130. % We need to be able to cope with \textsf{fleqn} and \textsf{leqno} options.
  4131. % This will adjust our magic modified \env{eqnarray} environment
  4132. % appropriately.
  4133. %
  4134. % \begin{macrocode}
  4135. \newif\if@fleqn
  4136. \newif\if@leqno
  4137. \DeclareOption{fleqn}{\@fleqntrue}
  4138. \DeclareOption{leqno}{\@leqnotrue}
  4139. \ProcessOptions
  4140. % \end{macrocode}
  4141. %
  4142. % We use the \package{mdwtab} package for all its nice table handling things.
  4143. % (Oh, and to inflict it on users who want to do nice equations and don't
  4144. % care about our tables.)
  4145. %
  4146. % \begin{macrocode}
  4147. \RequirePackage{mdwtab}
  4148. % \end{macrocode}
  4149. %
  4150. %
  4151. % \subsection{Some useful registers}
  4152. %
  4153. % The old \LaTeX\ version puts the equation numbers in by keeping a count of
  4154. % where it is in the alignment. Since I don't know how may columns there are
  4155. % going to be, I'll just use a switch in the preamble to tell me to stop
  4156. % tabbing.
  4157. %
  4158. % \begin{macrocode}
  4159. \newif\if@eqalast
  4160. % \end{macrocode}
  4161. %
  4162. % Now define some useful length parameters. First allocate them:
  4163. %
  4164. % \begin{macrocode}
  4165. \newskip\eqaopenskip
  4166. \newskip\eqacloseskip
  4167. \newskip\eqacolskip
  4168. \newskip\eqainskip
  4169. \newskip\splitleft
  4170. \newskip\splitright
  4171. % \end{macrocode}
  4172. %
  4173. % Now assign some default values. Users can play with these if they really
  4174. % want although I can't see the point myself.
  4175. %
  4176. % \begin{macrocode}
  4177. \AtBeginDocument{%
  4178. \eqacloseskip\@centering%
  4179. \eqacolskip1.5em\@plus\@m\p@
  4180. \eqainskip\z@%
  4181. \if@fleqn%
  4182. \eqaopenskip\mathindent%
  4183. \splitleft\mathindent\relax%
  4184. \splitright\mathindent\@minus\mathindent\relax%
  4185. \else%
  4186. \eqaopenskip\@centering%
  4187. \splitleft2.5em\@minus2.5em%
  4188. \splitright\splitleft%
  4189. \fi%
  4190. \relax%
  4191. }
  4192. % \end{macrocode}
  4193. %
  4194. %
  4195. % \subsection{A little display handling}
  4196. %
  4197. % I'm probably going a little far here, and invading territory already
  4198. % claimed by the \package{amsmath} stuff (and done a good deal better than
  4199. % I can be bothered to do), but just for completeness, this is how we handle
  4200. % attempts to put displays inside other displays without screwing up the
  4201. % spacing.
  4202. %
  4203. % \begin{macro}{\dsp@startouter}
  4204. %
  4205. % This is how we start an outermost display. It's fairly easy really. We
  4206. % make |\dsp@start| start an inner display, and make |\dsp@end| close the
  4207. % outer display.
  4208. %
  4209. % \begin{macrocode}
  4210. \def\dsp@startouter{%
  4211. \let\dsp@end\dsp@endouter%
  4212. $$%
  4213. }
  4214. % \end{macrocode}
  4215. %
  4216. % \end{macro}
  4217. %
  4218. % \begin{macro}{\dsp@endouter}
  4219. %
  4220. % Ending the outer display is utterly trivial.
  4221. %
  4222. % \begin{macrocode}
  4223. \def\dsp@endouter{$$}
  4224. % \end{macrocode}
  4225. %
  4226. % \end{macro}
  4227. %
  4228. % \begin{macro}{\dsp@startinner}
  4229. %
  4230. % Starting inner displays is done in a vbox (actually I choose |\vbox| or
  4231. % |\vtop| depending on the setting of \textsf{leqno} to put the equation
  4232. % number the right way round).
  4233. %
  4234. % \begin{macrocode}
  4235. \def\dsp@startinner{%
  4236. \let\dsp@end\dsp@endinner%
  4237. \if@fleqn\kern-\mathindent\fi%
  4238. \if@leqno\vtop\else\vtop\fi\bgroup%
  4239. }
  4240. % \end{macrocode}
  4241. %
  4242. % \end{macro}
  4243. %
  4244. % \begin{macro}{\dsp@endinner}
  4245. %
  4246. % Ending an inner display is also really easy.
  4247. %
  4248. % \begin{macrocode}
  4249. \def\dsp@endinner{\egroup}
  4250. % \end{macrocode}
  4251. %
  4252. % \end{macro}
  4253. %
  4254. % \begin{macro}{\dsp@start}
  4255. %
  4256. % This is what other bits of code uses to start displays. It's one of the
  4257. % start macros up above, and outer by default.
  4258. %
  4259. % \begin{macrocode}
  4260. \def\dsp@start{%
  4261. \ifmmode%
  4262. \ifinner\mth@err@mdsp\fi%
  4263. \expandafter\dsp@startinner%
  4264. \else%
  4265. \ifhmode\ifinner\mth@err@hdsp\fi\fi%
  4266. \expandafter\dsp@startouter%
  4267. \fi%
  4268. }
  4269. % \end{macrocode}
  4270. %
  4271. % \end{macro}
  4272. %
  4273. % \begin{macro}{\dsp@tabpause}
  4274. %
  4275. % This sets up the correct pre- and postambles for the |\tabpause| macro in
  4276. % maths displays. This is fairly simple stuff.
  4277. %
  4278. % \begin{macrocode}
  4279. \def\dsp@tabpause{%
  4280. \def\tab@startpause%
  4281. {\penalty\postdisplaypenalty\vskip\belowdisplayskip}%
  4282. \def\tab@endpause%
  4283. {\penalty\predisplaypenalty\vskip\abovedisplayskip}%
  4284. }
  4285. % \end{macrocode}
  4286. %
  4287. % \end{macro}
  4288. %
  4289. %
  4290. % \subsection{The \env{eqnarray} environment}
  4291. %
  4292. % We allow the user to play with the style if this is really wanted. I dunno
  4293. % why, really. Maybe someone wants very small alignments.
  4294. %
  4295. % \begin{macrocode}
  4296. \let\eqastyle\displaystyle
  4297. % \end{macrocode}
  4298. %
  4299. % \subsubsection{The main environments}
  4300. %
  4301. % \begin{environment}{eqnarray}
  4302. % \begin{environment}{eqnarray*}
  4303. %
  4304. % We define the toplevel commands here. They just add in default arguments
  4305. % and then call |\@eqnarray| with a preamble string. We handle equation
  4306. % numbers by setting up a default (|\eqa@defnumber|) which is put into
  4307. % the final column. At the beginning of each row, we globally |\let|
  4308. % |\eqa@number| equal to |\eqa@defnumber|. The |\eqnumber| macro just
  4309. % changes |\eqa@number| as required. Since |\eqa@number| is changed globally
  4310. % we must save it in this environment.
  4311. %
  4312. % First, we must sort out the optional arguments and things. This is really
  4313. % easy. The only difference between the starred and non-starred environments
  4314. % is the default definition of |\eqa@defnumber|.
  4315. %
  4316. % \begin{macrocode}
  4317. \def\eqnarray{%
  4318. \eqnarray@i\eqa@eqcount%
  4319. }
  4320. \@namedef{eqnarray*}{\eqnarray@i{}}
  4321. \def\eqnarray@i#1{\@ifnextchar[{\eqnarray@ii{#1}}{\eqnarray@ii{#1}[rcl]}}
  4322. % \end{macrocode}
  4323. %
  4324. % Right. Now for the real work. The first argument is the default numbering
  4325. % tokens; the second is the preamble string.
  4326. %
  4327. % \begin{macrocode}
  4328. \def\eqnarray@ii#1[#2]{%
  4329. % \end{macrocode}
  4330. %
  4331. % Set up the equation counter and labels correctly.
  4332. %
  4333. % \medskip\par\noindent|\begin{rant}|\par
  4334. % The hacking with |\@currentlabel| is here because (in the author's opinion)
  4335. % \LaTeX's |\refstepcounter| macro is broken. It's currently defined as
  4336. % \begin{listing}
  4337. %\def\refstepcounter#1{%
  4338. % \stepcounter{#1}%
  4339. % \protected@edef\@currentlabel%
  4340. % {\csname p@#1\endcsname\csname the#1\endcsname}%
  4341. %}
  4342. % \end{listing}
  4343. % which means that the current label gets `frozen' as soon as you do the
  4344. % counter step. By redefining the macro as
  4345. % \begin{listing}
  4346. %\def\refstepcounter#1{%
  4347. % \stepcounter{#1}%
  4348. % \edef\@currentlabel{%
  4349. % \expandafter\noexpand\csname p@#1\endcsname%
  4350. % \expandafter\noexpand\csname the#1\endcsname%
  4351. % }%
  4352. %}
  4353. % \end{listing}
  4354. % these sorts of problems would be avoided, without any loss of functionality
  4355. % or compatibility that I can see.
  4356. % \par\noindent|\end{rant}|\par
  4357. %
  4358. % \begin{macrocode}
  4359. \stepcounter{equation}%
  4360. \def\@currentlabel{\p@equation\theequation}%
  4361. % \end{macrocode}
  4362. %
  4363. % The next step is to set up the numbering. I must save the old numbering
  4364. % so I can restore it later (once in the alignment, I must assign these
  4365. % things globally).
  4366. %
  4367. % \begin{macrocode}
  4368. \let\eqa@oldnumber\eqa@number%
  4369. \def\eqa@defnumber{#1}%
  4370. \global\let\eqa@number\eqa@defnumber%
  4371. % \end{macrocode}
  4372. %
  4373. % The |\if@eqalastfalse| switch is false everywhere except when we're in the
  4374. % final column.
  4375. %
  4376. % \begin{macrocode}
  4377. \@eqalastfalse%
  4378. % \end{macrocode}
  4379. %
  4380. % Remove the |\mathsurround| kerning, since it will look very odd inside
  4381. % the display. We have our own spacing parameters for configuring these
  4382. % things, so |\mathsurround| is unnecessary.
  4383. %
  4384. % \begin{macrocode}
  4385. \m@th%
  4386. % \end{macrocode}
  4387. %
  4388. % Time to parse the preamble string now. I must choose the correct column
  4389. % set, initialise the preamble parser and set up the various macros. The%
  4390. % extra `|@{\tabskip\eqacloseskip}|' item sets up the tabskip glue to centre
  4391. % the alignment properly.
  4392. %
  4393. % \begin{macrocode}
  4394. \colset{eqnarray}%
  4395. \tab@initread%
  4396. \def\tab@tabtext{&\tabskip\z@skip}%
  4397. \tab@preamble{\tabskip\z@skip}%
  4398. \tab@readpreamble{#2@{\tabskip\eqacloseskip}}%
  4399. \dsp@tabpause%
  4400. % \end{macrocode}
  4401. %
  4402. % Now for some final setting up. The column separation is set from the
  4403. % user's parameter, the |\everycr| tokens are cleared, and I set up the
  4404. % newline command appropriately.
  4405. %
  4406. % \begin{macrocode}
  4407. \[email protected]\eqainskip%
  4408. \everycr{}%
  4409. \let\\\@eqncr%
  4410. % \end{macrocode}
  4411. %
  4412. % Now start a maths display and do the alignment. Set up the left hand
  4413. % tabskip glue to centre the alignment, and do the actual alignment.
  4414. % The preamble used is mainly that generated from the user's string, although
  4415. % the stuff at the end is how we set up the equation number -- it repeats
  4416. % appropriately so we can always find it.
  4417. %
  4418. % \begin{macrocode}
  4419. \dsp@start%
  4420. \tabskip\eqaopenskip%
  4421. \halign to\displaywidth\expandafter\bgroup%
  4422. \the\tab@preamble%
  4423. &&\eqa@lastcol\hb@xt@\z@{\hss##}\tabskip\z@\cr%
  4424. }
  4425. % \end{macrocode}
  4426. %
  4427. % Now for the end of the environment. This is really easy. Set the final
  4428. % equation number, close the |\halign|, tidy up the equation counter (it's
  4429. % been stepped once too many times) and close the display.
  4430. %
  4431. % \begin{macrocode}
  4432. \def\endeqnarray{%
  4433. \eqa@eqnum%
  4434. \egroup%
  4435. \dsp@end%
  4436. \global\let\eqa@number\eqa@oldnumber%
  4437. \global\@ignoretrue%
  4438. \global\advance\c@equation\m@ne%
  4439. }
  4440. \expandafter\let\csname endeqnarray*\endcsname\endeqnarray
  4441. % \end{macrocode}
  4442. %
  4443. % \end{environment}
  4444. % \end{environment}
  4445. %
  4446. % Now we can define the column types.
  4447. %
  4448. % \begin{macrocode}
  4449. \colpush{eqnarray}
  4450. % \end{macrocode}
  4451. %
  4452. % Note the positioning of ord atoms in the stuff below. This will space out
  4453. % relations and binops correctly when they occur at the edges of columns, and
  4454. % won't affect ord atoms at the edges, because ords pack closely.
  4455. %
  4456. % First the easy onces. Just stick |\hfil| in the right places and
  4457. % everything will be all right.
  4458. %
  4459. % \begin{macrocode}
  4460. \coldef r{\tabcoltype{\hfil$\eqastyle}{{}$}}
  4461. \coldef c{\tabcoltype{\hfil$\eqastyle{}}{{}$\hfil}}
  4462. \coldef l{\tabcoltype{$\eqastyle{}}{$\hfil}}
  4463. \coldef x{\tabcoltype{\if@fleqn\else\hfil\fi$\eqastyle}{$\hfil}}
  4464. % \end{macrocode}
  4465. %
  4466. % Now for the textual ones. This is also fairly easy.
  4467. %
  4468. % \begin{macrocode}
  4469. \collet T [tabular]T
  4470. % \end{macrocode}
  4471. %
  4472. % Sort of split types of equations. I mustn't use |\rlap| here, or
  4473. % everything goes wrong -- |\\| doesn't get noticed by \TeX\ in the same way
  4474. % as |\cr| does.
  4475. %
  4476. % \begin{macrocode}
  4477. \coldef L{\tabcoltype{\hb@xt@2em\bgroup$\eqastyle}{$\hss\egroup}}
  4478. % \end{macrocode}
  4479. %
  4480. % The \lit{:} column type is fairly simple.
  4481. %
  4482. % \begin{macrocode}
  4483. \coldef :{\tabspctype{\tabskip\eqacolskip}}
  4484. \coldef q{\tabspctype{\quad}}
  4485. % \end{macrocode}
  4486. %
  4487. % The other column types just insert given text in an appropriate way.
  4488. %
  4489. % \begin{macrocode}
  4490. \collet > [tabular]>
  4491. \collet < [tabular]<
  4492. \collet * [tabular]*
  4493. \collet @ [tabular]@
  4494. % \end{macrocode}
  4495. %
  4496. % Finally, the magical `|\magic|' column type, which sets the equation
  4497. % number. We set up the |\tabskip| glue properly, tab on, and set the flag
  4498. % which marks the final column. The |\eqa@lastcol| command is there to
  4499. % raise an error if the user tabs over to this column. I'll temporarily
  4500. % redefine it to |\@eqalasttrue| when I enter this column legitimately.
  4501. % The extra magical bits here will make the final column repeat, so that we
  4502. % can find it if necessary. Well is this column type named.
  4503. %
  4504. % That's it. We can return to normal now.
  4505. %
  4506. % \begin{macrocode}
  4507. \colpop
  4508. % \end{macrocode}
  4509. %
  4510. % \subsubsection{Newline codes}
  4511. %
  4512. % Newline sequences (|\\|) get turned into calls of |\@eqncr|. The job is
  4513. % fairly simple, really.
  4514. %
  4515. % \begin{macrocode}
  4516. \def\@eqncr{\tab@cr\eqacr@i\interdisplaylinepenalty\@M}%
  4517. \def\eqacr@i#1#2{%
  4518. \eqa@eqnum%
  4519. \noalign{\penalty#2\vskip\jot\vskip#1}%
  4520. }
  4521. % \end{macrocode}
  4522. %
  4523. % \subsubsection{Setting equation numbers}
  4524. %
  4525. % \begin{macro}{\eqa@eqpos}
  4526. %
  4527. % Before we start, we need to generalise the flush-left number handling bits.
  4528. % The macro |\eqa@eqpos| will put its argument in the right place.
  4529. %
  4530. % \begin{macrocode}
  4531. \if@leqno
  4532. \def\eqa@eqpos#1{%
  4533. \hb@[email protected]\p@{}\rlap{\normalfont\normalcolor\hskip-\displaywidth#1}%
  4534. }
  4535. \else
  4536. \def\eqa@eqpos#1{\normalfont\normalcolor#1}
  4537. \fi
  4538. % \end{macrocode}
  4539. %
  4540. % \end{macro}
  4541. %
  4542. % \begin{macro}{\eqa@eqnum}
  4543. %
  4544. % Here we typeset an equation number in roughly the right place. First I'll
  4545. % redefine |\eqa@lastcol| so that it tells me I'm in the right place, and
  4546. % start a loop to find that place.
  4547. %
  4548. % \begin{macrocode}
  4549. \def\eqa@eqnum{%
  4550. \global\let\eqa@lastcol\@eqalasttrue%
  4551. \eqa@eqnum@i%
  4552. }
  4553. % \end{macrocode}
  4554. %
  4555. % Now for the loop. The |\relax| here is absolutely vital -- it starts the
  4556. % table column, inserting useful tokens like `|\eqa@lastcol|' which tell
  4557. % me where I am in the alignment. Then, if I've reached the end, I can
  4558. % typeset the equation number; otherwise I go off into another macro and
  4559. % step on to the next column.
  4560. %
  4561. % \begin{macrocode}
  4562. \def\eqa@eqnum@i{%
  4563. \relax%
  4564. \if@eqalast%
  4565. \expandafter\eqa@eqnum@ii%
  4566. \else%
  4567. \expandafter\eqa@eqnum@iii%
  4568. \fi%
  4569. }
  4570. \def\eqa@eqnum@ii{%
  4571. \eqa@eqpos\eqa@number%
  4572. \global\let\eqa@number\eqa@defnumber%
  4573. \global\let\eqa@lastcol\eqa@@lastcol%
  4574. \cr%
  4575. }
  4576. \def\eqa@eqnum@iii{&\eqa@eqnum@i}
  4577. % \end{macrocode}
  4578. %
  4579. % \end{macro}
  4580. %
  4581. % \begin{macro}{\eqa@lastcol}
  4582. %
  4583. % This is used as a marker for the final column in an \env{eqnarray}
  4584. % environment. By default it informs the user that they've been very
  4585. % silly and swallows the contents of the column. I'll redefine it to
  4586. % something more useful at appropriate times, and then turn it back again.
  4587. %
  4588. % \begin{macrocode}
  4589. \def\eqa@@lastcol{\mth@err@number\setbox\z@}
  4590. \let\eqa@lastcol\eqa@@lastcol
  4591. % \end{macrocode}
  4592. %
  4593. % \end{macro}
  4594. %
  4595. % \subsubsection{Numbering control}
  4596. %
  4597. % \begin{macro}{\eqnumber}
  4598. %
  4599. % The |\eqnumber| command sets the equation number on the current equation.
  4600. % This is really easy, actually.
  4601. %
  4602. % \begin{macrocode}
  4603. \newcommand\eqnumber[1][\eqa@eqcount]{\gdef\eqa@number{#1}}
  4604. % \end{macrocode}
  4605. %
  4606. % \end{macro}
  4607. %
  4608. % \begin{macro}{\eqa@eqcount}
  4609. %
  4610. % This is how a standard equation number is set, stepping the counter and
  4611. % all. It's really easy and obvious.
  4612. %
  4613. % \begin{macrocode}
  4614. \def\eqa@eqcount{(\theequation)\global\advance\c@equation\@ne}
  4615. % \end{macrocode}
  4616. %
  4617. % \end{macro}
  4618. %
  4619. % \begin{macro}{\nonumber}
  4620. %
  4621. % The \LaTeX\ |\nonumber| command could be defined by saying
  4622. % \begin{listing}
  4623. %\renewcommand{\nonumber}{\eqnumber[]}
  4624. % \end{listing}
  4625. % but I'll be slightly more efficient and redefine |\eqa@number| directly.
  4626. %
  4627. % \begin{macrocode}
  4628. \def\nonumber{\global\let\eqa@number\@empty}
  4629. % \end{macrocode}
  4630. %
  4631. % \end{macro}
  4632. %
  4633. % \subsubsection{The \env{eqnalign} environment}
  4634. %
  4635. % As a sort of companion to \env{eqnarray}, here's an environment which does
  4636. % similar things inside a box, rather than taking up the whole display width.
  4637. % It uses the same column types that we've already created, so there should
  4638. % be no problems.
  4639. %
  4640. % \begin{environment}{eqnalign}
  4641. %
  4642. % First, sort out some simple things like optional arguments.
  4643. %
  4644. % \begin{macrocode}
  4645. \def\eqnalign{\@ifnextchar[\eqnalign@i{\eqnalign@i[rcl]}}
  4646. \def\eqnalign@i[#1]{%
  4647. \@ifnextchar[{\eqnalign@ii{#1}}{\eqnalign@ii{#1}[c]}%
  4648. }
  4649. % \end{macrocode}
  4650. %
  4651. % Now we actually do the environment. This is fairly easy, actually.
  4652. %
  4653. % \begin{macrocode}
  4654. \def\eqnalign@ii#1[#2]{%
  4655. \let\\\eqn@cr%
  4656. \colset{eqnarray}%
  4657. \tab@initread%
  4658. \def\tab@tabtext{&\tabskip\z@skip}%
  4659. \tabskip\z@skip%
  4660. \[email protected]\eqainskip%
  4661. \tab@readpreamble{#1}%
  4662. \everycr{}%
  4663. \if#2t\vtop\else%
  4664. \if#2b\vbox\else%
  4665. \vcenter%
  4666. \fi%
  4667. \fi%
  4668. \bgroup%
  4669. \halign\expandafter\bgroup\the\tab@preamble\cr%
  4670. }
  4671. % \end{macrocode}
  4672. %
  4673. % Finishing the environment is even simpler.
  4674. %
  4675. % \begin{macrocode}
  4676. \def\endeqnalign{%
  4677. \crcr%
  4678. \egroup%
  4679. \egroup%
  4680. }
  4681. % \end{macrocode}
  4682. %
  4683. % \end{environment}
  4684. %
  4685. % \begin{macro}{\eqn@cr}
  4686. %
  4687. % Newlines are really easy here.
  4688. %
  4689. % \begin{macrocode}
  4690. \def\eqn@cr{\tab@cr\eqn@cr@i{}{}}
  4691. \def\eqn@cr@i#1{\cr\noalign{\vskip\jot\vskip#1}\@gobble}
  4692. % \end{macrocode}
  4693. %
  4694. % \end{macro}
  4695. %
  4696. %
  4697. % \subsection{Simple multiline equations}
  4698. %
  4699. % As a sort of example and abbreviation, here's a multiline display
  4700. % environment which just centres everything.
  4701. %
  4702. % \begin{environment}{eqlines}
  4703. %
  4704. % We just get |\eqnarray| to do everything for us. This is really easy.
  4705. %
  4706. % \begin{macrocode}
  4707. \def\eqlines{\eqnarray[x]}
  4708. \let\endeqlines\endeqnarray
  4709. % \end{macrocode}
  4710. %
  4711. % \end{environment}
  4712. %
  4713. % \begin{environment}{eqlines*}
  4714. %
  4715. % There's a $*$ version which omits numbers. This is easy too. Lots of
  4716. % hacking with expansion here to try and reduce the number of tokens being
  4717. % used. Is it worth it?
  4718. %
  4719. % \begin{macrocode}
  4720. \expandafter\edef\csname eqlines*\endcsname{%
  4721. \expandafter\noexpand\csname eqnarray*\endcsname[x]%
  4722. }
  4723. \expandafter\let\csname endeqlines*\expandafter\endcsname
  4724. \csname endeqnarray*\endcsname
  4725. % \end{macrocode}
  4726. %
  4727. % \end{environment}
  4728. %
  4729. %
  4730. % \subsection{Split equations}
  4731. %
  4732. % Based on an idea from \textit{The \TeX book}, we provide some simple
  4733. % environments for doing split equations. These's plenty of scope for
  4734. % improvement here, though.
  4735. %
  4736. % \begin{environment}{spliteqn}
  4737. % \begin{environment}{spliteqn*}
  4738. %
  4739. % The only difference between these two is that the $*$-version doesn't put
  4740. % in an equation number by default (although this behaviour can be
  4741. % changed by |\eqnumber|).
  4742. %
  4743. % The fun here mainly concerns putting in the equation number at the right
  4744. % place -- for |leqno| users, we need to put the number on the first line;
  4745. % otherwise we put it on the last line.
  4746. %
  4747. % The way we handle this is to have two macros, |\\| (which clearly does
  4748. % all the user line breaks) and |\seq@lastcr| which is used at the end of
  4749. % the environment to wrap everything up. The |\seq@eqnocr| macro puts an
  4750. % equation number on the current line and then does a normal |\\|. It also
  4751. % resets |\\| and |\seq@lastcr| so that they don't try to put another
  4752. % equation number in. This must be done globally, although anyone who tries
  4753. % to nest maths displays will get what they deserve.
  4754. %
  4755. % For the non-$*$ environment, then, we need to step the equation counter,
  4756. % and set |\\| to |\seq@cr| or |\seq@eqnocr| as appropriate for the setting
  4757. % of the |leqno| flag -- |\seq@lastcr| always gets set to put an equation
  4758. % number in (because it will be reset if the number actually gets done
  4759. % earlier -- this catches stupid users trying to put a single row into
  4760. % a split environment).
  4761. %
  4762. % \begin{macrocode}
  4763. \def\spliteqn{%
  4764. \let\eqa@oldnumber\eqa@number%
  4765. \global\let\eqa@number\eqa@eqcount%
  4766. \spliteqn@i%
  4767. }
  4768. % \end{macrocode}
  4769. %
  4770. % For the $*$ variant, we don't need to bother with equation numbering, so
  4771. % this is really easy.
  4772. %
  4773. % \begin{macrocode}
  4774. \@namedef{spliteqn*}{%
  4775. \let\eqa@oldnumber\eqa@number%
  4776. \gdef\eqa@number{}%
  4777. \spliteqn@i%
  4778. }
  4779. % \end{macrocode}
  4780. %
  4781. % Ending the environments is easy. Most of the stuff here will be described
  4782. % later.
  4783. %
  4784. % \begin{macrocode}
  4785. \def\endspliteqn{%
  4786. \hfilneg\seq@lastcr%
  4787. \egroup%
  4788. \dsp@end%
  4789. \global\let\eqa@number\eqa@oldnumber%
  4790. \global\advance\c@equation\m@ne%
  4791. }
  4792. \expandafter\let\csname endspliteqn*\endcsname\endspliteqn
  4793. % \end{macrocode}
  4794. %
  4795. % \end{environment}
  4796. % \end{environment}
  4797. %
  4798. % \begin{macro}{\spliteqn@i}
  4799. %
  4800. % Here we handle the full display splits. Start a maths display, and make
  4801. % each row of the alignment take up the full display width.
  4802. %
  4803. % The macro |\seq@dosplit| does most of the real work for us -- setting up
  4804. % the alignment and so forth. The template column is interesting. There
  4805. % are two items glue on both sides of the actual text:
  4806. %
  4807. % \begin{itemize}
  4808. %
  4809. % \item Some glue which can shrink. This keeps the display from the edges
  4810. % of the page unless we get a really wide item.
  4811. %
  4812. % \item An |\hfil| to do the alignment. By default, this centres the
  4813. % equations. On the first line, however, we put a leading |\hfilneg|
  4814. % which cancels the first |\hfil|, making the first row left aligned.
  4815. % Similarly, at the end, we put an |\hfilneg| after the last equation
  4816. % to right align the last line.
  4817. %
  4818. % \end{itemize}
  4819. %
  4820. % We pass this information on as an argument. It's easy really.
  4821. %
  4822. % \begin{macrocode}
  4823. \def\spliteqn@i{%
  4824. % \end{macrocode}
  4825. %
  4826. % First, set up equation numbering properly. See my rant about
  4827. % |\refstepcounter| above.
  4828. %
  4829. % \begin{macrocode}
  4830. \stepcounter{equation}%
  4831. \def\@currentlabel{\p@equation\theequation}%
  4832. % \end{macrocode}
  4833. %
  4834. % Right; now to sort out the numbering and newline handling. If the number's
  4835. % meant to be on the first line (for \textsf{leqno} users), then it gets
  4836. % typeset on the first like; otherwise we just do a normal newline on
  4837. % all lines except the first. Once |\seq@eqnocr| has done its stuff, it
  4838. % redefines all the newline handling not to insert another number.
  4839. %
  4840. % \begin{macrocode}
  4841. \if@leqno%
  4842. \global\let\seq@docr\seq@eqnocr%
  4843. \else%
  4844. \global\let\seq@docr\seq@cr%
  4845. \fi%
  4846. \global\let\seq@lastcr\seq@eqnocr%
  4847. % \end{macrocode}
  4848. %
  4849. % For my next trick, I'll do some display handling -- start a (possibly
  4850. % nested) maths display, set up the |\tabpause| macro appropriately, and
  4851. % set the newline command to do the right thing.
  4852. %
  4853. % \begin{macrocode}
  4854. \dsp@start%
  4855. \dsp@tabpause%
  4856. \def\\{\seq@docr}%
  4857. % \end{macrocode}
  4858. %
  4859. % Finally, call another macro to do the remaining bits of setting up.
  4860. %
  4861. % \begin{macrocode}
  4862. \seq@dosplit%
  4863. {\hb@xt@\displaywidth{%
  4864. \hskip\splitleft\hfil$\displaystyle##$%
  4865. \hfil\hskip\splitright}}%
  4866. {\hfilneg}%
  4867. }
  4868. % \end{macrocode}
  4869. %
  4870. % \end{macro}
  4871. %
  4872. % \begin{environment}{subsplit}
  4873. %
  4874. % For doing splits in the middle of equations, we provide a similar
  4875. % environment. Here, we make |\\| just start a new line. We also use
  4876. % a |\vcenter| rather than a full maths display. The glue items are also
  4877. % a bit different: we use plain double-quads on each side of the item, and
  4878. % we need to remove them by hand at the extremeties of the environment.
  4879. %
  4880. % \begin{macrocode}
  4881. \def\subsplit{%
  4882. \let\\\seq@cr%
  4883. \vcenter\bgroup%
  4884. \seq@dosplit{\hfil\qquad$##$\qquad\hfil}{\hfilneg\hskip-2em}%
  4885. }
  4886. % \end{macrocode}
  4887. %
  4888. % Ending the environment is fairly easy. We remove the final glue item,
  4889. % and close the alignment and the vbox.
  4890. %
  4891. % \begin{macrocode}
  4892. \def\endsubsplit{%
  4893. \hfilneg\hskip-2em\cr%
  4894. \egroup\egroup%
  4895. }
  4896. % \end{macrocode}
  4897. %
  4898. % \end{environment}
  4899. %
  4900. % \begin{macro}{\seq@dosplit}
  4901. %
  4902. % Here we do most of the real work. Actually, since the preamble is passed
  4903. % in as an argument, most of the work is already done. The only thing to
  4904. % really note is the template for subsequent columns. To stop users putting
  4905. % in extra columns (which is where we put the equation number) we raise an
  4906. % error and discard the input in a scratch box register. This template is
  4907. % repeated infinitely so as to allow us to put the equation number in nicely.
  4908. % However, the final negative glue item won't work properly, so the equation
  4909. % will look awful.
  4910. %
  4911. % \begin{macrocode}
  4912. \def\seq@dosplit#1#2{%
  4913. \halign\bgroup%
  4914. #1&&\mth@err@number\setbox\z@\hbox{##}\cr%
  4915. #2\relax%
  4916. }
  4917. % \end{macrocode}
  4918. %
  4919. % \end{macro}
  4920. %
  4921. % \begin{macro}{\seq@eqnocr}
  4922. %
  4923. % Here's how we set equation numbers. Since the column provided raises
  4924. % errors as soon as a token finds its way into it, we start with a |&\omit|.
  4925. % Then we just put the equation number in a zero-width box. Finally, we
  4926. % reset the newline commands to avoid putting in more than one equation
  4927. % number, and do normal newline things.
  4928. %
  4929. % \begin{macrocode}
  4930. \def\seq@eqnocr{%
  4931. &\omit%
  4932. \hb@xt@\z@{\hss\eqa@eqpos\eqa@number}%
  4933. \global\let\seq@docr\seq@cr%
  4934. \global\let\seq@lastcr\seq@cr%
  4935. \seq@cr%
  4936. }
  4937. % \end{macrocode}
  4938. %
  4939. % \end{macro}
  4940. %
  4941. % \begin{macro}{\seq@cr}
  4942. %
  4943. % Newlines are very easy. We add a |\jot| of extra space, since this is
  4944. % a nice thing to do.
  4945. %
  4946. % \begin{macrocode}
  4947. \def\seq@cr{\tab@cr\seq@cr@i\interdisplaylinepenalty\@M}
  4948. \def\seq@cr@i#1#2{\cr\noalign{\penalty#2\vskip\jot\vskip#1}}
  4949. % \end{macrocode}
  4950. %
  4951. % \end{macro}
  4952. %
  4953. %
  4954. % \subsection{Matrix handling}
  4955. %
  4956. % There's been a complete and total overhaul of the spacing calculations
  4957. % for matrices here. The vertical spacing now bears an uncanny similarity
  4958. % to the rules \TeX\ uses to space out |\atop|-like fractions, the difference
  4959. % being that you can have more than one column in a matrix. This has the
  4960. % interesting side-effect that we get an \package{amsmath}-style
  4961. % sub/superscript environment almost free of charge with the matrix handling
  4962. % (it just ends up being a script-size single-column matrix).
  4963. %
  4964. % What is rather gratifying is that our \env{matrix} environment looks
  4965. % rather nicer than \package{amsmath}'s (which is based directly on
  4966. % \env{array}, giving it nasty restrictions on the numbers of columns and
  4967. % so on); in particular, the version here gives the `correct' result for
  4968. % Knuth's exercise~18.42 (which states categorically that a |\smallskip|
  4969. % should be placed between the rows of the big matrix).
  4970. %
  4971. % The reason the interrow space doesn't come out in the AMS version is
  4972. % that \env{array} inserts extra vertical space by extending the depth of
  4973. % the final row using a strut: the big matrix already extends deeper than
  4974. % this, so the strut doesn't make any difference. If the space was added
  4975. % by |\hlx{s[\smallskipamount]}| instead of the |\\| command, things would
  4976. % be different.
  4977. %
  4978. % \begin{figure}
  4979. %
  4980. % ^^A This is essentially what amsmath (version 1.2b) does. The real
  4981. % ^^A implementation requires a counter MaxMatrixCols, and has fewer braces:
  4982. % ^^A that's all the difference. Oh, and I turn off \arrayextrasep here,
  4983. % ^^A since amsmath doesn't expect it to be there (accurate emulation, see?)
  4984. % ^^A and I've used \hspace instead of \hskip since everything else is
  4985. % ^^A `proper' LaTeX stuff.
  4986. %
  4987. % \newenvironment{ams-pmatrix}{^^A
  4988. % \setlength{\arrayextrasep}{0pt}^^A
  4989. % \left(^^A
  4990. % \hspace{-\arraycolsep}^^A
  4991. % \begin{array}{*{10}{c}}^^A
  4992. % }{^^A
  4993. % \end{array}^^A
  4994. % \hspace{-\arraycolsep}^^A
  4995. % \right)^^A
  4996. % }
  4997. %
  4998. % \begin{demo}{Exercise 18.42 from \emph{The \TeX book}}
  4999. %\newcommand{\domatrix}[1]{
  5000. % \def\mat##1
  5001. % {\begin{#1}##1\end{#1}}
  5002. % \[ \begin{#1}
  5003. % \mat{a & b \\ c & d} &
  5004. % \mat{e & f \\ g & h}
  5005. % \\[\smallskipamount]
  5006. % 0 &
  5007. % \mat{i & j \\ k & l}
  5008. % \end{#1}
  5009. % \]
  5010. %}
  5011. %\domatrix{pmatrix}
  5012. %\domatrix{ams-pmatrix}
  5013. % \end{demo}
  5014. %
  5015. % \end{figure}
  5016. %
  5017. % \begin{environment}{genmatrix}
  5018. %
  5019. % The first job is to store my maths style and font away, because I'll be
  5020. % needing it lots later.
  5021. %
  5022. % \begin{macrocode}
  5023. \def\genmatrix#1#2#3#4#5{%
  5024. \let\mat@style#1%
  5025. \ifx#2\scriptstyle%
  5026. \let\mat@font\scriptfont%
  5027. \else\ifx#2\scriptscriptstyle%
  5028. \let\mat@font\scriptscriptfont%
  5029. \else%
  5030. \let\mat@font\textfont%
  5031. \fi\fi%
  5032. % \end{macrocode}
  5033. %
  5034. % Now to cope with inserted text. This is easy.
  5035. %
  5036. % \begin{macrocode}
  5037. \ifx\mat@style\scriptstyle%
  5038. \let\mat@textsize\scriptsize%
  5039. \else\ifx\mat@style\scriptscriptstyle%
  5040. \let\mat@textsize\scriptscriptsize%
  5041. \else%
  5042. \let\mat@textsize\relax%
  5043. \fi\fi%
  5044. % \end{macrocode}
  5045. %
  5046. % Now for some fun. I'll remember how to start and end the matrix in a
  5047. % couple of macros |\mat@left| and |\mat@right|. I haven't yet worked out
  5048. % exactly what needs to be in |\mat@right| yet, though, so I'll build that
  5049. % up in a scratch token list while I'm making my mind up.
  5050. %
  5051. % Initially, I want to open a group (to trap the style changes), set the
  5052. % maths style (to get the right spacing), insert the left delimiter, insert
  5053. % some spacing around the matrix, and start a centred box. The ending just
  5054. % closes all the groups and delimiters I opened.
  5055. %
  5056. % \begin{macrocode}
  5057. \def\mat@left{\bgroup\mat@style\left#4#3\vcenter\bgroup}%
  5058. \toks@{\egroup#3\right#5\egroup}%
  5059. % \end{macrocode}
  5060. %
  5061. % Now comes a slightly trickier bit. If the maths style is script or
  5062. % scriptscript, then I need to raise the box by a little bit to make it look
  5063. % really good. The right amount is somewhere around \smallf 3/4\,pt, I
  5064. % think, so that's what I'll use.
  5065. %
  5066. % \begin{macrocode}
  5067. \@tempswatrue%
  5068. \ifx\mat@style\displaystyle\else\ifx\mat@style\textstyle\else%
  5069. \@tempswafalse%
  5070. \setbox\z@\hbox\bgroup$%
  5071. \toks@\expandafter{\the\toks@$\m@th\egroup\raise.75\p@\box\z@}%
  5072. \fi\fi%
  5073. % \end{macrocode}
  5074. %
  5075. % If I'm not in maths mode right now, then I should enter maths mode, and
  5076. % remember to leave it later.
  5077. %
  5078. % \begin{macrocode}
  5079. \if@tempswa\ifmmode\else%
  5080. $\m@th%
  5081. \toks@\expandafter{\the\toks@$}%
  5082. \fi\fi%
  5083. % \end{macrocode}
  5084. %
  5085. % Now I've sorted out how to end the environment properly, so I can set up
  5086. % the macro, using |\edef|.
  5087. %
  5088. % \begin{macrocode}
  5089. \edef\mat@right{\the\toks@}%
  5090. % \end{macrocode}
  5091. %
  5092. % Now see if there's an optional argument. If not, create lots of centred
  5093. % columns.
  5094. %
  5095. % \begin{macrocode}
  5096. \@ifnextchar[\genmatrix@i{\genmatrix@i[[c]}%
  5097. }
  5098. % \end{macrocode}
  5099. %
  5100. % Now to sort out everything else.
  5101. %
  5102. % \begin{macrocode}
  5103. \def\genmatrix@i[#1]{%
  5104. % \end{macrocode}
  5105. %
  5106. % Some initial setting up: choose the correct column set, and set up some
  5107. % variables for reading the preamble.
  5108. %
  5109. % \begin{macrocode}
  5110. \colset{matrix}%
  5111. \tab@initread%
  5112. % \end{macrocode}
  5113. %
  5114. % Now comes some of the tricky stuff. The space between columns should be
  5115. % 12\,mu (by trial and error). We put the space in a box so we can measure
  5116. % it in the correct mathstyle.
  5117. %
  5118. % \begin{macrocode}
  5119. \setbox\z@\hbox{$\mat@style\mskip12mu$}%
  5120. \edef\tab@tabtext{&\kern\the\wd\z@}%
  5121. \tab@readpreamble{#1}%
  5122. % \end{macrocode}
  5123. %
  5124. % Now we need to decide how to space out the rows. The code here is based
  5125. % on the information in appendix~G of \emph{The \TeX book}: I think it'd be
  5126. % nice if my matrices were spaced out in the same way as normal fractions
  5127. % (particularly |\choose|y things). The standard |\baselineskip| and
  5128. % |\lineskip| parameters come in really handy here.
  5129. %
  5130. % The parameters vary according to the size of the text, so I need to see
  5131. % if we have scriptsize or less, or not. The tricky |\if| sorts this out.
  5132. %
  5133. % \begin{macrocode}
  5134. \if1\ifx\mat@style\scriptstyle1\else%
  5135. \ifx\mat@style\scriptscriptstyle1\else0\fi\fi%
  5136. \baselineskip\fontdimen10\mat@font\tw@%
  5137. \advance\baselineskip\fontdimen12\mat@font\tw@%
  5138. \lineskip\thr@@\fontdimen8\mat@font\thr@@%
  5139. \else%
  5140. \baselineskip\fontdimen8\mat@font\tw@%
  5141. \advance\baselineskip\fontdimen11\mat@font\tw@%
  5142. \lineskip7\fontdimen8\mat@font\thr@@%
  5143. \fi%
  5144. \lineskiplimit\lineskip%
  5145. % \end{macrocode}
  5146. %
  5147. % Now actually set up for the alignment. Assign |\\| to the correct value.
  5148. % Set up the |\tabskip|. Do the appropriate |\mat@left| thing set up above.
  5149. % And then start the alignment.
  5150. %
  5151. % \begin{macrocode}
  5152. \let\\\mat@cr%
  5153. \tabskip\z@skip%
  5154. \col@sep\z@%
  5155. \mat@left%
  5156. \halign\expandafter\bgroup\the\tab@preamble\tabskip\z@skip\cr%
  5157. % \end{macrocode}
  5158. %
  5159. % Now for a little hack to make the spacing consistent between matrices of
  5160. % the same height. This comes directly from \PlainTeX. This appears to
  5161. % make the spacing \emph{exactly} the same as the \TeX\ primites, oddly
  5162. % enough.
  5163. %
  5164. % \begin{macrocode}
  5165. \ifx\mat@font\textfont%
  5166. \omit$\mat@style\mathstrut$\cr\noalign{\kern-\baselineskip}%
  5167. \fi%
  5168. }
  5169. % \end{macrocode}
  5170. %
  5171. % Finishing the environment is really easy. We do the spacing hack again
  5172. % at the bottom, close the alignment and then tidy whatever we started in
  5173. % |\mat@left|.
  5174. %
  5175. % \begin{macrocode}
  5176. \def\endgenmatrix{%
  5177. \crcr%
  5178. \ifx\mat@font\textfont%
  5179. \omit$\mat@style\mathstrut$\cr\noalign{\kern-\baselineskip}%
  5180. \fi%
  5181. \egroup%
  5182. \mat@right%
  5183. }
  5184. % \end{macrocode}
  5185. %
  5186. % \end{environment}
  5187. %
  5188. % \begin{macro}{\mat@cr}
  5189. %
  5190. % Newlines are really easy. The $*$-form means nothing here, so we ignore
  5191. % it.
  5192. %
  5193. % \begin{macrocode}
  5194. \def\mat@cr{\tab@cr\mat@cr@i{}{}}
  5195. \def\mat@cr@i#1{\cr\noalign{\vskip#1}\@gobble}
  5196. % \end{macrocode}
  5197. %
  5198. % \end{macro}
  5199. %
  5200. % \begin{macro}{\newmatrix}
  5201. %
  5202. % This is how we define new matrix environments. It's simple fun with
  5203. % |\csname| and |\expandafter|.
  5204. %
  5205. % \begin{macrocode}
  5206. \def\newmatrix#1#2{%
  5207. \@namedef{#1}{\genmatrix#2}%
  5208. \expandafter\let\csname end#1\endcsname\endgenmatrix%
  5209. }
  5210. % \end{macrocode}
  5211. %
  5212. % \end{macro}
  5213. %
  5214. % \begin{environment}{matrix}
  5215. % \begin{environment}{pmatrix}
  5216. % \begin{environment}{dmatrix}
  5217. % \begin{environment}{smatrix}
  5218. % \begin{environment}{spmatrix}
  5219. % \begin{environment}{sdmatrix}
  5220. % \begin{environment}{smatrix*}
  5221. % \begin{environment}{spmatrix*}
  5222. % \begin{environment}{sdmatrix*}
  5223. %
  5224. % Now we define all the other environments we promised. This is easy.
  5225. %
  5226. % \begin{macrocode}
  5227. \newmatrix{matrix}{{\textstyle}{\textstyle}{\,}{.}{.}}
  5228. \newmatrix{pmatrix}{{\textstyle}{\textstyle}{\,}{(}{)}}
  5229. \newmatrix{dmatrix}{{\textstyle}{\textstyle}{\,}}
  5230. \newmatrix{smatrix}{{\scriptstyle}{\scriptstyle}{}{.}{.}}
  5231. \newmatrix{spmatrix}{{\scriptstyle}{\scriptstyle}{}{(}{)}}
  5232. \newmatrix{sdmatrix}{{\scriptstyle}{\scriptstyle}{}}
  5233. \newmatrix{smatrix*}{{\scriptstyle}{\textstyle}{}{.}{.}}
  5234. \newmatrix{spmatrix*}{{\scriptstyle}{\textstyle}{}{(}{)}}
  5235. \newmatrix{sdmatrix*}{{\scriptstyle}{\textstyle}{}}
  5236. % \end{macrocode}
  5237. %
  5238. % \end{environment}
  5239. % \end{environment}
  5240. % \end{environment}
  5241. % \end{environment}
  5242. % \end{environment}
  5243. % \end{environment}
  5244. % \end{environment}
  5245. % \end{environment}
  5246. % \end{environment}
  5247. %
  5248. % \begin{environment}{script}
  5249. %
  5250. % Now for superscripts and subscripts. This is fairly easy, because I
  5251. % took so much care over the matrix handling.
  5252. %
  5253. % \begin{macrocode}
  5254. \def\script{%
  5255. \let\mat@style\scriptstyle%
  5256. \def\mat@left{\vcenter\bgroup}%
  5257. \def\mat@right{\egroup}%
  5258. \let\mat@font\scriptfont%
  5259. \let\mat@textsize\scriptsize%
  5260. \@ifnextchar[\genmatrix@i{\genmatrix@i[c]}%
  5261. }
  5262. \let\endscript\endgenmatrix
  5263. % \end{macrocode}
  5264. %
  5265. % \end{environment}
  5266. %
  5267. % Now define the column types.
  5268. %
  5269. % \begin{macrocode}
  5270. \colpush{matrix}
  5271. \coldef l{\tabcoltype{\kern\z@$\mat@style}{\m@th$\hfil}}
  5272. \coldef c{\tabcoltype{\hfil$\mat@style}{\m@th$\hfil}}
  5273. \coldef r{\tabcoltype{\hfil$\mat@style}{\m@th$}}
  5274. \coldef T#1{\tab@aligncol{#1}{\begingroup\mat@textsize}{\endgroup}}
  5275. % \end{macrocode}
  5276. %
  5277. % The repeating type is more awkward. Things will go wrong if this is
  5278. % given before the first column, so we must do a whole repeat by hand. We
  5279. % can tell if we haven't contributed a column yet, since |\tab@column| will
  5280. % be zero. Otherwise, we fiddle the parser state to start a new column, and
  5281. % insert the |&| character to make \TeX\ repeat the preamble.
  5282. %
  5283. % \begin{macrocode}
  5284. \coldef {[}{%
  5285. \@firstoftwo{%
  5286. \ifnum\tab@columns=\z@%
  5287. \def\@tempa##1\q@delim{%
  5288. \tab@mkpreamble##1[##1\q@delim%
  5289. }%
  5290. \expandafter\@tempa%
  5291. \else%
  5292. \tab@setstate\tab@prestate%
  5293. \tab@append\tab@preamble{&}%
  5294. \expandafter\tab@mkpreamble%
  5295. \fi%
  5296. }%
  5297. }
  5298. % \end{macrocode}
  5299. %
  5300. % We're done defining columns now.
  5301. %
  5302. % \begin{macrocode}
  5303. \colpop
  5304. % \end{macrocode}
  5305. %
  5306. %
  5307. % \subsection{Dots\dots}
  5308. %
  5309. % Nothing whatsoever to do with alignments, although vertical and diagonal
  5310. % dots in small matrices look really silly. The following hacky definitions
  5311. % work rather better.
  5312. %
  5313. % \begin{macro}{\mdw@dots}
  5314. %
  5315. % First of all, here's some definitions common to both of the dots macros.
  5316. % The macro takes as an argument the actual code to draw the dots, passing
  5317. % it the scaled size of a point in the scratch register |\dimen@|; the
  5318. % register |\box 0| is set to contain a dot of the appropriate size.
  5319. %
  5320. % \begin{macrocode}
  5321. \def\mdw@dots#1{\ensuremath{\mathpalette\mdw@dots@i{#1}}}
  5322. \def\mdw@dots@i#1#2{%
  5323. \setbox\z@\hbox{$#1\mskip1.8mu$}%
  5324. \dimen@\wd\z@%
  5325. \setbox\z@\hbox{$#1.$}%
  5326. #2%
  5327. }
  5328. % \end{macrocode}
  5329. %
  5330. % \end{macro}
  5331. %
  5332. % \begin{macro}{\vdots}
  5333. %
  5334. % I'll start with the easy one. This is a simple translation of the original
  5335. % implementation.
  5336. %
  5337. % \begin{macrocode}
  5338. \def\vdots{%
  5339. \mdw@dots{\vbox{%
  5340. \baselineskip4\dimen@%
  5341. \lineskiplimit\z@%
  5342. \kern6\dimen@%
  5343. \copy\z@\copy\z@\box\z@%
  5344. }}%
  5345. }
  5346. % \end{macrocode}
  5347. %
  5348. % \end{macro}
  5349. %
  5350. % \begin{macro}{\ddots}
  5351. %
  5352. % And I'll end with the other easy one\dots
  5353. %
  5354. % \begin{macrocode}
  5355. \def\ddots{%
  5356. \mdw@dots{\mathinner{%
  5357. \mkern1mu%
  5358. \raise7\dimen@\vbox{\kern7\dimen@\copy\z@}%
  5359. \mkern2mu%
  5360. \raise4\dimen@\copy\z@%
  5361. \mkern2mu%
  5362. \raise\dimen@\box\z@%
  5363. \mkern1mu%
  5364. }}%
  5365. }
  5366. % \end{macrocode}
  5367. %
  5368. % \end{macro}
  5369. %
  5370. %
  5371. % \subsection{Lucky dip}
  5372. %
  5373. % Time to round off with some trivial environments, just to show how easy
  5374. % this stuff is.
  5375. %
  5376. % \begin{environment}{cases}
  5377. % \begin{environment}{smcases}
  5378. %
  5379. % These are totally and utterly trivial.
  5380. %
  5381. % \begin{macrocode}
  5382. \def\cases{\left\{\,\array{@{}lTl@{}}}
  5383. \def\endcases{\endarray\,\right.}
  5384. \def\smcases{\left\{\smarray{@{}lTl@{}}}
  5385. \def\endsmcases{\endsmarray\,\right.}
  5386. % \end{macrocode}
  5387. %
  5388. % \end{environment}
  5389. % \end{environment}
  5390. %
  5391. % \subsection{Error messages}
  5392. %
  5393. % Some token saving:
  5394. %
  5395. % \begin{macrocode}
  5396. \def\mth@error{\PackageError{mathenv}}
  5397. % \end{macrocode}
  5398. %
  5399. % Now for the error messages.
  5400. %
  5401. % \begin{macrocode}
  5402. \def\mth@err@number{%
  5403. \mth@error{Too many `&' characters found}{%
  5404. You've put too many `&' characters in an alignment^^J%
  5405. environment (like `eqnarray' or `spliteqn') and wandered^^J%
  5406. into trouble. I've gobbled the contents of that column^^J%
  5407. and hopefully I can recover fairly easily.%
  5408. }%
  5409. }
  5410. % \end{macrocode}
  5411. %
  5412. % \begin{macrocode}
  5413. \def\mth@err@mdsp{%
  5414. \mth@error{Can't do displays in nondisplay maths mode}{%
  5415. You're trying to start a display environment, but you're^^J%
  5416. in nondisplay maths mode. The display will appear but^^J%
  5417. don't blame me when it looks horrible.%
  5418. }%
  5419. }
  5420. % \end{macrocode}
  5421. %
  5422. % \begin{macrocode}
  5423. \def\mth@err@hdsp{%
  5424. \mth@error{Can't do displays in LR mode}{%
  5425. You're trying to start a display environment, but you're^^J%
  5426. in LR (restricted horizontal) mode. Everything will go^^J%
  5427. totally wrong, so your best bet is to type `X', fix the^^J%
  5428. mistake and start again.%
  5429. }%
  5430. }
  5431. % \end{macrocode}
  5432. %
  5433. % \vskip\parskip\vbox{ ^^A The best way I could find of keeping this lot
  5434. % ^^A together, I'm afraid.
  5435. % That's all there is. Byebye.
  5436. %
  5437. % \begin{macrocode}
  5438. %</mathenv>
  5439. % \end{macrocode}
  5440. % \nopagebreak
  5441. %
  5442. % \hfill Mark Wooding, \today
  5443. % }
  5444. %
  5445. % \Finale
  5446. %
  5447. \endinput