table.el 229 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592
  1. ;;; table.el --- create and edit WYSIWYG text based embedded tables
  2. ;; Copyright (C) 2000-2012 Free Software Foundation, Inc.
  3. ;; Keywords: wp, convenience
  4. ;; Author: Takaaki Ota <Takaaki.Ota@am.sony.com>
  5. ;; Created: Sat Jul 08 2000 13:28:45 (PST)
  6. ;; This file is part of GNU Emacs.
  7. ;; GNU Emacs is free software: you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation, either version 3 of the License, or
  10. ;; (at your option) any later version.
  11. ;; GNU Emacs is distributed in the hope that it will be useful,
  12. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;; GNU General Public License for more details.
  15. ;; You should have received a copy of the GNU General Public License
  16. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;; -------------
  19. ;; Introduction:
  20. ;; -------------
  21. ;;
  22. ;; This package provides text based table creation and editing
  23. ;; feature. With this package Emacs is capable of editing tables that
  24. ;; are embedded inside a text document, the feature similar to the
  25. ;; ones seen in modern WYSIWYG word processors. A table is a
  26. ;; rectangular text area consisting from a surrounding frame and
  27. ;; content inside the frame. The content is usually subdivided into
  28. ;; multiple rectangular cells, see the actual tables used below in
  29. ;; this document. Once a table is recognized, editing operation
  30. ;; inside a table cell is confined into that specific cell's
  31. ;; rectangular area. This means that typing and deleting characters
  32. ;; inside a cell do not affect any outside text but introduces
  33. ;; appropriate formatting only to the cell contents. If necessary for
  34. ;; accommodating added text in the cell, the cell automatically grows
  35. ;; vertically and/or horizontally. The package uses no major mode nor
  36. ;; minor mode for its implementation because the subject text is
  37. ;; localized within a buffer. Therefore the special behaviors inside
  38. ;; a table cells are implemented by using keymap text property
  39. ;; instead of buffer wide mode-map.
  40. ;;
  41. ;;
  42. ;; -----------
  43. ;; Background:
  44. ;; -----------
  45. ;;
  46. ;; Paul Georgief is one of my best friends. He became an Emacs
  47. ;; convert after I recommended him trying it several years ago. Now
  48. ;; we both are devoted disciples of Emacsism and elisp cult. One day
  49. ;; in his Emacs exploration he asked me "Tak, what is a command to
  50. ;; edit tables in Emacs?". This question started my journey of this
  51. ;; table package development. May the code be with me! In the
  52. ;; software world Emacs is probably one of the longest lifetime record
  53. ;; holders. Amazingly there have been no direct support for WYSIWYG
  54. ;; table editing tasks in Emacs. Many people must have experienced
  55. ;; manipulating existing overwrite-mode and picture-mode for this task
  56. ;; and only dreamed of having such a lisp package which supports this
  57. ;; specific task directly. Certainly, I have been one of them. The
  58. ;; most difficult part of dealing with table editing in Emacs probably
  59. ;; is how to realize localized rectangular editing effect. Emacs has
  60. ;; no rectangular narrowing mechanism. Existing rect package provides
  61. ;; basically kill, delete and yank operations of a rectangle, which
  62. ;; internally is a mere list of strings. A simple approach for
  63. ;; realizing the localized virtual rectangular operation is combining
  64. ;; rect package capability with a temporary buffer. Insertion and
  65. ;; deletion of a character to a table cell can be trapped by a
  66. ;; function that copies the cell rectangle to a temporary buffer then
  67. ;; apply the insertion/deletion to the temporary contents. Then it
  68. ;; formats the contents by filling the paragraphs in order to fit it
  69. ;; into the original rectangular area and finally copy it back to the
  70. ;; original buffer. This simplistic approach has to bear with
  71. ;; significant performance hit. As cell grows larger the copying
  72. ;; rectangle back and forth between the original buffer and the
  73. ;; temporary buffer becomes expensive and unbearably slow. It was
  74. ;; completely impractical and an obvious failure. An idea has been
  75. ;; borrowed from the original Emacs design to overcome this
  76. ;; shortcoming. When the terminal screen update was slow and
  77. ;; expensive Emacs employed a clever algorithm to reduce actual screen
  78. ;; update by removing redundant redrawing operations. Also the actual
  79. ;; redrawing was done only when there was enough idling time. This
  80. ;; technique significantly improved the previously mentioned
  81. ;; undesirable situation. Now the original buffer's rectangle is
  82. ;; copied into a cache buffer only once. Any cell editing operation
  83. ;; is done only to the cache contents. When there is enough idling
  84. ;; time the original buffer's rectangle is updated with the current
  85. ;; cache contents. This delayed operation is implemented by using
  86. ;; Emacs's timer function. To reduce the visual awkwardness
  87. ;; introduced by the delayed effect the cursor location is updated in
  88. ;; real-time as a user types while the cell contents remains the same
  89. ;; until the next idling time. A key to the success of this approach
  90. ;; is how to maintain cache coherency. As a user moves point in and
  91. ;; out of a cell the table buffer contents and the cache buffer
  92. ;; contents must be synchronized without a mistake. By observing user
  93. ;; action carefully this is possible however not easy. Once this
  94. ;; mechanism is firmly implemented the rest of table features grew in
  95. ;; relatively painless progression. Those users who are familiar with
  96. ;; Emacs internals appreciate this table package more. Because it
  97. ;; demonstrates how extensible Emacs is by showing something that
  98. ;; appears like a magic. It lets you re-discover the potential of
  99. ;; Emacs.
  100. ;;
  101. ;;
  102. ;; -------------
  103. ;; Entry Points:
  104. ;; -------------
  105. ;;
  106. ;; If this is the first time for you to try this package, go ahead and
  107. ;; load the package by M-x `load-file' RET. Specify the package file
  108. ;; name "table.el". Then switch to a new test buffer and issue the
  109. ;; command M-x `table-insert' RET. It'll ask you number of columns,
  110. ;; number of rows, cell width and cell height. Give some small
  111. ;; numbers for each of them. Play with the resulted table for a
  112. ;; while. If you have menu system find the item "Table" under "Tools"
  113. ;; and "Table" in the menu bar when the point is in a table cell.
  114. ;; Some of them are pretty intuitive and you can easily guess what
  115. ;; they do. M-x `describe-function' and get the documentation of
  116. ;; `table-insert'. The document includes a short tutorial. When you
  117. ;; are tired of guessing how it works come back to this document
  118. ;; again.
  119. ;;
  120. ;; To use the package regularly place this file in the site library
  121. ;; directory and add the next expression in your .emacs file. Make
  122. ;; sure that directory is included in the `load-path'.
  123. ;;
  124. ;; (require 'table)
  125. ;;
  126. ;; Have the next expression also, if you want always be ready to edit
  127. ;; tables inside text files. This mechanism is analogous to
  128. ;; fontification in a sense that tables are recognized at editing time
  129. ;; without having table information saved along with the text itself.
  130. ;;
  131. ;; (add-hook 'text-mode-hook 'table-recognize)
  132. ;;
  133. ;; Following is a table of entry points and brief description of each
  134. ;; of them. The tables below are of course generated and edited by
  135. ;; using this package. Not all the commands are bound to keys. Many
  136. ;; of them must be invoked by "M-x" (`execute-extended-command')
  137. ;; command. Refer to the section "Keymap" below for the commands
  138. ;; available from keys.
  139. ;;
  140. ;; +------------------------------------------------------------------+
  141. ;; | User Visible Entry Points |
  142. ;; +-------------------------------+----------------------------------+
  143. ;; | Function | Description |
  144. ;; +-------------------------------+----------------------------------+
  145. ;; |`table-insert' |Insert a table consisting of grid |
  146. ;; | |of cells by specifying the number |
  147. ;; | |of COLUMNS, number of ROWS, cell |
  148. ;; | |WIDTH and cell HEIGHT. |
  149. ;; +-------------------------------+----------------------------------+
  150. ;; |`table-insert-row' |Insert row(s) of cells before the |
  151. ;; | |current row that matches the |
  152. ;; | |current row structure. |
  153. ;; +-------------------------------+----------------------------------+
  154. ;; |`table-insert-column' |Insert column(s) of cells before |
  155. ;; | |the current column that matches |
  156. ;; | |the current column structure. |
  157. ;; +-------------------------------+----------------------------------+
  158. ;; |`table-delete-row' |Delete row(s) of cells. The row |
  159. ;; | |must consist from cells of the |
  160. ;; | |same height. |
  161. ;; +-------------------------------+----------------------------------+
  162. ;; |`table-delete-column' |Delete column(s) of cells. The |
  163. ;; | |column must consist from cells of |
  164. ;; | |the same width. |
  165. ;; +-------------------------------+----------------------------------+
  166. ;; |`table-recognize' |Recognize all tables in the |
  167. ;; |`table-unrecognize' |current buffer and |
  168. ;; | |activate/deactivate them. |
  169. ;; +-------------------------------+----------------------------------+
  170. ;; |`table-recognize-region' |Recognize all the cells in a |
  171. ;; |`table-unrecognize-region' |region and activate/deactivate |
  172. ;; | |them. |
  173. ;; +-------------------------------+----------------------------------+
  174. ;; |`table-recognize-table' |Recognize all the cells in a |
  175. ;; |`table-unrecognize-table' |single table and |
  176. ;; | |activate/deactivate them. |
  177. ;; +-------------------------------+----------------------------------+
  178. ;; |`table-recognize-cell' |Recognize a cell. Find a cell |
  179. ;; |`table-unrecognize-cell' |which contains the current point |
  180. ;; | |and activate/deactivate that cell.|
  181. ;; +-------------------------------+----------------------------------+
  182. ;; |`table-forward-cell' |Move point to the next Nth cell in|
  183. ;; | |a table. |
  184. ;; +-------------------------------+----------------------------------+
  185. ;; |`table-backward-cell' |Move point to the previous Nth |
  186. ;; | |cell in a table. |
  187. ;; +-------------------------------+----------------------------------+
  188. ;; |`table-span-cell' |Span the current cell toward the |
  189. ;; | |specified direction and merge it |
  190. ;; | |with the adjacent cell. The |
  191. ;; | |direction is right, left, above or|
  192. ;; | |below. |
  193. ;; +-------------------------------+----------------------------------+
  194. ;; |`table-split-cell-vertically' |Split the current cell vertically |
  195. ;; | |and create a cell above and a cell|
  196. ;; | |below the point location. |
  197. ;; +-------------------------------+----------------------------------+
  198. ;; |`table-split-cell-horizontally'|Split the current cell |
  199. ;; | |horizontally and create a cell on |
  200. ;; | |the left and a cell on the right |
  201. ;; | |of the point location. |
  202. ;; +-------------------------------+----------------------------------+
  203. ;; |`table-split-cell' |Split the current cell vertically |
  204. ;; | |or horizontally. This is a |
  205. ;; | |wrapper command to the other two |
  206. ;; | |orientation specific commands. |
  207. ;; +-------------------------------+----------------------------------+
  208. ;; |`table-heighten-cell' |Heighten the current cell. |
  209. ;; +-------------------------------+----------------------------------+
  210. ;; |`table-shorten-cell' |Shorten the current cell. |
  211. ;; +-------------------------------+----------------------------------+
  212. ;; |`table-widen-cell' |Widen the current cell. |
  213. ;; +-------------------------------+----------------------------------+
  214. ;; |`table-narrow-cell' |Narrow the current cell. |
  215. ;; +-------------------------------+----------------------------------+
  216. ;; |`table-fixed-width-mode' |Toggle fixed width mode. In the |
  217. ;; | |fixed width mode, typing inside a |
  218. ;; | |cell never changes the cell width,|
  219. ;; | |while in the normal mode the cell |
  220. ;; | |width expands automatically in |
  221. ;; | |order to prevent a word being |
  222. ;; | |folded into multiple lines. Fixed|
  223. ;; | |width mode reverses video or |
  224. ;; | |underline the cell contents for |
  225. ;; | |its indication. |
  226. ;; +-------------------------------+----------------------------------+
  227. ;; |`table-query-dimension' |Compute and report the current |
  228. ;; | |cell dimension, current table |
  229. ;; | |dimension and the number of |
  230. ;; | |columns and rows in the table. |
  231. ;; +-------------------------------+----------------------------------+
  232. ;; |`table-generate-source' |Generate the source of the current|
  233. ;; | |table in the specified language |
  234. ;; | |and insert it into a specified |
  235. ;; | |buffer. |
  236. ;; +-------------------------------+----------------------------------+
  237. ;; |`table-insert-sequence' |Travel cells forward while |
  238. ;; | |inserting a specified sequence |
  239. ;; | |string into each cell. |
  240. ;; +-------------------------------+----------------------------------+
  241. ;; |`table-capture' |Convert plain text into a table by|
  242. ;; | |capturing the text in the region. |
  243. ;; +-------------------------------+----------------------------------+
  244. ;; |`table-release' |Convert a table into plain text by|
  245. ;; | |removing the frame from a table. |
  246. ;; +-------------------------------+----------------------------------+
  247. ;; |`table-justify' |Justify the contents of cell(s). |
  248. ;; +-------------------------------+----------------------------------+
  249. ;;
  250. ;;
  251. ;; *Note*
  252. ;;
  253. ;; You may find that some of commonly expected table commands are
  254. ;; missing such as copying a row/column and yanking it. Those
  255. ;; functions can be obtained through existing Emacs text editing
  256. ;; commands. Rows are easily manipulated with region commands and
  257. ;; columns can be copied and pasted through rectangle commands. After
  258. ;; all a table is still a part of text in the buffer. Only the
  259. ;; special behaviors exist inside each cell through text properties.
  260. ;;
  261. ;; `table-generate-html' which appeared in earlier releases is
  262. ;; deprecated in favor of `table-generate-source'. Now HTML is
  263. ;; treated as one of the languages used for describing the table's
  264. ;; logical structure.
  265. ;;
  266. ;;
  267. ;; -------
  268. ;; Keymap:
  269. ;; -------
  270. ;;
  271. ;; Although this package does not use a mode it does use its own
  272. ;; keymap inside a table cell by way of keymap text property. Some of
  273. ;; the standard basic editing commands bound to certain keys are
  274. ;; replaced with the table specific version of corresponding commands.
  275. ;; This replacement combination is listed in the constant alist
  276. ;; `table-command-remap-alist' declared below. This alist is
  277. ;; not meant to be user configurable but mentioned here for your
  278. ;; better understanding of using this package. In addition, table
  279. ;; cells have some table specific bindings for cell navigation and
  280. ;; cell reformation. You can find these additional bindings in the
  281. ;; constant `table-cell-bindings'. Those key bound functions are
  282. ;; considered as internal functions instead of normal commands,
  283. ;; therefore they have special prefix, *table-- instead of table-, for
  284. ;; symbols. The purpose of this is to make it easier for a user to
  285. ;; use command name completion. There is a "normal hooks" variable
  286. ;; `table-cell-map-hook' prepared for users to override the default
  287. ;; table cell bindings. Following is the table of predefined default
  288. ;; key bound commands inside a table cell. Remember these bindings
  289. ;; exist only inside a table cell. When your terminal is a tty, the
  290. ;; control modifier may not be available or applicable for those
  291. ;; special characters. In this case use "C-cC-c", which is
  292. ;; customizable via `table-command-prefix', as the prefix key
  293. ;; sequence. This should preceding the following special character
  294. ;; without the control modifier. For example, use "C-cC-c|" instead
  295. ;; of "C-|".
  296. ;;
  297. ;; +------------------------------------------------------------------+
  298. ;; | Default Bindings in a Table Cell |
  299. ;; +-------+----------------------------------------------------------+
  300. ;; | Key | Function |
  301. ;; +-------+----------------------------------------------------------+
  302. ;; | TAB |Move point forward to the beginning of the next cell. |
  303. ;; +-------+----------------------------------------------------------+
  304. ;; | "C->" |Widen the current cell. |
  305. ;; +-------+----------------------------------------------------------+
  306. ;; | "C-<" |Narrow the current cell. |
  307. ;; +-------+----------------------------------------------------------+
  308. ;; | "C-}" |Heighten the current cell. |
  309. ;; +-------+----------------------------------------------------------+
  310. ;; | "C-{" |Shorten the current cell. |
  311. ;; +-------+----------------------------------------------------------+
  312. ;; | "C--" |Split current cell vertically. (one above and one below) |
  313. ;; +-------+----------------------------------------------------------+
  314. ;; | "C-|" |Split current cell horizontally. (one left and one right) |
  315. ;; +-------+----------------------------------------------------------+
  316. ;; | "C-*" |Span current cell into adjacent one. |
  317. ;; +-------+----------------------------------------------------------+
  318. ;; | "C-+" |Insert row(s)/column(s). |
  319. ;; +-------+----------------------------------------------------------+
  320. ;; | "C-!" |Toggle between normal mode and fixed width mode. |
  321. ;; +-------+----------------------------------------------------------+
  322. ;; | "C-#" |Report cell and table dimension. |
  323. ;; +-------+----------------------------------------------------------+
  324. ;; | "C-^" |Generate the source in a language from the current table. |
  325. ;; +-------+----------------------------------------------------------+
  326. ;; | "C-:" |Justify the contents of cell(s). |
  327. ;; +-------+----------------------------------------------------------+
  328. ;;
  329. ;; *Note*
  330. ;;
  331. ;; When using `table-cell-map-hook' do not use `local-set-key'.
  332. ;;
  333. ;; (add-hook 'table-cell-map-hook
  334. ;; (function (lambda ()
  335. ;; (local-set-key [<key sequence>] '<function>))))
  336. ;;
  337. ;; Above code is well known ~/.emacs idiom for customizing a mode
  338. ;; specific keymap however it does not work for this package. This is
  339. ;; because there is no table mode in effect. This package does not
  340. ;; use a local map therefore you must modify `table-cell-map'
  341. ;; explicitly. The correct way of achieving above task is:
  342. ;;
  343. ;; (add-hook 'table-cell-map-hook
  344. ;; (function (lambda ()
  345. ;; (define-key table-cell-map [<key sequence>] '<function>))))
  346. ;;
  347. ;; -----
  348. ;; Menu:
  349. ;; -----
  350. ;;
  351. ;; If a menu system is available a group of table specific menu items,
  352. ;; "Table" under "Tools" section of the menu bar, is globally added
  353. ;; after this package is loaded. The commands in this group are
  354. ;; limited to the ones that are related to creation and initialization
  355. ;; of tables, such as to insert a table, to insert rows and columns,
  356. ;; or recognize and unrecognize tables. Once tables are created and
  357. ;; point is placed inside of a table cell a table specific menu item
  358. ;; "Table" appears directly on the menu bar. The commands in this
  359. ;; menu give full control on table manipulation that include cell
  360. ;; navigation, insertion, splitting, spanning, shrinking, expansion
  361. ;; and unrecognizing. In addition to above two types of menu there is
  362. ;; a pop-up menu available within a table cell. The content of pop-up
  363. ;; menu is identical to the full table menu. [mouse-3] is the default
  364. ;; button, defined in `table-cell-bindings', to bring up the pop-up
  365. ;; menu. It can be reconfigured via `table-cell-map-hook'. The
  366. ;; benefit of a pop-up menu is that it combines selection of the
  367. ;; location (which cell, where in the cell) and selection of the
  368. ;; desired operation into a single clicking action.
  369. ;;
  370. ;;
  371. ;; -------------------------------
  372. ;; Definition of tables and cells:
  373. ;; -------------------------------
  374. ;;
  375. ;; There is no artificial-intelligence magic in this package. The
  376. ;; definition of a table and the cells inside the table is reasonably
  377. ;; limited in order to achieve acceptable performance in the
  378. ;; interactive operation under Emacs lisp implementation. A valid
  379. ;; table is a rectangular text area completely filled with valid
  380. ;; cells. A valid cell is a rectangle text area, which four borders
  381. ;; consist of valid border characters. Cells can not be nested one to
  382. ;; another or overlapped to each other except sharing the border
  383. ;; lines. A valid character of a cell's vertical border is either
  384. ;; table-cell-vertical-char `|' or table-cell-intersection-char `+'.
  385. ;; A valid character of a cell's horizontal border is either
  386. ;; one of table-cell-horizontal-chars (`-' or `=')
  387. ;; or table-cell-intersection-char `+'.
  388. ;; A valid character of the four corners of a cell must be
  389. ;; table-cell-intersection-char `+'. A cell must contain at least one
  390. ;; character space inside. There is no restriction about the contents
  391. ;; of a table cell, however it is advised if possible to avoid using
  392. ;; any of the border characters inside a table cell. Normally a few
  393. ;; boarder characters inside a table cell are harmless. But it is
  394. ;; possible that they accidentally align up to emulate a bogus cell
  395. ;; corner on which software relies on for cell recognition. When this
  396. ;; happens the software may be fooled by it and fail to determine
  397. ;; correct cell dimension.
  398. ;;
  399. ;; Following are the examples of valid tables.
  400. ;;
  401. ;; +--+----+---+ +-+ +--+-----+
  402. ;; | | | | | | | | |
  403. ;; +--+----+---+ +-+ | +--+--+
  404. ;; | | | | | | | |
  405. ;; +--+----+---+ +--+--+ |
  406. ;; | | |
  407. ;; +-----+--+
  408. ;;
  409. ;; The next five tables are the examples of invalid tables. (From
  410. ;; left to right, 1. nested cells 2. overlapped cells and a
  411. ;; non-rectangle cell 3. non-rectangle table 4. zero width/height
  412. ;; cells 5. zero sized cell)
  413. ;;
  414. ;; +-----+ +-----+ +--+ +-++--+ ++
  415. ;; | | | | | | | || | ++
  416. ;; | +-+ | | | | | | || |
  417. ;; | | | | +--+ | +--+--+ +-++--+
  418. ;; | +-+ | | | | | | | +-++--+
  419. ;; | | | | | | | | | || |
  420. ;; +-----+ +--+--+ +--+--+ +-++--+
  421. ;;
  422. ;; Although the program may recognizes some of these invalid tables,
  423. ;; results from the subsequent editing operations inside those cells
  424. ;; are not predictable and will most likely start destroying the table
  425. ;; structures.
  426. ;;
  427. ;; It is strongly recommended to have at least one blank line above
  428. ;; and below a table. For a table to coexist peacefully with
  429. ;; surrounding environment table needs to be separated from unrelated
  430. ;; text. This is necessary for the left table to grow or shrink
  431. ;; horizontally without breaking the right table in the following
  432. ;; example.
  433. ;;
  434. ;; +-----+-----+-----+
  435. ;; +-----+-----+ | | | |
  436. ;; | | | +-----+-----+-----+
  437. ;; +-----+-----+ | | | |
  438. ;; +-----+-----+-----+
  439. ;;
  440. ;;
  441. ;; -------------------------
  442. ;; Cell contents formatting:
  443. ;; -------------------------
  444. ;;
  445. ;; The cell contents are formatted by filling a paragraph immediately
  446. ;; after characters are inserted into or deleted from a cell. Because
  447. ;; of this, cell contents always remain fit inside a cell neatly. One
  448. ;; drawback of this is that users do not have full control over
  449. ;; spacing between words and line breaking. Only one space can be
  450. ;; entered between words and up to two spaces between sentences. For
  451. ;; a newline to be effective the new line must form a beginning of
  452. ;; paragraph, otherwise it'll automatically be merged with the
  453. ;; previous line in a same paragraph. To form a new paragraph the
  454. ;; line must start with some space characters or immediately follow a
  455. ;; blank line. Here is a typical example of how to list items within
  456. ;; a cell. Without a space at the beginning of each line the items
  457. ;; can not stand on their own.
  458. ;;
  459. ;; +---------------------------------+
  460. ;; |Each one of the following three |
  461. ;; |items starts with a space |
  462. ;; |character thus forms a paragraph |
  463. ;; |of its own. Limitations in cell |
  464. ;; |contents formatting are: |
  465. ;; | |
  466. ;; | 1. Only one space between words.|
  467. ;; | 2. Up to two spaces between |
  468. ;; |sentences. |
  469. ;; | 3. A paragraph must start with |
  470. ;; |spaces or follow a blank line. |
  471. ;; | |
  472. ;; |This paragraph stays away from |
  473. ;; |the item 3 because there is a |
  474. ;; |blank line between them. |
  475. ;; +---------------------------------+
  476. ;;
  477. ;; In the normal operation table cell width grows automatically when
  478. ;; certain word has to be folded into the next line if the width had
  479. ;; not been increased. This normal operation is useful and
  480. ;; appropriate for most of the time, however, it is sometimes useful
  481. ;; or necessary to fix the width of table and width of table cells.
  482. ;; For this purpose the package provides fixed width mode. You can
  483. ;; toggle between fixed width mode and normal mode by "C-!".
  484. ;;
  485. ;; Here is a simple example of the fixed width mode. Suppose we have
  486. ;; a table like this one.
  487. ;;
  488. ;; +-----+
  489. ;; | |
  490. ;; +-----+
  491. ;;
  492. ;; In normal mode if you type a word "antidisestablishmentarianism" it
  493. ;; grows the cell horizontally like this.
  494. ;;
  495. ;; +----------------------------+
  496. ;; |antidisestablishmentarianism|
  497. ;; +----------------------------+
  498. ;;
  499. ;; In the fixed width mode the same action produces the following
  500. ;; result. The folded locations are indicated by a continuation
  501. ;; character (`\' is the default). The continuation character is
  502. ;; treated specially so it is recommended to choose a character that
  503. ;; does not appear elsewhere in table cells. This character is
  504. ;; configurable via customization and is kept in the variable
  505. ;; `table-word-continuation-char'. The continuation character is
  506. ;; treated specially only in the fixed width mode and has no special
  507. ;; meaning in the normal mode however.
  508. ;;
  509. ;; +-----+
  510. ;; |anti\|
  511. ;; |dise\|
  512. ;; |stab\|
  513. ;; |lish\|
  514. ;; |ment\|
  515. ;; |aria\|
  516. ;; |nism |
  517. ;; +-----+
  518. ;;
  519. ;;
  520. ;; -------------------
  521. ;; Cell Justification:
  522. ;; -------------------
  523. ;;
  524. ;; By default the cell contents are filled with left justification and
  525. ;; no vertical justification. A paragraph can be justified
  526. ;; individually but only horizontally. Paragraph justification is for
  527. ;; appearance only and does not change any structural information
  528. ;; while cell justification affects table's structural information.
  529. ;; For cell justification a user can select horizontal justification
  530. ;; and vertical justification independently. Horizontal justification
  531. ;; must be one of the three 'left, 'center or 'right. Vertical
  532. ;; justification can be 'top, 'middle, 'bottom or 'none. When a cell
  533. ;; is justified, that information is recorded as a part of text
  534. ;; property therefore the information is persistent as long as the
  535. ;; cell remains within the Emacs world. Even copying tables by region
  536. ;; and rectangle manipulation commands preserve this information.
  537. ;; However, once the table text is saved as a file and the buffer is
  538. ;; killed the justification information vanishes permanently. To
  539. ;; alleviate this shortcoming without forcing users to save and
  540. ;; maintain a separate attribute file, the table code detects
  541. ;; justification of each cell when recognizing a table. This
  542. ;; detection is done by guessing the justification by looking at the
  543. ;; appearance of the cell contents. Since it is a guessing work it
  544. ;; does not guarantee the perfectness but it is designed to be
  545. ;; practically good enough. The guessing algorithm is implemented in
  546. ;; the function `table--detect-cell-alignment'. If you have better
  547. ;; algorithm or idea any suggestion is welcome.
  548. ;;
  549. ;;
  550. ;; -----
  551. ;; Todo: (in the order of priority, some are just possibility)
  552. ;; -----
  553. ;;
  554. ;; Fix compatibilities with other input method than quail
  555. ;; Resolve conflict with flyspell
  556. ;; Use mouse for resizing cells
  557. ;; A mechanism to link cells internally
  558. ;; Consider the use of variable width font under Emacs 21
  559. ;; Consider the use of `:box' face attribute under Emacs 21
  560. ;; Consider the use of `modification-hooks' text property instead of
  561. ;; rebinding the keymap
  562. ;; Maybe provide complete XEmacs support in the future however the
  563. ;; "extent" is the single largest obstacle lying ahead, read the
  564. ;; document in Emacs info.
  565. ;; (eval '(progn (require 'info) (Info-find-node "elisp" "Not Intervals")))
  566. ;;
  567. ;;
  568. ;; ---------------
  569. ;; Acknowledgment:
  570. ;; ---------------
  571. ;;
  572. ;; Table would not have been possible without the help and
  573. ;; encouragement of the following spirited contributors.
  574. ;;
  575. ;; Paul Georgief <georgief@igpp.ucsd.edu> has been the best tester
  576. ;; of the code as well as the constructive criticizer.
  577. ;;
  578. ;; Gerd Moellmann <gerd@gnu.org> gave me useful suggestions from Emacs
  579. ;; 21 point of view.
  580. ;;
  581. ;; Richard Stallman <rms@gnu.org> showed the initial interest in this
  582. ;; attempt of implementing the table feature to Emacs. This greatly
  583. ;; motivated me to follow through to its completion.
  584. ;;
  585. ;; Kenichi Handa <handa@etl.go.jp> kindly guided me through to
  586. ;; overcome many technical issues while I was struggling with quail
  587. ;; related internationalization problems.
  588. ;;
  589. ;; Christoph Conrad <christoph.conrad@gmx.de> suggested making symbol
  590. ;; names consistent as well as fixing several bugs.
  591. ;;
  592. ;; Paul Lew <paullew@cisco.com> suggested implementing fixed width
  593. ;; mode as well as multi column width (row height) input interface.
  594. ;;
  595. ;; Michael Smith <smith@xml-doc.org> a well-informed DocBook user
  596. ;; asked for CALS table source generation and helped me following
  597. ;; through the work by offering valuable suggestions and testing out
  598. ;; the code. Jorge Godoy <godoy@conectiva.com> has also suggested
  599. ;; supporting for DocBook tables.
  600. ;;
  601. ;; And many other individuals who reported bugs and suggestions.
  602. ;;; Code:
  603. (require 'regexp-opt)
  604. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  605. ;;;
  606. ;;; Compatibility:
  607. ;;;
  608. ;; hush up the byte-compiler
  609. (defvar quail-translating)
  610. (defvar quail-converting)
  611. (defvar flyspell-mode)
  612. (defvar real-last-command)
  613. (defvar delete-selection-mode)
  614. ;; This is evil!!
  615. ;; (eval-when-compile
  616. ;; (unless (fboundp 'set-face-property)
  617. ;; (defun set-face-property (face prop value)))
  618. ;; (unless (fboundp 'unibyte-char-to-multibyte)
  619. ;; (defun unibyte-char-to-multibyte (char)))
  620. ;; (defun table--point-in-cell-p (&optional location)))
  621. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  622. ;;;
  623. ;;; Customization:
  624. ;;;
  625. (defgroup table nil
  626. "Text based table manipulation utilities."
  627. :tag "Table"
  628. :prefix "table-"
  629. :group 'wp
  630. :version "22.1")
  631. (defgroup table-hooks nil
  632. "Hooks for table manipulation utilities."
  633. :group 'table)
  634. (defcustom table-time-before-update 0.2
  635. "Time in seconds before updating the cell contents after typing.
  636. Updating the cell contents on the screen takes place only after this
  637. specified amount of time has passed after the last modification to the
  638. cell contents. When the contents of a table cell changes repetitively
  639. and frequently the updating the cell contents on the screen is
  640. deferred until at least this specified amount of quiet time passes. A
  641. smaller number wastes more computation resource by unnecessarily
  642. frequent screen update. A large number presents noticeable and
  643. annoying delay before the typed result start appearing on the screen."
  644. :tag "Time Before Cell Update"
  645. :type 'number
  646. :group 'table)
  647. (defcustom table-time-before-reformat 0.2
  648. "Time in seconds before reformatting the table.
  649. This many seconds must pass in addition to `table-time-before-update'
  650. before the table is updated with newly widened width or heightened
  651. height."
  652. :tag "Time Before Cell Reformat"
  653. :type 'number
  654. :group 'table)
  655. (defcustom table-command-prefix [(control c) (control c)]
  656. "Key sequence to be used as prefix for table command key bindings."
  657. :type '(vector (repeat :inline t sexp))
  658. :tag "Table Command Prefix"
  659. :group 'table)
  660. (defface table-cell
  661. '((((min-colors 88) (class color))
  662. (:foreground "gray90" :background "blue1"))
  663. (((class color))
  664. (:foreground "gray90" :background "blue"))
  665. (t (:bold t)))
  666. "Face used for table cell contents."
  667. :tag "Cell Face"
  668. :group 'table)
  669. (defcustom table-cell-horizontal-chars "-="
  670. "Characters that may be used for table cell's horizontal border line."
  671. :tag "Cell Horizontal Boundary Characters"
  672. :type 'string
  673. :group 'table)
  674. (defcustom table-cell-vertical-char ?\|
  675. "Character that forms table cell's vertical border line."
  676. :tag "Cell Vertical Boundary Character"
  677. :type 'character
  678. :group 'table)
  679. (defcustom table-cell-intersection-char ?\+
  680. "Character that forms table cell's corner."
  681. :tag "Cell Intersection Character"
  682. :type 'character
  683. :group 'table)
  684. (defcustom table-word-continuation-char ?\\
  685. "Character that indicates word continuation into the next line.
  686. This character has a special meaning only in the fixed width mode,
  687. that is when `table-fixed-width-mode' is non-nil . In the fixed width
  688. mode this character indicates that the location is continuing into the
  689. next line. Be careful about the choice of this character. It is
  690. treated substantially different manner than ordinary characters. Try
  691. select a character that is unlikely to appear in your document."
  692. :tag "Cell Word Continuation Character"
  693. :type 'character
  694. :group 'table)
  695. (defun table-set-table-fixed-width-mode (variable value)
  696. (if (fboundp variable)
  697. (funcall variable (if value 1 -1))))
  698. (defun table-initialize-table-fixed-width-mode (variable value)
  699. (set variable value))
  700. (defcustom table-fixed-width-mode nil
  701. "Cell width is fixed when this is non-nil.
  702. Normally it should be nil for allowing automatic cell width expansion
  703. that widens a cell when it is necessary. When non-nil, typing in a
  704. cell does not automatically expand the cell width. A word that is too
  705. long to fit in a cell is chopped into multiple lines. The chopped
  706. location is indicated by `table-word-continuation-char'. This
  707. variable's value can be toggled by \\[table-fixed-width-mode] at
  708. run-time."
  709. :tag "Fix Cell Width"
  710. :type 'boolean
  711. :initialize 'table-initialize-table-fixed-width-mode
  712. :set 'table-set-table-fixed-width-mode
  713. :group 'table)
  714. (defcustom table-detect-cell-alignment t
  715. "Detect cell contents alignment automatically.
  716. When non-nil cell alignment is automatically determined by the
  717. appearance of the current cell contents when recognizing tables as a
  718. whole. This applies to `table-recognize', `table-recognize-region'
  719. and `table-recognize-table' but not to `table-recognize-cell'."
  720. :tag "Detect Cell Alignment"
  721. :type 'boolean
  722. :group 'table)
  723. (defcustom table-dest-buffer-name "table"
  724. "Default buffer name (without a suffix) for source generation."
  725. :tag "Source Buffer Name"
  726. :type 'string
  727. :group 'table)
  728. (defcustom table-html-delegate-spacing-to-user-agent nil
  729. "Non-nil delegates cell contents spacing entirely to user agent.
  730. Otherwise, when nil, it preserves the original spacing and line breaks."
  731. :tag "HTML delegate spacing"
  732. :type 'boolean
  733. :group 'table)
  734. (defcustom table-html-th-rows 0
  735. "Number of top rows to become header cells automatically in HTML generation."
  736. :tag "HTML Header Rows"
  737. :type 'integer
  738. :group 'table)
  739. (defcustom table-html-th-columns 0
  740. "Number of left columns to become header cells automatically in HTML generation."
  741. :tag "HTML Header Columns"
  742. :type 'integer
  743. :group 'table)
  744. (defcustom table-html-table-attribute "border=\"1\""
  745. "Table attribute that applies to the table in HTML generation."
  746. :tag "HTML table attribute"
  747. :type 'string
  748. :group 'table)
  749. (defcustom table-html-cell-attribute ""
  750. "Cell attribute that applies to all cells in HTML generation.
  751. Do not specify \"align\" and \"valign\" because they are determined by
  752. the cell contents dynamically."
  753. :tag "HTML cell attribute"
  754. :type 'string
  755. :group 'table)
  756. (defcustom table-cals-thead-rows 1
  757. "Number of top rows to become header rows in CALS table."
  758. :tag "CALS Header Rows"
  759. :type 'integer
  760. :group 'table)
  761. ;;;###autoload
  762. (defcustom table-cell-map-hook nil
  763. "Normal hooks run when finishing construction of `table-cell-map'.
  764. User can modify `table-cell-map' by adding custom functions here."
  765. :tag "Cell Keymap Hooks"
  766. :type 'hook
  767. :group 'table-hooks)
  768. (defcustom table-disable-incompatibility-warning nil
  769. "Disable compatibility warning notice.
  770. When nil user is reminded of known incompatible issues."
  771. :tag "Disable Incompatibility Warning"
  772. :type 'boolean
  773. :group 'table)
  774. (defcustom table-abort-recognition-when-input-pending t
  775. "Abort current recognition process when input pending.
  776. Abort current recognition process when we are not sure that no input
  777. is available. When non-nil lengthy recognition process is aborted
  778. simply by any key input."
  779. :tag "Abort Recognition When Input Pending"
  780. :type 'boolean
  781. :group 'table)
  782. ;;;###autoload
  783. (defcustom table-load-hook nil
  784. "List of functions to be called after the table is first loaded."
  785. :type 'hook
  786. :group 'table-hooks)
  787. ;;;###autoload
  788. (defcustom table-point-entered-cell-hook nil
  789. "List of functions to be called after point entered a table cell."
  790. :type 'hook
  791. :group 'table-hooks)
  792. ;;;###autoload
  793. (defcustom table-point-left-cell-hook nil
  794. "List of functions to be called after point left a table cell."
  795. :type 'hook
  796. :group 'table-hooks)
  797. (defvar table-yank-handler '(nil nil t nil)
  798. "Yank handler for tables.")
  799. (setplist 'table-disable-incompatibility-warning nil)
  800. (defvar table-disable-menu (null (and (locate-library "easymenu")
  801. (require 'easymenu)
  802. (fboundp 'easy-menu-add-item)))
  803. "*When non-nil, use of menu by table package is disabled.
  804. It must be set before loading this package `table.el' for the first
  805. time.")
  806. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  807. ;;;
  808. ;;; Implementation:
  809. ;;;
  810. ;;; Internal variables and constants
  811. ;;; No need of user configuration
  812. (defconst table-paragraph-start "[ \t\n\f]"
  813. "Regexp for beginning of a line that starts OR separates paragraphs.")
  814. (defconst table-cache-buffer-name " *table cell cache*"
  815. "Cell cache buffer name.")
  816. (defvar table-cell-info-lu-coordinate nil
  817. "Zero based coordinate of the cached cell's left upper corner.")
  818. (defvar table-cell-info-rb-coordinate nil
  819. "Zero based coordinate of the cached cell's right bottom corner.")
  820. (defvar table-cell-info-width nil
  821. "Number of characters per cached cell width.")
  822. (defvar table-cell-info-height nil
  823. "Number of lines per cached cell height.")
  824. (defvar table-cell-info-justify nil
  825. "Justification information of the cached cell.")
  826. (defvar table-cell-info-valign nil
  827. "Vertical alignment information of the cached cell.")
  828. (defvar table-cell-self-insert-command-count 0
  829. "Counter for undo control.")
  830. (defvar table-cell-map nil
  831. "Keymap for table cell contents.")
  832. (defvar table-cell-global-map-alist nil
  833. "Alist of copy of global maps that are substituted in `table-cell-map'.")
  834. (defvar table-global-menu-map nil
  835. "Menu map created via `easy-menu-define'.")
  836. (defvar table-cell-menu-map nil
  837. "Menu map created via `easy-menu-define'.")
  838. (defvar table-cell-buffer nil
  839. "Buffer that contains the table cell.")
  840. (defvar table-cell-cache-point-coordinate nil
  841. "Cache point coordinate based from the cell origin.")
  842. (defvar table-cell-cache-mark-coordinate nil
  843. "Cache mark coordinate based from the cell origin.")
  844. (defvar table-cell-entered-state nil
  845. "Records the state whether currently in a cell or nor.")
  846. (defvar table-update-timer nil
  847. "Timer id for deferred cell update.")
  848. (defvar table-widen-timer nil
  849. "Timer id for deferred cell update.")
  850. (defvar table-heighten-timer nil
  851. "Timer id for deferred cell update.")
  852. (defvar table-inhibit-update nil
  853. "Non-nil inhibits implicit cell and cache updates.
  854. It inhibits `table-with-cache-buffer' to update data in both direction, cell to cache and cache to cell.")
  855. (defvar table-inhibit-auto-fill-paragraph nil
  856. "Non-nil inhibits auto fill paragraph when `table-with-cache-buffer' exits.
  857. This is always set to nil at the entry to `table-with-cache-buffer' before executing body forms.")
  858. (defvar table-mode-indicator nil
  859. "For mode line indicator")
  860. ;; This is not a real minor-mode but placed in the minor-mode-alist
  861. ;; so that we can show the indicator on the mode line handy.
  862. (make-variable-buffer-local 'table-mode-indicator)
  863. (unless (assq table-mode-indicator minor-mode-alist)
  864. (push '(table-mode-indicator (table-fixed-width-mode " Fixed-Table" " Table"))
  865. minor-mode-alist))
  866. (defconst table-source-languages '(html latex cals)
  867. "Supported source languages.")
  868. (defvar table-source-info-plist nil
  869. "General storage for temporary information used while generating source.")
  870. ;; The following history containers not only keep the history of user
  871. ;; entries but also serve as the default value providers. When an
  872. ;; interactive command is invoked it offers a user the latest entry
  873. ;; of the history as a default selection. Therefore the values below
  874. ;; are the first default value when a command is invoked for the very
  875. ;; first time when there is no real history existing yet.
  876. (defvar table-cell-span-direction-history '("right"))
  877. (defvar table-cell-split-orientation-history '("horizontally"))
  878. (defvar table-cell-split-contents-to-history '("split"))
  879. (defvar table-insert-row-column-history '("row"))
  880. (defvar table-justify-history '("center"))
  881. (defvar table-columns-history '("3"))
  882. (defvar table-rows-history '("3"))
  883. (defvar table-cell-width-history '("5"))
  884. (defvar table-cell-height-history '("1"))
  885. (defvar table-source-caption-history '("Table"))
  886. (defvar table-sequence-string-history '("0"))
  887. (defvar table-sequence-count-history '("0"))
  888. (defvar table-sequence-increment-history '("1"))
  889. (defvar table-sequence-interval-history '("1"))
  890. (defvar table-sequence-justify-history '("left"))
  891. (defvar table-source-language-history '("html"))
  892. (defvar table-col-delim-regexp-history '(""))
  893. (defvar table-row-delim-regexp-history '(""))
  894. (defvar table-capture-justify-history '("left"))
  895. (defvar table-capture-min-cell-width-history '("5"))
  896. (defvar table-capture-columns-history '(""))
  897. (defvar table-target-history '("cell"))
  898. ;; Some entries in `table-cell-bindings' are duplicated in
  899. ;; `table-command-remap-alist'. There is a good reason for
  900. ;; this. Common key like return key may be taken by some other
  901. ;; function than normal `newline' function. Thus binding return key
  902. ;; directly for `*table--cell-newline' ensures that the correct enter
  903. ;; operation in a table cell. However
  904. ;; `table-command-remap-alist' has an additional role than
  905. ;; replacing commands. It is also used to construct a table command
  906. ;; list. This list is very important because it is used to check if
  907. ;; the previous command was one of them in this list or not. If the
  908. ;; previous command is found in the list the current command will not
  909. ;; refill the table cache. If the command were not listed fast
  910. ;; typing can cause unwanted cache refill.
  911. (defconst table-cell-bindings
  912. '(([(control i)] . table-forward-cell)
  913. ([(control I)] . table-backward-cell)
  914. ([tab] . table-forward-cell)
  915. ([(shift backtab)] . table-backward-cell) ; for HPUX console keyboard
  916. ([(shift iso-lefttab)] . table-backward-cell) ; shift-tab on a microsoft natural keyboard and redhat linux
  917. ([(shift tab)] . table-backward-cell)
  918. ([return] . *table--cell-newline)
  919. ([(control m)] . *table--cell-newline)
  920. ([(control j)] . *table--cell-newline-and-indent)
  921. ([mouse-3] . *table--present-cell-popup-menu)
  922. ([(control ?>)] . table-widen-cell)
  923. ([(control ?<)] . table-narrow-cell)
  924. ([(control ?})] . table-heighten-cell)
  925. ([(control ?{)] . table-shorten-cell)
  926. ([(control ?-)] . table-split-cell-vertically)
  927. ([(control ?|)] . table-split-cell-horizontally)
  928. ([(control ?*)] . table-span-cell)
  929. ([(control ?+)] . table-insert-row-column)
  930. ([(control ?!)] . table-fixed-width-mode)
  931. ([(control ?#)] . table-query-dimension)
  932. ([(control ?^)] . table-generate-source)
  933. ([(control ?:)] . table-justify)
  934. )
  935. "Bindings for table cell commands.")
  936. (defvar table-command-remap-alist
  937. '((self-insert-command . *table--cell-self-insert-command)
  938. (completion-separator-self-insert-autofilling . *table--cell-self-insert-command)
  939. (completion-separator-self-insert-command . *table--cell-self-insert-command)
  940. (delete-char . *table--cell-delete-char)
  941. (delete-backward-char . *table--cell-delete-backward-char)
  942. (backward-delete-char . *table--cell-delete-backward-char)
  943. (backward-delete-char-untabify . *table--cell-delete-backward-char)
  944. (newline . *table--cell-newline)
  945. (newline-and-indent . *table--cell-newline-and-indent)
  946. (open-line . *table--cell-open-line)
  947. (quoted-insert . *table--cell-quoted-insert)
  948. (describe-mode . *table--cell-describe-mode)
  949. (describe-bindings . *table--cell-describe-bindings)
  950. (dabbrev-expand . *table--cell-dabbrev-expand)
  951. (dabbrev-completion . *table--cell-dabbrev-completion))
  952. "List of cons cells consisting of (ORIGINAL-COMMAND . TABLE-VERSION-OF-THE-COMMAND).")
  953. (defvar table-command-list nil
  954. "List of commands that override original commands.")
  955. ;; construct the real contents of the `table-command-list'
  956. (let ((remap-alist table-command-remap-alist))
  957. (setq table-command-list nil)
  958. (while remap-alist
  959. (setq table-command-list (cons (cdar remap-alist) table-command-list))
  960. (setq remap-alist (cdr remap-alist))))
  961. (defconst table-global-menu
  962. '("Table"
  963. ("Insert"
  964. ["a Table..." table-insert
  965. :active (and (not buffer-read-only) (not (table--probe-cell)))
  966. :help "Insert a text based table at point"]
  967. ["Row" table-insert-row
  968. :active (table--row-column-insertion-point-p)
  969. :help "Insert row(s) of cells in table"]
  970. ["Column" table-insert-column
  971. :active (table--row-column-insertion-point-p 'column)
  972. :help "Insert column(s) of cells in table"])
  973. "----"
  974. ("Recognize"
  975. ["in Buffer" table-recognize
  976. :active t
  977. :help "Recognize all tables in the current buffer"]
  978. ["in Region" table-recognize-region
  979. :active (and mark-active (not (eq (mark t) (point))))
  980. :help "Recognize all tables in the current region"]
  981. ["a Table" table-recognize-table
  982. :active (table--probe-cell)
  983. :help "Recognize a table at point"]
  984. ["a Cell" table-recognize-cell
  985. :active (let ((cell (table--probe-cell)))
  986. (and cell (null (table--at-cell-p (car cell)))))
  987. :help "Recognize a cell at point"])
  988. ("Unrecognize"
  989. ["in Buffer" table-unrecognize
  990. :active t
  991. :help "Unrecognize all tables in the current buffer"]
  992. ["in Region" table-unrecognize-region
  993. :active (and mark-active (not (eq (mark t) (point))))
  994. :help "Unrecognize all tables in the current region"]
  995. ["a Table" table-unrecognize-table
  996. :active (table--probe-cell)
  997. :help "Unrecognize the current table"]
  998. ["a Cell" table-unrecognize-cell
  999. :active (let ((cell (table--probe-cell)))
  1000. (and cell (table--at-cell-p (car cell))))
  1001. :help "Unrecognize the current cell"])
  1002. "----"
  1003. ["Capture Region" table-capture
  1004. :active (and (not buffer-read-only) mark-active (not (eq (mark t) (point))) (not (table--probe-cell)))
  1005. :help "Capture text in the current region as a table"]
  1006. ["Release" table-release
  1007. :active (table--editable-cell-p)
  1008. :help "Release the current table as plain text"]))
  1009. (defconst table-cell-menu
  1010. '("Table"
  1011. ("Insert"
  1012. ["Row" table-insert-row
  1013. :active (table--row-column-insertion-point-p)
  1014. :help "Insert row(s) of cells in table"]
  1015. ["Column" table-insert-column
  1016. :active (table--row-column-insertion-point-p 'column)
  1017. :help "Insert column(s) of cells in table"])
  1018. ("Delete"
  1019. ["Row" table-delete-row
  1020. :active (table--editable-cell-p)
  1021. :help "Delete row(s) of cells in table"]
  1022. ["Column" table-delete-column
  1023. :active (table--editable-cell-p)
  1024. :help "Delete column(s) of cells in table"])
  1025. "----"
  1026. ("Split a Cell"
  1027. ["Horizontally" table-split-cell-horizontally
  1028. :active (table--cell-can-split-horizontally-p)
  1029. :help "Split the current cell horizontally at point"]
  1030. ["Vertically" table-split-cell-vertically
  1031. :active (table--cell-can-split-vertically-p)
  1032. :help "Split the current cell vertical at point"])
  1033. ("Span a Cell to"
  1034. ["Right" (table-span-cell 'right)
  1035. :active (table--cell-can-span-p 'right)
  1036. :help "Span the current cell into the right cell"]
  1037. ["Left" (table-span-cell 'left)
  1038. :active (table--cell-can-span-p 'left)
  1039. :help "Span the current cell into the left cell"]
  1040. ["Above" (table-span-cell 'above)
  1041. :active (table--cell-can-span-p 'above)
  1042. :help "Span the current cell into the cell above"]
  1043. ["Below" (table-span-cell 'below)
  1044. :active (table--cell-can-span-p 'below)
  1045. :help "Span the current cell into the cell below"])
  1046. "----"
  1047. ("Shrink Cells"
  1048. ["Horizontally" table-narrow-cell
  1049. :active (table--editable-cell-p)
  1050. :help "Shrink the current cell horizontally"]
  1051. ["Vertically" table-shorten-cell
  1052. :active (table--editable-cell-p)
  1053. :help "Shrink the current cell vertically"])
  1054. ("Expand Cells"
  1055. ["Horizontally" table-widen-cell
  1056. :active (table--editable-cell-p)
  1057. :help "Expand the current cell horizontally"]
  1058. ["Vertically" table-heighten-cell
  1059. :active (table--editable-cell-p)
  1060. :help "Expand the current cell vertically"])
  1061. "----"
  1062. ("Justify"
  1063. ("a Cell"
  1064. ["Left" (table-justify-cell 'left)
  1065. :active (table--editable-cell-p)
  1066. :help "Left justify the contents of the current cell"]
  1067. ["Center" (table-justify-cell 'center)
  1068. :active (table--editable-cell-p)
  1069. :help "Center justify the contents of the current cell"]
  1070. ["Right" (table-justify-cell 'right)
  1071. :active (table--editable-cell-p)
  1072. :help "Right justify the contents of the current cell"]
  1073. "----"
  1074. ["Top" (table-justify-cell 'top)
  1075. :active (table--editable-cell-p)
  1076. :help "Top align the contents of the current cell"]
  1077. ["Middle" (table-justify-cell 'middle)
  1078. :active (table--editable-cell-p)
  1079. :help "Middle align the contents of the current cell"]
  1080. ["Bottom" (table-justify-cell 'bottom)
  1081. :active (table--editable-cell-p)
  1082. :help "Bottom align the contents of the current cell"]
  1083. ["None" (table-justify-cell 'none)
  1084. :active (table--editable-cell-p)
  1085. :help "Remove vertical alignment from the current cell"])
  1086. ("a Row"
  1087. ["Left" (table-justify-row 'left)
  1088. :active (table--editable-cell-p)
  1089. :help "Left justify the contents of all cells in the current row"]
  1090. ["Center" (table-justify-row 'center)
  1091. :active (table--editable-cell-p)
  1092. :help "Center justify the contents of all cells in the current row"]
  1093. ["Right" (table-justify-row 'right)
  1094. :active (table--editable-cell-p)
  1095. :help "Right justify the contents of all cells in the current row"]
  1096. "----"
  1097. ["Top" (table-justify-row 'top)
  1098. :active (table--editable-cell-p)
  1099. :help "Top align the contents of all cells in the current row"]
  1100. ["Middle" (table-justify-row 'middle)
  1101. :active (table--editable-cell-p)
  1102. :help "Middle align the contents of all cells in the current row"]
  1103. ["Bottom" (table-justify-row 'bottom)
  1104. :active (table--editable-cell-p)
  1105. :help "Bottom align the contents of all cells in the current row"]
  1106. ["None" (table-justify-cell 'none)
  1107. :active (table--editable-cell-p)
  1108. :help "Remove vertical alignment from all cells in the current row"])
  1109. ("a Column"
  1110. ["Left" (table-justify-column 'left)
  1111. :active (table--editable-cell-p)
  1112. :help "Left justify the contents of all cells in the current column"]
  1113. ["Center" (table-justify-column 'center)
  1114. :active (table--editable-cell-p)
  1115. :help "Center justify the contents of all cells in the current column"]
  1116. ["Right" (table-justify-column 'right)
  1117. :active (table--editable-cell-p)
  1118. :help "Right justify the contents of all cells in the current column"]
  1119. "----"
  1120. ["Top" (table-justify-column 'top)
  1121. :active (table--editable-cell-p)
  1122. :help "Top align the contents of all cells in the current column"]
  1123. ["Middle" (table-justify-column 'middle)
  1124. :active (table--editable-cell-p)
  1125. :help "Middle align the contents of all cells in the current column"]
  1126. ["Bottom" (table-justify-column 'bottom)
  1127. :active (table--editable-cell-p)
  1128. :help "Bottom align the contents of all cells in the current column"]
  1129. ["None" (table-justify-cell 'none)
  1130. :active (table--editable-cell-p)
  1131. :help "Remove vertical alignment from all cells in the current column"])
  1132. ("a Paragraph"
  1133. ["Left" (table-justify-cell 'left t)
  1134. :active (table--editable-cell-p)
  1135. :help "Left justify the current paragraph"]
  1136. ["Center" (table-justify-cell 'center t)
  1137. :active (table--editable-cell-p)
  1138. :help "Center justify the current paragraph"]
  1139. ["Right" (table-justify-cell 'right t)
  1140. :active (table--editable-cell-p)
  1141. :help "Right justify the current paragraph"]))
  1142. "----"
  1143. ["Query Dimension" table-query-dimension
  1144. :active (table--probe-cell)
  1145. :help "Get the dimension of the current cell and the current table"]
  1146. ["Generate Source" table-generate-source
  1147. :active (table--probe-cell)
  1148. :help "Generate source of the current table in the specified language"]
  1149. ["Insert Sequence" table-insert-sequence
  1150. :active (table--editable-cell-p)
  1151. :help "Travel cells forward while inserting a specified sequence string in each cell"]
  1152. ("Unrecognize"
  1153. ["a Table" table-unrecognize-table
  1154. :active (table--probe-cell)
  1155. :help "Unrecognize the current table"]
  1156. ["a Cell" table-unrecognize-cell
  1157. :active (let ((cell (table--probe-cell)))
  1158. (and cell (table--at-cell-p (car cell))))
  1159. :help "Unrecognize the current cell"])
  1160. ["Release" table-release
  1161. :active (table--editable-cell-p)
  1162. :help "Release the current table as plain text"]
  1163. ("Configure Width to"
  1164. ["Auto Expand Mode" (table-fixed-width-mode -1)
  1165. :active t
  1166. :style radio
  1167. :selected (not table-fixed-width-mode)
  1168. :help "A mode that allows automatic horizontal cell expansion"]
  1169. ["Fixed Width Mode" (table-fixed-width-mode 1)
  1170. :active t
  1171. :style radio
  1172. :selected table-fixed-width-mode
  1173. :help "A mode that does not allow automatic horizontal cell expansion"])
  1174. ("Navigate"
  1175. ["Forward Cell" table-forward-cell
  1176. :active (table--probe-cell)
  1177. :help "Move point forward by cell(s)"]
  1178. ["Backward Cell" table-backward-cell
  1179. :active (table--probe-cell)
  1180. :help "Move point backward by cell(s)"])
  1181. ))
  1182. ;; XEmacs causes an error when encountering unknown keywords in the
  1183. ;; menu definition. Specifically the :help keyword is new in Emacs 21
  1184. ;; and causes error for the XEmacs function `check-menu-syntax'. IMHO
  1185. ;; it is unwise to generate an error for unknown keywords because it
  1186. ;; kills the nice backward compatible extensibility of keyword use.
  1187. ;; Unknown keywords should be quietly ignore so that future extension
  1188. ;; does not cause a problem in the old implementation. Sigh...
  1189. (when (featurep 'xemacs)
  1190. (mapcar
  1191. (defun table--tweak-menu-for-xemacs (menu)
  1192. (cond
  1193. ((listp menu)
  1194. (mapcar 'table--tweak-menu-for-xemacs menu))
  1195. ((vectorp menu)
  1196. (let ((i 0) (len (length menu)))
  1197. (while (< i len)
  1198. ;; replace :help with something harmless.
  1199. (if (eq (aref menu i) :help) (aset menu i :included))
  1200. (setq i (1+ i)))))))
  1201. (list table-global-menu table-cell-menu))
  1202. (defvar mark-active t))
  1203. ;; register table menu under global tools menu
  1204. (unless table-disable-menu
  1205. (easy-menu-define table-global-menu-map nil "Table global menu" table-global-menu)
  1206. (if (featurep 'xemacs)
  1207. (progn
  1208. (easy-menu-add-item nil '("Tools") table-global-menu-map))
  1209. (easy-menu-add-item (current-global-map) '("menu-bar" "tools") "--")
  1210. (easy-menu-add-item (current-global-map) '("menu-bar" "tools") table-global-menu-map)))
  1211. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1212. ;;
  1213. ;; Macros
  1214. ;;
  1215. (defmacro table-with-cache-buffer (&rest body)
  1216. "Execute the forms in BODY with table cache buffer as the current buffer.
  1217. This macro simplifies the rest of the work greatly by condensing the
  1218. common idiom used in many of the cell manipulation functions. It does
  1219. not return any meaningful value.
  1220. Save the current buffer and set the cache buffer as the current
  1221. buffer. Move the point to the cache buffer coordinate
  1222. `table-cell-cache-point-coordinate'. After BODY forms are executed,
  1223. the paragraph is filled as long as `table-inhibit-auto-fill-paragraph'
  1224. remains nil. BODY can set it to t when it does not want to fill the
  1225. paragraph. If necessary the cell width and height are extended as the
  1226. consequence of cell content modification by the BODY. Then the
  1227. current buffer is restored to the original one. The last cache point
  1228. coordinate is stored in `table-cell-cache-point-coordinate'. The
  1229. original buffer's point is moved to the location that corresponds to
  1230. the last cache point coordinate."
  1231. (let ((height-expansion (make-symbol "height-expansion-var-symbol"))
  1232. (width-expansion (make-symbol "width-expansion-var-symbol")))
  1233. `(let (,height-expansion ,width-expansion)
  1234. ;; make sure cache has valid data unless it is explicitly inhibited.
  1235. (unless table-inhibit-update
  1236. (table-recognize-cell))
  1237. (with-current-buffer (get-buffer-create table-cache-buffer-name)
  1238. ;; goto the cell coordinate based on `table-cell-cache-point-coordinate'.
  1239. (set-mark (table--goto-coordinate table-cell-cache-mark-coordinate))
  1240. (table--goto-coordinate table-cell-cache-point-coordinate)
  1241. (table--untabify-line)
  1242. ;; always reset before executing body forms because auto-fill behavior is the default.
  1243. (setq table-inhibit-auto-fill-paragraph nil)
  1244. ;; do the body
  1245. ,@body
  1246. ;; fill paragraph unless the body does not want to by setting `table-inhibit-auto-fill-paragraph'.
  1247. (unless table-inhibit-auto-fill-paragraph
  1248. (if (and table-cell-info-justify
  1249. (not (eq table-cell-info-justify 'left)))
  1250. (table--fill-region (point-min) (point-max))
  1251. (table--fill-region
  1252. (save-excursion (forward-paragraph -1) (point))
  1253. (save-excursion (forward-paragraph 1) (point)))))
  1254. ;; keep the updated cell coordinate.
  1255. (setq table-cell-cache-point-coordinate (table--get-coordinate))
  1256. ;; determine the cell width expansion.
  1257. (setq ,width-expansion (table--measure-max-width))
  1258. (if (<= ,width-expansion table-cell-info-width) nil
  1259. (table--fill-region (point-min) (point-max) ,width-expansion)
  1260. ;; keep the updated cell coordinate.
  1261. (setq table-cell-cache-point-coordinate (table--get-coordinate)))
  1262. (setq ,width-expansion (- ,width-expansion table-cell-info-width))
  1263. ;; determine the cell height expansion.
  1264. (if (looking-at "\\s *\\'") nil
  1265. (goto-char (point-min))
  1266. (if (re-search-forward "\\(\\s *\\)\\'" nil t)
  1267. (goto-char (match-beginning 1))))
  1268. (setq ,height-expansion (- (cdr (table--get-coordinate)) (1- table-cell-info-height))))
  1269. ;; now back to the table buffer.
  1270. ;; expand the cell width in the table buffer if necessary.
  1271. (if (> ,width-expansion 0)
  1272. (table-widen-cell ,width-expansion 'no-copy 'no-update))
  1273. ;; expand the cell height in the table buffer if necessary.
  1274. (if (> ,height-expansion 0)
  1275. (table-heighten-cell ,height-expansion 'no-copy 'no-update))
  1276. ;; do valign
  1277. (with-current-buffer (get-buffer-create table-cache-buffer-name)
  1278. (table--goto-coordinate table-cell-cache-point-coordinate)
  1279. (setq table-cell-cache-point-coordinate (table--valign)))
  1280. ;; move the point in the table buffer to the location that corresponds to
  1281. ;; the location in the cell cache buffer
  1282. (table--goto-coordinate (table--transcoord-cache-to-table table-cell-cache-point-coordinate))
  1283. ;; set up the update timer unless it is explicitly inhibited.
  1284. (unless table-inhibit-update
  1285. (table--update-cell)))))
  1286. ;; for debugging the body form of the macro
  1287. (put 'table-with-cache-buffer 'edebug-form-spec '(body))
  1288. ;; for neat presentation use the same indentation as `progn'
  1289. (put 'table-with-cache-buffer 'lisp-indent-function 0)
  1290. (if (or (featurep 'xemacs)
  1291. (null (fboundp 'font-lock-add-keywords))) nil
  1292. ;; color it as a keyword
  1293. (font-lock-add-keywords
  1294. 'emacs-lisp-mode
  1295. '("\\<table-with-cache-buffer\\>")))
  1296. (defmacro table-put-source-info (prop value)
  1297. "Register source generation information."
  1298. `(put 'table-source-info-plist ,prop ,value))
  1299. (defmacro table-get-source-info (prop)
  1300. "Retrieve source generation information."
  1301. `(get 'table-source-info-plist ,prop))
  1302. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1303. ;;
  1304. ;; Modified commands for cell operation
  1305. ;;
  1306. ;; Point Motion Only Group
  1307. (mapc
  1308. (lambda (command)
  1309. (let ((func-symbol (intern (format "*table--cell-%s" command)))
  1310. (doc-string (format "Table remapped function for `%s'." command)))
  1311. (fset func-symbol
  1312. `(lambda
  1313. (&rest args)
  1314. ,doc-string
  1315. (interactive)
  1316. (let ((table-inhibit-update t)
  1317. (deactivate-mark nil))
  1318. (table--finish-delayed-tasks)
  1319. (table-recognize-cell 'force)
  1320. (table-with-cache-buffer
  1321. (call-interactively ',command)
  1322. (setq table-inhibit-auto-fill-paragraph t)))))
  1323. (setq table-command-remap-alist
  1324. (cons (cons command func-symbol)
  1325. table-command-remap-alist))))
  1326. '(move-beginning-of-line
  1327. beginning-of-line
  1328. move-end-of-line
  1329. end-of-line
  1330. beginning-of-buffer
  1331. end-of-buffer
  1332. forward-word
  1333. backward-word
  1334. forward-sentence
  1335. backward-sentence
  1336. forward-paragraph
  1337. backward-paragraph))
  1338. ;; Extraction Group
  1339. (mapc
  1340. (lambda (command)
  1341. (let ((func-symbol (intern (format "*table--cell-%s" command)))
  1342. (doc-string (format "Table remapped function for `%s'." command)))
  1343. (fset func-symbol
  1344. `(lambda
  1345. (&rest args)
  1346. ,doc-string
  1347. (interactive)
  1348. (table--finish-delayed-tasks)
  1349. (table-recognize-cell 'force)
  1350. (table-with-cache-buffer
  1351. (table--remove-cell-properties (point-min) (point-max))
  1352. (table--remove-eol-spaces (point-min) (point-max))
  1353. (call-interactively ',command))
  1354. (table--finish-delayed-tasks)))
  1355. (setq table-command-remap-alist
  1356. (cons (cons command func-symbol)
  1357. table-command-remap-alist))))
  1358. '(kill-region
  1359. kill-ring-save
  1360. delete-region
  1361. copy-region-as-kill
  1362. kill-line
  1363. kill-word
  1364. backward-kill-word
  1365. kill-sentence
  1366. backward-kill-sentence
  1367. kill-paragraph
  1368. backward-kill-paragraph
  1369. kill-sexp
  1370. backward-kill-sexp))
  1371. ;; Pasting Group
  1372. (mapc
  1373. (lambda (command)
  1374. (let ((func-symbol (intern (format "*table--cell-%s" command)))
  1375. (doc-string (format "Table remapped function for `%s'." command)))
  1376. (fset func-symbol
  1377. `(lambda
  1378. (&rest args)
  1379. ,doc-string
  1380. (interactive)
  1381. (table--finish-delayed-tasks)
  1382. (table-recognize-cell 'force)
  1383. (table-with-cache-buffer
  1384. (call-interactively ',command)
  1385. (table--untabify (point-min) (point-max))
  1386. (table--fill-region (point-min) (point-max))
  1387. (setq table-inhibit-auto-fill-paragraph t))
  1388. (table--finish-delayed-tasks)))
  1389. (setq table-command-remap-alist
  1390. (cons (cons command func-symbol)
  1391. table-command-remap-alist))))
  1392. '(yank
  1393. clipboard-yank
  1394. yank-clipboard-selection
  1395. insert))
  1396. ;; Formatting Group
  1397. (mapc
  1398. (lambda (command)
  1399. (let ((func-symbol (intern (format "*table--cell-%s" command)))
  1400. (doc-string (format "Table remapped function for `%s'." command)))
  1401. (fset func-symbol
  1402. `(lambda
  1403. (&rest args)
  1404. ,doc-string
  1405. (interactive)
  1406. (table--finish-delayed-tasks)
  1407. (table-recognize-cell 'force)
  1408. (table-with-cache-buffer
  1409. (let ((fill-column table-cell-info-width))
  1410. (call-interactively ',command))
  1411. (setq table-inhibit-auto-fill-paragraph t))
  1412. (table--finish-delayed-tasks)))
  1413. (setq table-command-remap-alist
  1414. (cons (cons command func-symbol)
  1415. table-command-remap-alist))))
  1416. '(center-line
  1417. center-region
  1418. center-paragraph
  1419. fill-paragraph))
  1420. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1421. ;;
  1422. ;; Commands
  1423. ;;
  1424. ;;;###autoload
  1425. (defun table-insert (columns rows &optional cell-width cell-height)
  1426. "Insert an editable text table.
  1427. Insert a table of specified number of COLUMNS and ROWS. Optional
  1428. parameter CELL-WIDTH and CELL-HEIGHT can specify the size of each
  1429. cell. The cell size is uniform across the table if the specified size
  1430. is a number. They can be a list of numbers to specify different size
  1431. for each cell. When called interactively, the list of number is
  1432. entered by simply listing all the numbers with space characters
  1433. delimiting them.
  1434. Examples:
  1435. \\[table-insert] inserts a table at the current point location.
  1436. Suppose we have the following situation where `-!-' indicates the
  1437. location of point.
  1438. -!-
  1439. Type \\[table-insert] and hit ENTER key. As it asks table
  1440. specification, provide 3 for number of columns, 1 for number of rows,
  1441. 5 for cell width and 1 for cell height. Now you shall see the next
  1442. table and the point is automatically moved to the beginning of the
  1443. first cell.
  1444. +-----+-----+-----+
  1445. |-!- | | |
  1446. +-----+-----+-----+
  1447. Inside a table cell, there are special key bindings. \\<table-cell-map>
  1448. M-9 \\[table-widen-cell] (or \\[universal-argument] 9 \\[table-widen-cell]) widens the first cell by 9 character
  1449. width, which results as
  1450. +--------------+-----+-----+
  1451. |-!- | | |
  1452. +--------------+-----+-----+
  1453. Type TAB \\[table-widen-cell] then type TAB M-2 M-7 \\[table-widen-cell] (or \\[universal-argument] 2 7 \\[table-widen-cell]). Typing
  1454. TAB moves the point forward by a cell. The result now looks like this:
  1455. +--------------+------+--------------------------------+
  1456. | | |-!- |
  1457. +--------------+------+--------------------------------+
  1458. If you knew each width of the columns prior to the table creation,
  1459. what you could have done better was to have had given the complete
  1460. width information to `table-insert'.
  1461. Cell width(s): 14 6 32
  1462. instead of
  1463. Cell width(s): 5
  1464. This would have eliminated the previously mentioned width adjustment
  1465. work all together.
  1466. If the point is in the last cell type S-TAB S-TAB to move it to the
  1467. first cell. Now type \\[table-heighten-cell] which heighten the row by a line.
  1468. +--------------+------+--------------------------------+
  1469. |-!- | | |
  1470. | | | |
  1471. +--------------+------+--------------------------------+
  1472. Type \\[table-insert-row-column] and tell it to insert a row.
  1473. +--------------+------+--------------------------------+
  1474. |-!- | | |
  1475. | | | |
  1476. +--------------+------+--------------------------------+
  1477. | | | |
  1478. | | | |
  1479. +--------------+------+--------------------------------+
  1480. Move the point under the table as shown below.
  1481. +--------------+------+--------------------------------+
  1482. | | | |
  1483. | | | |
  1484. +--------------+------+--------------------------------+
  1485. | | | |
  1486. | | | |
  1487. +--------------+------+--------------------------------+
  1488. -!-
  1489. Type M-x table-insert-row instead of \\[table-insert-row-column]. \\[table-insert-row-column] does not work
  1490. when the point is outside of the table. This insertion at
  1491. outside of the table effectively appends a row at the end.
  1492. +--------------+------+--------------------------------+
  1493. | | | |
  1494. | | | |
  1495. +--------------+------+--------------------------------+
  1496. | | | |
  1497. | | | |
  1498. +--------------+------+--------------------------------+
  1499. |-!- | | |
  1500. | | | |
  1501. +--------------+------+--------------------------------+
  1502. Text editing inside the table cell produces reasonably expected
  1503. results.
  1504. +--------------+------+--------------------------------+
  1505. | | | |
  1506. | | | |
  1507. +--------------+------+--------------------------------+
  1508. | | |Text editing inside the table |
  1509. | | |cell produces reasonably |
  1510. | | |expected results.-!- |
  1511. +--------------+------+--------------------------------+
  1512. | | | |
  1513. | | | |
  1514. +--------------+------+--------------------------------+
  1515. Inside a table cell has a special keymap.
  1516. \\{table-cell-map}
  1517. "
  1518. (interactive
  1519. (progn
  1520. (barf-if-buffer-read-only)
  1521. (if (table--probe-cell)
  1522. (error "Can't insert a table inside a table"))
  1523. (mapcar (function table--read-from-minibuffer)
  1524. '(("Number of columns" . table-columns-history)
  1525. ("Number of rows" . table-rows-history)
  1526. ("Cell width(s)" . table-cell-width-history)
  1527. ("Cell height(s)" . table-cell-height-history)))))
  1528. (table--make-cell-map)
  1529. ;; reform the arguments.
  1530. (if (null cell-width) (setq cell-width (car table-cell-width-history)))
  1531. (if (null cell-height) (setq cell-height (car table-cell-height-history)))
  1532. (if (stringp columns) (setq columns (string-to-number columns)))
  1533. (if (stringp rows) (setq rows (string-to-number rows)))
  1534. (if (stringp cell-width) (setq cell-width (table--string-to-number-list cell-width)))
  1535. (if (stringp cell-height) (setq cell-height (table--string-to-number-list cell-height)))
  1536. (if (numberp cell-width) (setq cell-width (cons cell-width nil)))
  1537. (if (numberp cell-height) (setq cell-height (cons cell-height nil)))
  1538. ;; test validity of the arguments.
  1539. (mapc (lambda (arg)
  1540. (let* ((value (symbol-value arg))
  1541. (error-handler
  1542. (function (lambda ()
  1543. (error "%s must be a positive integer%s" arg
  1544. (if (listp value) " or a list of positive integers" ""))))))
  1545. (if (null value) (funcall error-handler))
  1546. (mapcar (function (lambda (arg1)
  1547. (if (or (not (integerp arg1))
  1548. (< arg1 1))
  1549. (funcall error-handler))))
  1550. (if (listp value) value
  1551. (cons value nil)))))
  1552. '(columns rows cell-width cell-height))
  1553. (let ((orig-coord (table--get-coordinate))
  1554. (coord (table--get-coordinate))
  1555. r i cw ch cell-str border-str)
  1556. ;; prefabricate the building blocks border-str and cell-str.
  1557. (with-temp-buffer
  1558. ;; construct border-str
  1559. (insert table-cell-intersection-char)
  1560. (setq cw cell-width)
  1561. (setq i 0)
  1562. (while (< i columns)
  1563. (insert (make-string (car cw) (string-to-char table-cell-horizontal-chars)) table-cell-intersection-char)
  1564. (if (cdr cw) (setq cw (cdr cw)))
  1565. (setq i (1+ i)))
  1566. (setq border-str (buffer-substring (point-min) (point-max)))
  1567. ;; construct cell-str
  1568. (erase-buffer)
  1569. (insert table-cell-vertical-char)
  1570. (setq cw cell-width)
  1571. (setq i 0)
  1572. (while (< i columns)
  1573. (let ((beg (point)))
  1574. (insert (make-string (car cw) ?\s))
  1575. (insert table-cell-vertical-char)
  1576. (table--put-cell-line-property beg (1- (point))))
  1577. (if (cdr cw) (setq cw (cdr cw)))
  1578. (setq i (1+ i)))
  1579. (setq cell-str (buffer-substring (point-min) (point-max))))
  1580. ;; if the construction site has an empty border push that border down.
  1581. (save-excursion
  1582. (beginning-of-line)
  1583. (if (looking-at "\\s *$")
  1584. (progn
  1585. (setq border-str (concat border-str "\n"))
  1586. (setq cell-str (concat cell-str "\n")))))
  1587. ;; now build the table using the prefabricated building blocks
  1588. (setq r 0)
  1589. (setq ch cell-height)
  1590. (while (< r rows)
  1591. (if (> r 0) nil
  1592. (table--goto-coordinate coord) (setcdr coord (1+ (cdr coord)))
  1593. (table--untabify-line (point))
  1594. (insert border-str))
  1595. (setq i 0)
  1596. (while (< i (car ch))
  1597. (table--goto-coordinate coord) (setcdr coord (1+ (cdr coord)))
  1598. (table--untabify-line (point))
  1599. (insert cell-str)
  1600. (setq i (1+ i)))
  1601. (table--goto-coordinate coord) (setcdr coord (1+ (cdr coord)))
  1602. (table--untabify-line (point))
  1603. (insert border-str)
  1604. (if (cdr ch) (setq ch (cdr ch)))
  1605. (setq r (1+ r)))
  1606. ;; stand by at the first cell
  1607. (table--goto-coordinate (table--offset-coordinate orig-coord '(1 . 1)))
  1608. (table-recognize-cell 'force)))
  1609. ;;;###autoload
  1610. (defun table-insert-row (n)
  1611. "Insert N table row(s).
  1612. When point is in a table the newly inserted row(s) are placed above
  1613. the current row. When point is outside of the table it must be below
  1614. the table within the table width range, then the newly created row(s)
  1615. are appended at the bottom of the table."
  1616. (interactive "*p")
  1617. (if (< n 0) (setq n 1))
  1618. (let* ((current-coordinate (table--get-coordinate))
  1619. (coord-list (table--cell-list-to-coord-list (table--horizontal-cell-list t nil 'top)))
  1620. (append-row (if coord-list nil (setq coord-list (table--find-row-column))))
  1621. (cell-height (cdr (table--min-coord-list coord-list)))
  1622. (left-list nil)
  1623. (this-list coord-list)
  1624. (right-list (cdr coord-list))
  1625. (bottom-border-y (1+ (cdr (table--get-coordinate (cdr (table--vertical-cell-list nil t))))))
  1626. (vertical-str (string table-cell-vertical-char))
  1627. (vertical-str-with-properties (let ((str (string table-cell-vertical-char)))
  1628. (table--put-cell-keymap-property 0 (length str) str)
  1629. (table--put-cell-rear-nonsticky 0 (length str) str) str))
  1630. (first-time t))
  1631. ;; create the space below for the table to grow
  1632. (table--create-growing-space-below (* n (+ 1 cell-height)) coord-list bottom-border-y)
  1633. ;; vertically expand each cell from left to right
  1634. (while this-list
  1635. (let* ((left (prog1 (car left-list) (setq left-list (if left-list (cdr left-list) coord-list))))
  1636. (this (prog1 (car this-list) (setq this-list (cdr this-list))))
  1637. (right (prog1 (car right-list) (setq right-list (cdr right-list))))
  1638. (exclude-left (and left (< (cdar left) (cdar this))))
  1639. (exclude-right (and right (<= (cdar right) (cdar this))))
  1640. (beg (table--goto-coordinate
  1641. (cons (if exclude-left (caar this) (1- (caar this)))
  1642. (cdar this))))
  1643. (end (table--goto-coordinate
  1644. (cons (if exclude-right (cadr this) (1+ (cadr this)))
  1645. bottom-border-y)))
  1646. (rect (if append-row nil (extract-rectangle beg end))))
  1647. ;; prepend blank cell lines to the extracted rectangle
  1648. (let ((i n))
  1649. (while (> i 0)
  1650. (setq rect (cons
  1651. (concat (if exclude-left "" (char-to-string table-cell-intersection-char))
  1652. (make-string (- (cadr this) (caar this)) (string-to-char table-cell-horizontal-chars))
  1653. (if exclude-right "" (char-to-string table-cell-intersection-char)))
  1654. rect))
  1655. (let ((j cell-height))
  1656. (while (> j 0)
  1657. (setq rect (cons
  1658. (concat (if exclude-left ""
  1659. (if first-time vertical-str vertical-str-with-properties))
  1660. (table--cell-blank-str (- (cadr this) (caar this)))
  1661. (if exclude-right "" vertical-str-with-properties))
  1662. rect))
  1663. (setq j (1- j))))
  1664. (setq i (1- i))))
  1665. (setq first-time nil)
  1666. (if append-row
  1667. (table--goto-coordinate (cons (if exclude-left (caar this) (1- (caar this)))
  1668. (1+ bottom-border-y)))
  1669. (delete-rectangle beg end)
  1670. (goto-char beg))
  1671. (table--insert-rectangle rect)))
  1672. ;; fix up the intersections
  1673. (setq this-list (if append-row nil coord-list))
  1674. (while this-list
  1675. (let ((this (prog1 (car this-list) (setq this-list (cdr this-list))))
  1676. (i 0))
  1677. (while (< i n)
  1678. (let ((y (1- (* i (+ 1 cell-height)))))
  1679. (table--goto-coordinate (table--offset-coordinate (car this) (cons -1 y)))
  1680. (delete-char 1) (insert table-cell-intersection-char)
  1681. (table--goto-coordinate (table--offset-coordinate (cons (cadr this) (cdar this)) (cons 0 y)))
  1682. (delete-char 1) (insert table-cell-intersection-char)
  1683. (setq i (1+ i))))))
  1684. ;; move the point to the beginning of the first newly inserted cell.
  1685. (if (table--goto-coordinate
  1686. (if append-row (cons (car (caar coord-list)) (1+ bottom-border-y))
  1687. (caar coord-list))) nil
  1688. (table--goto-coordinate current-coordinate))
  1689. ;; re-recognize the current cell's new dimension
  1690. (table-recognize-cell 'force)))
  1691. ;;;###autoload
  1692. (defun table-insert-column (n)
  1693. "Insert N table column(s).
  1694. When point is in a table the newly inserted column(s) are placed left
  1695. of the current column. When point is outside of the table it must be
  1696. right side of the table within the table height range, then the newly
  1697. created column(s) are appended at the right of the table."
  1698. (interactive "*p")
  1699. (if (< n 0) (setq n 1))
  1700. (let* ((current-coordinate (table--get-coordinate))
  1701. (coord-list (table--cell-list-to-coord-list (table--vertical-cell-list t nil 'left)))
  1702. (append-column (if coord-list nil (setq coord-list (table--find-row-column 'column))))
  1703. (cell-width (car (table--min-coord-list coord-list)))
  1704. (border-str (table--multiply-string (concat (make-string cell-width (string-to-char table-cell-horizontal-chars))
  1705. (char-to-string table-cell-intersection-char)) n))
  1706. (cell-str (table--multiply-string (concat (table--cell-blank-str cell-width)
  1707. (let ((str (string table-cell-vertical-char)))
  1708. (table--put-cell-keymap-property 0 (length str) str)
  1709. (table--put-cell-rear-nonsticky 0 (length str) str) str)) n))
  1710. (columns-to-extend (* n (+ 1 cell-width)))
  1711. (above-list nil)
  1712. (this-list coord-list)
  1713. (below-list (cdr coord-list))
  1714. (right-border-x (car (table--get-coordinate (cdr (table--horizontal-cell-list nil t))))))
  1715. ;; push back the affected area above and below this table
  1716. (table--horizontally-shift-above-and-below columns-to-extend coord-list)
  1717. ;; process each cell vertically from top to bottom
  1718. (while this-list
  1719. (let* ((above (prog1 (car above-list) (setq above-list (if above-list (cdr above-list) coord-list))))
  1720. (this (prog1 (car this-list) (setq this-list (cdr this-list))))
  1721. (below (prog1 (car below-list) (setq below-list (cdr below-list))))
  1722. (exclude-above (and above (<= (caar above) (caar this))))
  1723. (exclude-below (and below (< (caar below) (caar this))))
  1724. (beg-coord (cons (if append-column (1+ right-border-x) (caar this))
  1725. (if exclude-above (cdar this) (1- (cdar this)))))
  1726. (end-coord (cons (1+ right-border-x)
  1727. (if exclude-below (cddr this) (1+ (cddr this)))))
  1728. rect)
  1729. ;; untabify the area right of the bar that is about to be inserted
  1730. (let ((coord (table--copy-coordinate beg-coord))
  1731. (i 0)
  1732. (len (length rect)))
  1733. (while (< i len)
  1734. (if (table--goto-coordinate coord 'no-extension)
  1735. (table--untabify-line (point)))
  1736. (setcdr coord (1+ (cdr coord)))
  1737. (setq i (1+ i))))
  1738. ;; extract and delete the rectangle area including the current
  1739. ;; cell and to the right border of the table.
  1740. (setq rect (extract-rectangle (table--goto-coordinate beg-coord)
  1741. (table--goto-coordinate end-coord)))
  1742. (delete-rectangle (table--goto-coordinate beg-coord)
  1743. (table--goto-coordinate end-coord))
  1744. ;; prepend the empty column string at the beginning of each
  1745. ;; rectangle string extracted before.
  1746. (let ((rect-str rect)
  1747. (first t))
  1748. (while rect-str
  1749. (if (and first (null exclude-above))
  1750. (setcar rect-str (concat border-str (car rect-str)))
  1751. (if (and (null (cdr rect-str)) (null exclude-below))
  1752. (setcar rect-str (concat border-str (car rect-str)))
  1753. (setcar rect-str (concat cell-str (car rect-str)))))
  1754. (setq first nil)
  1755. (setq rect-str (cdr rect-str))))
  1756. ;; insert the extended rectangle
  1757. (table--goto-coordinate beg-coord)
  1758. (table--insert-rectangle rect)))
  1759. ;; fix up the intersections
  1760. (setq this-list (if append-column nil coord-list))
  1761. (while this-list
  1762. (let ((this (prog1 (car this-list) (setq this-list (cdr this-list))))
  1763. (i 0))
  1764. (while (< i n)
  1765. (let ((x (1- (* (1+ i) (+ 1 cell-width)))))
  1766. (table--goto-coordinate (table--offset-coordinate (car this) (cons x -1)))
  1767. (delete-char 1) (insert table-cell-intersection-char)
  1768. (table--goto-coordinate (table--offset-coordinate (cons (caar this) (cddr this)) (cons x 1)))
  1769. (delete-char 1) (insert table-cell-intersection-char)
  1770. (setq i (1+ i))))))
  1771. ;; move the point to the beginning of the first newly inserted cell.
  1772. (if (table--goto-coordinate
  1773. (if append-column
  1774. (cons (1+ right-border-x)
  1775. (cdar (car coord-list)))
  1776. (caar coord-list))) nil
  1777. (table--goto-coordinate current-coordinate))
  1778. ;; re-recognize the current cell's new dimension
  1779. (table-recognize-cell 'force)))
  1780. ;;;###autoload
  1781. (defun table-insert-row-column (row-column n)
  1782. "Insert row(s) or column(s).
  1783. See `table-insert-row' and `table-insert-column'."
  1784. (interactive
  1785. (let ((n (prefix-numeric-value current-prefix-arg)))
  1786. (if (< n 0) (setq n 1))
  1787. (list (intern (let ((completion-ignore-case t)
  1788. (default (car table-insert-row-column-history)))
  1789. (downcase (completing-read
  1790. (format "Insert %s row%s/column%s (default %s): "
  1791. (if (> n 1) (format "%d" n) "a")
  1792. (if (> n 1) "s" "")
  1793. (if (> n 1) "s" "")
  1794. default)
  1795. '(("row") ("column"))
  1796. nil t nil 'table-insert-row-column-history default))))
  1797. n)))
  1798. (cond ((eq row-column 'row)
  1799. (table-insert-row n))
  1800. ((eq row-column 'column)
  1801. (table-insert-column n))))
  1802. ;;;###autoload
  1803. (defun table-recognize (&optional arg)
  1804. "Recognize all tables within the current buffer and activate them.
  1805. Scans the entire buffer and recognizes valid table cells. If the
  1806. optional numeric prefix argument ARG is negative the tables in the
  1807. buffer become inactive, meaning the tables become plain text and loses
  1808. all the table specific features."
  1809. (interactive "P")
  1810. (setq arg (prefix-numeric-value arg))
  1811. (let* ((inhibit-read-only t))
  1812. (table-recognize-region (point-min) (point-max) -1)
  1813. (if (>= arg 0)
  1814. (save-excursion
  1815. (goto-char (point-min))
  1816. (let* ((border (format "[%s%c%c]"
  1817. table-cell-horizontal-chars
  1818. table-cell-vertical-char
  1819. table-cell-intersection-char))
  1820. (border3 (concat border border border))
  1821. (non-border (format "^[^%s%c%c]*$"
  1822. table-cell-horizontal-chars
  1823. table-cell-vertical-char
  1824. table-cell-intersection-char)))
  1825. ;; `table-recognize-region' is an expensive function so minimize
  1826. ;; the search area. A minimum table at least consists of three consecutive
  1827. ;; table border characters to begin with such as
  1828. ;; +-+
  1829. ;; |A|
  1830. ;; +-+
  1831. ;; and any tables end with a line containing no table border characters
  1832. ;; or the end of buffer.
  1833. (while (and (re-search-forward border3 (point-max) t)
  1834. (not (and (input-pending-p)
  1835. table-abort-recognition-when-input-pending)))
  1836. (message "Recognizing tables...(%d%%)" (/ (* 100 (match-beginning 0)) (- (point-max) (point-min))))
  1837. (let ((beg (match-beginning 0))
  1838. end)
  1839. (if (re-search-forward non-border (point-max) t)
  1840. (setq end (match-beginning 0))
  1841. (setq end (goto-char (point-max))))
  1842. (table-recognize-region beg end arg)))
  1843. (message "Recognizing tables...done"))))))
  1844. ;;;###autoload
  1845. (defun table-unrecognize ()
  1846. (interactive)
  1847. (table-recognize -1))
  1848. ;;;###autoload
  1849. (defun table-recognize-region (beg end &optional arg)
  1850. "Recognize all tables within region.
  1851. BEG and END specify the region to work on. If the optional numeric
  1852. prefix argument ARG is negative the tables in the region become
  1853. inactive, meaning the tables become plain text and lose all the table
  1854. specific features."
  1855. (interactive "r\nP")
  1856. (setq arg (prefix-numeric-value arg))
  1857. (let ((inhibit-read-only t)
  1858. (modified-flag (buffer-modified-p)))
  1859. (if (< arg 0)
  1860. (table--remove-cell-properties beg end)
  1861. (save-excursion
  1862. (goto-char beg)
  1863. (let* ((border (format "[%s%c%c]"
  1864. table-cell-horizontal-chars
  1865. table-cell-vertical-char
  1866. table-cell-intersection-char))
  1867. (non-border (format "[^%s%c%c]"
  1868. table-cell-horizontal-chars
  1869. table-cell-vertical-char
  1870. table-cell-intersection-char))
  1871. (inhibit-read-only t))
  1872. (unwind-protect
  1873. (progn
  1874. (remove-text-properties beg end '(table-cell nil))
  1875. (while (and (< (point) end)
  1876. (not (and (input-pending-p)
  1877. table-abort-recognition-when-input-pending)))
  1878. (cond
  1879. ((looking-at "\n")
  1880. (forward-char 1))
  1881. ((looking-at border)
  1882. (if (re-search-forward non-border end t)
  1883. (goto-char (match-beginning 0))
  1884. (goto-char end)))
  1885. ((table--at-cell-p (point))
  1886. (goto-char (next-single-property-change (point) 'table-cell nil end)))
  1887. (t
  1888. (let ((cell (table-recognize-cell 'force 'no-copy)))
  1889. (if (and cell table-detect-cell-alignment)
  1890. (table--detect-cell-alignment cell)))
  1891. (unless (re-search-forward border end t)
  1892. (goto-char end))))))))))
  1893. (restore-buffer-modified-p modified-flag)))
  1894. ;;;###autoload
  1895. (defun table-unrecognize-region (beg end)
  1896. (interactive "r")
  1897. (table-recognize-region beg end -1))
  1898. ;;;###autoload
  1899. (defun table-recognize-table (&optional arg)
  1900. "Recognize a table at point.
  1901. If the optional numeric prefix argument ARG is negative the table
  1902. becomes inactive, meaning the table becomes plain text and loses all
  1903. the table specific features."
  1904. (interactive "P")
  1905. (setq arg (prefix-numeric-value arg))
  1906. (let ((unrecognize (< arg 0))
  1907. (origin-cell (table--probe-cell))
  1908. (inhibit-read-only t))
  1909. (if origin-cell
  1910. (save-excursion
  1911. (while
  1912. (progn
  1913. (table-forward-cell 1 nil unrecognize)
  1914. (let ((cell (table--probe-cell)))
  1915. (if (and cell table-detect-cell-alignment)
  1916. (table--detect-cell-alignment cell))
  1917. (and cell (not (equal cell origin-cell))))))))))
  1918. ;;;###autoload
  1919. (defun table-unrecognize-table ()
  1920. (interactive)
  1921. (table-recognize-table -1))
  1922. ;;;###autoload
  1923. (defun table-recognize-cell (&optional force no-copy arg)
  1924. "Recognize a table cell that contains current point.
  1925. Probe the cell dimension and prepare the cell information. The
  1926. optional two arguments FORCE and NO-COPY are for internal use only and
  1927. must not be specified. When the optional numeric prefix argument ARG
  1928. is negative the cell becomes inactive, meaning that the cell becomes
  1929. plain text and loses all the table specific features."
  1930. (interactive "i\ni\np")
  1931. (table--make-cell-map)
  1932. (if (or force (not (memq (table--get-last-command) table-command-list)))
  1933. (let* ((cell (table--probe-cell (called-interactively-p 'interactive)))
  1934. (cache-buffer (get-buffer-create table-cache-buffer-name))
  1935. (modified-flag (buffer-modified-p))
  1936. (inhibit-read-only t))
  1937. (unwind-protect
  1938. (unless (null cell)
  1939. ;; initialize the cell info variables
  1940. (let ((lu-coordinate (table--get-coordinate (car cell)))
  1941. (rb-coordinate (table--get-coordinate (cdr cell))))
  1942. ;; update the previous cell if this cell is different from the previous one.
  1943. ;; care only lu but ignore rb since size change does not matter.
  1944. (unless (equal table-cell-info-lu-coordinate lu-coordinate)
  1945. (table--finish-delayed-tasks))
  1946. (setq table-cell-info-lu-coordinate lu-coordinate)
  1947. (setq table-cell-info-rb-coordinate rb-coordinate)
  1948. (setq table-cell-info-width (- (car table-cell-info-rb-coordinate)
  1949. (car table-cell-info-lu-coordinate)))
  1950. (setq table-cell-info-height (+ (- (cdr table-cell-info-rb-coordinate)
  1951. (cdr table-cell-info-lu-coordinate)) 1))
  1952. (setq table-cell-info-justify (table--get-cell-justify-property cell))
  1953. (setq table-cell-info-valign (table--get-cell-valign-property cell)))
  1954. ;; set/remove table cell properties
  1955. (if (< (prefix-numeric-value arg) 0)
  1956. (let ((coord (table--get-coordinate (car cell)))
  1957. (n table-cell-info-height))
  1958. (save-excursion
  1959. (while (> n 0)
  1960. (table--remove-cell-properties
  1961. (table--goto-coordinate coord)
  1962. (table--goto-coordinate (cons (+ (car coord) table-cell-info-width 1) (cdr coord))))
  1963. (setq n (1- n))
  1964. (setcdr coord (1+ (cdr coord))))))
  1965. (table--put-cell-property cell))
  1966. ;; copy the cell contents to the cache buffer
  1967. ;; only if no-copy is nil and timers are not set
  1968. (unless no-copy
  1969. (setq table-cell-cache-point-coordinate (table--transcoord-table-to-cache))
  1970. (setq table-cell-cache-mark-coordinate (table--transcoord-table-to-cache
  1971. (table--get-coordinate (marker-position (mark-marker)))))
  1972. (setq table-cell-buffer (current-buffer))
  1973. (let ((rectangle (extract-rectangle (car cell)
  1974. (cdr cell))))
  1975. (save-current-buffer
  1976. (set-buffer cache-buffer)
  1977. (erase-buffer)
  1978. (table--insert-rectangle rectangle)))))
  1979. (restore-buffer-modified-p modified-flag))
  1980. (if (featurep 'xemacs)
  1981. (table--warn-incompatibility))
  1982. cell)))
  1983. ;;;###autoload
  1984. (defun table-unrecognize-cell ()
  1985. (interactive)
  1986. (table-recognize-cell nil nil -1))
  1987. ;;;###autoload
  1988. (defun table-heighten-cell (n &optional no-copy no-update)
  1989. "Heighten the current cell by N lines by expanding the cell vertically.
  1990. Heightening is done by adding blank lines at the bottom of the current
  1991. cell. Other cells aligned horizontally with the current one are also
  1992. heightened in order to keep the rectangular table structure. The
  1993. optional argument NO-COPY is internal use only and must not be
  1994. specified."
  1995. (interactive "*p")
  1996. (if (< n 0) (setq n 1))
  1997. (let* ((coord-list (table--cell-list-to-coord-list (table--horizontal-cell-list t)))
  1998. (left-list nil)
  1999. (this-list coord-list)
  2000. (right-list (cdr coord-list))
  2001. (bottom-border-y (1+ (cdr (table--get-coordinate (cdr (table--vertical-cell-list nil t))))))
  2002. (vertical-str (string table-cell-vertical-char))
  2003. (vertical-str-with-properties (string table-cell-vertical-char))
  2004. (first-time t)
  2005. (current-coordinate (table--get-coordinate)))
  2006. ;; prepare the right vertical string with appropriate properties put
  2007. (table--put-cell-keymap-property 0 (length vertical-str-with-properties) vertical-str-with-properties)
  2008. ;; create the space below for the table to grow
  2009. (table--create-growing-space-below n coord-list bottom-border-y)
  2010. ;; vertically expand each cell from left to right
  2011. (while this-list
  2012. (let* ((left (prog1 (car left-list) (setq left-list (if left-list (cdr left-list) coord-list))))
  2013. (this (prog1 (car this-list) (setq this-list (cdr this-list))))
  2014. (right (prog1 (car right-list) (setq right-list (cdr right-list))))
  2015. (exclude-left (and left (< (cddr left) (cddr this))))
  2016. (exclude-right (and right (<= (cddr right) (cddr this))))
  2017. (beg (table--goto-coordinate
  2018. (cons (if exclude-left (caar this) (1- (caar this)))
  2019. (1+ (cddr this)))))
  2020. (end (table--goto-coordinate
  2021. (cons (if exclude-right (cadr this) (1+ (cadr this)))
  2022. bottom-border-y)))
  2023. (rect (extract-rectangle beg end)))
  2024. ;; prepend blank cell lines to the extracted rectangle
  2025. (let ((i n))
  2026. (while (> i 0)
  2027. (setq rect (cons
  2028. (concat (if exclude-left ""
  2029. (if first-time vertical-str vertical-str-with-properties))
  2030. (table--cell-blank-str (- (cadr this) (caar this)))
  2031. (if exclude-right "" vertical-str-with-properties))
  2032. rect))
  2033. (setq i (1- i))))
  2034. (setq first-time nil)
  2035. (delete-rectangle beg end)
  2036. (goto-char beg)
  2037. (table--insert-rectangle rect)))
  2038. (table--goto-coordinate current-coordinate)
  2039. ;; re-recognize the current cell's new dimension
  2040. (table-recognize-cell 'force no-copy)
  2041. (unless no-update
  2042. (table--update-cell-heightened))))
  2043. ;;;###autoload
  2044. (defun table-shorten-cell (n)
  2045. "Shorten the current cell by N lines by shrinking the cell vertically.
  2046. Shortening is done by removing blank lines from the bottom of the cell
  2047. and possibly from the top of the cell as well. Therefore, the cell
  2048. must have some bottom/top blank lines to be shorten effectively. This
  2049. is applicable to all the cells aligned horizontally with the current
  2050. one because they are also shortened in order to keep the rectangular
  2051. table structure."
  2052. (interactive "*p")
  2053. (if (< n 0) (setq n 1))
  2054. (table--finish-delayed-tasks)
  2055. (let* ((table-inhibit-update t)
  2056. (coord-list (table--cell-list-to-coord-list (table--horizontal-cell-list t)))
  2057. (left-list nil)
  2058. (this-list coord-list)
  2059. (right-list (cdr coord-list))
  2060. (bottom-budget-list nil)
  2061. (bottom-border-y (1+ (cdr (table--get-coordinate (cdr (table--vertical-cell-list nil t))))))
  2062. (current-coordinate (table--get-coordinate))
  2063. (current-cell-coordinate (table--cell-to-coord (table--probe-cell)))
  2064. (blank-line-regexp "\\s *$"))
  2065. (message "Shortening...");; this operation may be lengthy
  2066. ;; for each cell calculate the maximum number of blank lines we can delete
  2067. ;; and adjust the argument n. n is adjusted so that the total number of
  2068. ;; blank lines from top and bottom of a cell do not exceed n, all cell has
  2069. ;; at least one line height after blank line deletion.
  2070. (while this-list
  2071. (let ((this (prog1 (car this-list) (setq this-list (cdr this-list)))))
  2072. (table--goto-coordinate (car this))
  2073. (table-recognize-cell 'force)
  2074. (table-with-cache-buffer
  2075. (catch 'end-count
  2076. (let ((blank-line-count 0))
  2077. (table--goto-coordinate (cons 0 (1- table-cell-info-height)))
  2078. ;; count bottom
  2079. (while (and (looking-at blank-line-regexp)
  2080. (setq blank-line-count (1+ blank-line-count))
  2081. ;; need to leave at least one blank line
  2082. (if (> blank-line-count n) (throw 'end-count nil) t)
  2083. (if (zerop (forward-line -1)) t
  2084. (setq n (if (zerop blank-line-count) 0
  2085. (1- blank-line-count)))
  2086. (throw 'end-count nil))))
  2087. (table--goto-coordinate (cons 0 0))
  2088. ;; count top
  2089. (while (and (looking-at blank-line-regexp)
  2090. (setq blank-line-count (1+ blank-line-count))
  2091. ;; can consume all blank lines
  2092. (if (>= blank-line-count n) (throw 'end-count nil) t)
  2093. (zerop (forward-line 1))))
  2094. (setq n blank-line-count))))))
  2095. ;; construct the bottom-budget-list which is a list of numbers where each number
  2096. ;; corresponds to how many lines to be deleted from the bottom of each cell. If
  2097. ;; this number, say bb, is smaller than n (bb < n) that means the difference (n - bb)
  2098. ;; number of lines must be deleted from the top of the cell in addition to deleting
  2099. ;; bb lines from the bottom of the cell.
  2100. (setq this-list coord-list)
  2101. (while this-list
  2102. (let ((this (prog1 (car this-list) (setq this-list (cdr this-list)))))
  2103. (table--goto-coordinate (car this))
  2104. (table-recognize-cell 'force)
  2105. (table-with-cache-buffer
  2106. (setq bottom-budget-list
  2107. (cons
  2108. (let ((blank-line-count 0))
  2109. (table--goto-coordinate (cons 0 (1- table-cell-info-height)))
  2110. (while (and (looking-at blank-line-regexp)
  2111. (< blank-line-count n)
  2112. (setq blank-line-count (1+ blank-line-count))
  2113. (zerop (forward-line -1))))
  2114. blank-line-count)
  2115. bottom-budget-list)))))
  2116. (setq bottom-budget-list (nreverse bottom-budget-list))
  2117. ;; vertically shorten each cell from left to right
  2118. (setq this-list coord-list)
  2119. (while this-list
  2120. (let* ((left (prog1 (car left-list) (setq left-list (if left-list (cdr left-list) coord-list))))
  2121. (this (prog1 (car this-list) (setq this-list (cdr this-list))))
  2122. (right (prog1 (car right-list) (setq right-list (cdr right-list))))
  2123. (bottom-budget (prog1 (car bottom-budget-list) (setq bottom-budget-list (cdr bottom-budget-list))))
  2124. (exclude-left (and left (< (cddr left) (cddr this))))
  2125. (exclude-right (and right (<= (cddr right) (cddr this))))
  2126. (beg (table--goto-coordinate (cons (caar this) (cdar this))))
  2127. (end (table--goto-coordinate (cons (cadr this) bottom-border-y)))
  2128. (rect (extract-rectangle beg end))
  2129. (height (+ (- (cddr this) (cdar this)) 1))
  2130. (blank-line (make-string (- (cadr this) (caar this)) ?\s)))
  2131. ;; delete lines from the bottom of the cell
  2132. (setcdr (nthcdr (- height bottom-budget 1) rect) (nthcdr height rect))
  2133. ;; delete lines from the top of the cell
  2134. (if (> n bottom-budget)
  2135. (let ((props (text-properties-at 0 (car rect))))
  2136. (setq rect (nthcdr (- n bottom-budget) rect))
  2137. (set-text-properties 0 1 props (car rect))))
  2138. ;; append blank lines below the table
  2139. (setq rect (append rect (make-list n blank-line)))
  2140. ;; now swap the area with the prepared rect of the same size
  2141. (delete-rectangle beg end)
  2142. (goto-char beg)
  2143. (table--insert-rectangle rect)
  2144. ;; for the left and right borders always delete lines from the bottom of the cell
  2145. (unless exclude-left
  2146. (let* ((beg (table--goto-coordinate (cons (1- (caar this)) (cdar this))))
  2147. (end (table--goto-coordinate (cons (caar this) bottom-border-y)))
  2148. (rect (extract-rectangle beg end)))
  2149. (setcdr (nthcdr (- height n 1) rect) (nthcdr height rect))
  2150. (setq rect (append rect (make-list n " ")))
  2151. (delete-rectangle beg end)
  2152. (goto-char beg)
  2153. (table--insert-rectangle rect)))
  2154. (unless exclude-right
  2155. (let* ((beg (table--goto-coordinate (cons (cadr this) (cdar this))))
  2156. (end (table--goto-coordinate (cons (1+ (cadr this)) bottom-border-y)))
  2157. (rect (extract-rectangle beg end)))
  2158. (setcdr (nthcdr (- height n 1) rect) (nthcdr height rect))
  2159. (setq rect (append rect (make-list n " ")))
  2160. (delete-rectangle beg end)
  2161. (goto-char beg)
  2162. (table--insert-rectangle rect)))
  2163. ;; if this is the cell where the original point was in, adjust the point location
  2164. (if (null (equal this current-cell-coordinate)) nil
  2165. (let ((y (- (cdr current-coordinate) (cdar this))))
  2166. (if (< y (- n bottom-budget))
  2167. (setcdr current-coordinate (cdar this))
  2168. (if (< (- y (- n bottom-budget)) (- height n))
  2169. (setcdr current-coordinate (+ (cdar this) (- y (- n bottom-budget))))
  2170. (setcdr current-coordinate (+ (cdar this) (- height n 1)))))))))
  2171. ;; remove the appended blank lines below the table if they are unnecessary
  2172. (table--goto-coordinate (cons 0 (1+ (- bottom-border-y n))))
  2173. (table--remove-blank-lines n)
  2174. ;; re-recognize the current cell's new dimension
  2175. (table--goto-coordinate current-coordinate)
  2176. (table-recognize-cell 'force)
  2177. (table--update-cell-heightened)
  2178. (message "")))
  2179. ;;;###autoload
  2180. (defun table-widen-cell (n &optional no-copy no-update)
  2181. "Widen the current cell by N columns and expand the cell horizontally.
  2182. Some other cells in the same table are widen as well to keep the
  2183. table's rectangle structure."
  2184. (interactive "*p")
  2185. (if (< n 0) (setq n 1))
  2186. (let* ((coord-list (table--cell-list-to-coord-list (table--vertical-cell-list)))
  2187. (below-list nil)
  2188. (this-list coord-list)
  2189. (above-list (cdr coord-list)))
  2190. (save-excursion
  2191. ;; push back the affected area above and below this table
  2192. (table--horizontally-shift-above-and-below n (reverse coord-list))
  2193. ;; now widen vertically for each cell
  2194. (while this-list
  2195. (let* ((below (prog1 (car below-list) (setq below-list (if below-list (cdr below-list) coord-list))))
  2196. (this (prog1 (car this-list) (setq this-list (cdr this-list))))
  2197. (above (prog1 (car above-list) (setq above-list (cdr above-list))))
  2198. (beg (table--goto-coordinate
  2199. (cons (car (cdr this))
  2200. (if (or (null above) (<= (car (cdr this)) (car (cdr above))))
  2201. (1- (cdr (car this)))
  2202. (cdr (car this))))))
  2203. (end (table--goto-coordinate
  2204. (cons (1+ (car (cdr this)))
  2205. (if (or (null below) (< (car (cdr this)) (car (cdr below))))
  2206. (1+ (cdr (cdr this)))
  2207. (cdr (cdr this))))))
  2208. (tmp (extract-rectangle (1- beg) end))
  2209. (border (format "[%s%c]\\%c"
  2210. table-cell-horizontal-chars
  2211. table-cell-intersection-char
  2212. table-cell-intersection-char))
  2213. (blank (table--cell-blank-str))
  2214. rectangle)
  2215. ;; create a single wide vertical bar of empty cell fragment
  2216. (while tmp
  2217. ; (message "tmp is %s" tmp)
  2218. (setq rectangle (cons
  2219. (if (string-match border (car tmp))
  2220. (substring (car tmp) 0 1)
  2221. blank)
  2222. rectangle))
  2223. ; (message "rectangle is %s" rectangle)
  2224. (setq tmp (cdr tmp)))
  2225. (setq rectangle (nreverse rectangle))
  2226. ;; untabify the area right of the bar that is about to be inserted
  2227. (let ((coord (table--get-coordinate beg))
  2228. (i 0)
  2229. (len (length rectangle)))
  2230. (while (< i len)
  2231. (if (table--goto-coordinate coord 'no-extension)
  2232. (table--untabify-line (point)))
  2233. (setcdr coord (1+ (cdr coord)))
  2234. (setq i (1+ i))))
  2235. ;; insert the bar n times
  2236. (goto-char beg)
  2237. (let ((i 0))
  2238. (while (< i n)
  2239. (save-excursion
  2240. (table--insert-rectangle rectangle))
  2241. (setq i (1+ i)))))))
  2242. (table-recognize-cell 'force no-copy)
  2243. (unless no-update
  2244. (table--update-cell-widened))))
  2245. ;;;###autoload
  2246. (defun table-narrow-cell (n)
  2247. "Narrow the current cell by N columns and shrink the cell horizontally.
  2248. Some other cells in the same table are narrowed as well to keep the
  2249. table's rectangle structure."
  2250. (interactive "*p")
  2251. (if (< n 0) (setq n 1))
  2252. (table--finish-delayed-tasks)
  2253. (let* ((coord-list (table--cell-list-to-coord-list (table--vertical-cell-list)))
  2254. (current-cell (table--cell-to-coord (table--probe-cell)))
  2255. (current-coordinate (table--get-coordinate))
  2256. tmp-list)
  2257. (message "Narrowing...");; this operation may be lengthy
  2258. ;; determine the doable n by try narrowing each cell.
  2259. (setq tmp-list coord-list)
  2260. (while tmp-list
  2261. (let ((cell (prog1 (car tmp-list) (setq tmp-list (cdr tmp-list))))
  2262. (table-inhibit-update t)
  2263. cell-n)
  2264. (table--goto-coordinate (car cell))
  2265. (table-recognize-cell 'force)
  2266. (table-with-cache-buffer
  2267. (table--fill-region (point-min) (point-max) (- table-cell-info-width n))
  2268. (if (< (setq cell-n (- table-cell-info-width (table--measure-max-width))) n)
  2269. (setq n cell-n))
  2270. (erase-buffer)
  2271. (setq table-inhibit-auto-fill-paragraph t))))
  2272. (if (< n 1) nil
  2273. ;; narrow only the contents of each cell but leave the cell frame as is because
  2274. ;; we need to have valid frame structure in order for table-with-cache-buffer
  2275. ;; to work correctly.
  2276. (setq tmp-list coord-list)
  2277. (while tmp-list
  2278. (let* ((cell (prog1 (car tmp-list) (setq tmp-list (cdr tmp-list))))
  2279. (table-inhibit-update t)
  2280. (currentp (equal cell current-cell))
  2281. old-height)
  2282. (if currentp (table--goto-coordinate current-coordinate)
  2283. (table--goto-coordinate (car cell)))
  2284. (table-recognize-cell 'force)
  2285. (setq old-height table-cell-info-height)
  2286. (table-with-cache-buffer
  2287. (let ((out-of-bound (>= (- (car current-coordinate) (car table-cell-info-lu-coordinate))
  2288. (- table-cell-info-width n)))
  2289. (sticky (and currentp
  2290. (save-excursion
  2291. (unless (bolp) (forward-char -1))
  2292. (looking-at ".*\\S ")))))
  2293. (table--fill-region (point-min) (point-max) (- table-cell-info-width n))
  2294. (if (or sticky (and currentp (looking-at ".*\\S ")))
  2295. (setq current-coordinate (table--transcoord-cache-to-table))
  2296. (if out-of-bound (setcar current-coordinate
  2297. (+ (car table-cell-info-lu-coordinate) (- table-cell-info-width n 1))))))
  2298. (setq table-inhibit-auto-fill-paragraph t))
  2299. (table--update-cell 'now)
  2300. ;; if this cell heightens and pushes the current cell below, move
  2301. ;; the current-coordinate (point location) down accordingly.
  2302. (if currentp (setq current-coordinate (table--get-coordinate))
  2303. (if (and (> table-cell-info-height old-height)
  2304. (> (cdr current-coordinate) (cdr table-cell-info-lu-coordinate)))
  2305. (setcdr current-coordinate (+ (cdr current-coordinate)
  2306. (- table-cell-info-height old-height)))))
  2307. ))
  2308. ;; coord-list is now possibly invalid since some cells may have already
  2309. ;; been heightened so recompute them by table--vertical-cell-list.
  2310. (table--goto-coordinate current-coordinate)
  2311. (setq coord-list (table--cell-list-to-coord-list (table--vertical-cell-list)))
  2312. ;; push in the affected area above and below this table so that things
  2313. ;; on the right side of the table are shifted horizontally neatly.
  2314. (table--horizontally-shift-above-and-below (- n) (reverse coord-list))
  2315. ;; finally narrow the frames for each cell.
  2316. (let* ((below-list nil)
  2317. (this-list coord-list)
  2318. (above-list (cdr coord-list)))
  2319. (while this-list
  2320. (let* ((below (prog1 (car below-list) (setq below-list (if below-list (cdr below-list) coord-list))))
  2321. (this (prog1 (car this-list) (setq this-list (cdr this-list))))
  2322. (above (prog1 (car above-list) (setq above-list (cdr above-list)))))
  2323. (delete-rectangle
  2324. (table--goto-coordinate
  2325. (cons (- (cadr this) n)
  2326. (if (or (null above) (<= (cadr this) (cadr above)))
  2327. (1- (cdar this))
  2328. (cdar this))))
  2329. (table--goto-coordinate
  2330. (cons (cadr this)
  2331. (if (or (null below) (< (cadr this) (cadr below)))
  2332. (1+ (cddr this))
  2333. (cddr this)))))))))
  2334. (table--goto-coordinate current-coordinate)
  2335. ;; re-recognize the current cell's new dimension
  2336. (table-recognize-cell 'force)
  2337. (message "")))
  2338. ;;;###autoload
  2339. (defun table-forward-cell (&optional arg no-recognize unrecognize)
  2340. "Move point forward to the beginning of the next cell.
  2341. With argument ARG, do it ARG times;
  2342. a negative argument ARG = -N means move backward N cells.
  2343. Do not specify NO-RECOGNIZE and UNRECOGNIZE. They are for internal use only.
  2344. Sample Cell Traveling Order (In Irregular Table Cases)
  2345. You can actually try how it works in this buffer. Press
  2346. \\[table-recognize] and go to cells in the following tables and press
  2347. \\[table-forward-cell] or TAB key.
  2348. +-----+--+ +--+-----+ +--+--+--+ +--+--+--+ +---------+ +--+---+--+
  2349. |0 |1 | |0 |1 | |0 |1 |2 | |0 |1 |2 | |0 | |0 |1 |2 |
  2350. +--+--+ | | +--+--+ +--+ | | | | +--+ +----+----+ +--+-+-+--+
  2351. |2 |3 | | | |2 |3 | |3 +--+ | | +--+3 | |1 |2 | |3 |4 |
  2352. | +--+--+ +--+--+ | +--+4 | | | |4 +--+ +--+-+-+--+ +----+----+
  2353. | |4 | |4 | | |5 | | | | | |5 | |3 |4 |5 | |5 |
  2354. +--+-----+ +-----+--+ +--+--+--+ +--+--+--+ +--+---+--+ +---------+
  2355. +--+--+--+ +--+--+--+ +--+--+--+ +--+--+--+
  2356. |0 |1 |2 | |0 |1 |2 | |0 |1 |2 | |0 |1 |2 |
  2357. | | | | | +--+ | | | | | +--+ +--+
  2358. +--+ +--+ +--+3 +--+ | +--+ | |3 +--+4 |
  2359. |3 | |4 | |4 +--+5 | | |3 | | +--+5 +--+
  2360. | | | | | |6 | | | | | | |6 | |7 |
  2361. +--+--+--+ +--+--+--+ +--+--+--+ +--+--+--+
  2362. +--+--+--+ +--+--+--+ +--+--+--+--+ +--+-----+--+ +--+--+--+--+
  2363. |0 |1 |2 | |0 |1 |2 | |0 |1 |2 |3 | |0 |1 |2 | |0 |1 |2 |3 |
  2364. | +--+ | | +--+ | | +--+--+ | | | | | | +--+--+ |
  2365. | |3 +--+ +--+3 | | +--+4 +--+ +--+ +--+ +--+4 +--+
  2366. +--+ |4 | |4 | +--+ |5 +--+--+6 | |3 +--+--+4 | |5 | |6 |
  2367. |5 +--+ | | +--+5 | | |7 |8 | | | |5 |6 | | | | | |
  2368. | |6 | | | |6 | | +--+--+--+--+ +--+--+--+--+ +--+-----+--+
  2369. +--+--+--+ +--+--+--+
  2370. "
  2371. ;; After modifying this function, test against the above tables in
  2372. ;; the doc string. It is quite tricky. The tables above do not
  2373. ;; mean to cover every possible cases of cell layout, of course.
  2374. ;; They are examples of tricky cases from implementation point of
  2375. ;; view and provided for simple regression test purpose.
  2376. (interactive "p")
  2377. (or arg (setq arg 1))
  2378. (table--finish-delayed-tasks)
  2379. (while (null (zerop arg))
  2380. (let* ((pivot (table--probe-cell 'abort-on-error))
  2381. (cell pivot) edge tip)
  2382. ;; go to the beginning of the first right/left cell with same height if exists
  2383. (while (and (setq cell (table--goto-coordinate
  2384. (cons (if (> arg 0) (1+ (car (table--get-coordinate (cdr cell))))
  2385. (1- (car (table--get-coordinate (car cell)))))
  2386. (cdr (table--get-coordinate (car pivot)))) 'no-extension))
  2387. (setq cell (table--probe-cell))
  2388. (/= (cdr (table--get-coordinate (car cell)))
  2389. (cdr (table--get-coordinate (car pivot))))))
  2390. (if cell (goto-char (car cell)) ; done
  2391. ;; if the horizontal move fails search the most left/right edge cell below/above the pivot
  2392. ;; but first find the edge cell
  2393. (setq edge pivot)
  2394. (while (and (table--goto-coordinate
  2395. (cons (if (> arg 0) (1- (car (table--get-coordinate (car edge))))
  2396. (1+ (car (table--get-coordinate (cdr edge)))))
  2397. (cdr (table--get-coordinate (car pivot)))) 'no-extension)
  2398. (setq cell (table--probe-cell))
  2399. (setq edge cell)))
  2400. (setq cell (if (> arg 0) edge
  2401. (or (and (table--goto-coordinate
  2402. (cons (car (table--get-coordinate (cdr edge)))
  2403. (1- (cdr (table--get-coordinate (car edge))))))
  2404. (table--probe-cell))
  2405. edge)))
  2406. ;; now search for the tip which is the highest/lowest below/above cell
  2407. (while cell
  2408. (let (below/above)
  2409. (and (table--goto-coordinate
  2410. (cons (car (table--get-coordinate (if (> arg 0) (car cell)
  2411. (cdr cell))))
  2412. (if (> arg 0) (+ 2 (cdr (table--get-coordinate (cdr cell))))
  2413. (1- (cdr (table--get-coordinate (car pivot)))))) 'no-extension)
  2414. (setq below/above (table--probe-cell))
  2415. (or (null tip)
  2416. (if (> arg 0)
  2417. (< (cdr (table--get-coordinate (car below/above)))
  2418. (cdr (table--get-coordinate (car tip))))
  2419. (> (cdr (table--get-coordinate (car below/above)))
  2420. (cdr (table--get-coordinate (car tip))))))
  2421. (setq tip below/above)))
  2422. (and (setq cell (table--goto-coordinate
  2423. (cons (if (> arg 0) (1+ (car (table--get-coordinate (cdr cell))))
  2424. (1- (car (table--get-coordinate (car cell)))))
  2425. (if (> arg 0) (cdr (table--get-coordinate (car pivot)))
  2426. (1- (cdr (table--get-coordinate (car pivot)))))) 'no-extension))
  2427. (setq cell (table--probe-cell))))
  2428. (if tip (goto-char (car tip)) ; done
  2429. ;; let's climb up/down to the top/bottom from the edge
  2430. (while (and (table--goto-coordinate
  2431. (cons (if (> arg 0) (car (table--get-coordinate (car edge)))
  2432. (car (table--get-coordinate (cdr edge))))
  2433. (if (> arg 0) (1- (cdr (table--get-coordinate (car edge))))
  2434. (+ 2 (cdr (table--get-coordinate (cdr edge)))))) 'no-extension)
  2435. (setq cell (table--probe-cell))
  2436. (setq edge cell)))
  2437. (if (< arg 0)
  2438. (progn
  2439. (setq cell edge)
  2440. (while (and (table--goto-coordinate
  2441. (cons (1- (car (table--get-coordinate (car cell))))
  2442. (cdr (table--get-coordinate (cdr cell)))) 'no-extension)
  2443. (setq cell (table--probe-cell)))
  2444. (if (> (cdr (table--get-coordinate (car cell)))
  2445. (cdr (table--get-coordinate (car edge))))
  2446. (setq edge cell)))))
  2447. (goto-char (car edge))))) ; the top left cell
  2448. (setq arg (if (> arg 0) (1- arg) (1+ arg))))
  2449. (unless no-recognize
  2450. (table-recognize-cell 'force nil (if unrecognize -1 nil)))) ; refill the cache with new cell contents
  2451. ;;;###autoload
  2452. (defun table-backward-cell (&optional arg)
  2453. "Move backward to the beginning of the previous cell.
  2454. With argument ARG, do it ARG times;
  2455. a negative argument ARG = -N means move forward N cells."
  2456. (interactive "p")
  2457. (or arg (setq arg 1))
  2458. (table-forward-cell (- arg)))
  2459. ;;;###autoload
  2460. (defun table-span-cell (direction)
  2461. "Span current cell into adjacent cell in DIRECTION.
  2462. DIRECTION is one of symbols; right, left, above or below."
  2463. (interactive
  2464. (list
  2465. (let* ((dummy (barf-if-buffer-read-only))
  2466. (direction-list
  2467. (let* ((tmp (delete nil
  2468. (mapcar (lambda (d)
  2469. (if (table--cell-can-span-p d)
  2470. (list (symbol-name d))))
  2471. '(right left above below)))))
  2472. (if (null tmp)
  2473. (error "Can't span this cell"))
  2474. tmp))
  2475. (default-direction (if (member (list (car table-cell-span-direction-history)) direction-list)
  2476. (car table-cell-span-direction-history)
  2477. (caar direction-list)))
  2478. (completion-ignore-case t))
  2479. (intern (downcase (completing-read
  2480. (format "Span into (default %s): " default-direction)
  2481. direction-list
  2482. nil t nil 'table-cell-span-direction-history default-direction))))))
  2483. (unless (memq direction '(right left above below))
  2484. (error "Invalid direction %s, must be right, left, above or below"
  2485. (symbol-name direction)))
  2486. (table-recognize-cell 'force)
  2487. (unless (table--cell-can-span-p direction)
  2488. (error "Can't span %s" (symbol-name direction)))
  2489. ;; prepare beginning and ending positions of the border bar to strike through
  2490. (let ((beg (cond
  2491. ((eq direction 'right)
  2492. (save-excursion
  2493. (table--goto-coordinate
  2494. (cons (car table-cell-info-rb-coordinate)
  2495. (1- (cdr table-cell-info-lu-coordinate))) 'no-extension)))
  2496. ((eq direction 'below)
  2497. (save-excursion
  2498. (table--goto-coordinate
  2499. (cons (1- (car table-cell-info-lu-coordinate))
  2500. (1+ (cdr table-cell-info-rb-coordinate))) 'no-extension)))
  2501. (t
  2502. (save-excursion
  2503. (table--goto-coordinate
  2504. (cons (1- (car table-cell-info-lu-coordinate))
  2505. (1- (cdr table-cell-info-lu-coordinate))) 'no-extension)))))
  2506. (end (cond
  2507. ((eq direction 'left)
  2508. (save-excursion
  2509. (table--goto-coordinate
  2510. (cons (car table-cell-info-lu-coordinate)
  2511. (1+ (cdr table-cell-info-rb-coordinate))) 'no-extension)))
  2512. ((eq direction 'above)
  2513. (save-excursion
  2514. (table--goto-coordinate
  2515. (cons (1+ (car table-cell-info-rb-coordinate))
  2516. (1- (cdr table-cell-info-lu-coordinate))) 'no-extension)))
  2517. (t
  2518. (save-excursion
  2519. (table--goto-coordinate
  2520. (cons (1+ (car table-cell-info-rb-coordinate))
  2521. (1+ (cdr table-cell-info-rb-coordinate))) 'no-extension))))))
  2522. ;; replace the bar with blank space while taking care of edges to be border or intersection
  2523. (save-excursion
  2524. (goto-char beg)
  2525. (if (memq direction '(left right))
  2526. (let* ((column (current-column))
  2527. rectangle
  2528. (n-element (- (length (extract-rectangle beg end)) 2))
  2529. (above-contp (and (goto-char beg)
  2530. (zerop (forward-line -1))
  2531. (= (move-to-column column) column)
  2532. (looking-at (regexp-quote (char-to-string table-cell-vertical-char)))))
  2533. (below-contp (and (goto-char end)
  2534. (progn (forward-char -1) t)
  2535. (zerop (forward-line 1))
  2536. (= (move-to-column column) column)
  2537. (looking-at (regexp-quote (char-to-string table-cell-vertical-char))))))
  2538. (setq rectangle
  2539. (cons (if below-contp
  2540. (char-to-string table-cell-intersection-char)
  2541. (substring table-cell-horizontal-chars 0 1))
  2542. rectangle))
  2543. (while (> n-element 0)
  2544. (setq rectangle (cons (table--cell-blank-str 1) rectangle))
  2545. (setq n-element (1- n-element)))
  2546. (setq rectangle
  2547. (cons (if above-contp
  2548. (char-to-string table-cell-intersection-char)
  2549. (substring table-cell-horizontal-chars 0 1))
  2550. rectangle))
  2551. (delete-rectangle beg end)
  2552. (goto-char beg)
  2553. (table--insert-rectangle rectangle))
  2554. (delete-region beg end)
  2555. (insert (if (and (> (point) (point-min))
  2556. (save-excursion
  2557. (forward-char -1)
  2558. (looking-at (regexp-opt-charset
  2559. (string-to-list table-cell-horizontal-chars)))))
  2560. table-cell-intersection-char
  2561. table-cell-vertical-char)
  2562. (table--cell-blank-str (- end beg 2))
  2563. (if (looking-at (regexp-opt-charset
  2564. (string-to-list table-cell-horizontal-chars)))
  2565. table-cell-intersection-char
  2566. table-cell-vertical-char))))
  2567. ;; recognize the newly created spanned cell
  2568. (table-recognize-cell 'force)
  2569. (if (member direction '(right left))
  2570. (table-with-cache-buffer
  2571. (table--fill-region (point-min) (point-max))
  2572. (setq table-inhibit-auto-fill-paragraph t)))))
  2573. ;;;###autoload
  2574. (defun table-split-cell-vertically ()
  2575. "Split current cell vertically.
  2576. Creates a cell above and a cell below the current point location."
  2577. (interactive "*")
  2578. (table-recognize-cell 'force)
  2579. (let ((point-y (cdr (table--get-coordinate))))
  2580. (unless (table--cell-can-split-vertically-p)
  2581. (error "Can't split here"))
  2582. (let* ((old-coordinate (table--get-coordinate))
  2583. (column (current-column))
  2584. (beg (table--goto-coordinate
  2585. (cons (1- (car table-cell-info-lu-coordinate))
  2586. point-y)))
  2587. (end (table--goto-coordinate
  2588. (cons (1+ (car table-cell-info-rb-coordinate))
  2589. point-y)))
  2590. (line (buffer-substring (1+ beg) (1- end))))
  2591. (when (= (cdr old-coordinate) (cdr table-cell-info-rb-coordinate))
  2592. (table--goto-coordinate old-coordinate)
  2593. (table-heighten-cell 1 'no-copy 'no-update))
  2594. (goto-char beg)
  2595. (delete-region beg end)
  2596. (insert table-cell-intersection-char
  2597. (make-string table-cell-info-width (string-to-char table-cell-horizontal-chars))
  2598. table-cell-intersection-char)
  2599. (table--goto-coordinate old-coordinate)
  2600. (forward-line 1)
  2601. (move-to-column column)
  2602. (setq old-coordinate (table--get-coordinate))
  2603. (table-recognize-cell 'force)
  2604. (unless (string-match "^\\s *$" line)
  2605. (table-with-cache-buffer
  2606. (goto-char (point-min))
  2607. (insert line ?\n)
  2608. (goto-char (point-min)) ;; don't heighten cell unnecessarily
  2609. (setq table-inhibit-auto-fill-paragraph t)))
  2610. (table--update-cell 'now) ;; can't defer this operation
  2611. (table--goto-coordinate old-coordinate)
  2612. (move-to-column column)
  2613. (table-recognize-cell 'force))))
  2614. ;;;###autoload
  2615. (defun table-split-cell-horizontally ()
  2616. "Split current cell horizontally.
  2617. Creates a cell on the left and a cell on the right of the current point location."
  2618. (interactive "*")
  2619. (table-recognize-cell 'force)
  2620. (let* ((o-coordinate (table--get-coordinate))
  2621. (point-x (car o-coordinate))
  2622. cell-empty cell-contents cell-coordinate
  2623. contents-to beg end rectangle strip-rect
  2624. (right-edge (= (car o-coordinate) (1- (car table-cell-info-rb-coordinate)))))
  2625. (unless (table--cell-can-split-horizontally-p)
  2626. (error "Can't split here"))
  2627. (let ((table-inhibit-update t))
  2628. (table-with-cache-buffer
  2629. (setq cell-coordinate (table--get-coordinate))
  2630. (save-excursion
  2631. (goto-char (point-min))
  2632. (setq cell-empty (null (re-search-forward "\\S " nil t))))
  2633. (setq cell-contents (buffer-substring (point-min) (point-max)))
  2634. (setq table-inhibit-auto-fill-paragraph t)))
  2635. (setq contents-to
  2636. (if cell-empty 'left
  2637. (let* ((completion-ignore-case t)
  2638. (default (car table-cell-split-contents-to-history)))
  2639. (intern
  2640. (if (member 'click (event-modifiers last-input-event))
  2641. (x-popup-menu last-input-event
  2642. '("Existing cell contents to:"
  2643. ("Title"
  2644. ("Split" . "split") ("Left" . "left") ("Right" . "right"))))
  2645. (downcase (completing-read
  2646. (format "Existing cell contents to (default %s): " default)
  2647. '(("split") ("left") ("right"))
  2648. nil t nil 'table-cell-split-contents-to-history default)))))))
  2649. (unless (eq contents-to 'split)
  2650. (table-with-cache-buffer
  2651. (erase-buffer)
  2652. (setq table-inhibit-auto-fill-paragraph t)))
  2653. (table--update-cell 'now)
  2654. (setq beg (table--goto-coordinate
  2655. (cons point-x
  2656. (1- (cdr table-cell-info-lu-coordinate)))))
  2657. (setq end (table--goto-coordinate
  2658. (cons (1+ point-x)
  2659. (1+ (cdr table-cell-info-rb-coordinate)))))
  2660. (setq rectangle (cons (char-to-string table-cell-intersection-char) nil))
  2661. (let ((n table-cell-info-height))
  2662. (while (prog1 (> n 0) (setq n (1- n)))
  2663. (setq rectangle (cons (char-to-string table-cell-vertical-char) rectangle))))
  2664. (setq rectangle (cons (char-to-string table-cell-intersection-char) rectangle))
  2665. (if (eq contents-to 'split)
  2666. (setq strip-rect (extract-rectangle beg end)))
  2667. (delete-rectangle beg end)
  2668. (goto-char beg)
  2669. (table--insert-rectangle rectangle)
  2670. (table--goto-coordinate o-coordinate)
  2671. (if cell-empty
  2672. (progn
  2673. (forward-char 1)
  2674. (if right-edge
  2675. (table-widen-cell 1)))
  2676. (unless (eq contents-to 'left)
  2677. (forward-char 1))
  2678. (table-recognize-cell 'force)
  2679. (table-with-cache-buffer
  2680. (if (eq contents-to 'split)
  2681. ;; split inserts strip-rect after removing
  2682. ;; top and bottom borders
  2683. (let ((o-coord (table--get-coordinate))
  2684. (l (setq strip-rect (cdr strip-rect))))
  2685. (while (cddr l) (setq l (cdr l)))
  2686. (setcdr l nil)
  2687. ;; insert the strip only when it is not a completely blank one
  2688. (unless (let ((cl (mapcar (lambda (s) (string= s " ")) strip-rect)))
  2689. (and (car cl)
  2690. (table--uniform-list-p cl)))
  2691. (goto-char (point-min))
  2692. (table--insert-rectangle strip-rect)
  2693. (table--goto-coordinate o-coord)))
  2694. ;; left or right inserts original contents
  2695. (erase-buffer)
  2696. (insert cell-contents)
  2697. (table--goto-coordinate cell-coordinate)
  2698. (table--fill-region (point-min) (point-max))
  2699. ;; avoid unnecessary vertical cell expansion
  2700. (and (looking-at "\\s *\\'")
  2701. (re-search-backward "\\S \\(\\s *\\)\\=" nil t)
  2702. (goto-char (match-beginning 1))))
  2703. ;; in either case do not fill paragraph
  2704. (setq table-inhibit-auto-fill-paragraph t))
  2705. (table--update-cell 'now)) ;; can't defer this operation
  2706. (table-recognize-cell 'force)))
  2707. ;;;###autoload
  2708. (defun table-split-cell (orientation)
  2709. "Split current cell in ORIENTATION.
  2710. ORIENTATION is a symbol either horizontally or vertically."
  2711. (interactive
  2712. (list
  2713. (let* ((dummy (barf-if-buffer-read-only))
  2714. (completion-ignore-case t)
  2715. (default (car table-cell-split-orientation-history)))
  2716. (intern (downcase (completing-read
  2717. (format "Split orientation (default %s): " default)
  2718. '(("horizontally") ("vertically"))
  2719. nil t nil 'table-cell-split-orientation-history default))))))
  2720. (unless (memq orientation '(horizontally vertically))
  2721. (error "Invalid orientation %s, must be horizontally or vertically"
  2722. (symbol-name orientation)))
  2723. (if (eq orientation 'horizontally)
  2724. (table-split-cell-horizontally)
  2725. (table-split-cell-vertically)))
  2726. ;;;###autoload
  2727. (defun table-justify (what justify)
  2728. "Justify contents of a cell, a row of cells or a column of cells.
  2729. WHAT is a symbol 'cell, 'row or 'column. JUSTIFY is a symbol 'left,
  2730. 'center, 'right, 'top, 'middle, 'bottom or 'none."
  2731. (interactive
  2732. (list (let* ((dummy (barf-if-buffer-read-only))
  2733. (completion-ignore-case t)
  2734. (default (car table-target-history)))
  2735. (intern (downcase (completing-read
  2736. (format "Justify what (default %s): " default)
  2737. '(("cell") ("row") ("column"))
  2738. nil t nil 'table-target-history default))))
  2739. (table--query-justification)))
  2740. (funcall (intern (concat "table-justify-" (symbol-name what))) justify))
  2741. ;;;###autoload
  2742. (defun table-justify-cell (justify &optional paragraph)
  2743. "Justify cell contents.
  2744. JUSTIFY is a symbol 'left, 'center or 'right for horizontal, or 'top,
  2745. 'middle, 'bottom or 'none for vertical. When optional PARAGRAPH is
  2746. non-nil the justify operation is limited to the current paragraph,
  2747. otherwise the entire cell contents is justified."
  2748. (interactive
  2749. (list (table--query-justification)))
  2750. (table--finish-delayed-tasks)
  2751. (table-recognize-cell 'force)
  2752. (table--justify-cell-contents justify paragraph))
  2753. ;;;###autoload
  2754. (defun table-justify-row (justify)
  2755. "Justify cells of a row.
  2756. JUSTIFY is a symbol 'left, 'center or 'right for horizontal, or top,
  2757. 'middle, 'bottom or 'none for vertical."
  2758. (interactive
  2759. (list (table--query-justification)))
  2760. (let((cell-list (table--horizontal-cell-list nil nil 'top)))
  2761. (table--finish-delayed-tasks)
  2762. (save-excursion
  2763. (while cell-list
  2764. (let ((cell (car cell-list)))
  2765. (setq cell-list (cdr cell-list))
  2766. (goto-char (car cell))
  2767. (table-recognize-cell 'force)
  2768. (table--justify-cell-contents justify))))))
  2769. ;;;###autoload
  2770. (defun table-justify-column (justify)
  2771. "Justify cells of a column.
  2772. JUSTIFY is a symbol 'left, 'center or 'right for horizontal, or top,
  2773. 'middle, 'bottom or 'none for vertical."
  2774. (interactive
  2775. (list (table--query-justification)))
  2776. (let((cell-list (table--vertical-cell-list nil nil 'left)))
  2777. (table--finish-delayed-tasks)
  2778. (save-excursion
  2779. (while cell-list
  2780. (let ((cell (car cell-list)))
  2781. (setq cell-list (cdr cell-list))
  2782. (goto-char (car cell))
  2783. (table-recognize-cell 'force)
  2784. (table--justify-cell-contents justify))))))
  2785. ;;;###autoload
  2786. (defun table-fixed-width-mode (&optional arg)
  2787. "Toggle fixing width mode.
  2788. In the fixed width mode, typing inside a cell never changes the cell
  2789. width where in the normal mode the cell width expands automatically in
  2790. order to prevent a word being folded into multiple lines."
  2791. (interactive "P")
  2792. (table--finish-delayed-tasks)
  2793. (setq table-fixed-width-mode
  2794. (if (null arg)
  2795. (not table-fixed-width-mode)
  2796. (> (prefix-numeric-value arg) 0)))
  2797. (table--update-cell-face))
  2798. ;;;###autoload
  2799. (defun table-query-dimension (&optional where)
  2800. "Return the dimension of the current cell and the current table.
  2801. The result is a list (cw ch tw th c r cells) where cw is the cell
  2802. width, ch is the cell height, tw is the table width, th is the table
  2803. height, c is the number of columns, r is the number of rows and cells
  2804. is the total number of cells. The cell dimension excludes the cell
  2805. frame while the table dimension includes the table frame. The columns
  2806. and the rows are counted by the number of cell boundaries. Therefore
  2807. the number tends to be larger than it appears for the tables with
  2808. non-uniform cell structure (heavily spanned and split). When optional
  2809. WHERE is provided the cell and table at that location is reported."
  2810. (interactive)
  2811. (save-excursion
  2812. (if where (goto-char where))
  2813. (let ((starting-cell (table--probe-cell))
  2814. cell table-lu table-rb col-list row-list (cells 0))
  2815. (if (null starting-cell) nil
  2816. (setq table-lu (car starting-cell))
  2817. (setq table-rb (cdr starting-cell))
  2818. (setq col-list (cons (car (table--get-coordinate (car starting-cell))) nil))
  2819. (setq row-list (cons (cdr (table--get-coordinate (car starting-cell))) nil))
  2820. (and (called-interactively-p 'interactive)
  2821. (message "Computing cell dimension..."))
  2822. (while
  2823. (progn
  2824. (table-forward-cell 1 t)
  2825. (setq cells (1+ cells))
  2826. (and (setq cell (table--probe-cell))
  2827. (not (equal cell starting-cell))))
  2828. (if (< (car cell) table-lu)
  2829. (setq table-lu (car cell)))
  2830. (if (> (cdr cell) table-rb)
  2831. (setq table-rb (cdr cell)))
  2832. (let ((lu-coordinate (table--get-coordinate (car cell))))
  2833. (if (memq (car lu-coordinate) col-list) nil
  2834. (setq col-list (cons (car lu-coordinate) col-list)))
  2835. (if (memq (cdr lu-coordinate) row-list) nil
  2836. (setq row-list (cons (cdr lu-coordinate) row-list)))))
  2837. (let* ((cell-lu-coordinate (table--get-coordinate (car starting-cell)))
  2838. (cell-rb-coordinate (table--get-coordinate (cdr starting-cell)))
  2839. (table-lu-coordinate (table--get-coordinate table-lu))
  2840. (table-rb-coordinate (table--get-coordinate table-rb))
  2841. (cw (- (car cell-rb-coordinate) (car cell-lu-coordinate)))
  2842. (ch (1+ (- (cdr cell-rb-coordinate) (cdr cell-lu-coordinate))))
  2843. (tw (+ 2 (- (car table-rb-coordinate) (car table-lu-coordinate))))
  2844. (th (+ 3 (- (cdr table-rb-coordinate) (cdr table-lu-coordinate))))
  2845. (c (length col-list))
  2846. (r (length row-list)))
  2847. (and (called-interactively-p 'interactive)
  2848. (message "Cell: (%dw, %dh), Table: (%dw, %dh), Dim: (%dc, %dr), Total Cells: %d" cw ch tw th c r cells))
  2849. (list cw ch tw th c r cells))))))
  2850. ;;;###autoload
  2851. (defun table-generate-source (language &optional dest-buffer caption)
  2852. "Generate source of the current table in the specified language.
  2853. LANGUAGE is a symbol that specifies the language to describe the
  2854. structure of the table. It must be either 'html, 'latex or 'cals.
  2855. The resulted source text is inserted into DEST-BUFFER and the buffer
  2856. object is returned. When DEST-BUFFER is omitted or nil the default
  2857. buffer specified in `table-dest-buffer-name' is used. In this case
  2858. the content of the default buffer is erased prior to the generation.
  2859. When DEST-BUFFER is non-nil it is expected to be either a destination
  2860. buffer or a name of the destination buffer. In this case the
  2861. generated result is inserted at the current point in the destination
  2862. buffer and the previously existing contents in the buffer are
  2863. untouched.
  2864. References used for this implementation:
  2865. HTML:
  2866. URL `http://www.w3.org'
  2867. LaTeX:
  2868. URL `http://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/Tables.html'
  2869. CALS (DocBook DTD):
  2870. URL `http://www.oasis-open.org/html/a502.htm'
  2871. URL `http://www.oreilly.com/catalog/docbook/chapter/book/table.html#AEN114751'
  2872. "
  2873. (interactive
  2874. (let* ((dummy (unless (table--probe-cell) (error "Table not found here")))
  2875. (completion-ignore-case t)
  2876. (default (car table-source-language-history))
  2877. (language (downcase (completing-read
  2878. (format "Language (default %s): " default)
  2879. (mapcar (lambda (s) (list (symbol-name s)))
  2880. table-source-languages)
  2881. nil t nil 'table-source-language-history default))))
  2882. (list
  2883. (intern language)
  2884. (read-buffer "Destination buffer: " (concat table-dest-buffer-name "." language))
  2885. (table--read-from-minibuffer '("Table Caption" . table-source-caption-history)))))
  2886. (let ((default-buffer-name (concat table-dest-buffer-name "." (symbol-name language))))
  2887. (unless (or (called-interactively-p 'interactive) (table--probe-cell))
  2888. (error "Table not found here"))
  2889. (unless (bufferp dest-buffer)
  2890. (setq dest-buffer (get-buffer-create (or dest-buffer default-buffer-name))))
  2891. (if (string= (buffer-name dest-buffer) default-buffer-name)
  2892. (with-current-buffer dest-buffer
  2893. (erase-buffer)))
  2894. (save-excursion
  2895. (let ((starting-cell (table--probe-cell))
  2896. cell origin-cell tail-cell col-list row-list (n 0) i)
  2897. ;; first analyze the table structure and prepare:
  2898. ;; 1. origin cell (left up corner cell)
  2899. ;; 2. tail cell (right bottom corner cell)
  2900. ;; 3. column boundary list
  2901. ;; 4. row boundary list
  2902. (setq origin-cell starting-cell)
  2903. (setq tail-cell starting-cell)
  2904. (setq col-list (cons (car (table--get-coordinate (car starting-cell))) nil))
  2905. (setq row-list (cons (cdr (table--get-coordinate (car starting-cell))) nil))
  2906. (setq i 0)
  2907. (let ((wheel [?- ?\\ ?| ?/]))
  2908. (while
  2909. (progn
  2910. (if (called-interactively-p 'interactive)
  2911. (progn
  2912. (message "Analyzing table...%c" (aref wheel i))
  2913. (if (eq (setq i (1+ i)) (length wheel))
  2914. (setq i 0))
  2915. (setq n (1+ n))))
  2916. (table-forward-cell 1 t)
  2917. (and (setq cell (table--probe-cell))
  2918. (not (equal cell starting-cell))))
  2919. (if (< (car cell) (car origin-cell))
  2920. (setq origin-cell cell))
  2921. (if (> (cdr cell) (cdr tail-cell))
  2922. (setq tail-cell cell))
  2923. (let ((lu-coordinate (table--get-coordinate (car cell))))
  2924. (unless (memq (car lu-coordinate) col-list)
  2925. (setq col-list (cons (car lu-coordinate) col-list)))
  2926. (unless (memq (cdr lu-coordinate) row-list)
  2927. (setq row-list (cons (cdr lu-coordinate) row-list))))))
  2928. (setq col-list (sort col-list '<))
  2929. (setq row-list (sort row-list '<))
  2930. (message "Generating source...")
  2931. ;; clear the source generation property list
  2932. (setplist 'table-source-info-plist nil)
  2933. ;; prepare to start from the origin cell
  2934. (goto-char (car origin-cell))
  2935. ;; first put some header information
  2936. (table--generate-source-prologue dest-buffer language caption col-list row-list)
  2937. (cond
  2938. ((eq language 'latex)
  2939. ;; scan by character lines
  2940. (table--generate-source-scan-lines dest-buffer language origin-cell tail-cell col-list row-list))
  2941. (t
  2942. ;; scan by table cells
  2943. (table--generate-source-scan-rows dest-buffer language origin-cell col-list row-list)))
  2944. ;; insert closing
  2945. (table--generate-source-epilogue dest-buffer language col-list row-list))
  2946. ;; lastly do some convenience work
  2947. (if (called-interactively-p 'interactive)
  2948. (save-selected-window
  2949. (pop-to-buffer dest-buffer t)
  2950. (goto-char (point-min))
  2951. (and (string= (buffer-name dest-buffer) default-buffer-name)
  2952. (buffer-file-name dest-buffer)
  2953. (save-buffer))
  2954. (message "Generating source...done")
  2955. (let ((mode
  2956. (if (memq language '(cals)) 'sgml-mode
  2957. (intern (concat (symbol-name language) "-mode")))))
  2958. (if (fboundp mode)
  2959. (call-interactively mode)))
  2960. )))
  2961. dest-buffer))
  2962. (defun table--generate-source-prologue (dest-buffer language caption col-list row-list)
  2963. "Generate and insert source prologue into DEST-BUFFER."
  2964. (with-current-buffer dest-buffer
  2965. (cond
  2966. ((eq language 'html)
  2967. (insert (format "<!-- This HTML table template is generated by emacs %s -->\n" emacs-version)
  2968. (format "<table %s>\n" table-html-table-attribute)
  2969. (if (and (stringp caption)
  2970. (not (string= caption "")))
  2971. (format " <caption>%s</caption>\n" caption)
  2972. "")))
  2973. ((eq language 'latex)
  2974. (insert (format "%% This LaTeX table template is generated by emacs %s\n" emacs-version)
  2975. "\\begin{tabular}{|" (apply 'concat (make-list (length col-list) "l|")) "}\n"
  2976. "\\hline\n"))
  2977. ((eq language 'cals)
  2978. (insert (format "<!-- This CALS table template is generated by emacs %s -->\n" emacs-version)
  2979. "<table frame=\"all\">\n")
  2980. (if (and (stringp caption)
  2981. (not (string= caption "")))
  2982. (insert " <title>" caption "</title>\n"))
  2983. (insert (format " <tgroup cols=\"%d\" align=\"left\" colsep=\"1\" rowsep=\"1\">\n" (length col-list)))
  2984. (table-put-source-info 'colspec-marker (point-marker))
  2985. (table-put-source-info 'row-type (if (zerop table-cals-thead-rows) "tbody" "thead"))
  2986. (set-marker-insertion-type (table-get-source-info 'colspec-marker) nil) ;; insert after
  2987. (insert (format " <%s valign=\"top\">\n" (table-get-source-info 'row-type))))
  2988. )))
  2989. (defun table--generate-source-epilogue (dest-buffer language col-list row-list)
  2990. "Generate and insert source epilogue into DEST-BUFFER."
  2991. (with-current-buffer dest-buffer
  2992. (cond
  2993. ((eq language 'html)
  2994. (insert "</table>\n"))
  2995. ((eq language 'latex)
  2996. (insert "\\end{tabular}\n"))
  2997. ((eq language 'cals)
  2998. (set-marker-insertion-type (table-get-source-info 'colspec-marker) t) ;; insert before
  2999. (save-excursion
  3000. (goto-char (table-get-source-info 'colspec-marker))
  3001. (mapc
  3002. (lambda (col)
  3003. (insert (format " <colspec colnum=\"%d\" colname=\"c%d\"/>\n" col col)))
  3004. (sort (table-get-source-info 'colnum-list) '<)))
  3005. (insert (format " </%s>\n </tgroup>\n</table>\n" (table-get-source-info 'row-type))))
  3006. )))
  3007. (defun table--generate-source-scan-rows (dest-buffer language origin-cell col-list row-list)
  3008. "Generate and insert source rows into DEST-BUFFER."
  3009. (table-put-source-info 'current-row 1)
  3010. (while row-list
  3011. (with-current-buffer dest-buffer
  3012. (cond
  3013. ((eq language 'html)
  3014. (insert " <tr>\n"))
  3015. ((eq language 'cals)
  3016. (insert " <row>\n"))
  3017. ))
  3018. (table--generate-source-cells-in-a-row dest-buffer language col-list row-list)
  3019. (with-current-buffer dest-buffer
  3020. (cond
  3021. ((eq language 'html)
  3022. (insert " </tr>\n"))
  3023. ((eq language 'cals)
  3024. (insert " </row>\n")
  3025. (unless (/= (table-get-source-info 'current-row) table-cals-thead-rows)
  3026. (insert (format " </%s>\n" (table-get-source-info 'row-type)))
  3027. (insert (format " <%s valign=\"top\">\n" (table-put-source-info 'row-type "tbody")))))))
  3028. (table-put-source-info 'current-row (1+ (table-get-source-info 'current-row)))
  3029. (setq row-list (cdr row-list))))
  3030. (defun table--generate-source-cells-in-a-row (dest-buffer language col-list row-list)
  3031. "Generate and insert source cells into DEST-BUFFER."
  3032. (table-put-source-info 'current-column 1)
  3033. (while col-list
  3034. (let* ((cell (table--probe-cell))
  3035. (lu (table--get-coordinate (car cell)))
  3036. (rb (table--get-coordinate (cdr cell)))
  3037. (alignment (table--get-cell-justify-property cell))
  3038. (valign (table--get-cell-valign-property cell))
  3039. (row-list row-list)
  3040. (colspan 1)
  3041. (rowspan 1))
  3042. (if (< (car lu) (car col-list))
  3043. (setq col-list nil)
  3044. (while (and col-list
  3045. (> (car lu) (car col-list)))
  3046. (setq col-list (cdr col-list))
  3047. (table-put-source-info 'current-column (1+ (table-get-source-info 'current-column))))
  3048. (setq col-list (cdr col-list))
  3049. (table-put-source-info 'next-column (1+ (table-get-source-info 'current-column)))
  3050. (while (and col-list
  3051. (> (1+ (car rb)) (car col-list)))
  3052. (setq colspan (1+ colspan))
  3053. (setq col-list (cdr col-list))
  3054. (table-put-source-info 'next-column (1+ (table-get-source-info 'next-column))))
  3055. (setq row-list (cdr row-list))
  3056. (while (and row-list
  3057. (> (+ (cdr rb) 2) (car row-list)))
  3058. (setq rowspan (1+ rowspan))
  3059. (setq row-list (cdr row-list)))
  3060. (with-current-buffer dest-buffer
  3061. (cond
  3062. ((eq language 'html)
  3063. (insert (format " <%s"
  3064. (table-put-source-info
  3065. 'cell-type
  3066. (if (or (<= (table-get-source-info 'current-row) table-html-th-rows)
  3067. (<= (table-get-source-info 'current-column) table-html-th-columns))
  3068. "th" "td"))))
  3069. (if (and table-html-cell-attribute (not (string= table-html-cell-attribute "")))
  3070. (insert " " table-html-cell-attribute))
  3071. (if (> colspan 1) (insert (format " colspan=\"%d\"" colspan)))
  3072. (if (> rowspan 1) (insert (format " rowspan=\"%d\"" rowspan)))
  3073. (insert (format " align=\"%s\"" (if alignment (symbol-name alignment) "left")))
  3074. (insert (format " valign=\"%s\"" (if valign (symbol-name valign) "top")))
  3075. (insert ">\n"))
  3076. ((eq language 'cals)
  3077. (insert " <entry")
  3078. (if (> colspan 1)
  3079. (let ((scol (table-get-source-info 'current-column))
  3080. (ecol (+ (table-get-source-info 'current-column) colspan -1)))
  3081. (mapc (lambda (col)
  3082. (unless (memq col (table-get-source-info 'colnum-list))
  3083. (table-put-source-info 'colnum-list
  3084. (cons col (table-get-source-info 'colnum-list)))))
  3085. (list scol ecol))
  3086. (insert (format " namest=\"c%d\" nameend=\"c%d\"" scol ecol))))
  3087. (if (> rowspan 1) (insert (format " morerows=\"%d\"" (1- rowspan))))
  3088. (if (and alignment
  3089. (not (memq alignment '(left none))))
  3090. (insert " align=\"" (symbol-name alignment) "\""))
  3091. (if (and valign
  3092. (not (memq valign '(top none))))
  3093. (insert " valign=\"" (symbol-name valign) "\""))
  3094. (insert ">\n"))
  3095. ))
  3096. (table--generate-source-cell-contents dest-buffer language cell)
  3097. (with-current-buffer dest-buffer
  3098. (cond
  3099. ((eq language 'html)
  3100. (insert (format" </%s>\n" (table-get-source-info 'cell-type))))
  3101. ((eq language 'cals)
  3102. (insert " </entry>\n"))
  3103. ))
  3104. (table-forward-cell 1 t)
  3105. (table-put-source-info 'current-column (table-get-source-info 'next-column))
  3106. ))))
  3107. (defun table--generate-source-cell-contents (dest-buffer language cell)
  3108. "Generate and insert source cell contents of a CELL into DEST-BUFFER."
  3109. (let ((cell-contents (extract-rectangle (car cell) (cdr cell))))
  3110. (with-temp-buffer
  3111. (table--insert-rectangle cell-contents)
  3112. (table--remove-cell-properties (point-min) (point-max))
  3113. (goto-char (point-min))
  3114. (cond
  3115. ((eq language 'html)
  3116. (if table-html-delegate-spacing-to-user-agent
  3117. (progn
  3118. (table--remove-eol-spaces (point-min) (point-max))
  3119. (if (re-search-forward "\\s +\\'" nil t)
  3120. (replace-match "")))
  3121. (while (search-forward " " nil t)
  3122. (replace-match "&nbsp;"))
  3123. (goto-char (point-min))
  3124. (while (and (re-search-forward "$" nil t)
  3125. (not (eobp)))
  3126. (insert "<br />")
  3127. (forward-char 1)))
  3128. (unless (and table-html-delegate-spacing-to-user-agent
  3129. (progn
  3130. (goto-char (point-min))
  3131. (looking-at "\\s *\\'")))))
  3132. ((eq language 'cals)
  3133. (table--remove-eol-spaces (point-min) (point-max))
  3134. (if (re-search-forward "\\s +\\'" nil t)
  3135. (replace-match "")))
  3136. )
  3137. (setq cell-contents (buffer-substring (point-min) (point-max))))
  3138. (with-current-buffer dest-buffer
  3139. (let ((beg (point)))
  3140. (insert cell-contents)
  3141. (indent-rigidly beg (point)
  3142. (cond
  3143. ((eq language 'html) 6)
  3144. ((eq language 'cals) 10)))
  3145. (insert ?\n)))))
  3146. (defun table--cell-horizontal-char-p (c)
  3147. "Test if character C is one of the horizontal characters"
  3148. (memq c (string-to-list table-cell-horizontal-chars)))
  3149. (defun table--generate-source-scan-lines (dest-buffer language origin-cell tail-cell col-list row-list)
  3150. "Scan the table line by line.
  3151. Currently this method is for LaTeX only."
  3152. (let* ((lu-coord (table--get-coordinate (car origin-cell)))
  3153. (rb-coord (table--get-coordinate (cdr tail-cell)))
  3154. (x0 (car lu-coord))
  3155. (x1 (car rb-coord))
  3156. (y (cdr lu-coord))
  3157. (y1 (cdr rb-coord)))
  3158. (while (<= y y1)
  3159. (let* ((border-p (memq (1+ y) row-list))
  3160. (border-char-list
  3161. (mapcar (lambda (x)
  3162. (if border-p (char-after (table--goto-coordinate (cons x y)))
  3163. (char-before (table--goto-coordinate (cons x y)))))
  3164. col-list))
  3165. start i c)
  3166. (if border-p
  3167. ;; horizontal cell border processing
  3168. (if (and (table--cell-horizontal-char-p (car border-char-list))
  3169. (table--uniform-list-p border-char-list))
  3170. (with-current-buffer dest-buffer
  3171. (insert "\\hline\n"))
  3172. (setq i 0)
  3173. (while (setq c (nth i border-char-list))
  3174. (if (and start (not (table--cell-horizontal-char-p c)))
  3175. (progn
  3176. (with-current-buffer dest-buffer
  3177. (insert (format "\\cline{%d-%d}\n" (1+ start) i)))
  3178. (setq start nil)))
  3179. (if (and (not start) (table--cell-horizontal-char-p c))
  3180. (setq start i))
  3181. (setq i (1+ i)))
  3182. (if start
  3183. (with-current-buffer dest-buffer
  3184. (insert (format "\\cline{%d-%d}\n" (1+ start) i)))))
  3185. ;; horizontal cell contents processing
  3186. (let* ((span 1) ;; spanning length
  3187. (first-p t) ;; first in a row
  3188. (insert-column ;; a function that processes one column/multicolumn
  3189. (function
  3190. (lambda (from to)
  3191. (let ((line (table--buffer-substring-and-trim
  3192. (table--goto-coordinate (cons from y))
  3193. (table--goto-coordinate (cons to y)))))
  3194. ;; escape special characters
  3195. (with-temp-buffer
  3196. (insert line)
  3197. (goto-char (point-min))
  3198. (while (re-search-forward "\\([#$~_^%{}]\\)\\|\\(\\\\\\)\\|\\([<>|]\\)" nil t)
  3199. (if (match-beginning 1)
  3200. (save-excursion
  3201. (goto-char (match-beginning 1))
  3202. (insert "\\"))
  3203. (if (match-beginning 2)
  3204. (replace-match "$\\backslash$" t t)
  3205. (replace-match (concat "$" (match-string 3) "$")) t t)))
  3206. (setq line (buffer-substring (point-min) (point-max))))
  3207. ;; insert a column separator and column/multicolumn contents
  3208. (with-current-buffer dest-buffer
  3209. (unless first-p
  3210. (insert (if (eq (char-before) ?\s) "" " ") "& "))
  3211. (if (> span 1)
  3212. (insert (format "\\multicolumn{%d}{%sl|}{%s}" span (if first-p "|" "") line))
  3213. (insert line)))
  3214. (setq first-p nil)
  3215. (setq span 1)
  3216. (setq start (nth i col-list)))))))
  3217. (setq start x0)
  3218. (setq i 1)
  3219. (while (setq c (nth i border-char-list))
  3220. (if (eq c table-cell-vertical-char)
  3221. (funcall insert-column start (1- (nth i col-list)))
  3222. (setq span (1+ span)))
  3223. (setq i (1+ i)))
  3224. (funcall insert-column start x1))
  3225. (with-current-buffer dest-buffer
  3226. (insert (if (eq (char-before) ?\s) "" " ") "\\\\\n"))))
  3227. (setq y (1+ y)))
  3228. (with-current-buffer dest-buffer
  3229. (insert "\\hline\n"))
  3230. ))
  3231. ;;;###autoload
  3232. (defun table-insert-sequence (str n increment interval justify)
  3233. "Travel cells forward while inserting a specified sequence string in each cell.
  3234. STR is the base string from which the sequence starts. When STR is an
  3235. empty string then each cell content is erased. When STR ends with
  3236. numerical characters (they may optionally be surrounded by a pair of
  3237. parentheses) they are incremented as a decimal number. Otherwise the
  3238. last character in STR is incremented in ASCII code order. N is the
  3239. number of sequence elements to insert. When N is negative the cell
  3240. traveling direction is backward. When N is zero it travels forward
  3241. entire table. INCREMENT is the increment between adjacent sequence
  3242. elements and can be a negative number for effectively decrementing.
  3243. INTERVAL is the number of cells to travel between sequence element
  3244. insertion which is normally 1. When zero or less is given for
  3245. INTERVAL it is interpreted as number of cells per row so that sequence
  3246. is placed straight down vertically as long as the table's cell
  3247. structure is uniform. JUSTIFY is one of the symbol 'left, 'center or
  3248. 'right, that specifies justification of the inserted string.
  3249. Example:
  3250. (progn
  3251. (table-insert 16 3 5 1)
  3252. (table-forward-cell 15)
  3253. (table-insert-sequence \"D0\" -16 1 1 'center)
  3254. (table-forward-cell 16)
  3255. (table-insert-sequence \"A[0]\" -16 1 1 'center)
  3256. (table-forward-cell 1)
  3257. (table-insert-sequence \"-\" 16 0 1 'center))
  3258. (progn
  3259. (table-insert 16 8 5 1)
  3260. (table-insert-sequence \"@\" 0 1 2 'right)
  3261. (table-forward-cell 1)
  3262. (table-insert-sequence \"64\" 0 1 2 'left))
  3263. "
  3264. (interactive
  3265. (progn
  3266. (barf-if-buffer-read-only)
  3267. (unless (table--probe-cell) (error "Table not found here"))
  3268. (list (read-from-minibuffer
  3269. "Sequence base string: " (car table-sequence-string-history) nil nil 'table-sequence-string-history)
  3270. (string-to-number
  3271. (table--read-from-minibuffer
  3272. '("How many elements (0: maximum, negative: backward traveling)" . table-sequence-count-history)))
  3273. (string-to-number
  3274. (table--read-from-minibuffer
  3275. '("Increment element by" . table-sequence-increment-history)))
  3276. (string-to-number
  3277. (table--read-from-minibuffer
  3278. '("Cell interval (0: vertical, 1:horizontal)" . table-sequence-interval-history)))
  3279. (let* ((completion-ignore-case t)
  3280. (default (car table-sequence-justify-history)))
  3281. (intern (downcase (completing-read
  3282. (format "Justify (default %s): " default)
  3283. '(("left") ("center") ("right"))
  3284. nil t nil 'table-sequence-justify-history default)))))))
  3285. (unless (or (called-interactively-p 'interactive) (table--probe-cell))
  3286. (error "Table not found here"))
  3287. (string-match "\\([0-9]*\\)\\([]})>]*\\)\\'" str)
  3288. (if (called-interactively-p 'interactive)
  3289. (message "Sequencing..."))
  3290. (let* ((prefix (substring str 0 (match-beginning 1)))
  3291. (index (match-string 1 str))
  3292. (fmt (format "%%%s%dd" (if (eq (string-to-char index) ?0) "0" "") (length index)))
  3293. (postfix (match-string 2 str))
  3294. (dim (table-query-dimension))
  3295. (cells (nth 6 dim))
  3296. (direction (if (< n 0) -1 1))
  3297. (interval-count 0))
  3298. (if (string= index "")
  3299. (progn
  3300. (setq index nil)
  3301. (if (string= prefix "")
  3302. (setq prefix nil)))
  3303. (setq index (string-to-number index)))
  3304. (if (< n 0) (setq n (- n)))
  3305. (if (or (zerop n) (> n cells)) (setq n cells))
  3306. (if (< interval 0) (setq interval (- interval)))
  3307. (if (zerop interval) (setq interval (nth 4 dim)))
  3308. (save-excursion
  3309. (while (progn
  3310. (if (> interval-count 0) nil
  3311. (setq interval-count interval)
  3312. (table-with-cache-buffer
  3313. (goto-char (point-min))
  3314. (if (not (or prefix index))
  3315. (erase-buffer)
  3316. (insert prefix)
  3317. (if index (insert (format fmt index)))
  3318. (insert postfix)
  3319. (table--fill-region (point-min) (point) table-cell-info-width justify)
  3320. (setq table-cell-info-justify justify))
  3321. (setq table-inhibit-auto-fill-paragraph t))
  3322. (table--update-cell 'now)
  3323. (if index
  3324. (setq index (+ index increment))
  3325. (if (and prefix (string= postfix ""))
  3326. (let ((len-1 (1- (length prefix))))
  3327. (setq prefix (concat (substring prefix 0 len-1)
  3328. (char-to-string
  3329. (+ (string-to-char (substring prefix len-1)) increment)))))))
  3330. (setq n (1- n)))
  3331. (table-forward-cell direction t)
  3332. (setq interval-count (1- interval-count))
  3333. (setq cells (1- cells))
  3334. (and (> n 0) (> cells 0)))))
  3335. (table-recognize-cell 'force)
  3336. (if (called-interactively-p 'interactive)
  3337. (message "Sequencing...done"))
  3338. ))
  3339. ;;;###autoload
  3340. (defun table-delete-row (n)
  3341. "Delete N row(s) of cells.
  3342. Delete N rows of cells from current row. The current row is the row
  3343. contains the current cell where point is located. Each row must
  3344. consists from cells of same height."
  3345. (interactive "*p")
  3346. (let ((orig-coord (table--get-coordinate))
  3347. (bt-coord (table--get-coordinate (cdr (table--vertical-cell-list nil 'first-only))))
  3348. lu-coord rb-coord rect)
  3349. ;; determine the area to delete while testing row height uniformity
  3350. (while (> n 0)
  3351. (setq n (1- n))
  3352. (unless (table--probe-cell)
  3353. (error "Table not found"))
  3354. (let ((cell-list (table--horizontal-cell-list 'left-to-right)))
  3355. (unless
  3356. (and (table--uniform-list-p
  3357. (mapcar (lambda (cell) (cdr (table--get-coordinate (car cell)))) cell-list))
  3358. (table--uniform-list-p
  3359. (mapcar (lambda (cell) (cdr (table--get-coordinate (cdr cell)))) cell-list)))
  3360. (error "Cells in this row are not in uniform height"))
  3361. (unless lu-coord
  3362. (setq lu-coord (table--get-coordinate (caar cell-list))))
  3363. (setq rb-coord (table--get-coordinate (cdar (last cell-list))))
  3364. (table--goto-coordinate (cons (car orig-coord) (+ 2 (cdr rb-coord))))))
  3365. ;; copy the remaining area (below the deleting area)
  3366. (setq rect (extract-rectangle
  3367. (table--goto-coordinate (cons (1- (car lu-coord)) (1+ (cdr rb-coord))))
  3368. (table--goto-coordinate (cons (1+ (car rb-coord)) (1+ (cdr bt-coord))))))
  3369. ;; delete the deleting area and below together
  3370. (delete-rectangle
  3371. (table--goto-coordinate (cons (1- (car lu-coord)) (1- (cdr lu-coord))))
  3372. (table--goto-coordinate (cons (1+ (car rb-coord)) (1+ (cdr bt-coord)))))
  3373. (table--goto-coordinate (cons (1- (car lu-coord)) (1- (cdr lu-coord))))
  3374. ;; insert the remaining area while appending blank lines below it
  3375. (table--insert-rectangle
  3376. (append rect (make-list (+ 2 (- (cdr rb-coord) (cdr lu-coord)))
  3377. (make-string (+ 2 (- (car rb-coord) (car lu-coord))) ?\s))))
  3378. ;; remove the appended blank lines below the table if they are unnecessary
  3379. (table--goto-coordinate (cons 0 (- (cdr bt-coord) (- (cdr rb-coord) (cdr lu-coord)))))
  3380. (table--remove-blank-lines (+ 2 (- (cdr rb-coord) (cdr lu-coord))))
  3381. ;; fix up intersections
  3382. (let ((coord (cons (car lu-coord) (1- (cdr lu-coord))))
  3383. (n (1+ (- (car rb-coord) (car lu-coord)))))
  3384. (while (> n 0)
  3385. (table--goto-coordinate coord)
  3386. (if (save-excursion
  3387. (or (and (table--goto-coordinate (cons (car coord) (1- (cdr coord))) 'no-extension)
  3388. (looking-at (regexp-quote (char-to-string table-cell-vertical-char))))
  3389. (and (table--goto-coordinate (cons (car coord) (1+ (cdr coord))) 'no-extension)
  3390. (looking-at (regexp-quote (char-to-string table-cell-vertical-char))))))
  3391. (progn
  3392. (delete-char 1)
  3393. (insert table-cell-intersection-char))
  3394. (delete-char 1)
  3395. (insert (string-to-char table-cell-horizontal-chars)))
  3396. (setq n (1- n))
  3397. (setcar coord (1+ (car coord)))))
  3398. ;; goto appropriate end point
  3399. (table--goto-coordinate (cons (car orig-coord) (cdr lu-coord)))))
  3400. ;;;###autoload
  3401. (defun table-delete-column (n)
  3402. "Delete N column(s) of cells.
  3403. Delete N columns of cells from current column. The current column is
  3404. the column contains the current cell where point is located. Each
  3405. column must consists from cells of same width."
  3406. (interactive "*p")
  3407. (let ((orig-coord (table--get-coordinate))
  3408. lu-coord rb-coord)
  3409. ;; determine the area to delete while testing column width uniformity
  3410. (while (> n 0)
  3411. (setq n (1- n))
  3412. (unless (table--probe-cell)
  3413. (error "Table not found"))
  3414. (let ((cell-list (table--vertical-cell-list 'top-to-bottom)))
  3415. (unless
  3416. (and (table--uniform-list-p
  3417. (mapcar (function (lambda (cell) (car (table--get-coordinate (car cell))))) cell-list))
  3418. (table--uniform-list-p
  3419. (mapcar (function (lambda (cell) (car (table--get-coordinate (cdr cell))))) cell-list)))
  3420. (error "Cells in this column are not in uniform width"))
  3421. (unless lu-coord
  3422. (setq lu-coord (table--get-coordinate (caar cell-list))))
  3423. (setq rb-coord (table--get-coordinate (cdar (last cell-list))))
  3424. (table--goto-coordinate (cons (1+ (car rb-coord)) (cdr orig-coord)))))
  3425. ;; delete the area
  3426. (delete-rectangle
  3427. (table--goto-coordinate (cons (car lu-coord) (1- (cdr lu-coord))))
  3428. (table--goto-coordinate (cons (1+ (car rb-coord)) (1+ (cdr rb-coord)))))
  3429. ;; fix up the intersections
  3430. (let ((coord (cons (1- (car lu-coord)) (cdr lu-coord)))
  3431. (n (1+ (- (cdr rb-coord) (cdr lu-coord)))))
  3432. (while (> n 0)
  3433. (table--goto-coordinate coord)
  3434. (if (save-excursion
  3435. (or (and (table--goto-coordinate (cons (1- (car coord)) (cdr coord)) 'no-extension)
  3436. (looking-at (regexp-opt-charset
  3437. (string-to-list table-cell-horizontal-chars))))
  3438. (and (table--goto-coordinate (cons (1+ (car coord)) (cdr coord)) 'no-extension)
  3439. (looking-at (regexp-opt-charset
  3440. (string-to-list table-cell-horizontal-chars))))))
  3441. (progn
  3442. (delete-char 1)
  3443. (insert table-cell-intersection-char))
  3444. (delete-char 1)
  3445. (insert table-cell-vertical-char))
  3446. (setq n (1- n))
  3447. (setcdr coord (1+ (cdr coord)))))
  3448. ;; goto appropriate end point
  3449. (table--goto-coordinate (cons (car lu-coord) (cdr orig-coord)))))
  3450. ;;;###autoload
  3451. (defun table-capture (beg end &optional col-delim-regexp row-delim-regexp justify min-cell-width columns)
  3452. "Convert plain text into a table by capturing the text in the region.
  3453. Create a table with the text in region as cell contents. BEG and END
  3454. specify the region. The text in the region is replaced with a table.
  3455. The removed text is inserted in the table. When optional
  3456. COL-DELIM-REGEXP and ROW-DELIM-REGEXP are provided the region contents
  3457. is parsed and separated into individual cell contents by using the
  3458. delimiter regular expressions. This parsing determines the number of
  3459. columns and rows of the table automatically. If COL-DELIM-REGEXP and
  3460. ROW-DELIM-REGEXP are omitted the result table has only one cell and
  3461. the entire region contents is placed in that cell. Optional JUSTIFY
  3462. is one of 'left, 'center or 'right, which specifies the cell
  3463. justification. Optional MIN-CELL-WIDTH specifies the minimum cell
  3464. width. Optional COLUMNS specify the number of columns when
  3465. ROW-DELIM-REGEXP is not specified.
  3466. Example 1:
  3467. 1, 2, 3, 4
  3468. 5, 6, 7, 8
  3469. , 9, 10
  3470. Running `table-capture' on above 3 line region with COL-DELIM-REGEXP
  3471. \",\" and ROW-DELIM-REGEXP \"\\n\" creates the following table. In
  3472. this example the cells are centered and minimum cell width is
  3473. specified as 5.
  3474. +-----+-----+-----+-----+
  3475. | 1 | 2 | 3 | 4 |
  3476. +-----+-----+-----+-----+
  3477. | 5 | 6 | 7 | 8 |
  3478. +-----+-----+-----+-----+
  3479. | | 9 | 10 | |
  3480. +-----+-----+-----+-----+
  3481. Note:
  3482. In case the function is called interactively user must use \\[quoted-insert] `quoted-insert'
  3483. in order to enter \"\\n\" successfully. COL-DELIM-REGEXP at the end
  3484. of each row is optional.
  3485. Example 2:
  3486. This example shows how a table can be used for text layout editing.
  3487. Let `table-capture' capture the following region starting from
  3488. -!- and ending at -*-, that contains three paragraphs and two item
  3489. name headers. This time specify empty string for both
  3490. COL-DELIM-REGEXP and ROW-DELIM-REGEXP.
  3491. -!-`table-capture' is a powerful command however mastering its power
  3492. requires some practice. Here is a list of items what it can do.
  3493. Parse Cell Items By using column delimiter regular
  3494. expression and raw delimiter regular
  3495. expression, it parses the specified text
  3496. area and extracts cell items from
  3497. non-table text and then forms a table out
  3498. of them.
  3499. Capture Text Area When no delimiters are specified it
  3500. creates a single cell table. The text in
  3501. the specified region is placed in that
  3502. cell.-*-
  3503. Now the entire content is captured in a cell which is itself a table
  3504. like this.
  3505. +-----------------------------------------------------------------+
  3506. |`table-capture' is a powerful command however mastering its power|
  3507. |requires some practice. Here is a list of items what it can do. |
  3508. | |
  3509. |Parse Cell Items By using column delimiter regular |
  3510. | expression and raw delimiter regular |
  3511. | expression, it parses the specified text |
  3512. | area and extracts cell items from |
  3513. | non-table text and then forms a table out |
  3514. | of them. |
  3515. | |
  3516. |Capture Text Area When no delimiters are specified it |
  3517. | creates a single cell table. The text in |
  3518. | the specified region is placed in that |
  3519. | cell. |
  3520. +-----------------------------------------------------------------+
  3521. By splitting the cell appropriately we now have a table consisting of
  3522. paragraphs occupying its own cell. Each cell can now be edited
  3523. independently.
  3524. +-----------------------------------------------------------------+
  3525. |`table-capture' is a powerful command however mastering its power|
  3526. |requires some practice. Here is a list of items what it can do. |
  3527. +---------------------+-------------------------------------------+
  3528. |Parse Cell Items |By using column delimiter regular |
  3529. | |expression and raw delimiter regular |
  3530. | |expression, it parses the specified text |
  3531. | |area and extracts cell items from |
  3532. | |non-table text and then forms a table out |
  3533. | |of them. |
  3534. +---------------------+-------------------------------------------+
  3535. |Capture Text Area |When no delimiters are specified it |
  3536. | |creates a single cell table. The text in |
  3537. | |the specified region is placed in that |
  3538. | |cell. |
  3539. +---------------------+-------------------------------------------+
  3540. By applying `table-release', which does the opposite process, the
  3541. contents become once again plain text. `table-release' works as
  3542. companion command to `table-capture' this way.
  3543. "
  3544. (interactive
  3545. (let ((col-delim-regexp)
  3546. (row-delim-regexp))
  3547. (barf-if-buffer-read-only)
  3548. (if (table--probe-cell)
  3549. (error "Can't insert a table inside a table"))
  3550. (list
  3551. (mark) (point)
  3552. (setq col-delim-regexp
  3553. (read-from-minibuffer "Column delimiter regexp: "
  3554. (car table-col-delim-regexp-history) nil nil 'table-col-delim-regexp-history))
  3555. (setq row-delim-regexp
  3556. (read-from-minibuffer "Row delimiter regexp: "
  3557. (car table-row-delim-regexp-history) nil nil 'table-row-delim-regexp-history))
  3558. (let* ((completion-ignore-case t)
  3559. (default (car table-capture-justify-history)))
  3560. (if (and (string= col-delim-regexp "") (string= row-delim-regexp "")) 'left
  3561. (intern
  3562. (downcase (completing-read
  3563. (format "Justify (default %s): " default)
  3564. '(("left") ("center") ("right"))
  3565. nil t nil 'table-capture-justify-history default)))))
  3566. (if (and (string= col-delim-regexp "") (string= row-delim-regexp "")) "1"
  3567. (table--read-from-minibuffer '("Minimum cell width" . table-capture-min-cell-width-history)))
  3568. (if (and (not (string= col-delim-regexp "")) (string= row-delim-regexp ""))
  3569. (string-to-number
  3570. (table--read-from-minibuffer '("Number of columns" . table-capture-columns-history)))
  3571. nil)
  3572. )))
  3573. (if (> beg end) (let ((tmp beg)) (setq beg end) (setq end tmp)))
  3574. (if (string= col-delim-regexp "") (setq col-delim-regexp nil))
  3575. (if (string= row-delim-regexp "") (setq row-delim-regexp nil))
  3576. (if (and columns (< columns 1)) (setq columns nil))
  3577. (unless min-cell-width (setq min-cell-width "5"))
  3578. (let ((contents (buffer-substring beg end))
  3579. (cols 0) (rows 0) c r cell-list
  3580. (delim-pattern
  3581. (if (and col-delim-regexp row-delim-regexp)
  3582. (format "\\(\\(%s\\)?\\s *\\(%s\\)\\s *\\)\\|\\(\\(%s\\)\\s *\\)"
  3583. col-delim-regexp row-delim-regexp col-delim-regexp)
  3584. (if col-delim-regexp
  3585. (format "\\(\\)\\(\\)\\(\\)\\(\\(%s\\)\\s *\\)" col-delim-regexp))))
  3586. (contents-list))
  3587. ;; when delimiters are specified extract cells and determine the cell dimension
  3588. (if delim-pattern
  3589. (with-temp-buffer
  3590. (insert contents)
  3591. ;; make sure the contents ends with a newline
  3592. (goto-char (point-max))
  3593. (unless (zerop (current-column))
  3594. (insert ?\n))
  3595. ;; skip the preceding white spaces
  3596. (goto-char (point-min))
  3597. (if (looking-at "\\s +")
  3598. (goto-char (match-end 0)))
  3599. ;; extract cell contents
  3600. (let ((from (point)))
  3601. (setq cell-list nil)
  3602. (setq c 0)
  3603. (while (and (re-search-forward delim-pattern nil t)
  3604. (cond
  3605. ;; row delimiter
  3606. ((and (match-string 1) (not (string= (match-string 1) "")))
  3607. (setq rows (1+ rows))
  3608. (setq cell-list
  3609. (append cell-list (list (buffer-substring from (match-beginning 1)))))
  3610. (setq from (match-end 1))
  3611. (setq contents-list
  3612. (append contents-list (list cell-list)))
  3613. (setq cell-list nil)
  3614. (setq c (1+ c))
  3615. (if (> c cols) (setq cols c))
  3616. (setq c 0)
  3617. t)
  3618. ;; column delimiter
  3619. ((and (match-string 4) (not (string= (match-string 4) "")))
  3620. (setq cell-list
  3621. (append cell-list (list (buffer-substring from (match-beginning 4)))))
  3622. (setq from (match-end 4))
  3623. (setq c (1+ c))
  3624. (if (> c cols) (setq cols c))
  3625. t)
  3626. (t nil))))
  3627. ;; take care of the last element without a post delimiter
  3628. (unless (null (looking-at ".+$"))
  3629. (setq cell-list
  3630. (append cell-list (list (match-string 0))))
  3631. (setq cols (1+ cols)))
  3632. ;; take care of the last row without a terminating delimiter
  3633. (unless (null cell-list)
  3634. (setq rows (1+ rows))
  3635. (setq contents-list
  3636. (append contents-list (list cell-list)))))))
  3637. ;; finalize the table dimension
  3638. (if (and columns contents-list)
  3639. ;; when number of columns are specified and cells are parsed determine the dimension
  3640. (progn
  3641. (setq cols columns)
  3642. (setq rows (/ (+ (length (car contents-list)) columns -1) columns)))
  3643. ;; when dimensions are not specified default to a single cell table
  3644. (if (zerop rows) (setq rows 1))
  3645. (if (zerop cols) (setq cols 1)))
  3646. ;; delete the region and reform line breaks
  3647. (delete-region beg end)
  3648. (goto-char beg)
  3649. (unless (zerop (current-column))
  3650. (insert ?\n))
  3651. (unless (looking-at "\\s *$")
  3652. (save-excursion
  3653. (insert ?\n)))
  3654. ;; insert the table
  3655. ;; insert the cell contents
  3656. (if (null contents-list)
  3657. ;; single cell
  3658. (let ((width) (height))
  3659. (with-temp-buffer
  3660. (insert contents)
  3661. (table--remove-eol-spaces (point-min) (point-max))
  3662. (table--untabify (point-min) (point-max))
  3663. (setq width (table--measure-max-width))
  3664. (setq height (1+ (table--current-line (point-max))))
  3665. (setq contents (buffer-substring (point-min) (point-max))))
  3666. (table-insert cols rows width height)
  3667. (table-with-cache-buffer
  3668. (insert contents)
  3669. (setq table-inhibit-auto-fill-paragraph t)))
  3670. ;; multi cells
  3671. (table-insert cols rows min-cell-width 1)
  3672. (setq r 0)
  3673. (setq cell-list nil)
  3674. (while (< r rows)
  3675. (setq r (1+ r))
  3676. (setq c 0)
  3677. (unless cell-list
  3678. (setq cell-list (car contents-list))
  3679. (setq contents-list (cdr contents-list)))
  3680. (while (< c cols)
  3681. (setq c (1+ c))
  3682. (if (car cell-list)
  3683. (table-with-cache-buffer
  3684. (insert (car cell-list))
  3685. (setq cell-list (cdr cell-list))
  3686. (setq table-cell-info-justify justify)))
  3687. (table-forward-cell 1))))))
  3688. ;;;###autoload
  3689. (defun table-release ()
  3690. "Convert a table into plain text by removing the frame from a table.
  3691. Remove the frame from a table and deactivate the table. This command
  3692. converts a table into plain text without frames. It is a companion to
  3693. `table-capture' which does the opposite process."
  3694. (interactive)
  3695. (let ((origin-cell (table--probe-cell))
  3696. table-lu table-rb)
  3697. (if origin-cell
  3698. (let ((old-point (point-marker)))
  3699. ;; save-excursion is not sufficient for this
  3700. ;; because untabify operation moves point
  3701. (set-marker-insertion-type old-point t)
  3702. (unwind-protect
  3703. (progn
  3704. (while
  3705. (progn
  3706. (table-forward-cell 1 nil 'unrecognize)
  3707. (let ((cell (table--probe-cell)))
  3708. (if (or (null table-lu)
  3709. (< (car cell) table-lu))
  3710. (setq table-lu (car cell)))
  3711. (if (or (null table-rb)
  3712. (> (cdr cell) table-rb))
  3713. (setq table-rb (cdr cell)))
  3714. (and cell (not (equal cell origin-cell))))))
  3715. (let* ((lu-coord (table--get-coordinate table-lu))
  3716. (rb-coord (table--get-coordinate table-rb))
  3717. (lu (table--goto-coordinate (table--offset-coordinate lu-coord '(-1 . -1)))))
  3718. (table--spacify-frame)
  3719. (setcdr rb-coord (1+ (cdr rb-coord)))
  3720. (delete-rectangle lu (table--goto-coordinate (cons (car lu-coord) (cdr rb-coord))))
  3721. (table--remove-eol-spaces
  3722. (table--goto-coordinate (cons 0 (1- (cdr lu-coord))))
  3723. (table--goto-coordinate rb-coord) nil t)))
  3724. (goto-char old-point))))))
  3725. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3726. ;;
  3727. ;; Worker functions (executed implicitly)
  3728. ;;
  3729. (defun table--make-cell-map ()
  3730. "Make the table cell keymap if it does not exist yet."
  3731. ;; this is irrelevant to keymap but good place to make sure to be executed
  3732. (table--update-cell-face)
  3733. (unless table-cell-map
  3734. (let ((map (make-sparse-keymap))
  3735. (remap-alist table-command-remap-alist))
  3736. ;; table-command-prefix mode specific bindings
  3737. (if (vectorp table-command-prefix)
  3738. (mapc (lambda (binding)
  3739. (let ((seq (copy-sequence (car binding))))
  3740. (and (vectorp seq)
  3741. (listp (aref seq 0))
  3742. (eq (car (aref seq 0)) 'control)
  3743. (progn
  3744. (aset seq 0 (cadr (aref seq 0)))
  3745. (define-key map (vconcat table-command-prefix seq) (cdr binding))))))
  3746. table-cell-bindings))
  3747. ;; shorthand control bindings
  3748. (mapc (lambda (binding)
  3749. (define-key map (car binding) (cdr binding)))
  3750. table-cell-bindings)
  3751. ;; remap normal commands to table specific version
  3752. (while remap-alist
  3753. (define-key map (vector 'remap (caar remap-alist)) (cdar remap-alist))
  3754. (setq remap-alist (cdr remap-alist)))
  3755. ;;
  3756. (setq table-cell-map map)
  3757. (fset 'table-cell-map map)))
  3758. ;; add menu for table cells
  3759. (unless table-disable-menu
  3760. (easy-menu-define table-cell-menu-map table-cell-map "Table cell menu" table-cell-menu)
  3761. (if (featurep 'xemacs)
  3762. (easy-menu-add table-cell-menu)))
  3763. (run-hooks 'table-cell-map-hook))
  3764. ;; Create the keymap after running the user init file so that the user
  3765. ;; modification to the global-map is accounted.
  3766. (add-hook 'after-init-hook 'table--make-cell-map t)
  3767. (defun *table--cell-self-insert-command ()
  3768. "Table cell version of `self-insert-command'."
  3769. (interactive "*")
  3770. (let ((char last-command-event))
  3771. (if (eq buffer-undo-list t) nil
  3772. (if (not (eq last-command this-command))
  3773. (setq table-cell-self-insert-command-count 0)
  3774. (if (car buffer-undo-list) nil
  3775. (if (>= table-cell-self-insert-command-count 19)
  3776. (setq table-cell-self-insert-command-count 0)
  3777. (setq buffer-undo-list (cdr buffer-undo-list))
  3778. (setq table-cell-self-insert-command-count (1+ table-cell-self-insert-command-count))))))
  3779. (table--cell-insert-char char overwrite-mode)))
  3780. (defun *table--cell-delete-backward-char (n)
  3781. "Table cell version of `delete-backward-char'."
  3782. (interactive "*p")
  3783. (*table--cell-delete-char (- n)))
  3784. (defun *table--cell-newline (&optional indent)
  3785. "Table cell version of `newline'."
  3786. (interactive "*")
  3787. (table-with-cache-buffer
  3788. (let ((column (current-column)))
  3789. (insert ?\n)
  3790. (if indent (indent-to-column column))
  3791. ;; fill only when at the beginning of paragraph
  3792. (if (= (point)
  3793. (save-excursion
  3794. (forward-paragraph -1)
  3795. (if (looking-at "\\s *$")
  3796. (forward-line 1))
  3797. (point)))
  3798. nil ; yes, at the beginning of the paragraph
  3799. (setq table-inhibit-auto-fill-paragraph t)))))
  3800. (defun *table--cell-open-line (n)
  3801. "Table cell version of `open-line'."
  3802. (interactive "*p")
  3803. (table-with-cache-buffer
  3804. (save-excursion
  3805. (insert (make-string n ?\n))
  3806. (table--fill-region (point) (point))
  3807. (setq table-inhibit-auto-fill-paragraph t))))
  3808. (defun *table--cell-newline-and-indent ()
  3809. "Table cell version of `newline-and-indent'."
  3810. (interactive)
  3811. (*table--cell-newline t))
  3812. (defun *table--cell-delete-char (n)
  3813. "Table cell version of `delete-char'."
  3814. (interactive "*p")
  3815. (let ((overwrite overwrite-mode))
  3816. (table-with-cache-buffer
  3817. (if (and overwrite (< n 0))
  3818. (progn
  3819. (while (not (zerop n))
  3820. (let ((coordinate (table--get-coordinate)))
  3821. (if (zerop (car coordinate))
  3822. (unless (zerop (cdr coordinate))
  3823. (table--goto-coordinate (cons (1- table-cell-info-width) (1- (cdr coordinate))))
  3824. (unless (eolp)
  3825. (delete-char 1)))
  3826. (delete-char -1)
  3827. (insert ?\s)
  3828. (forward-char -1)))
  3829. (setq n (1+ n)))
  3830. (setq table-inhibit-auto-fill-paragraph t))
  3831. (let ((coordinate (table--get-coordinate))
  3832. (end-marker (copy-marker (+ (point) n)))
  3833. (deleted))
  3834. (if (or (< end-marker (point-min))
  3835. (> end-marker (point-max))) nil
  3836. (table--remove-eol-spaces (point-min) (point-max))
  3837. (setq deleted (buffer-substring (point) end-marker))
  3838. (delete-char n)
  3839. ;; in fixed width mode when two lines are concatenated
  3840. ;; remove continuation character if there is one.
  3841. (and table-fixed-width-mode
  3842. (string-match "^\n" deleted)
  3843. (equal (char-before) table-word-continuation-char)
  3844. (delete-char -2))
  3845. ;; see if the point is placed at the right tip of the previous
  3846. ;; blank line, if so get rid of the preceding blanks.
  3847. (if (and (not (bolp))
  3848. (/= (cdr coordinate) (cdr (table--get-coordinate)))
  3849. (let ((end (point)))
  3850. (save-excursion
  3851. (beginning-of-line)
  3852. (re-search-forward "\\s +" end t)
  3853. (= (point) end))))
  3854. (replace-match ""))
  3855. ;; do not fill the paragraph if the point is already at the end
  3856. ;; of this paragraph and is following a blank character
  3857. ;; (otherwise the filling squeezes the preceding blanks)
  3858. (if (and (looking-at "\\s *$")
  3859. (or (bobp)
  3860. (save-excursion
  3861. (backward-char)
  3862. (looking-at "\\s "))))
  3863. (setq table-inhibit-auto-fill-paragraph t))
  3864. )
  3865. (set-marker end-marker nil))))))
  3866. (defun *table--cell-quoted-insert (arg)
  3867. "Table cell version of `quoted-insert'."
  3868. (interactive "*p")
  3869. (let ((char (read-quoted-char)))
  3870. (while (> arg 0)
  3871. (table--cell-insert-char char nil)
  3872. (setq arg (1- arg)))))
  3873. (defun *table--cell-describe-mode ()
  3874. "Table cell version of `describe-mode'."
  3875. (interactive)
  3876. (if (not (table--point-in-cell-p))
  3877. (call-interactively 'describe-mode)
  3878. (with-output-to-temp-buffer "*Help*"
  3879. (princ "Table mode: (in ")
  3880. (princ (format-mode-line mode-name nil nil (current-buffer)))
  3881. (princ " mode)
  3882. Table is not a mode technically. You can regard it as a pseudo mode
  3883. which exists locally within a buffer. It overrides some standard
  3884. editing behaviors. Editing operations in a table produces confined
  3885. effects to the current cell. It may grow the cell horizontally and/or
  3886. vertically depending on the newly entered or deleted contents of the
  3887. cell, and also depending on the current mode of cell.
  3888. In the normal mode the table preserves word continuity. Which means
  3889. that a word never gets folded into multiple lines. For this purpose
  3890. table will occasionally grow the cell width. On the other hand, when
  3891. in a fixed width mode all cell width are fixed. When a word can not
  3892. fit in the cell width the word is folded into the next line. The
  3893. folded location is marked by a continuation character which is
  3894. specified in the variable `table-word-continuation-char'.
  3895. ")
  3896. (help-print-return-message))))
  3897. (defun *table--cell-describe-bindings ()
  3898. "Table cell version of `describe-bindings'."
  3899. (interactive)
  3900. (if (not (table--point-in-cell-p))
  3901. (call-interactively 'describe-bindings)
  3902. (with-output-to-temp-buffer "*Help*"
  3903. (princ "Table Bindings:
  3904. key binding
  3905. --- -------
  3906. ")
  3907. (mapc (lambda (binding)
  3908. (princ (format "%-16s%s\n"
  3909. (key-description (car binding))
  3910. (cdr binding))))
  3911. table-cell-bindings)
  3912. (help-print-return-message))))
  3913. (defun *table--cell-dabbrev-expand (arg)
  3914. "Table cell version of `dabbrev-expand'."
  3915. (interactive "*P")
  3916. (let ((dabbrev-abbrev-char-regexp (concat "[^"
  3917. (char-to-string table-cell-vertical-char)
  3918. (char-to-string table-cell-intersection-char)
  3919. " \n]")))
  3920. (table-with-cache-buffer
  3921. (dabbrev-expand arg))))
  3922. (defun *table--cell-dabbrev-completion (&optional arg)
  3923. "Table cell version of `dabbrev-completion'."
  3924. (interactive "*P")
  3925. (error "`dabbrev-completion' is incompatible with table")
  3926. (let ((dabbrev-abbrev-char-regexp (concat "[^"
  3927. (char-to-string table-cell-vertical-char)
  3928. (char-to-string table-cell-intersection-char)
  3929. " \n]")))
  3930. (table-with-cache-buffer
  3931. (dabbrev-completion arg))))
  3932. (defun *table--present-cell-popup-menu (event)
  3933. "Present and handle cell popup menu."
  3934. (interactive "e")
  3935. (unless table-disable-menu
  3936. (select-window (posn-window (event-start event)))
  3937. (goto-char (posn-point (event-start event)))
  3938. (let ((item-list (x-popup-menu event table-cell-menu-map))
  3939. (func table-cell-menu-map))
  3940. (while item-list
  3941. (setq func (nth 3 (assoc (car item-list) func)))
  3942. (setq item-list (cdr item-list)))
  3943. (if (and (symbolp func) (fboundp func))
  3944. (call-interactively func)))))
  3945. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3946. ;;
  3947. ;; Cell updating functions
  3948. ;;
  3949. (defun table--update-cell (&optional now)
  3950. "Update the table cell contents.
  3951. When the optional parameter NOW is nil it only sets up the update
  3952. timer. If it is non-nil the function copies the contents of the cell
  3953. cache buffer into the designated cell in the table buffer."
  3954. (if (null table-update-timer) nil
  3955. (table--cancel-timer table-update-timer)
  3956. (setq table-update-timer nil))
  3957. (if (or (not now)
  3958. (and (boundp 'quail-converting)
  3959. quail-converting) ;; defer operation while current quail work is not finished.
  3960. (and (boundp 'quail-translating)
  3961. quail-translating))
  3962. (setq table-update-timer
  3963. (table--set-timer table-time-before-update
  3964. (function table--update-cell)
  3965. 'now))
  3966. (save-current-buffer
  3967. (set-buffer table-cell-buffer)
  3968. (let ((cache-buffer (get-buffer-create table-cache-buffer-name))
  3969. (org-coord (table--get-coordinate))
  3970. (in-cell (equal (table--cell-to-coord (table--probe-cell))
  3971. (cons table-cell-info-lu-coordinate table-cell-info-rb-coordinate)))
  3972. rectangle)
  3973. (set-buffer cache-buffer)
  3974. (setq rectangle
  3975. (extract-rectangle
  3976. 1
  3977. (table--goto-coordinate (cons table-cell-info-width (1- table-cell-info-height)))))
  3978. (set-buffer table-cell-buffer)
  3979. (delete-rectangle (table--goto-coordinate table-cell-info-lu-coordinate)
  3980. (table--goto-coordinate table-cell-info-rb-coordinate))
  3981. (table--goto-coordinate table-cell-info-lu-coordinate)
  3982. (table--insert-rectangle rectangle)
  3983. (let* ((cell (table--probe-cell))) ; must probe again in case of wide characters
  3984. (table--put-cell-property cell)
  3985. (table--put-cell-justify-property cell table-cell-info-justify)
  3986. (table--put-cell-valign-property cell table-cell-info-valign))
  3987. (table--goto-coordinate
  3988. (if in-cell
  3989. (table--transcoord-cache-to-table table-cell-cache-point-coordinate)
  3990. org-coord))))
  3991. ;; simulate undo behavior under overwrite-mode
  3992. (if (and overwrite-mode (not (eq buffer-undo-list t)))
  3993. (setq buffer-undo-list (cons nil buffer-undo-list)))))
  3994. (defun table--update-cell-widened (&optional now)
  3995. "Update the contents of the cells that are affected by widening operation."
  3996. (if (null table-widen-timer) nil
  3997. (table--cancel-timer table-widen-timer)
  3998. (setq table-widen-timer nil))
  3999. (if (not now)
  4000. (setq table-widen-timer
  4001. (table--set-timer (+ table-time-before-update table-time-before-reformat)
  4002. (function table--update-cell-widened)
  4003. 'now))
  4004. (save-current-buffer
  4005. (if table-update-timer
  4006. (table--update-cell 'now))
  4007. (set-buffer table-cell-buffer)
  4008. (let* ((current-coordinate (table--get-coordinate))
  4009. (current-cell-coordinate (table--cell-to-coord (table--probe-cell)))
  4010. (cell-coord-list (progn
  4011. (table--goto-coordinate table-cell-info-lu-coordinate)
  4012. (table--cell-list-to-coord-list (table--vertical-cell-list)))))
  4013. (while cell-coord-list
  4014. (let* ((cell-coord (prog1 (car cell-coord-list) (setq cell-coord-list (cdr cell-coord-list))))
  4015. (currentp (equal cell-coord current-cell-coordinate)))
  4016. (if currentp (table--goto-coordinate current-coordinate)
  4017. (table--goto-coordinate (car cell-coord)))
  4018. (table-recognize-cell 'froce)
  4019. (let ((table-inhibit-update t))
  4020. (table-with-cache-buffer
  4021. (let ((sticky (and currentp
  4022. (save-excursion
  4023. (unless (bolp) (forward-char -1))
  4024. (looking-at ".*\\S ")))))
  4025. (table--fill-region (point-min) (point-max))
  4026. (if sticky
  4027. (setq current-coordinate (table--transcoord-cache-to-table))))))
  4028. (table--update-cell 'now)
  4029. ))
  4030. (table--goto-coordinate current-coordinate)
  4031. (table-recognize-cell 'froce)))))
  4032. (defun table--update-cell-heightened (&optional now)
  4033. "Update the contents of the cells that are affected by heightening operation."
  4034. (if (null table-heighten-timer) nil
  4035. (table--cancel-timer table-heighten-timer)
  4036. (setq table-heighten-timer nil))
  4037. (if (not now)
  4038. (setq table-heighten-timer
  4039. (table--set-timer (+ table-time-before-update table-time-before-reformat)
  4040. (function table--update-cell-heightened)
  4041. 'now))
  4042. (save-current-buffer
  4043. (if table-update-timer
  4044. (table--update-cell 'now))
  4045. (if table-widen-timer
  4046. (table--update-cell-widened 'now))
  4047. (set-buffer table-cell-buffer)
  4048. (let* ((current-coordinate (table--get-coordinate))
  4049. (current-cell-coordinate (table--cell-to-coord (table--probe-cell)))
  4050. (cell-coord-list (progn
  4051. (table--goto-coordinate table-cell-info-lu-coordinate)
  4052. (table--cell-list-to-coord-list (table--horizontal-cell-list)))))
  4053. (while cell-coord-list
  4054. (let* ((cell-coord (prog1 (car cell-coord-list) (setq cell-coord-list (cdr cell-coord-list))))
  4055. (currentp (equal cell-coord current-cell-coordinate)))
  4056. (if currentp (table--goto-coordinate current-coordinate)
  4057. (table--goto-coordinate (car cell-coord)))
  4058. (table-recognize-cell 'froce)
  4059. (let ((table-inhibit-update t))
  4060. (table-with-cache-buffer
  4061. (let ((sticky (and currentp
  4062. (save-excursion
  4063. (unless (bolp) (forward-char -1))
  4064. (looking-at ".*\\S ")))))
  4065. (table--valign)
  4066. (if sticky
  4067. (setq current-coordinate (table--transcoord-cache-to-table))))))
  4068. (table--update-cell 'now)
  4069. ))
  4070. (table--goto-coordinate current-coordinate)
  4071. (table-recognize-cell 'froce)))))
  4072. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4073. ;;
  4074. ;; Service functions (for external packages)
  4075. ;;
  4076. (defun table-goto-top-left-corner ()
  4077. "Move point to top left corner of the current table and return the char position."
  4078. (table--goto-coordinate
  4079. (cons
  4080. (1- (car (table--get-coordinate (car (table--horizontal-cell-list t t)))))
  4081. (1- (cdr (table--get-coordinate (car (table--vertical-cell-list t t))))))))
  4082. (defun table-goto-top-right-corner ()
  4083. "Move point to top right corner of the current table and return the char position."
  4084. (table--goto-coordinate
  4085. (cons
  4086. (car (table--get-coordinate (cdr (table--horizontal-cell-list nil t))))
  4087. (1- (cdr (table--get-coordinate (car (table--vertical-cell-list t t))))))))
  4088. (defun table-goto-bottom-left-corner ()
  4089. "Move point to bottom left corner of the current table and return the char position."
  4090. (table--goto-coordinate
  4091. (cons
  4092. (1- (car (table--get-coordinate (car (table--horizontal-cell-list t t)))))
  4093. (1+ (cdr (table--get-coordinate (cdr (table--vertical-cell-list nil t))))))))
  4094. (defun table-goto-bottom-right-corner ()
  4095. "Move point to bottom right corner of the current table and return the char position."
  4096. (table--goto-coordinate
  4097. (cons
  4098. (car (table--get-coordinate (cdr (table--horizontal-cell-list nil t))))
  4099. (1+ (cdr (table--get-coordinate (cdr (table--vertical-cell-list nil t))))))))
  4100. (defun table-call-interactively (function &optional record-flag keys)
  4101. "Call FUNCTION, or a table version of it if applicable.
  4102. See `call-interactively' for full description of the arguments."
  4103. (let ((table-func (intern-soft (format "*table--cell-%s" function))))
  4104. (call-interactively
  4105. (if (and table-func
  4106. (table--point-in-cell-p))
  4107. table-func
  4108. function) record-flag keys)))
  4109. (defun table-funcall (function &rest arguments)
  4110. "Call FUNCTION, or a table version of it if applicable.
  4111. See `funcall' for full description of the arguments."
  4112. (let ((table-func (intern-soft (format "*table--cell-%s" function))))
  4113. (apply
  4114. (if (and table-func
  4115. (table--point-in-cell-p))
  4116. table-func
  4117. function)
  4118. arguments)))
  4119. (defmacro table-apply (function &rest arguments)
  4120. "Call FUNCTION, or a table version of it if applicable.
  4121. See `apply' for full description of the arguments."
  4122. (let ((table-func (make-symbol "table-func")))
  4123. `(let ((,table-func (intern-soft (format "*table--cell-%s" ,function))))
  4124. (apply
  4125. (if (and ,table-func
  4126. (table--point-in-cell-p))
  4127. ,table-func
  4128. ,function)
  4129. ,@arguments))))
  4130. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4131. ;;
  4132. ;; Utility functions
  4133. ;;
  4134. (defun table--read-from-minibuffer (prompt-history)
  4135. "A wrapper to `read-from-minibuffer'.
  4136. PROMPT-HISTORY is a cons cell which car is the prompt string and the
  4137. cdr is the history symbol."
  4138. (let ((default (car (symbol-value (cdr prompt-history)))))
  4139. (read-from-minibuffer
  4140. (format "%s (default %s): " (car prompt-history) default)
  4141. "" nil nil (cdr prompt-history) default))
  4142. (and (featurep 'xemacs)
  4143. (equal (car (symbol-value (cdr prompt-history))) "")
  4144. (set (cdr prompt-history)
  4145. (cdr (symbol-value (cdr prompt-history)))))
  4146. (car (symbol-value (cdr prompt-history))))
  4147. (defun table--buffer-substring-and-trim (beg end)
  4148. "Extract buffer substring and remove blanks from front and the rear of it."
  4149. (save-excursion
  4150. (save-restriction
  4151. (narrow-to-region (goto-char beg) end)
  4152. (if (re-search-forward "\\s *")
  4153. (setq beg (match-end 0)))
  4154. (if (re-search-forward "\\s *\\'" end t)
  4155. (setq end (match-beginning 0)))
  4156. (table--remove-cell-properties
  4157. 0 (- end beg)
  4158. (buffer-substring beg end)))))
  4159. (defun table--valign ()
  4160. "Vertically align the cache cell contents.
  4161. Current buffer must be the cache buffer at the entry to this function.
  4162. Returns the coordinate of the final point location."
  4163. (if (or (null table-cell-info-valign)
  4164. (eq table-cell-info-valign 'none))
  4165. (table--get-coordinate)
  4166. (let ((saved-point (point-marker)))
  4167. ;;(set-marker-insertion-type saved-point t)
  4168. (goto-char (point-min))
  4169. (let* ((from (and (re-search-forward "^.*\\S " nil t)
  4170. (table--current-line)))
  4171. (to (let ((tmp from))
  4172. (while (re-search-forward "^.*\\S " nil t)
  4173. (setq tmp (table--current-line)))
  4174. tmp))
  4175. (content-height (and from to (1+ (- to from)))))
  4176. (unless (null content-height)
  4177. (goto-char (point-min))
  4178. (if (looking-at "\\s *\n")
  4179. (replace-match ""))
  4180. (cond ((eq table-cell-info-valign 'middle)
  4181. (insert (make-string (/ (- table-cell-info-height content-height) 2) ?\n)))
  4182. ((eq table-cell-info-valign 'bottom)
  4183. (insert (make-string (- table-cell-info-height content-height) ?\n))))
  4184. (table--goto-coordinate (cons table-cell-info-width (1- table-cell-info-height)))
  4185. (if (re-search-forward "\\s +\\'" nil t)
  4186. (replace-match ""))))
  4187. (goto-char saved-point)
  4188. (set-marker saved-point nil)
  4189. (let ((coord (table--get-coordinate)))
  4190. (unless (< (cdr coord) table-cell-info-height)
  4191. (setcdr coord (1- table-cell-info-height))
  4192. (table--goto-coordinate coord))
  4193. coord))))
  4194. (defun table--query-justification ()
  4195. (barf-if-buffer-read-only)
  4196. (let* ((completion-ignore-case t)
  4197. (default (car table-justify-history)))
  4198. (intern (downcase (completing-read
  4199. (format "Justify (default %s): " default)
  4200. '(("left") ("center") ("right") ("top") ("middle") ("bottom") ("none"))
  4201. nil t nil 'table-justify-history default)))))
  4202. (defun table--spacify-frame ()
  4203. "Spacify table frame.
  4204. Replace frame characters with spaces."
  4205. (let ((frame-char
  4206. (append (string-to-list table-cell-horizontal-chars)
  4207. (list table-cell-intersection-char table-cell-vertical-char))))
  4208. (while
  4209. (progn
  4210. (cond
  4211. ((eq (char-after) table-cell-intersection-char)
  4212. (save-excursion
  4213. (let ((col (current-column)))
  4214. (and (zerop (forward-line 1))
  4215. (zerop (current-column))
  4216. (move-to-column col)
  4217. (table--spacify-frame))))
  4218. (delete-char 1)
  4219. (insert-before-markers ?\s))
  4220. ((table--cell-horizontal-char-p (char-after))
  4221. (while (progn
  4222. (delete-char 1)
  4223. (insert-before-markers ?\s)
  4224. (table--cell-horizontal-char-p (char-after)))))
  4225. ((eq (char-after) table-cell-vertical-char)
  4226. (while (let ((col (current-column)))
  4227. (delete-char 1)
  4228. (insert-before-markers ?\s)
  4229. (and (zerop (forward-line 1))
  4230. (zerop (current-column))
  4231. (move-to-column col)
  4232. (eq (char-after) table-cell-vertical-char))))))
  4233. (memq (char-after) frame-char)))))
  4234. (defun table--remove-blank-lines (n)
  4235. "Delete N blank lines from the current line.
  4236. For adjusting below area of the table when the table is shortened."
  4237. (move-to-column 0)
  4238. (let ((first-blank t))
  4239. (while (> n 0)
  4240. (setq n (1- n))
  4241. (cond ((looking-at "\\s *\\'")
  4242. (delete-region (match-beginning 0) (match-end 0))
  4243. (setq n 0))
  4244. ((and (looking-at "\\([ \t]*\n[ \t]*\\)\n") first-blank)
  4245. (delete-region (match-beginning 1) (match-end 1)))
  4246. ((looking-at "[ \t]*$")
  4247. (delete-region (match-beginning 0) (match-end 0))
  4248. (forward-line 1))
  4249. (t
  4250. (setq first-blank nil)
  4251. (forward-line 1))))))
  4252. (defun table--uniform-list-p (l)
  4253. "Return nil when LIST contains non equal elements. Otherwise return t."
  4254. (if (null l) t
  4255. (catch 'end
  4256. (while (cdr l)
  4257. (if (not (equal (car l) (cadr l))) (throw 'end nil))
  4258. (setq l (cdr l)))
  4259. t)))
  4260. (defun table--detect-cell-alignment (cell)
  4261. "Detect CELL contents alignment.
  4262. Guess CELL contents alignment both horizontally and vertically by
  4263. looking at the appearance of the CELL contents."
  4264. (let ((cell-contents (extract-rectangle (car cell) (cdr cell)))
  4265. (left-margin 0)
  4266. (right-margin 0)
  4267. (top-margin 0)
  4268. (bottom-margin 0)
  4269. (margin-diff 0)
  4270. (margin-info-available nil)
  4271. justify valign)
  4272. (with-temp-buffer
  4273. (table--insert-rectangle cell-contents)
  4274. ;; determine the horizontal justification
  4275. (goto-char (point-min))
  4276. (while (re-search-forward "^\\( *\\).*[^ \n]\\( *\\)$" nil t)
  4277. (setq margin-info-available t)
  4278. (let* ((lm (- (match-end 1) (match-beginning 1)))
  4279. (rm (- (match-end 2) (match-beginning 2)))
  4280. (md (abs (- lm rm))))
  4281. (if (> lm left-margin)
  4282. (setq left-margin lm))
  4283. (if (> rm right-margin)
  4284. (setq right-margin rm))
  4285. (if (> md margin-diff)
  4286. (setq margin-diff md))))
  4287. (setq justify
  4288. (cond
  4289. ((and margin-info-available
  4290. (<= margin-diff 1)
  4291. (> left-margin 0)) 'center)
  4292. ((and margin-info-available
  4293. (zerop right-margin)
  4294. (> left-margin 0)) 'right)
  4295. (t 'left)))
  4296. ;; determine the vertical justification
  4297. (goto-char (point-min))
  4298. (if (and (re-search-forward "\\s *\\S " nil t)
  4299. (/= (match-beginning 0) (match-end 0)))
  4300. (setq top-margin (1- (count-lines (match-beginning 0) (match-end 0)))))
  4301. (if (and (re-search-forward "\\s *\\'" nil t)
  4302. (/= (match-beginning 0) (match-end 0)))
  4303. (setq bottom-margin (1- (count-lines (match-beginning 0) (match-end 0)))))
  4304. (setq valign
  4305. (cond
  4306. ((and (> top-margin 0)
  4307. (> bottom-margin 0)
  4308. (<= (abs (- top-margin bottom-margin)) 1)) 'middle)
  4309. ((and (> top-margin 0)
  4310. (zerop bottom-margin)) 'bottom)
  4311. (t nil))))
  4312. (table--put-cell-justify-property cell justify)
  4313. (table--put-cell-valign-property cell valign)))
  4314. (defun table--string-to-number-list (str)
  4315. "Return a list of numbers in STR."
  4316. (let ((idx 0)
  4317. (nl nil))
  4318. (while (string-match "[-0-9.]+" str idx)
  4319. (setq idx (match-end 0))
  4320. (setq nl (cons (string-to-number (match-string 0 str)) nl)))
  4321. (nreverse nl)))
  4322. (defun table--justify-cell-contents (justify &optional paragraph)
  4323. "Justify the current cell contents.
  4324. JUSTIFY is a symbol 'left, 'center or 'right for horizontal, or 'top,
  4325. 'middle, 'bottom or 'none for vertical. When PARAGRAPH is non-nil the
  4326. justify operation is limited to the current paragraph."
  4327. (table-with-cache-buffer
  4328. (let ((beg (point-min))
  4329. (end (point-max-marker))
  4330. (fill-column table-cell-info-width)
  4331. (adaptive-fill-mode nil)
  4332. (valign-symbols '(top middle bottom none)))
  4333. (unless paragraph
  4334. (if (memq justify valign-symbols)
  4335. (setq table-cell-info-valign
  4336. (if (eq justify 'none) nil justify))
  4337. (setq table-cell-info-justify justify)))
  4338. (save-excursion
  4339. (if paragraph
  4340. (let ((paragraph-start "\n"))
  4341. (forward-paragraph)
  4342. (or (bolp) (newline 1))
  4343. (set-marker end (point))
  4344. (setq beg (progn (forward-paragraph -1) (point)))))
  4345. (if (memq justify valign-symbols)
  4346. (table--valign)
  4347. (table--remove-eol-spaces beg end 'bol)
  4348. (let ((paragraph-start table-paragraph-start))
  4349. (fill-region beg end table-cell-info-justify))))
  4350. (setq table-inhibit-auto-fill-paragraph t)
  4351. (set-marker end nil)))
  4352. (table--update-cell 'now))
  4353. (defun table--horizontally-shift-above-and-below (columns-to-extend top-to-bottom-coord-list)
  4354. "Horizontally shift outside contents right above and right below of the table.
  4355. This function moves the surrounding text outside of the table so that
  4356. they match the horizontal growth/shrink of the table. It also
  4357. untabify the shift affected area including the right side of the table
  4358. so that tab related uneven shifting is avoided. COLUMNS-TO-EXTEND
  4359. specifies the number of columns the table grows, or shrinks if
  4360. negative. TOP-TO-BOTTOM-COORD-LIST is the vertical cell coordinate
  4361. list. This list can be any vertical list within the table."
  4362. (save-excursion
  4363. (let (beg-coord end-coord)
  4364. (table--goto-coordinate (caar top-to-bottom-coord-list))
  4365. (let* ((cell (table--horizontal-cell-list nil 'first-only 'top))
  4366. (coord (cons (car (table--get-coordinate (cdr cell)))
  4367. (cdr (table--get-coordinate (car cell))))))
  4368. (setcar coord (1+ (car coord)))
  4369. (setcdr coord (- (cdr coord) 2))
  4370. (setq beg-coord (cons (car coord) (1+ (cdr coord))))
  4371. (while (and (table--goto-coordinate coord 'no-extension)
  4372. (not (looking-at "\\s *$")))
  4373. (if (< columns-to-extend 0)
  4374. (progn
  4375. (table--untabify-line)
  4376. (delete-char columns-to-extend))
  4377. (table--untabify-line (point))
  4378. (insert (make-string columns-to-extend ?\s)))
  4379. (setcdr coord (1- (cdr coord)))))
  4380. (table--goto-coordinate (caar (last top-to-bottom-coord-list)))
  4381. (let ((coord (table--get-coordinate (cdr (table--horizontal-cell-list nil 'first-only 'bottom)))))
  4382. (setcar coord (1+ (car coord)))
  4383. (setcdr coord (+ (cdr coord) 2))
  4384. (setq end-coord (cons (car coord) (1- (cdr coord))))
  4385. (while (and (table--goto-coordinate coord 'no-extension)
  4386. (not (looking-at "\\s *$")))
  4387. (if (< columns-to-extend 0)
  4388. (progn
  4389. (table--untabify-line)
  4390. (delete-char columns-to-extend))
  4391. (table--untabify-line (point))
  4392. (insert (make-string columns-to-extend ?\s)))
  4393. (setcdr coord (1+ (cdr coord)))))
  4394. (while (<= (cdr beg-coord) (cdr end-coord))
  4395. (table--untabify-line (table--goto-coordinate beg-coord 'no-extension))
  4396. (setcdr beg-coord (1+ (cdr beg-coord)))))))
  4397. (defun table--create-growing-space-below (lines-to-extend left-to-right-coord-list bottom-border-y)
  4398. "Create growing space below the table.
  4399. This function creates growing space below the table slightly
  4400. intelligent fashion. Following is the cases it handles for each
  4401. growing line:
  4402. 1. When the first line below the table is a complete blank line it
  4403. inserts a blank line.
  4404. 2. When the line starts with a prefix that matches the prefix of the
  4405. bottom line of the table it inserts a line consisting of prefix alone.
  4406. 3. Otherwise it deletes the rectangular contents where table will
  4407. grow into."
  4408. (save-excursion
  4409. (let ((i 0)
  4410. (prefix (and (table--goto-coordinate (cons 0 bottom-border-y))
  4411. (re-search-forward
  4412. ".*\\S "
  4413. (save-excursion
  4414. (table--goto-coordinate
  4415. (cons (1- (caar (car left-to-right-coord-list))) bottom-border-y)))
  4416. t)
  4417. (buffer-substring (match-beginning 0) (match-end 0)))))
  4418. (while (< i lines-to-extend)
  4419. (let ((y (+ i bottom-border-y 1)))
  4420. (table--goto-coordinate (cons 0 y))
  4421. (cond
  4422. ((looking-at "\\s *$")
  4423. (insert ?\n))
  4424. ((and prefix (looking-at (concat (regexp-quote prefix) "\\s *$")))
  4425. (insert prefix ?\n))
  4426. (t
  4427. (delete-rectangle
  4428. (table--goto-coordinate (cons (1- (caar (car left-to-right-coord-list))) y))
  4429. (table--goto-coordinate (cons (1+ (cadr (car (last left-to-right-coord-list)))) y))))))
  4430. (setq i (1+ i))))))
  4431. (defun table--untabify-line (&optional from)
  4432. "Untabify current line.
  4433. Unlike save-excursion this guarantees preserving the cursor location
  4434. even when the point is on a tab character which is to be removed.
  4435. Optional FROM narrows the subject operation from this point to the end
  4436. of line."
  4437. (let ((current-coordinate (table--get-coordinate)))
  4438. (table--untabify (or from (progn (beginning-of-line) (point)))
  4439. (progn (end-of-line) (point)))
  4440. (table--goto-coordinate current-coordinate)))
  4441. (defun table--untabify (beg end)
  4442. "Wrapper to raw untabify."
  4443. (untabify beg end)
  4444. (if (featurep 'xemacs)
  4445. ;; Cancel strange behavior of xemacs
  4446. (message "")))
  4447. (defun table--multiply-string (string multiplier)
  4448. "Multiply string and return it."
  4449. (let ((ret-str ""))
  4450. (while (> multiplier 0)
  4451. (setq ret-str (concat ret-str string))
  4452. (setq multiplier (1- multiplier)))
  4453. ret-str))
  4454. (defun table--line-column-position (line column)
  4455. "Return the location of LINE forward at COLUMN."
  4456. (save-excursion
  4457. (forward-line line)
  4458. (move-to-column column)
  4459. (point)))
  4460. (defun table--row-column-insertion-point-p (&optional columnp)
  4461. "Return non-nil if it makes sense to insert a row or a column at point."
  4462. (and (not buffer-read-only)
  4463. (or (get-text-property (point) 'table-cell)
  4464. (let ((column (current-column)))
  4465. (if columnp
  4466. (or (text-property-any (line-beginning-position 0)
  4467. (table--line-column-position -1 column)
  4468. 'table-cell t)
  4469. (text-property-any (line-beginning-position) (point) 'table-cell t)
  4470. (text-property-any (line-beginning-position 2)
  4471. (table--line-column-position 1 column)
  4472. 'table-cell t))
  4473. (text-property-any (table--line-column-position -2 column)
  4474. (table--line-column-position -2 (+ 2 column))
  4475. 'table-cell t))))))
  4476. (defun table--find-row-column (&optional columnp no-error)
  4477. "Search table and return a cell coordinate list of row or column."
  4478. (let ((current-coordinate (table--get-coordinate)))
  4479. (catch 'end
  4480. (catch 'error
  4481. (let ((coord (table--get-coordinate)))
  4482. (while
  4483. (progn
  4484. (if columnp (setcar coord (1- (car coord)))
  4485. (setcdr coord (1- (cdr coord))))
  4486. (>= (if columnp (car coord) (cdr coord)) 0))
  4487. (while (progn
  4488. (table--goto-coordinate coord 'no-extension 'no-tab-expansion)
  4489. (not (looking-at (format "[%s%c%c]"
  4490. table-cell-horizontal-chars
  4491. table-cell-vertical-char
  4492. table-cell-intersection-char))))
  4493. (if columnp (setcar coord (1- (car coord)))
  4494. (setcdr coord (1- (cdr coord))))
  4495. (if (< (if columnp (car coord) (cdr coord)) 0)
  4496. (throw 'error nil)))
  4497. (if (table--probe-cell)
  4498. (throw 'end (table--cell-list-to-coord-list (if columnp
  4499. (table--vertical-cell-list t nil 'left)
  4500. (table--horizontal-cell-list t nil 'top))))
  4501. (table--goto-coordinate (table--offset-coordinate coord (if columnp '(0 . 1) '(1 . 0)))
  4502. 'no-extension 'no-tab-expansion)
  4503. (if (table--probe-cell)
  4504. (throw 'end (table--cell-list-to-coord-list (if columnp
  4505. (table--vertical-cell-list t nil 'left)
  4506. (table--horizontal-cell-list t nil 'top)))))))))
  4507. (table--goto-coordinate current-coordinate)
  4508. (if no-error nil
  4509. (error "Table not found")))))
  4510. (defun table--min-coord-list (coord-list)
  4511. "Return minimum cell dimension of COORD-LIST.
  4512. COORD-LIST is a list of coordinate pairs (lu-coord . rb-coord), where
  4513. each pair in the list represents a cell. lu-coord is the left upper
  4514. coordinate of a cell and rb-coord is the right bottom coordinate of a
  4515. cell. A coordinate is a pair of x and y axis coordinate values. The
  4516. return value is a cons cell (min-w . min-h), where min-w and min-h are
  4517. respectively the minimum width and the minimum height of all the cells
  4518. in the list."
  4519. (if (null coord-list) nil
  4520. (let ((min-width 134217727)
  4521. (min-height 134217727))
  4522. (while coord-list
  4523. (let* ((coord (prog1 (car coord-list) (setq coord-list (cdr coord-list))))
  4524. (width (- (cadr coord) (caar coord)))
  4525. (height (1+ (- (cddr coord) (cdar coord)))))
  4526. (if (< width min-width) (setq min-width width))
  4527. (if (< height min-height) (setq min-height height))))
  4528. (cons min-width min-height))))
  4529. (defun table--cell-can-split-horizontally-p ()
  4530. "Test if a cell can split at current location horizontally."
  4531. (and (not buffer-read-only)
  4532. (let ((point-x (car (table--get-coordinate))))
  4533. (table-recognize-cell 'force)
  4534. (and (> point-x (car table-cell-info-lu-coordinate))
  4535. (<= point-x (1- (car table-cell-info-rb-coordinate)))))))
  4536. (defun table--cell-can-split-vertically-p ()
  4537. "Test if a cell can split at current location vertically."
  4538. (and (not buffer-read-only)
  4539. (let ((point-y (cdr (table--get-coordinate))))
  4540. (table-recognize-cell 'force)
  4541. (and (> point-y (cdr table-cell-info-lu-coordinate))
  4542. (<= point-y (cdr table-cell-info-rb-coordinate))))))
  4543. (defun table--cell-can-span-p (direction)
  4544. "Test if the current cell can span to DIRECTION."
  4545. (table-recognize-cell 'force)
  4546. (and (not buffer-read-only)
  4547. (table--probe-cell)
  4548. ;; get two adjacent cells from each corner
  4549. (let ((cell (save-excursion
  4550. (and
  4551. (table--goto-coordinate
  4552. (cons (cond ((eq direction 'right) (1+ (car table-cell-info-rb-coordinate)))
  4553. ((eq direction 'left) (1- (car table-cell-info-lu-coordinate)))
  4554. (t (car table-cell-info-lu-coordinate)))
  4555. (cond ((eq direction 'above) (- (cdr table-cell-info-lu-coordinate) 2))
  4556. ((eq direction 'below) (+ (cdr table-cell-info-rb-coordinate) 2))
  4557. (t (cdr table-cell-info-lu-coordinate)))) 'no-extension)
  4558. (table--probe-cell))))
  4559. (cell2 (save-excursion
  4560. (and
  4561. (table--goto-coordinate
  4562. (cons (cond ((eq direction 'right) (1+ (car table-cell-info-rb-coordinate)))
  4563. ((eq direction 'left) (1- (car table-cell-info-lu-coordinate)))
  4564. (t (car table-cell-info-rb-coordinate)))
  4565. (cond ((eq direction 'above) (- (cdr table-cell-info-lu-coordinate) 2))
  4566. ((eq direction 'below) (+ (cdr table-cell-info-rb-coordinate) 2))
  4567. (t (cdr table-cell-info-rb-coordinate)))) 'no-extension)
  4568. (table--probe-cell)))))
  4569. ;; make sure the two cells exist, and they are identical, that cell's size matches the current one
  4570. (and cell
  4571. (equal cell cell2)
  4572. (if (or (eq direction 'right) (eq direction 'left))
  4573. (and (= (cdr (table--get-coordinate (car cell)))
  4574. (cdr table-cell-info-lu-coordinate))
  4575. (= (cdr (table--get-coordinate (cdr cell)))
  4576. (cdr table-cell-info-rb-coordinate)))
  4577. (and (= (car (table--get-coordinate (car cell)))
  4578. (car table-cell-info-lu-coordinate))
  4579. (= (car (table--get-coordinate (cdr cell)))
  4580. (car table-cell-info-rb-coordinate))))))))
  4581. (defun table--cell-insert-char (char &optional overwrite)
  4582. "Insert CHAR inside a table cell."
  4583. (let ((delete-selection-p (and (boundp 'delete-selection-mode)
  4584. delete-selection-mode
  4585. transient-mark-mode mark-active
  4586. (not buffer-read-only)))
  4587. (mark-coordinate (table--transcoord-table-to-cache (table--get-coordinate (mark t)))))
  4588. (table-with-cache-buffer
  4589. (and delete-selection-p
  4590. (>= (car mark-coordinate) 0)
  4591. (<= (car mark-coordinate) table-cell-info-width)
  4592. (>= (cdr mark-coordinate) 0)
  4593. (<= (cdr mark-coordinate) table-cell-info-height)
  4594. (save-excursion
  4595. (delete-region (point) (table--goto-coordinate mark-coordinate))))
  4596. (if overwrite
  4597. (let ((coordinate (table--get-coordinate)))
  4598. (setq table-inhibit-auto-fill-paragraph t)
  4599. (if (>= (car coordinate) table-cell-info-width)
  4600. (if (>= (cdr coordinate) (1- table-cell-info-height))
  4601. (insert "\n" char)
  4602. (forward-line 1)
  4603. (insert char)
  4604. (unless (eolp)
  4605. (delete-char 1)))
  4606. (insert char)
  4607. (unless (eolp)
  4608. (delete-char 1))))
  4609. (if (not (eq char ?\s))
  4610. (if char (insert char))
  4611. (if (not (looking-at "\\s *$"))
  4612. (if (and table-fixed-width-mode
  4613. (> (point) 2)
  4614. (save-excursion
  4615. (forward-char -2)
  4616. (looking-at (concat "\\("
  4617. (regexp-quote (char-to-string table-word-continuation-char))
  4618. "\\)\n"))))
  4619. (save-excursion
  4620. (replace-match " " nil nil nil 1))
  4621. (insert char))
  4622. (let ((coordinate (table--get-coordinate)))
  4623. (if (< (car coordinate) table-cell-info-width)
  4624. (move-to-column (1+ (car coordinate)) t)
  4625. (insert (make-string (forward-line 1) ?\n))
  4626. (unless (bolp) (insert ?\n))))
  4627. (setq table-inhibit-auto-fill-paragraph t))
  4628. (save-excursion
  4629. (let ((o-point (point)))
  4630. (if (and (bolp)
  4631. (or (progn
  4632. (forward-paragraph)
  4633. (forward-paragraph -1)
  4634. (= o-point (point)))
  4635. (progn
  4636. (goto-char o-point)
  4637. (forward-line)
  4638. (setq o-point (point))
  4639. (forward-paragraph)
  4640. (forward-paragraph -1)
  4641. (= o-point (point)))))
  4642. (insert ?\n)))))))))
  4643. (defun table--finish-delayed-tasks ()
  4644. "Finish all outstanding delayed tasks."
  4645. (if table-update-timer
  4646. (table--update-cell 'now))
  4647. (if table-widen-timer
  4648. (table--update-cell-widened 'now))
  4649. (if table-heighten-timer
  4650. (table--update-cell-heightened 'now)))
  4651. (defmacro table--log (&rest body)
  4652. "Debug logging macro."
  4653. `(with-current-buffer (get-buffer-create "log")
  4654. (goto-char (point-min))
  4655. (let ((standard-output (current-buffer)))
  4656. ,@body)))
  4657. (defun table--measure-max-width (&optional unlimited)
  4658. "Return maximum width of current buffer.
  4659. Normally the current buffer is expected to be already the cache
  4660. buffer. The width excludes following spaces at the end of each line.
  4661. Unless UNLIMITED is non-nil minimum return value is 1."
  4662. (save-excursion
  4663. (let ((width 0))
  4664. (goto-char (point-min))
  4665. (while
  4666. (progn
  4667. ;; do not count the following white spaces
  4668. (re-search-forward "\\s *$")
  4669. (goto-char (match-beginning 0))
  4670. (if (> (current-column) width)
  4671. (setq width (current-column)))
  4672. (forward-line)
  4673. (not (eobp))))
  4674. (if unlimited width
  4675. (max 1 width)))))
  4676. (defun table--cell-to-coord (cell)
  4677. "Create a cell coordinate pair from cell location pair."
  4678. (if cell
  4679. (cons (table--get-coordinate (car cell))
  4680. (table--get-coordinate (cdr cell)))
  4681. nil))
  4682. (defun table--cell-list-to-coord-list (cell-list)
  4683. "Create and return a coordinate list that corresponds to CELL-LIST.
  4684. CELL-LIST is a list of location pairs (lu . rb), where each pair
  4685. represents a cell in the list. lu is the left upper location and rb
  4686. is the right bottom location of a cell. The return value is a list of
  4687. coordinate pairs (lu-coord . rb-coord), where lu-coord is the left
  4688. upper coordinate and rb-coord is the right bottom coordinate of a
  4689. cell."
  4690. (let ((coord-list))
  4691. (while cell-list
  4692. (let ((cell (prog1 (car cell-list) (setq cell-list (cdr cell-list)))))
  4693. (setq coord-list
  4694. (cons (table--cell-to-coord cell) coord-list))))
  4695. (nreverse coord-list)))
  4696. (defun table--test-cell-list (&optional horizontal reverse first-only pivot)
  4697. "For testing `table--vertical-cell-list' and `table--horizontal-cell-list'."
  4698. (let* ((current-coordinate (table--get-coordinate))
  4699. (cell-list (if horizontal
  4700. (table--horizontal-cell-list reverse first-only pivot)
  4701. (table--vertical-cell-list reverse first-only pivot)))
  4702. (count 0))
  4703. (while cell-list
  4704. (let* ((cell (if first-only (prog1 cell-list (setq cell-list nil))
  4705. (prog1 (car cell-list) (setq cell-list (cdr cell-list)))))
  4706. (dig1-str (format "%1d" (prog1 (% count 10) (setq count (1+ count))))))
  4707. (goto-char (car cell))
  4708. (table-with-cache-buffer
  4709. (while (re-search-forward "." nil t)
  4710. (replace-match dig1-str nil nil))
  4711. (setq table-inhibit-auto-fill-paragraph t))
  4712. (table--finish-delayed-tasks)))
  4713. (table--goto-coordinate current-coordinate)))
  4714. (defun table--vertical-cell-list (&optional top-to-bottom first-only pivot internal-dir internal-list internal-px)
  4715. "Return a vertical cell list from the table.
  4716. The return value represents a list of cells including the current cell
  4717. that align vertically. Each element of the list is a cons cell (lu
  4718. . rb) where lu is the cell's left upper location and rb is the cell's
  4719. right bottom location. The cell order in the list is from bottom to
  4720. top of the table. If optional argument TOP-TO-BOTTOM is non-nil the
  4721. order is reversed as from top to bottom of the table. If optional
  4722. argument FIRST-ONLY is non-nil the return value is not a list of cells
  4723. but a single cons cell that is the first cell of the list, if the list
  4724. had been created. If optional argument PIVOT is a symbol `left' the
  4725. vertical cell search is aligned with the left edge of the current
  4726. cell, otherwise aligned with the right edge of the current cell. The
  4727. arguments INTERNAL-DIR, INTERNAL-LIST and INTERNAL-PX are internal use
  4728. only and must not be specified."
  4729. (save-excursion
  4730. (let* ((cell (table--probe-cell))
  4731. (lu-coordinate (table--get-coordinate (car cell)))
  4732. (rb-coordinate (table--get-coordinate (cdr cell)))
  4733. (px (or internal-px (car (if (eq pivot 'left) lu-coordinate rb-coordinate))))
  4734. (ty (- (cdr lu-coordinate) 2))
  4735. (by (+ (cdr rb-coordinate) 2)))
  4736. ;; in case of finding the first cell, get the last adding item on the list
  4737. (if (and (null internal-dir) first-only) (setq top-to-bottom (null top-to-bottom)))
  4738. ;; travel up and process as recursion traces back (reverse order)
  4739. (and cell
  4740. (or (eq internal-dir 'up) (null internal-dir))
  4741. (table--goto-coordinate (cons px (if top-to-bottom by ty)) 'no-extension 'no-tab-expansion)
  4742. (setq internal-list (table--vertical-cell-list top-to-bottom first-only nil 'up nil px)))
  4743. ;; return the last cell or add this cell to the list
  4744. (if first-only (or internal-list cell)
  4745. (setq internal-list (if cell (cons cell internal-list) internal-list))
  4746. ;; travel down and process as entering each recursion (forward order)
  4747. (and cell
  4748. (or (eq internal-dir 'down) (null internal-dir))
  4749. (table--goto-coordinate (cons px (if top-to-bottom ty by)) 'no-extension 'no-tab-expansion)
  4750. (setq internal-list (table--vertical-cell-list top-to-bottom nil nil 'down internal-list px)))
  4751. ;; return the result
  4752. internal-list))))
  4753. (defun table--horizontal-cell-list (&optional left-to-right first-only pivot internal-dir internal-list internal-py)
  4754. "Return a horizontal cell list from the table.
  4755. The return value represents a list of cells including the current cell
  4756. that align horizontally. Each element of the list is a cons cells (lu
  4757. . rb) where lu is the cell's left upper location and rb is the cell's
  4758. right bottom location. The cell order in the list is from right to
  4759. left of the table. If optional argument LEFT-TO-RIGHT is non-nil the
  4760. order is reversed as from left to right of the table. If optional
  4761. argument FIRST-ONLY is non-nil the return value is not a list of cells
  4762. but a single cons cell that is the first cell of the list, if the
  4763. list had been created. If optional argument PIVOT is a symbol `top'
  4764. the horizontal cell search is aligned with the top edge of the current
  4765. cell, otherwise aligned with the bottom edge of the current cell. The
  4766. arguments INTERNAL-DIR, INTERNAL-LIST and INTERNAL-PY are internal use
  4767. only and must not be specified."
  4768. (save-excursion
  4769. (let* ((cell (table--probe-cell))
  4770. (lu-coordinate (table--get-coordinate (car cell)))
  4771. (rb-coordinate (table--get-coordinate (cdr cell)))
  4772. (py (or internal-py (if (eq pivot 'top) (cdr lu-coordinate) (1+ (cdr rb-coordinate)))))
  4773. (lx (1- (car lu-coordinate)))
  4774. (rx (1+ (car rb-coordinate))))
  4775. ;; in case of finding the first cell, get the last adding item on the list
  4776. (if (and (null internal-dir) first-only) (setq left-to-right (null left-to-right)))
  4777. ;; travel left and process as recursion traces back (reverse order)
  4778. (and cell
  4779. (or (eq internal-dir 'left) (null internal-dir))
  4780. (table--goto-coordinate (cons (if left-to-right rx lx) py) 'no-extension 'no-tab-expansion)
  4781. (setq internal-list (table--horizontal-cell-list left-to-right first-only nil 'left nil py)))
  4782. ;; return the last cell or add this cell to the list
  4783. (if first-only (or internal-list cell)
  4784. (setq internal-list (if cell (cons cell internal-list) internal-list))
  4785. ;; travel right and process as entering each recursion (forward order)
  4786. (and cell
  4787. (or (eq internal-dir 'right) (null internal-dir))
  4788. (table--goto-coordinate (cons (if left-to-right lx rx) py) 'no-extension 'no-tab-expansion)
  4789. (setq internal-list (table--horizontal-cell-list left-to-right nil nil 'right internal-list py)))
  4790. ;; return the result
  4791. internal-list))))
  4792. (defun table--point-in-cell-p (&optional location)
  4793. "Return t when point is in a valid table cell in the current buffer.
  4794. When optional LOCATION is provided the test is performed at that location."
  4795. (and (table--at-cell-p (or location (point)))
  4796. (if location
  4797. (save-excursion
  4798. (goto-char location)
  4799. (table--probe-cell))
  4800. (table--probe-cell))))
  4801. (defun table--region-in-cell-p (beg end)
  4802. "Return t when location BEG and END are in a valid table cell in the current buffer."
  4803. (and (table--at-cell-p (min beg end))
  4804. (save-excursion
  4805. (let ((cell-beg (progn (goto-char beg) (table--probe-cell))))
  4806. (and cell-beg
  4807. (equal cell-beg (progn (goto-char end) (table--probe-cell))))))))
  4808. (defun table--at-cell-p (position &optional object at-column)
  4809. "Returns non-nil if POSITION has table-cell property in OBJECT.
  4810. OBJECT is optional and defaults to the current buffer.
  4811. If POSITION is at the end of OBJECT, the value is nil."
  4812. (if (and at-column (stringp object))
  4813. (setq position (table--str-index-at-column object position)))
  4814. (get-text-property position 'table-cell object))
  4815. (defun table--probe-cell-left-up ()
  4816. "Probe left up corner pattern of a cell.
  4817. If it finds a valid corner returns a position otherwise returns nil.
  4818. The position is the location before the first cell character.
  4819. Focus only on the corner pattern. Further cell validity check is required."
  4820. (save-excursion
  4821. (let ((vertical-str (regexp-quote (char-to-string table-cell-vertical-char)))
  4822. (intersection-str (regexp-quote (char-to-string table-cell-intersection-char)))
  4823. (v-border (format "[%c%c]" table-cell-vertical-char table-cell-intersection-char))
  4824. (h-border (format "[%s%c]" table-cell-horizontal-chars table-cell-intersection-char))
  4825. (limit (line-beginning-position)))
  4826. (catch 'end
  4827. (while t
  4828. (catch 'retry-horizontal
  4829. (if (not (search-backward-regexp v-border limit t))
  4830. (throw 'end nil))
  4831. (save-excursion
  4832. (let ((column (current-column)))
  4833. (while t
  4834. (catch 'retry-vertical
  4835. (if (zerop (forward-line -1)) nil (throw 'end nil))
  4836. (move-to-column column)
  4837. (while (and (looking-at vertical-str)
  4838. (= column (current-column)))
  4839. (if (zerop (forward-line -1)) nil (throw 'end nil))
  4840. (move-to-column column))
  4841. (cond
  4842. ((/= column (current-column))
  4843. (throw 'end nil))
  4844. ((looking-at (concat intersection-str h-border))
  4845. (forward-line 1)
  4846. (move-to-column column)
  4847. (forward-char 1)
  4848. (throw 'end (point)))
  4849. ((looking-at intersection-str)
  4850. (throw 'retry-vertical nil))
  4851. (t (throw 'retry-horizontal nil)))))))))))))
  4852. (defun table--probe-cell-right-bottom ()
  4853. "Probe right bottom corner pattern of a cell.
  4854. If it finds a valid corner returns a position otherwise returns nil.
  4855. The position is the location after the last cell character.
  4856. Focus only on the corner pattern. Further cell validity check is required."
  4857. (save-excursion
  4858. (let ((vertical-str (regexp-quote (char-to-string table-cell-vertical-char)))
  4859. (intersection-str (regexp-quote (char-to-string table-cell-intersection-char)))
  4860. (v-border (format "[%c%c]" table-cell-vertical-char table-cell-intersection-char))
  4861. (h-border (format "[%s%c]" table-cell-horizontal-chars table-cell-intersection-char))
  4862. (limit (line-end-position)))
  4863. (catch 'end
  4864. (while t
  4865. (catch 'retry-horizontal
  4866. (if (not (search-forward-regexp v-border limit t))
  4867. (throw 'end nil))
  4868. (save-excursion
  4869. (forward-char -1)
  4870. (let ((column (current-column)))
  4871. (while t
  4872. (catch 'retry-vertical
  4873. (while (and (looking-at vertical-str)
  4874. (= column (current-column)))
  4875. (if (and (zerop (forward-line 1)) (zerop (current-column))) nil (throw 'end nil))
  4876. (move-to-column column))
  4877. (cond
  4878. ((/= column (current-column))
  4879. (throw 'end nil))
  4880. ((save-excursion (forward-char -1) (looking-at (concat h-border intersection-str)))
  4881. (save-excursion
  4882. (and (zerop (forward-line -1))
  4883. (move-to-column column)
  4884. (looking-at v-border)
  4885. (throw 'end (point))))
  4886. (forward-char 1)
  4887. (throw 'retry-horizontal nil))
  4888. ((looking-at intersection-str)
  4889. (if (and (zerop (forward-line 1)) (zerop (current-column))) nil (throw 'end nil))
  4890. (move-to-column column)
  4891. (throw 'retry-vertical nil))
  4892. (t (throw 'retry-horizontal nil)))))))))))))
  4893. (defun table--editable-cell-p (&optional abort-on-error)
  4894. (and (not buffer-read-only)
  4895. (get-text-property (point) 'table-cell)))
  4896. (defun table--probe-cell (&optional abort-on-error)
  4897. "Probes a table cell around the point.
  4898. Searches for the left upper corner and the right bottom corner of a table
  4899. cell which contains the current point location.
  4900. The result is a cons cell (left-upper . right-bottom) where
  4901. the left-upper is the position before the cell's left upper corner character,
  4902. the right-bottom is the position after the cell's right bottom corner character.
  4903. When it fails to find either one of the cell corners it returns nil or
  4904. signals error if the optional ABORT-ON-ERROR is non-nil."
  4905. (let (lu rb
  4906. (border (format "^[%s%c%c]+$"
  4907. table-cell-horizontal-chars
  4908. table-cell-vertical-char
  4909. table-cell-intersection-char)))
  4910. (if (and (condition-case nil
  4911. (progn
  4912. (and (setq lu (table--probe-cell-left-up))
  4913. (setq rb (table--probe-cell-right-bottom))))
  4914. (error nil))
  4915. (< lu rb)
  4916. (let ((lu-coordinate (table--get-coordinate lu))
  4917. (rb-coordinate (table--get-coordinate rb)))
  4918. ;; test for valid upper and lower borders
  4919. (and (string-match
  4920. border
  4921. (buffer-substring
  4922. (save-excursion
  4923. (table--goto-coordinate
  4924. (cons (1- (car lu-coordinate))
  4925. (1- (cdr lu-coordinate)))))
  4926. (save-excursion
  4927. (table--goto-coordinate
  4928. (cons (1+ (car rb-coordinate))
  4929. (1- (cdr lu-coordinate)))))))
  4930. (string-match
  4931. border
  4932. (buffer-substring
  4933. (save-excursion
  4934. (table--goto-coordinate
  4935. (cons (1- (car lu-coordinate))
  4936. (1+ (cdr rb-coordinate)))))
  4937. (save-excursion
  4938. (table--goto-coordinate
  4939. (cons (1+ (car rb-coordinate))
  4940. (1+ (cdr rb-coordinate))))))))))
  4941. (cons lu rb)
  4942. (if abort-on-error
  4943. (error "Table cell not found")
  4944. nil))))
  4945. (defun table--insert-rectangle (rectangle)
  4946. "Insert text of RECTANGLE with upper left corner at point.
  4947. Same as insert-rectangle except that mark operation is eliminated."
  4948. (let ((lines rectangle)
  4949. (insertcolumn (current-column))
  4950. (first t))
  4951. (while lines
  4952. (or first
  4953. (progn
  4954. (forward-line 1)
  4955. (or (bolp) (insert ?\n))
  4956. (move-to-column insertcolumn t)))
  4957. (setq first nil)
  4958. (insert (car lines))
  4959. (setq lines (cdr lines)))))
  4960. (defun table--put-cell-property (cell)
  4961. "Put standard text properties to the CELL.
  4962. The CELL is a cons cell (left-upper . right-bottom) where the
  4963. left-upper is the position before the cell's left upper corner
  4964. character, the right-bottom is the position after the cell's right
  4965. bottom corner character."
  4966. (let ((lu (table--get-coordinate (car cell)))
  4967. (rb (table--get-coordinate (cdr cell))))
  4968. (save-excursion
  4969. (while (<= (cdr lu) (cdr rb))
  4970. (let ((beg (table--goto-coordinate lu 'no-extension))
  4971. (end (table--goto-coordinate (cons (car rb) (cdr lu)))))
  4972. (table--put-cell-line-property beg end))
  4973. (setcdr lu (1+ (cdr lu))))
  4974. (table--put-cell-justify-property cell table-cell-info-justify)
  4975. (table--put-cell-valign-property cell table-cell-info-valign))))
  4976. (defun table--put-cell-line-property (beg end &optional object)
  4977. "Put standard text properties to a line of a cell.
  4978. BEG is the beginning of the line that is the location between left
  4979. cell border character and the first content character. END is the end
  4980. of the line that is the location between the last content character
  4981. and the right cell border character."
  4982. (table--put-cell-content-property beg end object)
  4983. (table--put-cell-keymap-property end (1+ end) object)
  4984. (table--put-cell-indicator-property end (1+ end) object)
  4985. (table--put-cell-rear-nonsticky end (1+ end) object))
  4986. (defun table--put-cell-content-property (beg end &optional object)
  4987. "Put cell content text properties."
  4988. (table--put-cell-keymap-property beg end object)
  4989. (table--put-cell-indicator-property beg end object)
  4990. (table--put-cell-face-property beg end object)
  4991. (table--put-cell-point-entered/left-property beg end object))
  4992. (defun table--put-cell-indicator-property (beg end &optional object)
  4993. "Put cell property which indicates that the location is within a table cell."
  4994. (put-text-property beg end 'table-cell t object)
  4995. (put-text-property beg end 'yank-handler table-yank-handler object))
  4996. (defun table--put-cell-face-property (beg end &optional object)
  4997. "Put cell face property."
  4998. (put-text-property beg end 'face 'table-cell object))
  4999. (defun table--put-cell-keymap-property (beg end &optional object)
  5000. "Put cell keymap property."
  5001. (put-text-property beg end 'keymap 'table-cell-map object))
  5002. (defun table--put-cell-rear-nonsticky (beg end &optional object)
  5003. "Put rear-nonsticky property."
  5004. (put-text-property beg end 'rear-nonsticky t object))
  5005. (defun table--put-cell-point-entered/left-property (beg end &optional object)
  5006. "Put point-entered/left property."
  5007. (put-text-property beg end 'point-entered 'table--point-entered-cell-function object)
  5008. (put-text-property beg end 'point-left 'table--point-left-cell-function object))
  5009. (defun table--remove-cell-properties (beg end &optional object)
  5010. "Remove all cell properties.
  5011. If OBJECT is non-nil cell properties are removed from the OBJECT
  5012. instead of the current buffer and returns the OBJECT."
  5013. (while (< beg end)
  5014. (let ((next (next-single-property-change beg 'table-cell object end)))
  5015. (if (get-text-property beg 'table-cell object)
  5016. (remove-text-properties beg next
  5017. (list
  5018. 'table-cell nil
  5019. 'table-justify nil
  5020. 'table-valign nil
  5021. 'face nil
  5022. 'rear-nonsticky nil
  5023. 'point-entered nil
  5024. 'point-left nil
  5025. 'keymap nil)
  5026. object))
  5027. (setq beg next)))
  5028. object)
  5029. (defun table--update-cell-face ()
  5030. "Update cell face according to the current mode."
  5031. (if (featurep 'xemacs)
  5032. (set-face-property 'table-cell 'underline table-fixed-width-mode)
  5033. (set-face-inverse-video-p 'table-cell table-fixed-width-mode)))
  5034. (table--update-cell-face)
  5035. (defun table--get-property (cell property)
  5036. "Get CELL's PROPERTY."
  5037. (or (get-text-property (car cell) property)
  5038. (get-text-property (1- (cdr cell)) property)))
  5039. (defun table--get-cell-justify-property (cell)
  5040. "Get cell's justify property."
  5041. (table--get-property cell 'table-justify))
  5042. (defun table--get-cell-valign-property (cell)
  5043. "Get cell's vertical alignment property."
  5044. (table--get-property cell 'table-valign))
  5045. (defun table--put-property (cell property value)
  5046. "Put CELL's PROPERTY the VALUE."
  5047. (let ((beg (car cell))
  5048. (end (cdr cell)))
  5049. (put-text-property beg (1+ beg) property value)
  5050. (put-text-property (1- end) end property value)))
  5051. (defun table--put-cell-justify-property (cell justify)
  5052. "Put cell's justify property."
  5053. (table--put-property cell 'table-justify justify))
  5054. (defun table--put-cell-valign-property (cell valign)
  5055. "Put cell's vertical alignment property."
  5056. (table--put-property cell 'table-valign valign))
  5057. (defun table--point-entered-cell-function (&optional old-point new-point)
  5058. "Point has entered a cell.
  5059. Refresh the menu bar."
  5060. ;; Avoid calling point-motion-hooks recursively.
  5061. (let ((inhibit-point-motion-hooks t))
  5062. (unless table-cell-entered-state
  5063. (setq table-cell-entered-state t)
  5064. (setq table-mode-indicator t)
  5065. (force-mode-line-update)
  5066. (table--warn-incompatibility)
  5067. (run-hooks 'table-point-entered-cell-hook))))
  5068. (defun table--point-left-cell-function (&optional old-point new-point)
  5069. "Point has left a cell.
  5070. Refresh the menu bar."
  5071. ;; Avoid calling point-motion-hooks recursively.
  5072. (let ((inhibit-point-motion-hooks t))
  5073. (when table-cell-entered-state
  5074. (setq table-cell-entered-state nil)
  5075. (setq table-mode-indicator nil)
  5076. (force-mode-line-update)
  5077. (run-hooks 'table-point-left-cell-hook))))
  5078. (defun table--warn-incompatibility ()
  5079. "If called from interactive operation warn the know incompatibilities.
  5080. This feature is disabled when `table-disable-incompatibility-warning'
  5081. is non-nil. The warning is done only once per session for each item."
  5082. (unless (and table-disable-incompatibility-warning
  5083. (not (called-interactively-p 'interactive)))
  5084. (cond ((and (featurep 'xemacs)
  5085. (not (get 'table-disable-incompatibility-warning 'xemacs)))
  5086. (put 'table-disable-incompatibility-warning 'xemacs t)
  5087. (display-warning 'table
  5088. "
  5089. *** Warning ***
  5090. Table package mostly works fine under XEmacs, however, due to the
  5091. peculiar implementation of text property under XEmacs, cell splitting
  5092. and any undo operation of table exhibit some known strange problems,
  5093. such that a border characters dissolve into adjacent cells. Please be
  5094. aware of this.
  5095. "
  5096. :warning))
  5097. ((and (boundp 'flyspell-mode)
  5098. flyspell-mode
  5099. (not (get 'table-disable-incompatibility-warning 'flyspell)))
  5100. (put 'table-disable-incompatibility-warning 'flyspell t)
  5101. (display-warning 'table
  5102. "
  5103. *** Warning ***
  5104. Flyspell minor mode is known to be incompatible with this table
  5105. package. The flyspell version 1.5d at URL `http://kaolin.unice.fr/~serrano'
  5106. works better than the previous versions however not fully compatible.
  5107. "
  5108. :warning))
  5109. )))
  5110. (defun table--cell-blank-str (&optional n)
  5111. "Return blank table cell string of length N."
  5112. (let ((str (make-string (or n 1) ?\s)))
  5113. (table--put-cell-content-property 0 (length str) str)
  5114. str))
  5115. (defun table--remove-eol-spaces (beg end &optional bol force)
  5116. "Remove spaces at the end of each line in the BEG END region of the current buffer.
  5117. When optional BOL is non-nil spaces at the beginning of line are
  5118. removed. When optional FORCE is non-nil removal operation is enforced
  5119. even when point is within the removal area."
  5120. (if (> beg end)
  5121. (let ((tmp beg))
  5122. (setq beg end)
  5123. (setq end tmp)))
  5124. (let ((saved-point (point-marker))
  5125. (end-marker (copy-marker end)))
  5126. (save-excursion
  5127. (goto-char beg)
  5128. (while (if bol (re-search-forward "^\\( +\\)" end-marker t)
  5129. (re-search-forward "\\( +\\)$" end-marker t))
  5130. ;; avoid removal that causes the saved point to lose its location.
  5131. (if (and (null bol)
  5132. (<= (match-beginning 1) saved-point)
  5133. (<= saved-point (match-end 1))
  5134. (not force))
  5135. (delete-region saved-point (match-end 1))
  5136. (delete-region (match-beginning 1) (match-end 1)))))
  5137. (set-marker saved-point nil)
  5138. (set-marker end-marker nil)))
  5139. (defun table--fill-region (beg end &optional col justify)
  5140. "Fill paragraphs in table cell cache.
  5141. Current buffer must already be set to the cache buffer."
  5142. (let ((fill-column (or col table-cell-info-width))
  5143. (fill-prefix nil)
  5144. (enable-kinsoku nil)
  5145. (adaptive-fill-mode nil)
  5146. (marker-beg (copy-marker beg))
  5147. (marker-end (copy-marker end))
  5148. (marker-point (point-marker)))
  5149. (setq justify (or justify table-cell-info-justify))
  5150. (and justify
  5151. (not (eq justify 'left))
  5152. (not (featurep 'xemacs))
  5153. (set-marker-insertion-type marker-point t))
  5154. (table--remove-eol-spaces (point-min) (point-max))
  5155. (if table-fixed-width-mode
  5156. (table--fill-region-strictly marker-beg marker-end)
  5157. (let ((paragraph-start table-paragraph-start))
  5158. (fill-region marker-beg marker-end justify nil t)))
  5159. (goto-char marker-point)
  5160. (set-marker marker-beg nil)
  5161. (set-marker marker-end nil)
  5162. (set-marker marker-point nil)))
  5163. (defun table--fill-region-strictly (beg end)
  5164. "Fill region strictly so that no line exceeds fill-column.
  5165. When a word exceeds fill-column the word is chopped into pieces. The
  5166. chopped location is indicated with table-word-continuation-char."
  5167. (or (and (markerp beg) (markerp end))
  5168. (error "markerp"))
  5169. (if (< fill-column 2)
  5170. (setq fill-column 2))
  5171. ;; first remove all continuation characters.
  5172. (goto-char beg)
  5173. (while (re-search-forward (concat
  5174. (format "[^%c ]\\(" table-word-continuation-char)
  5175. (regexp-quote (char-to-string table-word-continuation-char))
  5176. "\\s +\\)")
  5177. end t)
  5178. (delete-region (match-beginning 1) (match-end 1)))
  5179. ;; then fill as normal
  5180. (let ((paragraph-start table-paragraph-start))
  5181. (fill-region beg end nil nil t))
  5182. ;; now fix up
  5183. (goto-char beg)
  5184. (while (let ((col (move-to-column fill-column t)))
  5185. (cond
  5186. ((and (<= col fill-column)
  5187. (looking-at " *$"))
  5188. (delete-region (match-beginning 0) (match-end 0))
  5189. (and (zerop (forward-line 1))
  5190. (< (point) end)))
  5191. (t (forward-char -1)
  5192. (insert-before-markers (if (equal (char-before) ?\s) ?\s table-word-continuation-char)
  5193. "\n")
  5194. t)))))
  5195. (defun table--goto-coordinate (coordinate &optional no-extension no-tab-expansion)
  5196. "Move point to the given COORDINATE and return the location.
  5197. When optional NO-EXTENSION is non-nil and the specified coordinate is
  5198. not reachable returns nil otherwise the blanks are added if necessary
  5199. to achieve the goal coordinate and returns the goal point. It
  5200. intentionally does not preserve the original point in case it fails
  5201. achieving the goal. When optional NO-TAB-EXPANSION is non-nil and the
  5202. goad happens to be in a tab character the tab is not expanded but the
  5203. goal ends at the beginning of tab."
  5204. (if (or (null coordinate)
  5205. (< (car coordinate) 0)
  5206. (< (cdr coordinate) 0)) nil
  5207. (goto-char (point-min))
  5208. (let ((x (car coordinate))
  5209. (more-lines (forward-line (cdr coordinate))))
  5210. (catch 'exit
  5211. (if (zerop (current-column)) nil
  5212. (if no-extension
  5213. (progn
  5214. (move-to-column x)
  5215. (throw 'exit nil))
  5216. (setq more-lines (1+ more-lines))))
  5217. (if (zerop more-lines) nil
  5218. (newline more-lines))
  5219. (if no-extension
  5220. (if (/= (move-to-column x) x)
  5221. (if (> (move-to-column x) x)
  5222. (if no-tab-expansion
  5223. (progn
  5224. (while (> (move-to-column x) x)
  5225. (setq x (1- x)))
  5226. (point))
  5227. (throw 'exit (move-to-column x t)))
  5228. (throw 'exit nil)))
  5229. (move-to-column x t))
  5230. (point)))))
  5231. (defun table--copy-coordinate (coord)
  5232. "Copy coordinate in a new cons cell."
  5233. (cons (car coord) (cdr coord)))
  5234. (defun table--get-coordinate (&optional where)
  5235. "Return the coordinate of point in current buffer.
  5236. When optional WHERE is given it returns the coordinate of that
  5237. location instead of point in the current buffer. It does not move the
  5238. point"
  5239. (save-excursion
  5240. (if where (goto-char where))
  5241. (cons (current-column)
  5242. (table--current-line))))
  5243. (defun table--current-line (&optional location)
  5244. "Return zero based line count of current line or if non-nil LOCATION line."
  5245. (save-excursion
  5246. (if location (goto-char location))
  5247. (beginning-of-line)
  5248. (count-lines (point-min) (point))))
  5249. (defun table--transcoord-table-to-cache (&optional coordinate)
  5250. "Transpose COORDINATE from table coordinate system to cache coordinate system.
  5251. When COORDINATE is omitted or nil the point in current buffer is assumed in place."
  5252. (table--offset-coordinate
  5253. (or coordinate (table--get-coordinate))
  5254. table-cell-info-lu-coordinate
  5255. 'negative))
  5256. (defun table--transcoord-cache-to-table (&optional coordinate)
  5257. "Transpose COORDINATE from cache coordinate system to table coordinate system.
  5258. When COORDINATE is omitted or nil the point in current buffer is assumed in place."
  5259. (table--offset-coordinate
  5260. (or coordinate (table--get-coordinate))
  5261. table-cell-info-lu-coordinate))
  5262. (defun table--offset-coordinate (coordinate offset &optional negative)
  5263. "Return the offset COORDINATE by OFFSET.
  5264. When optional NEGATIVE is non-nil offsetting direction is negative."
  5265. (cons (if negative (- (car coordinate) (car offset))
  5266. (+ (car coordinate) (car offset)))
  5267. (if negative (- (cdr coordinate) (cdr offset))
  5268. (+ (cdr coordinate) (cdr offset)))))
  5269. (defun table--char-in-str-at-column (str column)
  5270. "Return the character in STR at COLUMN location.
  5271. When COLUMN is out of range it returns null character."
  5272. (let ((idx (table--str-index-at-column str column)))
  5273. (if idx (aref str idx)
  5274. ?\0)))
  5275. (defun table--str-index-at-column (str column)
  5276. "Return the character index in STR that corresponds to COLUMN location.
  5277. It returns COLUMN unless STR contains some wide characters."
  5278. (let ((col 0)
  5279. (idx 0)
  5280. (len (length str)))
  5281. (while (and (< col column) (< idx len))
  5282. (setq col (+ col (char-width (aref str idx))))
  5283. (setq idx (1+ idx)))
  5284. (if (< idx len)
  5285. idx
  5286. nil)))
  5287. (defun table--set-timer (seconds func args)
  5288. "Generic wrapper for setting up a timer."
  5289. (if (featurep 'xemacs)
  5290. ;; the picky xemacs refuses to accept zero
  5291. (add-timeout (if (zerop seconds) 0.01 seconds) func args nil)
  5292. ;;(run-at-time seconds nil func args)))
  5293. ;; somehow run-at-time causes strange problem under Emacs 20.7
  5294. ;; this problem does not show up under Emacs 21.0.90
  5295. (run-with-idle-timer seconds nil func args)))
  5296. (defun table--cancel-timer (timer)
  5297. "Generic wrapper for canceling a timer."
  5298. (if (featurep 'xemacs)
  5299. (disable-timeout timer)
  5300. (cancel-timer timer)))
  5301. (defun table--get-last-command ()
  5302. "Generic wrapper for getting the real last command."
  5303. (if (boundp 'real-last-command)
  5304. real-last-command
  5305. last-command))
  5306. (run-hooks 'table-load-hook)
  5307. (provide 'table)
  5308. ;;; table.el ends here