TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

katedocument.cpp 129KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184
  1. /* This file is part of the KDE libraries
  2. Copyright (C) 2001-2004 Christoph Cullmann <cullmann@kde.org>
  3. Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
  4. Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License version 2 as published by the Free Software Foundation.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02111-13020, USA.
  16. */
  17. //BEGIN includes
  18. #include "katedocument.h"
  19. #include "katedocument.moc"
  20. #include "katekeyinterceptorfunctor.h"
  21. #include "katefactory.h"
  22. #include "katedialogs.h"
  23. #include "katehighlight.h"
  24. #include "kateview.h"
  25. #include "katesearch.h"
  26. #include "kateautoindent.h"
  27. #include "katetextline.h"
  28. #include "katedocumenthelpers.h"
  29. #include "kateprinter.h"
  30. #include "katelinerange.h"
  31. #include "katesupercursor.h"
  32. #include "katearbitraryhighlight.h"
  33. #include "katerenderer.h"
  34. #include "kateattribute.h"
  35. #include "kateconfig.h"
  36. #include "katefiletype.h"
  37. #include "kateschema.h"
  38. #include "katetemplatehandler.h"
  39. #include <tdetexteditor/plugin.h>
  40. #include <tdeio/job.h>
  41. #include <tdeio/netaccess.h>
  42. #include <tdeio/tdefileitem.h>
  43. #include <tdeparts/event.h>
  44. #include <tdelocale.h>
  45. #include <tdeglobal.h>
  46. #include <tdeapplication.h>
  47. #include <tdepopupmenu.h>
  48. #include <tdeconfig.h>
  49. #include <tdefiledialog.h>
  50. #include <tdemessagebox.h>
  51. #include <kstdaction.h>
  52. #include <kiconloader.h>
  53. #include <kxmlguifactory.h>
  54. #include <kdialogbase.h>
  55. #include <kdebug.h>
  56. #include <tdeglobalsettings.h>
  57. #include <klibloader.h>
  58. #include <kdirwatch.h>
  59. #include <twin.h>
  60. #include <kencodingfiledialog.h>
  61. #include <tdetempfile.h>
  62. #include <kmdcodec.h>
  63. #include <kstandarddirs.h>
  64. #include <tqtimer.h>
  65. #include <tqfile.h>
  66. #include <tqclipboard.h>
  67. #include <tqtextstream.h>
  68. #include <tqtextcodec.h>
  69. #include <tqmap.h>
  70. //END includes
  71. //BEGIN PRIVATE CLASSES
  72. class KatePartPluginItem
  73. {
  74. public:
  75. KTextEditor::Plugin *plugin;
  76. };
  77. //END PRIVATE CLASSES
  78. //BEGIN d'tor, c'tor
  79. //
  80. // KateDocument Constructor
  81. //
  82. KateDocument::KateDocument ( bool bSingleViewMode, bool bBrowserView,
  83. bool bReadOnly, TQWidget *parentWidget,
  84. const char *widgetName, TQObject *parent, const char *name)
  85. : Kate::Document(parent, name),
  86. m_plugins (KateFactory::self()->plugins().count()),
  87. m_undoDontMerge(false),
  88. m_undoIgnoreCancel(false),
  89. lastUndoGroupWhenSaved( 0 ),
  90. lastRedoGroupWhenSaved( 0 ),
  91. docWasSavedWhenUndoWasEmpty( true ),
  92. docWasSavedWhenRedoWasEmpty( true ),
  93. m_modOnHd (false),
  94. m_modOnHdReason (0),
  95. m_job (0),
  96. m_tempFile (0),
  97. m_tabInterceptor(0)
  98. {
  99. m_undoComplexMerge=false;
  100. m_isInUndo = false;
  101. // my dcop object
  102. setObjId ("KateDocument#"+documentDCOPSuffix());
  103. // tdetexteditor interfaces
  104. setBlockSelectionInterfaceDCOPSuffix (documentDCOPSuffix());
  105. setConfigInterfaceDCOPSuffix (documentDCOPSuffix());
  106. setConfigInterfaceExtensionDCOPSuffix (documentDCOPSuffix());
  107. setCursorInterfaceDCOPSuffix (documentDCOPSuffix());
  108. setEditInterfaceDCOPSuffix (documentDCOPSuffix());
  109. setEncodingInterfaceDCOPSuffix (documentDCOPSuffix());
  110. setHighlightingInterfaceDCOPSuffix (documentDCOPSuffix());
  111. setMarkInterfaceDCOPSuffix (documentDCOPSuffix());
  112. setMarkInterfaceExtensionDCOPSuffix (documentDCOPSuffix());
  113. setPrintInterfaceDCOPSuffix (documentDCOPSuffix());
  114. setSearchInterfaceDCOPSuffix (documentDCOPSuffix());
  115. setSelectionInterfaceDCOPSuffix (documentDCOPSuffix());
  116. setSelectionInterfaceExtDCOPSuffix (documentDCOPSuffix());
  117. setSessionConfigInterfaceDCOPSuffix (documentDCOPSuffix());
  118. setUndoInterfaceDCOPSuffix (documentDCOPSuffix());
  119. setWordWrapInterfaceDCOPSuffix (documentDCOPSuffix());
  120. // init local plugin array
  121. m_plugins.fill (0);
  122. // register doc at factory
  123. KateFactory::self()->registerDocument (this);
  124. m_reloading = false;
  125. m_loading = false;
  126. m_encodingSticky = false;
  127. m_buffer = new KateBuffer (this);
  128. // init the config object, be careful not to use it
  129. // until the initial readConfig() call is done
  130. m_config = new KateDocumentConfig (this);
  131. // init some more vars !
  132. m_activeView = 0L;
  133. hlSetByUser = false;
  134. m_fileType = -1;
  135. m_fileTypeSetByUser = false;
  136. setInstance( KateFactory::self()->instance() );
  137. editSessionNumber = 0;
  138. editIsRunning = false;
  139. m_editCurrentUndo = 0L;
  140. editWithUndo = false;
  141. m_docNameNumber = 0;
  142. m_bSingleViewMode = bSingleViewMode;
  143. m_bBrowserView = bBrowserView;
  144. m_bReadOnly = bReadOnly;
  145. m_marks.setAutoDelete( true );
  146. m_markPixmaps.setAutoDelete( true );
  147. m_markDescriptions.setAutoDelete( true );
  148. setMarksUserChangable( markType01 );
  149. m_undoMergeTimer = new TQTimer(this);
  150. connect(m_undoMergeTimer, TQT_SIGNAL(timeout()), TQT_SLOT(undoCancel()));
  151. clearMarks ();
  152. clearUndo ();
  153. clearRedo ();
  154. setModified (false);
  155. docWasSavedWhenUndoWasEmpty = true;
  156. // normal hl
  157. m_buffer->setHighlight (0);
  158. m_extension = new KateBrowserExtension( this );
  159. m_arbitraryHL = new KateArbitraryHighlight();
  160. m_indenter = KateAutoIndent::createIndenter ( this, 0 );
  161. m_indenter->updateConfig ();
  162. // some nice signals from the buffer
  163. connect(m_buffer, TQT_SIGNAL(tagLines(int,int)), this, TQT_SLOT(tagLines(int,int)));
  164. connect(m_buffer, TQT_SIGNAL(codeFoldingUpdated()),this,TQT_SIGNAL(codeFoldingUpdated()));
  165. // if the user changes the highlight with the dialog, notify the doc
  166. connect(KateHlManager::self(),TQT_SIGNAL(changed()),TQT_SLOT(internalHlChanged()));
  167. // signal for the arbitrary HL
  168. connect(m_arbitraryHL, TQT_SIGNAL(tagLines(KateView*, KateSuperRange*)), TQT_SLOT(tagArbitraryLines(KateView*, KateSuperRange*)));
  169. // signals for mod on hd
  170. connect( KateFactory::self()->dirWatch(), TQT_SIGNAL(dirty (const TQString &)),
  171. this, TQT_SLOT(slotModOnHdDirty (const TQString &)) );
  172. connect( KateFactory::self()->dirWatch(), TQT_SIGNAL(created (const TQString &)),
  173. this, TQT_SLOT(slotModOnHdCreated (const TQString &)) );
  174. connect( KateFactory::self()->dirWatch(), TQT_SIGNAL(deleted (const TQString &)),
  175. this, TQT_SLOT(slotModOnHdDeleted (const TQString &)) );
  176. // update doc name
  177. setDocName ("");
  178. // if single view mode, like in the konqui embedding, create a default view ;)
  179. if ( m_bSingleViewMode )
  180. {
  181. KTextEditor::View *view = createView( parentWidget, widgetName );
  182. insertChildClient( view );
  183. view->show();
  184. setWidget( view );
  185. }
  186. connect(this,TQT_SIGNAL(sigQueryClose(bool *, bool*)),this,TQT_SLOT(slotQueryClose_save(bool *, bool*)));
  187. m_isasking = 0;
  188. // plugins
  189. for (uint i=0; i<KateFactory::self()->plugins().count(); i++)
  190. {
  191. if (config()->plugin (i))
  192. loadPlugin (i);
  193. }
  194. }
  195. //
  196. // KateDocument Destructor
  197. //
  198. KateDocument::~KateDocument()
  199. {
  200. // remove file from dirwatch
  201. deactivateDirWatch ();
  202. if (!singleViewMode())
  203. {
  204. // clean up remaining views
  205. m_views.setAutoDelete( true );
  206. m_views.clear();
  207. }
  208. delete m_editCurrentUndo;
  209. delete m_arbitraryHL;
  210. // cleanup the undo items, very important, truee :/
  211. undoItems.setAutoDelete(true);
  212. undoItems.clear();
  213. // clean up plugins
  214. unloadAllPlugins ();
  215. delete m_config;
  216. delete m_indenter;
  217. KateFactory::self()->deregisterDocument (this);
  218. }
  219. //END
  220. //BEGIN Plugins
  221. void KateDocument::unloadAllPlugins ()
  222. {
  223. for (uint i=0; i<m_plugins.count(); i++)
  224. unloadPlugin (i);
  225. }
  226. void KateDocument::enableAllPluginsGUI (KateView *view)
  227. {
  228. for (uint i=0; i<m_plugins.count(); i++)
  229. enablePluginGUI (m_plugins[i], view);
  230. }
  231. void KateDocument::disableAllPluginsGUI (KateView *view)
  232. {
  233. for (uint i=0; i<m_plugins.count(); i++)
  234. disablePluginGUI (m_plugins[i], view);
  235. }
  236. void KateDocument::loadPlugin (uint pluginIndex)
  237. {
  238. if (m_plugins[pluginIndex]) return;
  239. m_plugins[pluginIndex] = KTextEditor::createPlugin (TQFile::encodeName((KateFactory::self()->plugins())[pluginIndex]->library()), this);
  240. enablePluginGUI (m_plugins[pluginIndex]);
  241. }
  242. void KateDocument::unloadPlugin (uint pluginIndex)
  243. {
  244. if (!m_plugins[pluginIndex]) return;
  245. disablePluginGUI (m_plugins[pluginIndex]);
  246. delete m_plugins[pluginIndex];
  247. m_plugins[pluginIndex] = 0L;
  248. }
  249. void KateDocument::enablePluginGUI (KTextEditor::Plugin *plugin, KateView *view)
  250. {
  251. if (!plugin) return;
  252. if (!KTextEditor::pluginViewInterface(plugin)) return;
  253. KXMLGUIFactory *factory = view->factory();
  254. if ( factory )
  255. factory->removeClient( view );
  256. KTextEditor::pluginViewInterface(plugin)->addView(view);
  257. if ( factory )
  258. factory->addClient( view );
  259. }
  260. void KateDocument::enablePluginGUI (KTextEditor::Plugin *plugin)
  261. {
  262. if (!plugin) return;
  263. if (!KTextEditor::pluginViewInterface(plugin)) return;
  264. for (uint i=0; i< m_views.count(); i++)
  265. enablePluginGUI (plugin, m_views.at(i));
  266. }
  267. void KateDocument::disablePluginGUI (KTextEditor::Plugin *plugin, KateView *view)
  268. {
  269. if (!plugin) return;
  270. if (!KTextEditor::pluginViewInterface(plugin)) return;
  271. KXMLGUIFactory *factory = view->factory();
  272. if ( factory )
  273. factory->removeClient( view );
  274. KTextEditor::pluginViewInterface( plugin )->removeView( view );
  275. if ( factory )
  276. factory->addClient( view );
  277. }
  278. void KateDocument::disablePluginGUI (KTextEditor::Plugin *plugin)
  279. {
  280. if (!plugin) return;
  281. if (!KTextEditor::pluginViewInterface(plugin)) return;
  282. for (uint i=0; i< m_views.count(); i++)
  283. disablePluginGUI (plugin, m_views.at(i));
  284. }
  285. //END
  286. //BEGIN KTextEditor::Document stuff
  287. KTextEditor::View *KateDocument::createView( TQWidget *parent, const char *name )
  288. {
  289. KateView* newView = new KateView( this, parent, name);
  290. connect(newView, TQT_SIGNAL(cursorPositionChanged()), TQT_SLOT(undoCancel()));
  291. if ( s_fileChangedDialogsActivated )
  292. connect( newView, TQT_SIGNAL(gotFocus( Kate::View * )), this, TQT_SLOT(slotModifiedOnDisk()) );
  293. return newView;
  294. }
  295. TQPtrList<KTextEditor::View> KateDocument::views () const
  296. {
  297. return m_textEditViews;
  298. }
  299. void KateDocument::setActiveView( KateView *view )
  300. {
  301. if ( m_activeView == view ) return;
  302. m_activeView = view;
  303. }
  304. //END
  305. //BEGIN KTextEditor::ConfigInterfaceExtension stuff
  306. uint KateDocument::configPages () const
  307. {
  308. return 10;
  309. }
  310. KTextEditor::ConfigPage *KateDocument::configPage (uint number, TQWidget *parent, const char * )
  311. {
  312. switch( number )
  313. {
  314. case 0:
  315. return new KateViewDefaultsConfig (parent);
  316. case 1:
  317. return new KateSchemaConfigPage (parent, this);
  318. case 2:
  319. return new KateSelectConfigTab (parent);
  320. case 3:
  321. return new KateEditConfigTab (parent);
  322. case 4:
  323. return new KateIndentConfigTab (parent);
  324. case 5:
  325. return new KateSaveConfigTab (parent);
  326. case 6:
  327. return new KateHlConfigPage (parent, this);
  328. case 7:
  329. return new KateFileTypeConfigTab (parent);
  330. case 8:
  331. return new KateEditKeyConfiguration (parent, this);
  332. case 9:
  333. return new KatePartPluginConfigPage (parent);
  334. default:
  335. return 0;
  336. }
  337. return 0;
  338. }
  339. TQString KateDocument::configPageName (uint number) const
  340. {
  341. switch( number )
  342. {
  343. case 0:
  344. return i18n ("Appearance");
  345. case 1:
  346. return i18n ("Fonts & Colors");
  347. case 2:
  348. return i18n ("Cursor & Selection");
  349. case 3:
  350. return i18n ("Editing");
  351. case 4:
  352. return i18n ("Indentation");
  353. case 5:
  354. return i18n("Open/Save");
  355. case 6:
  356. return i18n ("Highlighting");
  357. case 7:
  358. return i18n("Filetypes");
  359. case 8:
  360. return i18n ("Shortcuts");
  361. case 9:
  362. return i18n ("Plugins");
  363. default:
  364. return TQString ("");
  365. }
  366. return TQString ("");
  367. }
  368. TQString KateDocument::configPageFullName (uint number) const
  369. {
  370. switch( number )
  371. {
  372. case 0:
  373. return i18n("Appearance");
  374. case 1:
  375. return i18n ("Font & Color Schemas");
  376. case 2:
  377. return i18n ("Cursor & Selection Behavior");
  378. case 3:
  379. return i18n ("Editing Options");
  380. case 4:
  381. return i18n ("Indentation Rules");
  382. case 5:
  383. return i18n("File Opening & Saving");
  384. case 6:
  385. return i18n ("Highlighting Rules");
  386. case 7:
  387. return i18n("Filetype Specific Settings");
  388. case 8:
  389. return i18n ("Shortcuts Configuration");
  390. case 9:
  391. return i18n ("Plugin Manager");
  392. default:
  393. return TQString ("");
  394. }
  395. return TQString ("");
  396. }
  397. TQPixmap KateDocument::configPagePixmap (uint number, int size) const
  398. {
  399. switch( number )
  400. {
  401. case 0:
  402. return BarIcon("view_text",size);
  403. case 1:
  404. return BarIcon("colorize", size);
  405. case 2:
  406. return BarIcon("frame_edit", size);
  407. case 3:
  408. return BarIcon("edit", size);
  409. case 4:
  410. return BarIcon("rightjust", size);
  411. case 5:
  412. return BarIcon("filesave", size);
  413. case 6:
  414. return BarIcon("source", size);
  415. case 7:
  416. return BarIcon("edit", size);
  417. case 8:
  418. return BarIcon("key_enter", size);
  419. case 9:
  420. return BarIcon("connect_established", size);
  421. default:
  422. return BarIcon("edit", size);
  423. }
  424. return BarIcon("edit", size);
  425. }
  426. //END
  427. //BEGIN KTextEditor::EditInterface stuff
  428. TQString KateDocument::text() const
  429. {
  430. TQString s;
  431. for (uint i = 0; i < m_buffer->count(); i++)
  432. {
  433. KateTextLine::Ptr textLine = m_buffer->plainLine(i);
  434. if (textLine)
  435. {
  436. s.append (textLine->string());
  437. if ((i+1) < m_buffer->count())
  438. s.append('\n');
  439. }
  440. }
  441. return s;
  442. }
  443. TQString KateDocument::text ( uint startLine, uint startCol, uint endLine, uint endCol ) const
  444. {
  445. return text(startLine, startCol, endLine, endCol, false);
  446. }
  447. TQString KateDocument::text ( uint startLine, uint startCol, uint endLine, uint endCol, bool blockwise) const
  448. {
  449. if ( blockwise && (startCol > endCol) )
  450. return TQString ();
  451. TQString s;
  452. if (startLine == endLine)
  453. {
  454. if (startCol > endCol)
  455. return TQString ();
  456. KateTextLine::Ptr textLine = m_buffer->plainLine(startLine);
  457. if ( !textLine )
  458. return TQString ();
  459. return textLine->string(startCol, endCol-startCol);
  460. }
  461. else
  462. {
  463. for (uint i = startLine; (i <= endLine) && (i < m_buffer->count()); i++)
  464. {
  465. KateTextLine::Ptr textLine = m_buffer->plainLine(i);
  466. if ( !blockwise )
  467. {
  468. if (i == startLine)
  469. s.append (textLine->string(startCol, textLine->length()-startCol));
  470. else if (i == endLine)
  471. s.append (textLine->string(0, endCol));
  472. else
  473. s.append (textLine->string());
  474. }
  475. else
  476. {
  477. s.append( textLine->string( startCol, endCol-startCol));
  478. }
  479. if ( i < endLine )
  480. s.append('\n');
  481. }
  482. }
  483. return s;
  484. }
  485. TQString KateDocument::textLine( uint line ) const
  486. {
  487. KateTextLine::Ptr l = m_buffer->plainLine(line);
  488. if (!l)
  489. return TQString();
  490. return l->string();
  491. }
  492. bool KateDocument::setText(const TQString &s)
  493. {
  494. if (!isReadWrite())
  495. return false;
  496. TQPtrList<KTextEditor::Mark> m = marks ();
  497. TQValueList<KTextEditor::Mark> msave;
  498. for (uint i=0; i < m.count(); i++)
  499. msave.append (*m.at(i));
  500. editStart ();
  501. // delete the text
  502. clear();
  503. // insert the new text
  504. insertText (0, 0, s);
  505. editEnd ();
  506. for (uint i=0; i < msave.count(); i++)
  507. setMark (msave[i].line, msave[i].type);
  508. return true;
  509. }
  510. bool KateDocument::clear()
  511. {
  512. if (!isReadWrite())
  513. return false;
  514. for (KateView * view = m_views.first(); view != 0L; view = m_views.next() ) {
  515. view->clear();
  516. view->tagAll();
  517. view->update();
  518. }
  519. clearMarks ();
  520. return removeText (0,0,lastLine()+1, 0);
  521. }
  522. bool KateDocument::insertText( uint line, uint col, const TQString &s)
  523. {
  524. return insertText (line, col, s, false);
  525. }
  526. bool KateDocument::insertText( uint line, uint col, const TQString &s, bool blockwise )
  527. {
  528. if (!isReadWrite())
  529. return false;
  530. if (s.isEmpty())
  531. return true;
  532. if (line == numLines())
  533. editInsertLine(line,"");
  534. else if (line > lastLine())
  535. return false;
  536. editStart ();
  537. uint insertPos = col;
  538. uint len = s.length();
  539. TQString buf;
  540. bool replacetabs = ( config()->configFlags() & KateDocumentConfig::cfReplaceTabsDyn && ! m_isInUndo );
  541. uint tw = config()->tabWidth();
  542. uint insertPosExpanded = insertPos;
  543. KateTextLine::Ptr l = m_buffer->line( line );
  544. if (l != 0)
  545. insertPosExpanded = l->cursorX( insertPos, tw );
  546. for (uint pos = 0; pos < len; pos++)
  547. {
  548. TQChar ch = s[pos];
  549. if (ch == '\n')
  550. {
  551. editInsertText (line, insertPos, buf);
  552. if ( !blockwise )
  553. {
  554. editWrapLine (line, insertPos + buf.length());
  555. insertPos = insertPosExpanded = 0;
  556. }
  557. else
  558. {
  559. if ( line == lastLine() )
  560. editWrapLine (line, insertPos + buf.length());
  561. }
  562. line++;
  563. buf.truncate(0);
  564. l = m_buffer->line( line );
  565. if (l)
  566. insertPosExpanded = l->cursorX( insertPos, tw );
  567. }
  568. else
  569. {
  570. if ( replacetabs && ch == '\t' )
  571. {
  572. uint tr = tw - ( insertPosExpanded+buf.length() )%tw;
  573. for ( uint i=0; i < tr; i++ )
  574. buf += ' ';
  575. }
  576. else
  577. buf += ch; // append char to buffer
  578. }
  579. }
  580. editInsertText (line, insertPos, buf);
  581. editEnd ();
  582. emit textInserted(line,insertPos);
  583. return true;
  584. }
  585. bool KateDocument::removeText ( uint startLine, uint startCol, uint endLine, uint endCol )
  586. {
  587. return removeText (startLine, startCol, endLine, endCol, false);
  588. }
  589. bool KateDocument::removeText ( uint startLine, uint startCol, uint endLine, uint endCol, bool blockwise)
  590. {
  591. if (!isReadWrite())
  592. return false;
  593. if ( blockwise && (startCol > endCol) )
  594. return false;
  595. if ( startLine > endLine )
  596. return false;
  597. if ( startLine > lastLine() )
  598. return false;
  599. if (!blockwise) {
  600. emit aboutToRemoveText(KateTextRange(startLine,startCol,endLine,endCol));
  601. }
  602. editStart ();
  603. if ( !blockwise )
  604. {
  605. if ( endLine > lastLine() )
  606. {
  607. endLine = lastLine()+1;
  608. endCol = 0;
  609. }
  610. if (startLine == endLine)
  611. {
  612. editRemoveText (startLine, startCol, endCol-startCol);
  613. }
  614. else if ((startLine+1) == endLine)
  615. {
  616. if ( (m_buffer->plainLine(startLine)->length()-startCol) > 0 )
  617. editRemoveText (startLine, startCol, m_buffer->plainLine(startLine)->length()-startCol);
  618. editRemoveText (startLine+1, 0, endCol);
  619. editUnWrapLine (startLine);
  620. }
  621. else
  622. {
  623. for (uint line = endLine; line >= startLine; line--)
  624. {
  625. if ((line > startLine) && (line < endLine))
  626. {
  627. editRemoveLine (line);
  628. }
  629. else
  630. {
  631. if (line == endLine)
  632. {
  633. if ( endLine <= lastLine() )
  634. editRemoveText (line, 0, endCol);
  635. }
  636. else
  637. {
  638. if ( (m_buffer->plainLine(line)->length()-startCol) > 0 )
  639. editRemoveText (line, startCol, m_buffer->plainLine(line)->length()-startCol);
  640. editUnWrapLine (startLine);
  641. }
  642. }
  643. if ( line == 0 )
  644. break;
  645. }
  646. }
  647. } // if ( ! blockwise )
  648. else
  649. {
  650. if ( endLine > lastLine() )
  651. endLine = lastLine ();
  652. for (uint line = endLine; line >= startLine; line--)
  653. {
  654. editRemoveText (line, startCol, endCol-startCol);
  655. if ( line == 0 )
  656. break;
  657. }
  658. }
  659. editEnd ();
  660. emit textRemoved();
  661. return true;
  662. }
  663. bool KateDocument::insertLine( uint l, const TQString &str )
  664. {
  665. if (!isReadWrite())
  666. return false;
  667. if (l > numLines())
  668. return false;
  669. return editInsertLine (l, str);
  670. }
  671. bool KateDocument::removeLine( uint line )
  672. {
  673. if (!isReadWrite())
  674. return false;
  675. if (line > lastLine())
  676. return false;
  677. return editRemoveLine (line);
  678. }
  679. uint KateDocument::length() const
  680. {
  681. uint l = 0;
  682. for (uint i = 0; i < m_buffer->count(); i++)
  683. {
  684. KateTextLine::Ptr line = m_buffer->plainLine(i);
  685. if (line)
  686. l += line->length();
  687. }
  688. return l;
  689. }
  690. uint KateDocument::numLines() const
  691. {
  692. return m_buffer->count();
  693. }
  694. uint KateDocument::numVisLines() const
  695. {
  696. return m_buffer->countVisible ();
  697. }
  698. int KateDocument::lineLength ( uint line ) const
  699. {
  700. KateTextLine::Ptr l = m_buffer->plainLine(line);
  701. if (!l)
  702. return -1;
  703. return l->length();
  704. }
  705. //END
  706. //BEGIN KTextEditor::EditInterface internal stuff
  707. //
  708. // Starts an edit session with (or without) undo, update of view disabled during session
  709. //
  710. void KateDocument::editStart (bool withUndo)
  711. {
  712. editSessionNumber++;
  713. if (editSessionNumber > 1)
  714. return;
  715. editIsRunning = true;
  716. editWithUndo = withUndo;
  717. if (editWithUndo)
  718. undoStart();
  719. else
  720. undoCancel();
  721. for (uint z = 0; z < m_views.count(); z++)
  722. {
  723. m_views.at(z)->editStart ();
  724. }
  725. m_buffer->editStart ();
  726. }
  727. void KateDocument::undoStart()
  728. {
  729. if (m_editCurrentUndo || (m_activeView && m_activeView->imComposeEvent())) return;
  730. // Make sure the buffer doesn't get bigger than requested
  731. if ((config()->undoSteps() > 0) && (undoItems.count() > config()->undoSteps()))
  732. {
  733. undoItems.setAutoDelete(true);
  734. undoItems.removeFirst();
  735. undoItems.setAutoDelete(false);
  736. docWasSavedWhenUndoWasEmpty = false;
  737. }
  738. // new current undo item
  739. m_editCurrentUndo = new KateUndoGroup(this);
  740. }
  741. void KateDocument::undoEnd()
  742. {
  743. if (m_activeView && m_activeView->imComposeEvent())
  744. return;
  745. if (m_editCurrentUndo)
  746. {
  747. bool changedUndo = false;
  748. if (m_editCurrentUndo->isEmpty())
  749. delete m_editCurrentUndo;
  750. else if (!m_undoDontMerge && undoItems.last() && undoItems.last()->merge(m_editCurrentUndo,m_undoComplexMerge))
  751. delete m_editCurrentUndo;
  752. else
  753. {
  754. undoItems.append(m_editCurrentUndo);
  755. changedUndo = true;
  756. }
  757. m_undoDontMerge = false;
  758. m_undoIgnoreCancel = true;
  759. m_editCurrentUndo = 0L;
  760. // (Re)Start the single-shot timer to cancel the undo merge
  761. // the user has 5 seconds to input more data, or undo merging gets canceled for the current undo item.
  762. m_undoMergeTimer->start(5000, true);
  763. if (changedUndo)
  764. emit undoChanged();
  765. }
  766. }
  767. void KateDocument::undoCancel()
  768. {
  769. if (m_undoIgnoreCancel) {
  770. m_undoIgnoreCancel = false;
  771. return;
  772. }
  773. m_undoDontMerge = true;
  774. Q_ASSERT(!m_editCurrentUndo);
  775. // As you can see by the above assert, neither of these should really be required
  776. delete m_editCurrentUndo;
  777. m_editCurrentUndo = 0L;
  778. }
  779. void KateDocument::undoSafePoint() {
  780. Q_ASSERT(m_editCurrentUndo);
  781. if (!m_editCurrentUndo) return;
  782. m_editCurrentUndo->safePoint();
  783. }
  784. //
  785. // End edit session and update Views
  786. //
  787. void KateDocument::editEnd ()
  788. {
  789. if (editSessionNumber == 0)
  790. return;
  791. // wrap the new/changed text, if something really changed!
  792. if (m_buffer->editChanged() && (editSessionNumber == 1))
  793. if (editWithUndo && config()->wordWrap())
  794. wrapText (m_buffer->editTagStart(), m_buffer->editTagEnd());
  795. editSessionNumber--;
  796. if (editSessionNumber > 0)
  797. return;
  798. // end buffer edit, will trigger hl update
  799. // this will cause some possible adjustment of tagline start/end
  800. m_buffer->editEnd ();
  801. if (editWithUndo)
  802. undoEnd();
  803. // edit end for all views !!!!!!!!!
  804. for (uint z = 0; z < m_views.count(); z++)
  805. m_views.at(z)->editEnd (m_buffer->editTagStart(), m_buffer->editTagEnd(), m_buffer->editTagFrom());
  806. if (m_buffer->editChanged())
  807. {
  808. setModified(true);
  809. emit textChanged ();
  810. }
  811. editIsRunning = false;
  812. }
  813. bool KateDocument::wrapText (uint startLine, uint endLine)
  814. {
  815. uint col = config()->wordWrapAt();
  816. if (col == 0)
  817. return false;
  818. editStart ();
  819. for (uint line = startLine; (line <= endLine) && (line < numLines()); line++)
  820. {
  821. KateTextLine::Ptr l = m_buffer->line(line);
  822. if (!l)
  823. return false;
  824. kdDebug (13020) << "try wrap line: " << line << endl;
  825. if (l->lengthWithTabs(m_buffer->tabWidth()) > col)
  826. {
  827. KateTextLine::Ptr nextl = m_buffer->line(line+1);
  828. kdDebug (13020) << "do wrap line: " << line << endl;
  829. const TQChar *text = l->text();
  830. uint eolPosition = l->length()-1;
  831. // take tabs into account here, too
  832. uint x = 0;
  833. const TQString & t = l->string();
  834. uint z2 = 0;
  835. for ( ; z2 < l->length(); z2++)
  836. {
  837. if (t[z2] == TQChar('\t'))
  838. x += m_buffer->tabWidth() - (x % m_buffer->tabWidth());
  839. else
  840. x++;
  841. if (x > col)
  842. break;
  843. }
  844. uint searchStart = kMin (z2, l->length()-1);
  845. // If where we are wrapping is an end of line and is a space we don't
  846. // want to wrap there
  847. if (searchStart == eolPosition && text[searchStart].isSpace())
  848. searchStart--;
  849. // Scan backwards looking for a place to break the line
  850. // We are not interested in breaking at the first char
  851. // of the line (if it is a space), but we are at the second
  852. // anders: if we can't find a space, try breaking on a word
  853. // boundry, using KateHighlight::canBreakAt().
  854. // This could be a priority (setting) in the hl/filetype/document
  855. int z = 0;
  856. uint nw = 0; // alternative position, a non word character
  857. for (z=searchStart; z > 0; z--)
  858. {
  859. if (text[z].isSpace()) break;
  860. if ( ! nw && highlight()->canBreakAt( text[z] , l->attribute(z) ) )
  861. nw = z;
  862. }
  863. if (z > 0)
  864. {
  865. // cu space
  866. editRemoveText (line, z, 1);
  867. }
  868. else
  869. {
  870. // There was no space to break at so break at a nonword character if
  871. // found, or at the wrapcolumn ( that needs be configurable )
  872. // Don't try and add any white space for the break
  873. if ( nw && nw < col ) nw++; // break on the right side of the character
  874. z = nw ? nw : col;
  875. }
  876. if (nextl && !nextl->isAutoWrapped())
  877. {
  878. editWrapLine (line, z, true);
  879. editMarkLineAutoWrapped (line+1, true);
  880. endLine++;
  881. }
  882. else
  883. {
  884. if (nextl && (nextl->length() > 0) && !nextl->getChar(0).isSpace() && ((l->length() < 1) || !l->getChar(l->length()-1).isSpace()))
  885. editInsertText (line+1, 0, TQString (" "));
  886. bool newLineAdded = false;
  887. editWrapLine (line, z, false, &newLineAdded);
  888. editMarkLineAutoWrapped (line+1, true);
  889. endLine++;
  890. }
  891. }
  892. }
  893. editEnd ();
  894. return true;
  895. }
  896. void KateDocument::editAddUndo (KateUndoGroup::UndoType type, uint line, uint col, uint len, const TQString &text)
  897. {
  898. if (editIsRunning && editWithUndo && m_editCurrentUndo) {
  899. m_editCurrentUndo->addItem(type, line, col, len, text);
  900. // Clear redo buffer
  901. if (redoItems.count()) {
  902. redoItems.setAutoDelete(true);
  903. redoItems.clear();
  904. redoItems.setAutoDelete(false);
  905. }
  906. }
  907. }
  908. bool KateDocument::editInsertText ( uint line, uint col, const TQString &str )
  909. {
  910. if (!isReadWrite())
  911. return false;
  912. TQString s = str;
  913. KateTextLine::Ptr l = m_buffer->line(line);
  914. if (!l)
  915. return false;
  916. if ( config()->configFlags() & KateDocumentConfig::cfReplaceTabsDyn && ! m_isInUndo )
  917. {
  918. uint tw = config()->tabWidth();
  919. int pos = 0;
  920. uint l = 0;
  921. while ( (pos = s.find('\t')) > -1 )
  922. {
  923. l = tw - ( (col + pos)%tw );
  924. s.replace( pos, 1, TQString().fill( ' ', l ) );
  925. }
  926. }
  927. editStart ();
  928. editAddUndo (KateUndoGroup::editInsertText, line, col, s.length(), s);
  929. l->insertText (col, s.length(), s.unicode());
  930. // removeTrailingSpace(line); // ### nessecary?
  931. m_buffer->changeLine(line);
  932. for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
  933. it.current()->editTextInserted (line, col, s.length());
  934. editEnd ();
  935. return true;
  936. }
  937. bool KateDocument::editRemoveText ( uint line, uint col, uint len )
  938. {
  939. if (!isReadWrite())
  940. return false;
  941. KateTextLine::Ptr l = m_buffer->line(line);
  942. if (!l)
  943. return false;
  944. editStart ();
  945. editAddUndo (KateUndoGroup::editRemoveText, line, col, len, l->string().mid(col, len));
  946. l->removeText (col, len);
  947. removeTrailingSpace( line );
  948. m_buffer->changeLine(line);
  949. for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
  950. it.current()->editTextRemoved (line, col, len);
  951. editEnd ();
  952. return true;
  953. }
  954. bool KateDocument::editMarkLineAutoWrapped ( uint line, bool autowrapped )
  955. {
  956. if (!isReadWrite())
  957. return false;
  958. KateTextLine::Ptr l = m_buffer->line(line);
  959. if (!l)
  960. return false;
  961. editStart ();
  962. editAddUndo (KateUndoGroup::editMarkLineAutoWrapped, line, autowrapped ? 1 : 0, 0, TQString::null);
  963. l->setAutoWrapped (autowrapped);
  964. m_buffer->changeLine(line);
  965. editEnd ();
  966. return true;
  967. }
  968. bool KateDocument::editWrapLine ( uint line, uint col, bool newLine, bool *newLineAdded)
  969. {
  970. if (!isReadWrite())
  971. return false;
  972. KateTextLine::Ptr l = m_buffer->line(line);
  973. if (!l)
  974. return false;
  975. editStart ();
  976. KateTextLine::Ptr nextLine = m_buffer->line(line+1);
  977. int pos = l->length() - col;
  978. if (pos < 0)
  979. pos = 0;
  980. editAddUndo (KateUndoGroup::editWrapLine, line, col, pos, (!nextLine || newLine) ? "1" : "0");
  981. if (!nextLine || newLine)
  982. {
  983. KateTextLine::Ptr textLine = new KateTextLine();
  984. textLine->insertText (0, pos, l->text()+col, l->attributes()+col);
  985. l->truncate(col);
  986. m_buffer->insertLine (line+1, textLine);
  987. m_buffer->changeLine(line);
  988. TQPtrList<KTextEditor::Mark> list;
  989. for( TQIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
  990. {
  991. if( it.current()->line >= line )
  992. {
  993. if ((col == 0) || (it.current()->line > line))
  994. list.append( it.current() );
  995. }
  996. }
  997. for( TQPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
  998. {
  999. KTextEditor::Mark* mark = m_marks.take( it.current()->line );
  1000. mark->line++;
  1001. m_marks.insert( mark->line, mark );
  1002. }
  1003. if( !list.isEmpty() )
  1004. emit marksChanged();
  1005. // yes, we added a new line !
  1006. if (newLineAdded)
  1007. (*newLineAdded) = true;
  1008. }
  1009. else
  1010. {
  1011. nextLine->insertText (0, pos, l->text()+col, l->attributes()+col);
  1012. l->truncate(col);
  1013. m_buffer->changeLine(line);
  1014. m_buffer->changeLine(line+1);
  1015. // no, no new line added !
  1016. if (newLineAdded)
  1017. (*newLineAdded) = false;
  1018. }
  1019. for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
  1020. it.current()->editLineWrapped (line, col, !nextLine || newLine);
  1021. editEnd ();
  1022. return true;
  1023. }
  1024. bool KateDocument::editUnWrapLine ( uint line, bool removeLine, uint length )
  1025. {
  1026. if (!isReadWrite())
  1027. return false;
  1028. KateTextLine::Ptr l = m_buffer->line(line);
  1029. KateTextLine::Ptr nextLine = m_buffer->line(line+1);
  1030. if (!l || !nextLine)
  1031. return false;
  1032. editStart ();
  1033. uint col = l->length ();
  1034. editAddUndo (KateUndoGroup::editUnWrapLine, line, col, length, removeLine ? "1" : "0");
  1035. if (removeLine)
  1036. {
  1037. l->insertText (col, nextLine->length(), nextLine->text(), nextLine->attributes());
  1038. m_buffer->changeLine(line);
  1039. m_buffer->removeLine(line+1);
  1040. }
  1041. else
  1042. {
  1043. l->insertText (col, (nextLine->length() < length) ? nextLine->length() : length,
  1044. nextLine->text(), nextLine->attributes());
  1045. nextLine->removeText (0, (nextLine->length() < length) ? nextLine->length() : length);
  1046. m_buffer->changeLine(line);
  1047. m_buffer->changeLine(line+1);
  1048. }
  1049. TQPtrList<KTextEditor::Mark> list;
  1050. for( TQIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
  1051. {
  1052. if( it.current()->line >= line+1 )
  1053. list.append( it.current() );
  1054. if ( it.current()->line == line+1 )
  1055. {
  1056. KTextEditor::Mark* mark = m_marks.take( line );
  1057. if (mark)
  1058. {
  1059. it.current()->type |= mark->type;
  1060. }
  1061. }
  1062. }
  1063. for( TQPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
  1064. {
  1065. KTextEditor::Mark* mark = m_marks.take( it.current()->line );
  1066. mark->line--;
  1067. m_marks.insert( mark->line, mark );
  1068. }
  1069. if( !list.isEmpty() )
  1070. emit marksChanged();
  1071. for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
  1072. it.current()->editLineUnWrapped (line, col, removeLine, length);
  1073. editEnd ();
  1074. return true;
  1075. }
  1076. bool KateDocument::editInsertLine ( uint line, const TQString &s )
  1077. {
  1078. if (!isReadWrite())
  1079. return false;
  1080. if ( line > numLines() )
  1081. return false;
  1082. editStart ();
  1083. editAddUndo (KateUndoGroup::editInsertLine, line, 0, s.length(), s);
  1084. removeTrailingSpace( line ); // old line
  1085. KateTextLine::Ptr tl = new KateTextLine();
  1086. tl->insertText (0, s.length(), s.unicode(), 0);
  1087. m_buffer->insertLine(line, tl);
  1088. m_buffer->changeLine(line);
  1089. removeTrailingSpace( line ); // new line
  1090. TQPtrList<KTextEditor::Mark> list;
  1091. for( TQIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
  1092. {
  1093. if( it.current()->line >= line )
  1094. list.append( it.current() );
  1095. }
  1096. for( TQPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
  1097. {
  1098. KTextEditor::Mark* mark = m_marks.take( it.current()->line );
  1099. mark->line++;
  1100. m_marks.insert( mark->line, mark );
  1101. }
  1102. if( !list.isEmpty() )
  1103. emit marksChanged();
  1104. for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
  1105. it.current()->editLineInserted (line);
  1106. editEnd ();
  1107. return true;
  1108. }
  1109. bool KateDocument::editRemoveLine ( uint line )
  1110. {
  1111. if (!isReadWrite())
  1112. return false;
  1113. if ( line > lastLine() )
  1114. return false;
  1115. if ( numLines() == 1 )
  1116. return editRemoveText (0, 0, m_buffer->line(0)->length());
  1117. editStart ();
  1118. editAddUndo (KateUndoGroup::editRemoveLine, line, 0, lineLength(line), textLine(line));
  1119. m_buffer->removeLine(line);
  1120. TQPtrList<KTextEditor::Mark> list;
  1121. KTextEditor::Mark* rmark = 0;
  1122. for( TQIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
  1123. {
  1124. if ( (it.current()->line > line) )
  1125. list.append( it.current() );
  1126. else if ( (it.current()->line == line) )
  1127. rmark = it.current();
  1128. }
  1129. if (rmark)
  1130. delete (m_marks.take (rmark->line));
  1131. for( TQPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
  1132. {
  1133. KTextEditor::Mark* mark = m_marks.take( it.current()->line );
  1134. mark->line--;
  1135. m_marks.insert( mark->line, mark );
  1136. }
  1137. if( !list.isEmpty() )
  1138. emit marksChanged();
  1139. for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
  1140. it.current()->editLineRemoved (line);
  1141. editEnd();
  1142. return true;
  1143. }
  1144. //END
  1145. //BEGIN KTextEditor::UndoInterface stuff
  1146. uint KateDocument::undoCount () const
  1147. {
  1148. return undoItems.count ();
  1149. }
  1150. uint KateDocument::redoCount () const
  1151. {
  1152. return redoItems.count ();
  1153. }
  1154. uint KateDocument::undoSteps () const
  1155. {
  1156. return m_config->undoSteps();
  1157. }
  1158. void KateDocument::setUndoSteps(uint steps)
  1159. {
  1160. m_config->setUndoSteps (steps);
  1161. }
  1162. void KateDocument::undo()
  1163. {
  1164. m_isInUndo = true;
  1165. if ((undoItems.count() > 0) && undoItems.last())
  1166. {
  1167. clearSelection ();
  1168. undoItems.last()->undo();
  1169. redoItems.append (undoItems.last());
  1170. undoItems.removeLast ();
  1171. updateModified();
  1172. emit undoChanged ();
  1173. }
  1174. m_isInUndo = false;
  1175. }
  1176. void KateDocument::redo()
  1177. {
  1178. m_isInUndo = true;
  1179. if ((redoItems.count() > 0) && redoItems.last())
  1180. {
  1181. clearSelection ();
  1182. redoItems.last()->redo();
  1183. undoItems.append (redoItems.last());
  1184. redoItems.removeLast ();
  1185. updateModified();
  1186. emit undoChanged ();
  1187. }
  1188. m_isInUndo = false;
  1189. }
  1190. void KateDocument::updateModified()
  1191. {
  1192. /*
  1193. How this works:
  1194. After noticing that there where to many scenarios to take into
  1195. consideration when using 'if's to toggle the "Modified" flag
  1196. I came up with this baby, flexible and repetitive calls are
  1197. minimal.
  1198. A numeric unique pattern is generated by toggleing a set of bits,
  1199. each bit symbolizes a different state in the Undo Redo structure.
  1200. undoItems.isEmpty() != null BIT 1
  1201. redoItems.isEmpty() != null BIT 2
  1202. docWasSavedWhenUndoWasEmpty == true BIT 3
  1203. docWasSavedWhenRedoWasEmpty == true BIT 4
  1204. lastUndoGroupWhenSavedIsLastUndo BIT 5
  1205. lastUndoGroupWhenSavedIsLastRedo BIT 6
  1206. lastRedoGroupWhenSavedIsLastUndo BIT 7
  1207. lastRedoGroupWhenSavedIsLastRedo BIT 8
  1208. If you find a new pattern, please add it to the patterns array
  1209. */
  1210. unsigned char currentPattern = 0;
  1211. const unsigned char patterns[] = {5,16,24,26,88,90,93,133,144,149,165};
  1212. const unsigned char patternCount = sizeof(patterns);
  1213. KateUndoGroup* undoLast = 0;
  1214. KateUndoGroup* redoLast = 0;
  1215. if (undoItems.isEmpty())
  1216. {
  1217. currentPattern |= 1;
  1218. }
  1219. else
  1220. {
  1221. undoLast = undoItems.last();
  1222. }
  1223. if (redoItems.isEmpty())
  1224. {
  1225. currentPattern |= 2;
  1226. }
  1227. else
  1228. {
  1229. redoLast = redoItems.last();
  1230. }
  1231. if (docWasSavedWhenUndoWasEmpty) currentPattern |= 4;
  1232. if (docWasSavedWhenRedoWasEmpty) currentPattern |= 8;
  1233. if (lastUndoGroupWhenSaved == undoLast) currentPattern |= 16;
  1234. if (lastUndoGroupWhenSaved == redoLast) currentPattern |= 32;
  1235. if (lastRedoGroupWhenSaved == undoLast) currentPattern |= 64;
  1236. if (lastRedoGroupWhenSaved == redoLast) currentPattern |= 128;
  1237. // This will print out the pattern information
  1238. kdDebug(13020) << k_funcinfo
  1239. << "Pattern:" << static_cast<unsigned int>(currentPattern) << endl;
  1240. for (uint patternIndex = 0; patternIndex < patternCount; ++patternIndex)
  1241. {
  1242. if ( currentPattern == patterns[patternIndex] )
  1243. {
  1244. setModified( false );
  1245. kdDebug(13020) << k_funcinfo << "setting modified to false!" << endl;
  1246. break;
  1247. }
  1248. }
  1249. }
  1250. void KateDocument::clearUndo()
  1251. {
  1252. undoItems.setAutoDelete (true);
  1253. undoItems.clear ();
  1254. undoItems.setAutoDelete (false);
  1255. lastUndoGroupWhenSaved = 0;
  1256. docWasSavedWhenUndoWasEmpty = false;
  1257. emit undoChanged ();
  1258. }
  1259. void KateDocument::clearRedo()
  1260. {
  1261. redoItems.setAutoDelete (true);
  1262. redoItems.clear ();
  1263. redoItems.setAutoDelete (false);
  1264. lastRedoGroupWhenSaved = 0;
  1265. docWasSavedWhenRedoWasEmpty = false;
  1266. emit undoChanged ();
  1267. }
  1268. TQPtrList<KTextEditor::Cursor> KateDocument::cursors () const
  1269. {
  1270. return myCursors;
  1271. }
  1272. //END
  1273. //BEGIN KTextEditor::SearchInterface stuff
  1274. bool KateDocument::searchText (unsigned int startLine, unsigned int startCol, const TQString &text, unsigned int *foundAtLine, unsigned int *foundAtCol, unsigned int *matchLen, bool casesensitive, bool backwards)
  1275. {
  1276. if (text.isEmpty())
  1277. return false;
  1278. int line = startLine;
  1279. int col = startCol;
  1280. if (!backwards)
  1281. {
  1282. int searchEnd = lastLine();
  1283. while (line <= searchEnd)
  1284. {
  1285. KateTextLine::Ptr textLine = m_buffer->plainLine(line);
  1286. if (!textLine)
  1287. return false;
  1288. uint foundAt, myMatchLen;
  1289. bool found = textLine->searchText (col, text, &foundAt, &myMatchLen, casesensitive, false);
  1290. if (found)
  1291. {
  1292. (*foundAtLine) = line;
  1293. (*foundAtCol) = foundAt;
  1294. (*matchLen) = myMatchLen;
  1295. return true;
  1296. }
  1297. col = 0;
  1298. line++;
  1299. }
  1300. }
  1301. else
  1302. {
  1303. // backward search
  1304. int searchEnd = 0;
  1305. while (line >= searchEnd)
  1306. {
  1307. KateTextLine::Ptr textLine = m_buffer->plainLine(line);
  1308. if (!textLine)
  1309. return false;
  1310. uint foundAt, myMatchLen;
  1311. bool found = textLine->searchText (col, text, &foundAt, &myMatchLen, casesensitive, true);
  1312. if (found)
  1313. {
  1314. /* if ((uint) line == startLine && foundAt + myMatchLen >= (uint) col
  1315. && line == selectStart.line() && foundAt == (uint) selectStart.col()
  1316. && line == selectEnd.line() && foundAt + myMatchLen == (uint) selectEnd.col())
  1317. {
  1318. // To avoid getting stuck at one match we skip a match if it is already
  1319. // selected (most likely because it has just been found).
  1320. if (foundAt > 0)
  1321. col = foundAt - 1;
  1322. else {
  1323. if (--line >= 0)
  1324. col = lineLength(line);
  1325. }
  1326. continue;
  1327. }*/
  1328. (*foundAtLine) = line;
  1329. (*foundAtCol) = foundAt;
  1330. (*matchLen) = myMatchLen;
  1331. return true;
  1332. }
  1333. if (line >= 1)
  1334. col = lineLength(line-1);
  1335. line--;
  1336. }
  1337. }
  1338. return false;
  1339. }
  1340. bool KateDocument::searchText (unsigned int startLine, unsigned int startCol, const TQRegExp &regexp, unsigned int *foundAtLine, unsigned int *foundAtCol, unsigned int *matchLen, bool backwards)
  1341. {
  1342. kdDebug(13020)<<"KateDocument::searchText( "<<startLine<<", "<<startCol<<", "<<TQString(regexp.pattern())<<", "<<backwards<<" )"<<endl;
  1343. if (regexp.isEmpty() || !regexp.isValid())
  1344. return false;
  1345. int line = startLine;
  1346. int col = startCol;
  1347. if (!backwards)
  1348. {
  1349. int searchEnd = lastLine();
  1350. while (line <= searchEnd)
  1351. {
  1352. KateTextLine::Ptr textLine = m_buffer->plainLine(line);
  1353. if (!textLine)
  1354. return false;
  1355. uint foundAt, myMatchLen;
  1356. bool found = textLine->searchText (col, regexp, &foundAt, &myMatchLen, false);
  1357. if (found)
  1358. {
  1359. // A special case which can only occur when searching with a regular expression consisting
  1360. // only of a lookahead (e.g. ^(?=\{) for a function beginning without selecting '{').
  1361. if (myMatchLen == 0 && (uint) line == startLine && foundAt == (uint) col)
  1362. {
  1363. if (col < lineLength(line))
  1364. col++;
  1365. else {
  1366. line++;
  1367. col = 0;
  1368. }
  1369. continue;
  1370. }
  1371. (*foundAtLine) = line;
  1372. (*foundAtCol) = foundAt;
  1373. (*matchLen) = myMatchLen;
  1374. return true;
  1375. }
  1376. col = 0;
  1377. line++;
  1378. }
  1379. }
  1380. else
  1381. {
  1382. // backward search
  1383. int searchEnd = 0;
  1384. while (line >= searchEnd)
  1385. {
  1386. KateTextLine::Ptr textLine = m_buffer->plainLine(line);
  1387. if (!textLine)
  1388. return false;
  1389. uint foundAt, myMatchLen;
  1390. bool found = textLine->searchText (col, regexp, &foundAt, &myMatchLen, true);
  1391. if (found)
  1392. {
  1393. /*if ((uint) line == startLine && foundAt + myMatchLen >= (uint) col
  1394. && line == selectStart.line() && foundAt == (uint) selectStart.col()
  1395. && line == selectEnd.line() && foundAt + myMatchLen == (uint) selectEnd.col())
  1396. {
  1397. // To avoid getting stuck at one match we skip a match if it is already
  1398. // selected (most likely because it has just been found).
  1399. if (foundAt > 0)
  1400. col = foundAt - 1;
  1401. else {
  1402. if (--line >= 0)
  1403. col = lineLength(line);
  1404. }
  1405. continue;
  1406. }*/
  1407. (*foundAtLine) = line;
  1408. (*foundAtCol) = foundAt;
  1409. (*matchLen) = myMatchLen;
  1410. return true;
  1411. }
  1412. if (line >= 1)
  1413. col = lineLength(line-1);
  1414. line--;
  1415. }
  1416. }
  1417. return false;
  1418. }
  1419. //END
  1420. //BEGIN KTextEditor::HighlightingInterface stuff
  1421. uint KateDocument::hlMode ()
  1422. {
  1423. return KateHlManager::self()->findHl(highlight());
  1424. }
  1425. bool KateDocument::setHlMode (uint mode)
  1426. {
  1427. m_buffer->setHighlight (mode);
  1428. if (true)
  1429. {
  1430. setDontChangeHlOnSave();
  1431. return true;
  1432. }
  1433. return false;
  1434. }
  1435. void KateDocument::bufferHlChanged ()
  1436. {
  1437. // update all views
  1438. makeAttribs(false);
  1439. emit hlChanged();
  1440. }
  1441. uint KateDocument::hlModeCount ()
  1442. {
  1443. return KateHlManager::self()->highlights();
  1444. }
  1445. TQString KateDocument::hlModeName (uint mode)
  1446. {
  1447. return KateHlManager::self()->hlName (mode);
  1448. }
  1449. TQString KateDocument::hlModeSectionName (uint mode)
  1450. {
  1451. return KateHlManager::self()->hlSection (mode);
  1452. }
  1453. void KateDocument::setDontChangeHlOnSave()
  1454. {
  1455. hlSetByUser = true;
  1456. }
  1457. //END
  1458. //BEGIN KTextEditor::ConfigInterface stuff
  1459. void KateDocument::readConfig(TDEConfig *config)
  1460. {
  1461. config->setGroup("Kate Document Defaults");
  1462. // read max loadable blocks, more blocks will be swapped out
  1463. KateBuffer::setMaxLoadedBlocks (config->readNumEntry("Maximal Loaded Blocks", KateBuffer::maxLoadedBlocks()));
  1464. KateDocumentConfig::global()->readConfig (config);
  1465. config->setGroup("Kate View Defaults");
  1466. KateViewConfig::global()->readConfig (config);
  1467. config->setGroup("Kate Renderer Defaults");
  1468. KateRendererConfig::global()->readConfig (config);
  1469. }
  1470. void KateDocument::writeConfig(TDEConfig *config)
  1471. {
  1472. config->setGroup("Kate Document Defaults");
  1473. // write max loadable blocks, more blocks will be swapped out
  1474. config->writeEntry("Maximal Loaded Blocks", KateBuffer::maxLoadedBlocks());
  1475. KateDocumentConfig::global()->writeConfig (config);
  1476. config->setGroup("Kate View Defaults");
  1477. KateViewConfig::global()->writeConfig (config);
  1478. config->setGroup("Kate Renderer Defaults");
  1479. KateRendererConfig::global()->writeConfig (config);
  1480. }
  1481. void KateDocument::readConfig()
  1482. {
  1483. TDEConfig *config = kapp->config();
  1484. readConfig (config);
  1485. }
  1486. void KateDocument::writeConfig()
  1487. {
  1488. TDEConfig *config = kapp->config();
  1489. writeConfig (config);
  1490. config->sync();
  1491. }
  1492. void KateDocument::readSessionConfig(TDEConfig *tdeconfig)
  1493. {
  1494. // restore the url
  1495. KURL url (tdeconfig->readEntry("URL"));
  1496. // get the encoding
  1497. TQString tmpenc=tdeconfig->readEntry("Encoding");
  1498. if (!tmpenc.isEmpty() && (tmpenc != encoding()))
  1499. setEncoding(tmpenc);
  1500. // open the file if url valid
  1501. if (!url.isEmpty() && url.isValid())
  1502. openURL (url);
  1503. // restore the hl stuff
  1504. m_buffer->setHighlight(KateHlManager::self()->nameFind(tdeconfig->readEntry("Highlighting")));
  1505. if (hlMode() > 0)
  1506. hlSetByUser = true;
  1507. // indent mode
  1508. config()->setIndentationMode( (uint)tdeconfig->readNumEntry("Indentation Mode", config()->indentationMode() ) );
  1509. // Restore Bookmarks
  1510. TQValueList<int> marks = tdeconfig->readIntListEntry("Bookmarks");
  1511. for( uint i = 0; i < marks.count(); i++ )
  1512. addMark( marks[i], KateDocument::markType01 );
  1513. }
  1514. void KateDocument::writeSessionConfig(TDEConfig *tdeconfig)
  1515. {
  1516. if ( m_url.isLocalFile() && !TDEGlobal::dirs()->relativeLocation("tmp", m_url.path()).startsWith("/"))
  1517. return;
  1518. // save url
  1519. tdeconfig->writeEntry("URL", m_url.prettyURL() );
  1520. // save encoding
  1521. tdeconfig->writeEntry("Encoding",encoding());
  1522. // save hl
  1523. tdeconfig->writeEntry("Highlighting", highlight()->name());
  1524. tdeconfig->writeEntry("Indentation Mode", config()->indentationMode() );
  1525. // Save Bookmarks
  1526. TQValueList<int> marks;
  1527. for( TQIntDictIterator<KTextEditor::Mark> it( m_marks );
  1528. it.current() && it.current()->type & KTextEditor::MarkInterface::markType01;
  1529. ++it )
  1530. marks << it.current()->line;
  1531. tdeconfig->writeEntry( "Bookmarks", marks );
  1532. }
  1533. void KateDocument::configDialog()
  1534. {
  1535. KDialogBase *kd = new KDialogBase ( KDialogBase::IconList,
  1536. i18n("Configure"),
  1537. KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Help,
  1538. KDialogBase::Ok,
  1539. kapp->mainWidget() );
  1540. #ifndef Q_WS_WIN //TODO: reenable
  1541. KWin::setIcons( kd->winId(), kapp->icon(), kapp->miniIcon() );
  1542. #endif
  1543. TQPtrList<KTextEditor::ConfigPage> editorPages;
  1544. for (uint i = 0; i < KTextEditor::configInterfaceExtension (this)->configPages (); i++)
  1545. {
  1546. TQStringList path;
  1547. path.clear();
  1548. path << KTextEditor::configInterfaceExtension (this)->configPageName (i);
  1549. TQVBox *page = kd->addVBoxPage(path, KTextEditor::configInterfaceExtension (this)->configPageFullName (i),
  1550. KTextEditor::configInterfaceExtension (this)->configPagePixmap(i, TDEIcon::SizeMedium) );
  1551. editorPages.append (KTextEditor::configInterfaceExtension (this)->configPage(i, page));
  1552. }
  1553. if (kd->exec())
  1554. {
  1555. KateDocumentConfig::global()->configStart ();
  1556. KateViewConfig::global()->configStart ();
  1557. KateRendererConfig::global()->configStart ();
  1558. for (uint i=0; i<editorPages.count(); i++)
  1559. {
  1560. editorPages.at(i)->apply();
  1561. }
  1562. KateDocumentConfig::global()->configEnd ();
  1563. KateViewConfig::global()->configEnd ();
  1564. KateRendererConfig::global()->configEnd ();
  1565. writeConfig ();
  1566. }
  1567. delete kd;
  1568. }
  1569. uint KateDocument::mark( uint line )
  1570. {
  1571. if( !m_marks[line] )
  1572. return 0;
  1573. return m_marks[line]->type;
  1574. }
  1575. void KateDocument::setMark( uint line, uint markType )
  1576. {
  1577. clearMark( line );
  1578. addMark( line, markType );
  1579. }
  1580. void KateDocument::clearMark( uint line )
  1581. {
  1582. if( line > lastLine() )
  1583. return;
  1584. if( !m_marks[line] )
  1585. return;
  1586. KTextEditor::Mark* mark = m_marks.take( line );
  1587. emit markChanged( *mark, MarkRemoved );
  1588. emit marksChanged();
  1589. delete mark;
  1590. tagLines( line, line );
  1591. repaintViews(true);
  1592. }
  1593. void KateDocument::addMark( uint line, uint markType )
  1594. {
  1595. if( line > lastLine())
  1596. return;
  1597. if( markType == 0 )
  1598. return;
  1599. if( m_marks[line] ) {
  1600. KTextEditor::Mark* mark = m_marks[line];
  1601. // Remove bits already set
  1602. markType &= ~mark->type;
  1603. if( markType == 0 )
  1604. return;
  1605. // Add bits
  1606. mark->type |= markType;
  1607. } else {
  1608. KTextEditor::Mark *mark = new KTextEditor::Mark;
  1609. mark->line = line;
  1610. mark->type = markType;
  1611. m_marks.insert( line, mark );
  1612. }
  1613. // Emit with a mark having only the types added.
  1614. KTextEditor::Mark temp;
  1615. temp.line = line;
  1616. temp.type = markType;
  1617. emit markChanged( temp, MarkAdded );
  1618. emit marksChanged();
  1619. tagLines( line, line );
  1620. repaintViews(true);
  1621. }
  1622. void KateDocument::removeMark( uint line, uint markType )
  1623. {
  1624. if( line > lastLine() )
  1625. return;
  1626. if( !m_marks[line] )
  1627. return;
  1628. KTextEditor::Mark* mark = m_marks[line];
  1629. // Remove bits not set
  1630. markType &= mark->type;
  1631. if( markType == 0 )
  1632. return;
  1633. // Subtract bits
  1634. mark->type &= ~markType;
  1635. // Emit with a mark having only the types removed.
  1636. KTextEditor::Mark temp;
  1637. temp.line = line;
  1638. temp.type = markType;
  1639. emit markChanged( temp, MarkRemoved );
  1640. if( mark->type == 0 )
  1641. m_marks.remove( line );
  1642. emit marksChanged();
  1643. tagLines( line, line );
  1644. repaintViews(true);
  1645. }
  1646. TQPtrList<KTextEditor::Mark> KateDocument::marks()
  1647. {
  1648. TQPtrList<KTextEditor::Mark> list;
  1649. for( TQIntDictIterator<KTextEditor::Mark> it( m_marks );
  1650. it.current(); ++it ) {
  1651. list.append( it.current() );
  1652. }
  1653. return list;
  1654. }
  1655. void KateDocument::clearMarks()
  1656. {
  1657. for( TQIntDictIterator<KTextEditor::Mark> it( m_marks );
  1658. it.current(); ++it ) {
  1659. KTextEditor::Mark* mark = it.current();
  1660. emit markChanged( *mark, MarkRemoved );
  1661. tagLines( mark->line, mark->line );
  1662. }
  1663. m_marks.clear();
  1664. emit marksChanged();
  1665. repaintViews(true);
  1666. }
  1667. void KateDocument::setPixmap( MarkInterface::MarkTypes type, const TQPixmap& pixmap )
  1668. {
  1669. m_markPixmaps.replace( type, new TQPixmap( pixmap ) );
  1670. }
  1671. void KateDocument::setDescription( MarkInterface::MarkTypes type, const TQString& description )
  1672. {
  1673. m_markDescriptions.replace( type, new TQString( description ) );
  1674. }
  1675. TQPixmap *KateDocument::markPixmap( MarkInterface::MarkTypes type )
  1676. {
  1677. return m_markPixmaps[type];
  1678. }
  1679. TQColor KateDocument::markColor( MarkInterface::MarkTypes type )
  1680. {
  1681. uint reserved = (0x1 << KTextEditor::MarkInterface::reservedMarkersCount()) - 1;
  1682. if ((uint)type >= (uint)markType01 && (uint)type <= reserved) {
  1683. return KateRendererConfig::global()->lineMarkerColor(type);
  1684. } else {
  1685. return TQColor();
  1686. }
  1687. }
  1688. TQString KateDocument::markDescription( MarkInterface::MarkTypes type )
  1689. {
  1690. if( m_markDescriptions[type] )
  1691. return *m_markDescriptions[type];
  1692. return TQString::null;
  1693. }
  1694. void KateDocument::setMarksUserChangable( uint markMask )
  1695. {
  1696. m_editableMarks = markMask;
  1697. }
  1698. uint KateDocument::editableMarks()
  1699. {
  1700. return m_editableMarks;
  1701. }
  1702. //END
  1703. //BEGIN KTextEditor::PrintInterface stuff
  1704. bool KateDocument::printDialog ()
  1705. {
  1706. return KatePrinter::print (this);
  1707. }
  1708. bool KateDocument::print ()
  1709. {
  1710. return KatePrinter::print (this);
  1711. }
  1712. //END
  1713. //BEGIN KTextEditor::DocumentInfoInterface (### unfinished)
  1714. TQString KateDocument::mimeType()
  1715. {
  1716. KMimeType::Ptr result = KMimeType::defaultMimeTypePtr();
  1717. // if the document has a URL, try KMimeType::findByURL
  1718. if ( ! m_url.isEmpty() )
  1719. result = KMimeType::findByURL( m_url );
  1720. else if ( m_url.isEmpty() || ! m_url.isLocalFile() )
  1721. result = mimeTypeForContent();
  1722. return result->name();
  1723. }
  1724. // TODO implement this -- how to calculate?
  1725. long KateDocument::fileSize()
  1726. {
  1727. return 0;
  1728. }
  1729. // TODO implement this
  1730. TQString KateDocument::niceFileSize()
  1731. {
  1732. return "UNKNOWN";
  1733. }
  1734. KMimeType::Ptr KateDocument::mimeTypeForContent()
  1735. {
  1736. TQByteArray buf (1024);
  1737. uint bufpos = 0;
  1738. for (uint i=0; i < numLines(); i++)
  1739. {
  1740. TQString line = textLine( i );
  1741. uint len = line.length() + 1;
  1742. if (bufpos + len > 1024)
  1743. len = 1024 - bufpos;
  1744. memcpy(&buf[bufpos], (line + "\n").latin1(), len);
  1745. bufpos += len;
  1746. if (bufpos >= 1024)
  1747. break;
  1748. }
  1749. buf.resize( bufpos );
  1750. int accuracy = 0;
  1751. return KMimeType::findByContent( buf, &accuracy );
  1752. }
  1753. //END KTextEditor::DocumentInfoInterface
  1754. //BEGIN KParts::ReadWrite stuff
  1755. bool KateDocument::openURL( const KURL &url )
  1756. {
  1757. // kdDebug(13020)<<"KateDocument::openURL( "<<url.prettyURL()<<")"<<endl;
  1758. // no valid URL
  1759. if ( !url.isValid() )
  1760. return false;
  1761. // could not close old one
  1762. if ( !closeURL() )
  1763. return false;
  1764. // set my url
  1765. m_url = url;
  1766. if ( m_url.isLocalFile() )
  1767. {
  1768. // local mode, just like in kpart
  1769. m_file = m_url.path();
  1770. emit started( 0 );
  1771. if (openFile())
  1772. {
  1773. emit completed();
  1774. emit setWindowCaption( m_url.prettyURL() );
  1775. return true;
  1776. }
  1777. return false;
  1778. }
  1779. else
  1780. {
  1781. // remote mode
  1782. m_bTemp = true;
  1783. m_tempFile = new KTempFile ();
  1784. m_file = m_tempFile->name();
  1785. m_job = TDEIO::get ( url, false, isProgressInfoEnabled() );
  1786. // connect to slots
  1787. connect( m_job, TQT_SIGNAL( data( TDEIO::Job*, const TQByteArray& ) ),
  1788. TQT_SLOT( slotDataKate( TDEIO::Job*, const TQByteArray& ) ) );
  1789. connect( m_job, TQT_SIGNAL( result( TDEIO::Job* ) ),
  1790. TQT_SLOT( slotFinishedKate( TDEIO::Job* ) ) );
  1791. TQWidget *w = widget ();
  1792. if (!w && !m_views.isEmpty ())
  1793. w = m_views.first();
  1794. if (w)
  1795. m_job->setWindow (w->topLevelWidget());
  1796. emit started( m_job );
  1797. return true;
  1798. }
  1799. }
  1800. void KateDocument::slotDataKate ( TDEIO::Job *, const TQByteArray &data )
  1801. {
  1802. // kdDebug(13020) << "KateDocument::slotData" << endl;
  1803. if (!m_tempFile || !m_tempFile->file())
  1804. return;
  1805. m_tempFile->file()->writeBlock (data);
  1806. }
  1807. void KateDocument::slotFinishedKate ( TDEIO::Job * job )
  1808. {
  1809. // kdDebug(13020) << "KateDocument::slotJobFinished" << endl;
  1810. if (!m_tempFile)
  1811. return;
  1812. delete m_tempFile;
  1813. m_tempFile = 0;
  1814. m_job = 0;
  1815. if (job->error())
  1816. emit canceled( job->errorString() );
  1817. else
  1818. {
  1819. if ( openFile(job) )
  1820. emit setWindowCaption( m_url.prettyURL() );
  1821. emit completed();
  1822. }
  1823. }
  1824. void KateDocument::abortLoadKate()
  1825. {
  1826. if ( m_job )
  1827. {
  1828. kdDebug(13020) << "Aborting job " << m_job << endl;
  1829. m_job->kill();
  1830. m_job = 0;
  1831. }
  1832. delete m_tempFile;
  1833. m_tempFile = 0;
  1834. }
  1835. bool KateDocument::openFile()
  1836. {
  1837. return openFile (0);
  1838. }
  1839. bool KateDocument::openFile(TDEIO::Job * job)
  1840. {
  1841. m_loading = true;
  1842. // add new m_file to dirwatch
  1843. activateDirWatch ();
  1844. //
  1845. // use metadata
  1846. //
  1847. if (job)
  1848. {
  1849. TQString metaDataCharset = job->queryMetaData("charset");
  1850. // only overwrite config if nothing set
  1851. if (!metaDataCharset.isEmpty () && (!m_config->isSetEncoding() || m_config->encoding().isEmpty()))
  1852. setEncoding (metaDataCharset);
  1853. }
  1854. //
  1855. // service type magic to get encoding right
  1856. //
  1857. TQString serviceType = m_extension->urlArgs().serviceType.simplifyWhiteSpace();
  1858. int pos = serviceType.find(';');
  1859. if (pos != -1)
  1860. setEncoding (serviceType.mid(pos+1));
  1861. // if the encoding is set here - on the command line/from the dialog/from KIO
  1862. // we prevent file type and document variables from changing it
  1863. bool encodingSticky = m_encodingSticky;
  1864. m_encodingSticky = m_config->isSetEncoding();
  1865. // Try getting the filetype here, so that variables does not have to be reset.
  1866. int fileTypeFound = KateFactory::self()->fileTypeManager()->fileType (this);
  1867. if ( fileTypeFound > -1 )
  1868. updateFileType( fileTypeFound );
  1869. // read dir config (if possible and wanted)
  1870. if (!m_reloading)
  1871. readDirConfig ();
  1872. // do we have success ?
  1873. bool success = m_buffer->openFile (m_file);
  1874. //
  1875. // yeah, success
  1876. //
  1877. m_loading = false; // done reading file.
  1878. if (success)
  1879. {
  1880. /*if (highlight() && !m_url.isLocalFile()) {
  1881. // The buffer's highlighting gets nuked by KateBuffer::clear()
  1882. m_buffer->setHighlight(m_highlight);
  1883. }*/
  1884. // update our hl type if needed
  1885. if (!hlSetByUser)
  1886. {
  1887. int hl (KateHlManager::self()->detectHighlighting (this));
  1888. if (hl >= 0)
  1889. m_buffer->setHighlight(hl);
  1890. }
  1891. // update file type if we haven't allready done so.
  1892. if ( fileTypeFound < 0 )
  1893. updateFileType (KateFactory::self()->fileTypeManager()->fileType (this));
  1894. // read vars
  1895. readVariables();
  1896. // update the md5 digest
  1897. createDigest( m_digest );
  1898. }
  1899. //
  1900. // update views
  1901. //
  1902. for (KateView * view = m_views.first(); view != 0L; view = m_views.next() )
  1903. {
  1904. view->updateView(true);
  1905. }
  1906. //
  1907. // emit the signal we need for example for kate app
  1908. //
  1909. emit fileNameChanged ();
  1910. //
  1911. // set doc name, dummy value as arg, don't need it
  1912. //
  1913. setDocName (TQString::null);
  1914. //
  1915. // to houston, we are not modified
  1916. //
  1917. if (m_modOnHd)
  1918. {
  1919. m_modOnHd = false;
  1920. m_modOnHdReason = 0;
  1921. emit modifiedOnDisc (this, m_modOnHd, 0);
  1922. }
  1923. //
  1924. // display errors
  1925. //
  1926. if (s_openErrorDialogsActivated)
  1927. {
  1928. if (!success && m_buffer->loadingBorked())
  1929. KMessageBox::error (widget(), i18n ("The file %1 could not be loaded completely, as there is not enough temporary disk storage for it.").arg(m_url.url()));
  1930. else if (!success)
  1931. KMessageBox::error (widget(), i18n ("The file %1 could not be loaded, as it was not possible to read from it.\n\nCheck if you have read access to this file.").arg(m_url.url()));
  1932. }
  1933. // warn -> opened binary file!!!!!!!
  1934. if (m_buffer->binary())
  1935. {
  1936. // this file can't be saved again without killing it
  1937. setReadWrite( false );
  1938. KMessageBox::information (widget()
  1939. , i18n ("The file %1 is a binary, saving it will result in a corrupt file.").arg(m_url.url())
  1940. , i18n ("Binary File Opened")
  1941. , "Binary File Opened Warning");
  1942. }
  1943. m_encodingSticky = encodingSticky;
  1944. //
  1945. // return the success
  1946. //
  1947. return success;
  1948. }
  1949. bool KateDocument::save()
  1950. {
  1951. bool l ( url().isLocalFile() );
  1952. if ( ( l && config()->backupFlags() & KateDocumentConfig::LocalFiles )
  1953. || ( ! l && config()->backupFlags() & KateDocumentConfig::RemoteFiles ) )
  1954. {
  1955. KURL u( url() );
  1956. u.setFileName( config()->backupPrefix() + url().fileName() + config()->backupSuffix() );
  1957. kdDebug () << "backup src file name: " << url() << endl;
  1958. kdDebug () << "backup dst file name: " << u << endl;
  1959. // get the right permissions, start with safe default
  1960. mode_t perms = 0600;
  1961. TDEIO::UDSEntry fentry;
  1962. if (TDEIO::NetAccess::stat (url(), fentry, kapp->mainWidget()))
  1963. {
  1964. kdDebug () << "stating succesfull: " << url() << endl;
  1965. KFileItem item (fentry, url());
  1966. perms = item.permissions();
  1967. }
  1968. // first del existing file if any, than copy over the file we have
  1969. // failure if a: the existing file could not be deleted, b: the file could not be copied
  1970. if ( (!TDEIO::NetAccess::exists( u, false, kapp->mainWidget() ) || TDEIO::NetAccess::del( u, kapp->mainWidget() ))
  1971. && TDEIO::NetAccess::file_copy( url(), u, perms, true, false, kapp->mainWidget() ) )
  1972. {
  1973. kdDebug(13020)<<"backing up successfull ("<<url().prettyURL()<<" -> "<<u.prettyURL()<<")"<<endl;
  1974. }
  1975. else
  1976. {
  1977. kdDebug(13020)<<"backing up failed ("<<url().prettyURL()<<" -> "<<u.prettyURL()<<")"<<endl;
  1978. // FIXME: notify user for real ;)
  1979. }
  1980. }
  1981. return KParts::ReadWritePart::save();
  1982. }
  1983. bool KateDocument::saveFile()
  1984. {
  1985. //
  1986. // we really want to save this file ?
  1987. //
  1988. if (m_buffer->loadingBorked() && (KMessageBox::warningContinueCancel(widget(),
  1989. i18n("This file could not be loaded correctly due to lack of temporary disk space. Saving it could cause data loss.\n\nDo you really want to save it?"),i18n("Possible Data Loss"),i18n("Save Nevertheless")) != KMessageBox::Continue))
  1990. return false;
  1991. //
  1992. // warn -> try to save binary file!!!!!!!
  1993. //
  1994. if (m_buffer->binary() && (KMessageBox::warningContinueCancel (widget()
  1995. , i18n ("The file %1 is a binary, saving it will result in a corrupt file.").arg(m_url.url())
  1996. , i18n ("Trying to Save Binary File")
  1997. , i18n("Save Nevertheless"), "Binary File Save Warning") != KMessageBox::Continue))
  1998. return false;
  1999. if ( !url().isEmpty() )
  2000. {
  2001. if (s_fileChangedDialogsActivated && m_modOnHd)
  2002. {
  2003. TQString str = reasonedMOHString() + "\n\n";
  2004. if (!isModified())
  2005. {
  2006. if (KMessageBox::warningContinueCancel(0,
  2007. str + i18n("Do you really want to save this unmodified file? You could overwrite changed data in the file on disk."),i18n("Trying to Save Unmodified File"),i18n("Save Nevertheless")) != KMessageBox::Continue)
  2008. return false;
  2009. }
  2010. else
  2011. {
  2012. if (KMessageBox::warningContinueCancel(0,
  2013. str + i18n("Do you really want to save this file? Both your open file and the file on disk were changed. There could be some data lost."),i18n("Possible Data Loss"),i18n("Save Nevertheless")) != KMessageBox::Continue)
  2014. return false;
  2015. }
  2016. }
  2017. }
  2018. //
  2019. // can we encode it if we want to save it ?
  2020. //
  2021. if (!m_buffer->canEncode ()
  2022. && (KMessageBox::warningContinueCancel(0,
  2023. i18n("The selected encoding cannot encode every unicode character in this document. Do you really want to save it? There could be some data lost."),i18n("Possible Data Loss"),i18n("Save Nevertheless")) != KMessageBox::Continue))
  2024. {
  2025. return false;
  2026. }
  2027. // remove file from dirwatch
  2028. deactivateDirWatch ();
  2029. //
  2030. // try to save
  2031. //
  2032. bool success = m_buffer->saveFile (m_file);
  2033. // update the md5 digest
  2034. createDigest( m_digest );
  2035. // add m_file again to dirwatch
  2036. activateDirWatch ();
  2037. //
  2038. // hurray, we had success, do stuff we need
  2039. //
  2040. if (success)
  2041. {
  2042. // update our hl type if needed
  2043. if (!hlSetByUser)
  2044. {
  2045. int hl (KateHlManager::self()->detectHighlighting (this));
  2046. if (hl >= 0)
  2047. m_buffer->setHighlight(hl);
  2048. }
  2049. // read our vars
  2050. readVariables();
  2051. }
  2052. //
  2053. // we are not modified
  2054. //
  2055. if (success && m_modOnHd)
  2056. {
  2057. m_modOnHd = false;
  2058. m_modOnHdReason = 0;
  2059. emit modifiedOnDisc (this, m_modOnHd, 0);
  2060. }
  2061. //
  2062. // display errors
  2063. //
  2064. if (!success)
  2065. KMessageBox::error (widget(), i18n ("The document could not be saved, as it was not possible to write to %1.\n\nCheck that you have write access to this file or that enough disk space is available.").arg(m_url.url()));
  2066. //
  2067. // return success
  2068. //
  2069. return success;
  2070. }
  2071. bool KateDocument::saveAs( const KURL &u )
  2072. {
  2073. TQString oldDir = url().directory();
  2074. if ( KParts::ReadWritePart::saveAs( u ) )
  2075. {
  2076. // null means base on filename
  2077. setDocName( TQString::null );
  2078. if ( u.directory() != oldDir )
  2079. readDirConfig();
  2080. emit fileNameChanged();
  2081. emit nameChanged((Kate::Document *) this);
  2082. return true;
  2083. }
  2084. return false;
  2085. }
  2086. void KateDocument::readDirConfig ()
  2087. {
  2088. int depth = config()->searchDirConfigDepth ();
  2089. if (m_url.isLocalFile() && (depth > -1))
  2090. {
  2091. TQString currentDir = TQFileInfo (m_file).dirPath();
  2092. // only search as deep as specified or not at all ;)
  2093. while (depth > -1)
  2094. {
  2095. kdDebug (13020) << "search for config file in path: " << currentDir << endl;
  2096. // try to open config file in this dir
  2097. TQFile f (currentDir + "/.kateconfig");
  2098. if (f.open (IO_ReadOnly))
  2099. {
  2100. TQTextStream stream (&f);
  2101. uint linesRead = 0;
  2102. TQString line = stream.readLine();
  2103. while ((linesRead < 32) && !line.isNull())
  2104. {
  2105. readVariableLine( line );
  2106. line = stream.readLine();
  2107. linesRead++;
  2108. }
  2109. break;
  2110. }
  2111. TQString newDir = TQFileInfo (currentDir).dirPath();
  2112. // bail out on looping (for example reached /)
  2113. if (currentDir == newDir)
  2114. break;
  2115. currentDir = newDir;
  2116. --depth;
  2117. }
  2118. }
  2119. }
  2120. void KateDocument::activateDirWatch ()
  2121. {
  2122. // same file as we are monitoring, return
  2123. if (m_file == m_dirWatchFile)
  2124. return;
  2125. // remove the old watched file
  2126. deactivateDirWatch ();
  2127. // add new file if needed
  2128. if (m_url.isLocalFile() && !m_file.isEmpty())
  2129. {
  2130. KateFactory::self()->dirWatch ()->addFile (m_file);
  2131. m_dirWatchFile = m_file;
  2132. }
  2133. }
  2134. void KateDocument::deactivateDirWatch ()
  2135. {
  2136. if (!m_dirWatchFile.isEmpty())
  2137. KateFactory::self()->dirWatch ()->removeFile (m_dirWatchFile);
  2138. m_dirWatchFile = TQString::null;
  2139. }
  2140. bool KateDocument::closeURL()
  2141. {
  2142. abortLoadKate();
  2143. //
  2144. // file mod on hd
  2145. //
  2146. if ( !m_reloading && !url().isEmpty() )
  2147. {
  2148. if (s_fileChangedDialogsActivated && m_modOnHd)
  2149. {
  2150. if (!(KMessageBox::warningContinueCancel(
  2151. widget(),
  2152. reasonedMOHString() + "\n\n" + i18n("Do you really want to continue to close this file? Data loss may occur."),
  2153. i18n("Possible Data Loss"), i18n("Close Nevertheless"),
  2154. TQString("kate_close_modonhd_%1").arg( m_modOnHdReason ) ) == KMessageBox::Continue))
  2155. return false;
  2156. }
  2157. }
  2158. //
  2159. // first call the normal tdeparts implementation
  2160. //
  2161. if (!KParts::ReadWritePart::closeURL ())
  2162. return false;
  2163. // remove file from dirwatch
  2164. deactivateDirWatch ();
  2165. //
  2166. // empty url + filename
  2167. //
  2168. m_url = KURL ();
  2169. m_file = TQString::null;
  2170. // we are not modified
  2171. if (m_modOnHd)
  2172. {
  2173. m_modOnHd = false;
  2174. m_modOnHdReason = 0;
  2175. emit modifiedOnDisc (this, m_modOnHd, 0);
  2176. }
  2177. // clear the buffer
  2178. m_buffer->clear();
  2179. // remove all marks
  2180. clearMarks ();
  2181. // clear undo/redo history
  2182. clearUndo();
  2183. clearRedo();
  2184. // no, we are no longer modified
  2185. setModified(false);
  2186. // we have no longer any hl
  2187. m_buffer->setHighlight(0);
  2188. // update all our views
  2189. for (KateView * view = m_views.first(); view != 0L; view = m_views.next() )
  2190. {
  2191. // Explicitly call the internal version because we don't want this to look like
  2192. // an external request (and thus have the view not TQWidget::scroll()ed.
  2193. view->setCursorPositionInternal(0, 0, 1, false);
  2194. view->clearSelection();
  2195. view->updateView(true);
  2196. }
  2197. // uh, filename changed
  2198. emit fileNameChanged ();
  2199. // update doc name
  2200. setDocName (TQString::null);
  2201. // success
  2202. return true;
  2203. }
  2204. void KateDocument::setReadWrite( bool rw )
  2205. {
  2206. if (isReadWrite() != rw)
  2207. {
  2208. KParts::ReadWritePart::setReadWrite (rw);
  2209. for( KateView* view = m_views.first(); view != 0L; view = m_views.next() )
  2210. {
  2211. view->slotUpdate();
  2212. view->slotReadWriteChanged ();
  2213. }
  2214. }
  2215. }
  2216. void KateDocument::setModified(bool m) {
  2217. if (isModified() != m) {
  2218. KParts::ReadWritePart::setModified (m);
  2219. for( KateView* view = m_views.first(); view != 0L; view = m_views.next() )
  2220. {
  2221. view->slotUpdate();
  2222. }
  2223. emit modifiedChanged ();
  2224. emit modStateChanged ((Kate::Document *)this);
  2225. }
  2226. if ( m == false )
  2227. {
  2228. if ( ! undoItems.isEmpty() )
  2229. {
  2230. lastUndoGroupWhenSaved = undoItems.last();
  2231. }
  2232. if ( ! redoItems.isEmpty() )
  2233. {
  2234. lastRedoGroupWhenSaved = redoItems.last();
  2235. }
  2236. docWasSavedWhenUndoWasEmpty = undoItems.isEmpty();
  2237. docWasSavedWhenRedoWasEmpty = redoItems.isEmpty();
  2238. }
  2239. }
  2240. //END
  2241. //BEGIN Kate specific stuff ;)
  2242. void KateDocument::makeAttribs(bool needInvalidate)
  2243. {
  2244. for (uint z = 0; z < m_views.count(); z++)
  2245. m_views.at(z)->renderer()->updateAttributes ();
  2246. if (needInvalidate)
  2247. m_buffer->invalidateHighlighting();
  2248. tagAll ();
  2249. }
  2250. // the attributes of a hl have changed, update
  2251. void KateDocument::internalHlChanged()
  2252. {
  2253. makeAttribs();
  2254. }
  2255. void KateDocument::addView(KTextEditor::View *view) {
  2256. if (!view)
  2257. return;
  2258. m_views.append( (KateView *) view );
  2259. m_textEditViews.append( view );
  2260. // apply the view & renderer vars from the file type
  2261. const KateFileType *t = 0;
  2262. if ((m_fileType > -1) && (t = KateFactory::self()->fileTypeManager()->fileType(m_fileType)))
  2263. readVariableLine (t->varLine, true);
  2264. // apply the view & renderer vars from the file
  2265. readVariables (true);
  2266. m_activeView = (KateView *) view;
  2267. }
  2268. void KateDocument::removeView(KTextEditor::View *view) {
  2269. if (!view)
  2270. return;
  2271. if (m_activeView == view)
  2272. m_activeView = 0L;
  2273. m_views.removeRef( (KateView *) view );
  2274. m_textEditViews.removeRef( view );
  2275. }
  2276. void KateDocument::addSuperCursor(KateSuperCursor *cursor, bool privateC) {
  2277. if (!cursor)
  2278. return;
  2279. m_superCursors.append( cursor );
  2280. if (!privateC)
  2281. myCursors.append( cursor );
  2282. }
  2283. void KateDocument::removeSuperCursor(KateSuperCursor *cursor, bool privateC) {
  2284. if (!cursor)
  2285. return;
  2286. if (!privateC)
  2287. myCursors.removeRef( cursor );
  2288. m_superCursors.removeRef( cursor );
  2289. }
  2290. bool KateDocument::ownedView(KateView *view) {
  2291. // do we own the given view?
  2292. return (m_views.containsRef(view) > 0);
  2293. }
  2294. bool KateDocument::isLastView(int numViews) {
  2295. return ((int) m_views.count() == numViews);
  2296. }
  2297. uint KateDocument::currentColumn( const KateTextCursor& cursor )
  2298. {
  2299. KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
  2300. if (textLine)
  2301. return textLine->cursorX(cursor.col(), config()->tabWidth());
  2302. else
  2303. return 0;
  2304. }
  2305. bool KateDocument::typeChars ( KateView *view, const TQString &chars )
  2306. {
  2307. KateTextLine::Ptr textLine = m_buffer->plainLine(view->cursorLine ());
  2308. if (!textLine)
  2309. return false;
  2310. bool bracketInserted = false;
  2311. TQString buf;
  2312. TQChar c;
  2313. for( uint z = 0; z < chars.length(); z++ )
  2314. {
  2315. TQChar ch = c = chars[z];
  2316. if (ch.isPrint() || ch == '\t')
  2317. {
  2318. buf.append (ch);
  2319. if (!bracketInserted && (config()->configFlags() & KateDocument::cfAutoBrackets))
  2320. {
  2321. TQChar end_ch;
  2322. bool complete = true;
  2323. TQChar prevChar = textLine->getChar(view->cursorColumnReal()-1);
  2324. TQChar nextChar = textLine->getChar(view->cursorColumnReal());
  2325. switch(ch) {
  2326. case '(': end_ch = ')'; break;
  2327. case '[': end_ch = ']'; break;
  2328. case '{': end_ch = '}'; break;
  2329. case '\'':end_ch = '\'';break;
  2330. case '"': end_ch = '"'; break;
  2331. default: complete = false;
  2332. }
  2333. if (complete)
  2334. {
  2335. if (view->hasSelection())
  2336. { // there is a selection, enclose the selection
  2337. buf.append (view->selection());
  2338. buf.append (end_ch);
  2339. bracketInserted = true;
  2340. }
  2341. else
  2342. { // no selection, check whether we should better refuse to complete
  2343. if ( ( (ch == '\'' || ch == '"') &&
  2344. (prevChar.isLetterOrNumber() || prevChar == ch) )
  2345. || nextChar.isLetterOrNumber()
  2346. || (nextChar == end_ch && prevChar != ch) )
  2347. {
  2348. kdDebug(13020) << "AutoBracket refused before: " << nextChar << "\n";
  2349. }
  2350. else
  2351. {
  2352. buf.append (end_ch);
  2353. bracketInserted = true;
  2354. }
  2355. }
  2356. }
  2357. }
  2358. }
  2359. }
  2360. if (buf.isEmpty())
  2361. return false;
  2362. editStart ();
  2363. if (!view->config()->persistentSelection() && view->hasSelection() )
  2364. view->removeSelectedText();
  2365. int oldLine = view->cursorLine ();
  2366. int oldCol = view->cursorColumnReal ();
  2367. if (config()->configFlags() & KateDocument::cfOvr)
  2368. removeText (view->cursorLine(), view->cursorColumnReal(), view->cursorLine(), kMin( view->cursorColumnReal()+buf.length(), textLine->length() ) );
  2369. insertText (view->cursorLine(), view->cursorColumnReal(), buf);
  2370. m_indenter->processChar(c);
  2371. editEnd ();
  2372. if (bracketInserted)
  2373. view->setCursorPositionInternal (view->cursorLine(), view->cursorColumnReal()-1);
  2374. emit charactersInteractivelyInserted (oldLine, oldCol, chars);
  2375. return true;
  2376. }
  2377. void KateDocument::newLine( KateTextCursor& c, KateViewInternal *v )
  2378. {
  2379. editStart();
  2380. if( !v->view()->config()->persistentSelection() && v->view()->hasSelection() )
  2381. v->view()->removeSelectedText();
  2382. // temporary hack to get the cursor pos right !!!!!!!!!
  2383. c = v->getCursor ();
  2384. if (c.line() > (int)lastLine())
  2385. c.setLine(lastLine());
  2386. if ( c.line() < 0 )
  2387. c.setLine( 0 );
  2388. uint ln = c.line();
  2389. KateTextLine::Ptr textLine = kateTextLine(c.line());
  2390. if (c.col() > (int)textLine->length())
  2391. c.setCol(textLine->length());
  2392. if (m_indenter->canProcessNewLine ())
  2393. {
  2394. int pos = textLine->firstChar();
  2395. // length should do the job better
  2396. if (pos < 0)
  2397. pos = textLine->length();
  2398. if (c.col() < pos)
  2399. c.setCol(pos); // place cursor on first char if before
  2400. editWrapLine (c.line(), c.col());
  2401. KateDocCursor cursor (c.line() + 1, pos, this);
  2402. m_indenter->processNewline(cursor, true);
  2403. c.setPos(cursor);
  2404. }
  2405. else
  2406. {
  2407. editWrapLine (c.line(), c.col());
  2408. c.setPos(c.line() + 1, 0);
  2409. }
  2410. removeTrailingSpace( ln );
  2411. editEnd();
  2412. }
  2413. void KateDocument::transpose( const KateTextCursor& cursor)
  2414. {
  2415. KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
  2416. if (!textLine || (textLine->length() < 2))
  2417. return;
  2418. uint col = cursor.col();
  2419. if (col > 0)
  2420. col--;
  2421. if ((textLine->length() - col) < 2)
  2422. return;
  2423. uint line = cursor.line();
  2424. TQString s;
  2425. //clever swap code if first character on the line swap right&left
  2426. //otherwise left & right
  2427. s.append (textLine->getChar(col+1));
  2428. s.append (textLine->getChar(col));
  2429. //do the swap
  2430. // do it right, never ever manipulate a textline
  2431. editStart ();
  2432. editRemoveText (line, col, 2);
  2433. editInsertText (line, col, s);
  2434. editEnd ();
  2435. }
  2436. void KateDocument::backspace( KateView *view, const KateTextCursor& c )
  2437. {
  2438. if ( !view->config()->persistentSelection() && view->hasSelection() ) {
  2439. view->removeSelectedText();
  2440. return;
  2441. }
  2442. uint col = kMax( c.col(), 0 );
  2443. uint line = kMax( c.line(), 0 );
  2444. if ((col == 0) && (line == 0))
  2445. return;
  2446. int complement = 0;
  2447. if (col > 0)
  2448. {
  2449. if (config()->configFlags() & KateDocument::cfAutoBrackets)
  2450. {
  2451. // if inside empty (), {}, [], '', "" delete both
  2452. KateTextLine::Ptr tl = m_buffer->plainLine(line);
  2453. if(!tl) return;
  2454. TQChar prevChar = tl->getChar(col-1);
  2455. TQChar nextChar = tl->getChar(col);
  2456. if ( (prevChar == '"' && nextChar == '"') ||
  2457. (prevChar == '\'' && nextChar == '\'') ||
  2458. (prevChar == '(' && nextChar == ')') ||
  2459. (prevChar == '[' && nextChar == ']') ||
  2460. (prevChar == '{' && nextChar == '}') )
  2461. {
  2462. complement = 1;
  2463. }
  2464. }
  2465. if (!(config()->configFlags() & KateDocument::cfBackspaceIndents))
  2466. {
  2467. // ordinary backspace
  2468. //c.cursor.col--;
  2469. removeText(line, col-1, line, col+complement);
  2470. }
  2471. else
  2472. {
  2473. // backspace indents: erase to next indent position
  2474. KateTextLine::Ptr textLine = m_buffer->plainLine(line);
  2475. // don't forget this check!!!! really!!!!
  2476. if (!textLine)
  2477. return;
  2478. int colX = textLine->cursorX(col, config()->tabWidth());
  2479. int pos = textLine->firstChar();
  2480. if (pos > 0)
  2481. pos = textLine->cursorX(pos, config()->tabWidth());
  2482. if (pos < 0 || pos >= (int)colX)
  2483. {
  2484. // only spaces on left side of cursor
  2485. indent( view, line, -1);
  2486. }
  2487. else
  2488. removeText(line, col-1, line, col+complement);
  2489. }
  2490. }
  2491. else
  2492. {
  2493. // col == 0: wrap to previous line
  2494. if (line >= 1)
  2495. {
  2496. KateTextLine::Ptr textLine = m_buffer->plainLine(line-1);
  2497. // don't forget this check!!!! really!!!!
  2498. if (!textLine)
  2499. return;
  2500. if (config()->wordWrap() && textLine->endingWith(TQString::fromLatin1(" ")))
  2501. {
  2502. // gg: in hard wordwrap mode, backspace must also eat the trailing space
  2503. removeText (line-1, textLine->length()-1, line, 0);
  2504. }
  2505. else
  2506. removeText (line-1, textLine->length(), line, 0);
  2507. }
  2508. }
  2509. emit backspacePressed();
  2510. }
  2511. void KateDocument::del( KateView *view, const KateTextCursor& c )
  2512. {
  2513. if ( !view->config()->persistentSelection() && view->hasSelection() ) {
  2514. view->removeSelectedText();
  2515. return;
  2516. }
  2517. if( c.col() < (int) m_buffer->plainLine(c.line())->length())
  2518. {
  2519. removeText(c.line(), c.col(), c.line(), c.col()+1);
  2520. }
  2521. else if ( (uint)c.line() < lastLine() )
  2522. {
  2523. removeText(c.line(), c.col(), c.line()+1, 0);
  2524. }
  2525. }
  2526. void KateDocument::paste ( KateView* view )
  2527. {
  2528. TQString s = TQApplication::clipboard()->text();
  2529. if (s.isEmpty())
  2530. return;
  2531. uint lines = s.contains (TQChar ('\n'));
  2532. m_undoDontMerge = true;
  2533. editStart ();
  2534. if (!view->config()->persistentSelection() && view->hasSelection() )
  2535. view->removeSelectedText();
  2536. uint line = view->cursorLine ();
  2537. uint column = view->cursorColumnReal ();
  2538. insertText ( line, column, s, view->blockSelectionMode() );
  2539. editEnd();
  2540. // move cursor right for block select, as the user is moved right internal
  2541. // even in that case, but user expects other behavior in block selection
  2542. // mode !
  2543. if (view->blockSelectionMode())
  2544. view->setCursorPositionInternal (line+lines, column);
  2545. if (m_indenter->canProcessLine()
  2546. && config()->configFlags() & KateDocumentConfig::cfIndentPastedText)
  2547. {
  2548. editStart();
  2549. KateDocCursor begin(line, 0, this);
  2550. KateDocCursor end(line + lines, 0, this);
  2551. m_indenter->processSection (begin, end);
  2552. editEnd();
  2553. }
  2554. if (!view->blockSelectionMode()) emit charactersSemiInteractivelyInserted (line, column, s);
  2555. m_undoDontMerge = true;
  2556. }
  2557. void KateDocument::insertIndentChars ( KateView *view )
  2558. {
  2559. editStart ();
  2560. TQString s;
  2561. if (config()->configFlags() & KateDocument::cfSpaceIndent)
  2562. {
  2563. int width = config()->indentationWidth();
  2564. s.fill (' ', width - (view->cursorColumnReal() % width));
  2565. }
  2566. else
  2567. s.append ('\t');
  2568. insertText (view->cursorLine(), view->cursorColumnReal(), s);
  2569. editEnd ();
  2570. }
  2571. void KateDocument::indent ( KateView *v, uint line, int change)
  2572. {
  2573. editStart ();
  2574. if (!hasSelection())
  2575. {
  2576. // single line
  2577. optimizeLeadingSpace(line, config()->configFlags(), change);
  2578. }
  2579. else
  2580. {
  2581. int sl = v->selStartLine();
  2582. int el = v->selEndLine();
  2583. int ec = v->selEndCol();
  2584. if ((ec == 0) && ((el-1) >= 0))
  2585. {
  2586. el--; /* */
  2587. }
  2588. if (config()->configFlags() & KateDocument::cfKeepIndentProfile && change < 0) {
  2589. // unindent so that the existing indent profile doesn't get screwed
  2590. // if any line we may unindent is already full left, don't do anything
  2591. int adjustedChange = -change;
  2592. for (line = sl; (int) line <= el && adjustedChange > 0; line++) {
  2593. KateTextLine::Ptr textLine = m_buffer->plainLine(line);
  2594. int firstChar = textLine->firstChar();
  2595. if (firstChar >= 0 && (v->lineSelected(line) || v->lineHasSelected(line))) {
  2596. int maxUnindent = textLine->cursorX(firstChar, config()->tabWidth()) / config()->indentationWidth();
  2597. if (maxUnindent < adjustedChange)
  2598. adjustedChange = maxUnindent;
  2599. }
  2600. }
  2601. change = -adjustedChange;
  2602. }
  2603. const bool rts = config()->configFlags() & KateDocumentConfig::cfRemoveTrailingDyn;
  2604. for (line = sl; (int) line <= el; line++) {
  2605. if ((v->lineSelected(line) || v->lineHasSelected(line))
  2606. && (!rts || lineLength(line) > 0)) {
  2607. optimizeLeadingSpace(line, config()->configFlags(), change);
  2608. }
  2609. }
  2610. }
  2611. editEnd ();
  2612. }
  2613. void KateDocument::align(KateView *view, uint line)
  2614. {
  2615. if (m_indenter->canProcessLine())
  2616. {
  2617. editStart ();
  2618. if (!view->hasSelection())
  2619. {
  2620. KateDocCursor curLine(line, 0, this);
  2621. m_indenter->processLine (curLine);
  2622. editEnd ();
  2623. activeView()->setCursorPosition (line, curLine.col());
  2624. }
  2625. else
  2626. {
  2627. m_indenter->processSection (view->selStart(), view->selEnd());
  2628. editEnd ();
  2629. }
  2630. }
  2631. }
  2632. /*
  2633. Optimize the leading whitespace for a single line.
  2634. If change is > 0, it adds indentation units (indentationChars)
  2635. if change is == 0, it only optimizes
  2636. If change is < 0, it removes indentation units
  2637. This will be used to indent, unindent, and optimal-fill a line.
  2638. If excess space is removed depends on the flag cfKeepExtraSpaces
  2639. which has to be set by the user
  2640. */
  2641. void KateDocument::optimizeLeadingSpace(uint line, int flags, int change)
  2642. {
  2643. KateTextLine::Ptr textline = m_buffer->plainLine(line);
  2644. int first_char = textline->firstChar();
  2645. int w = 0;
  2646. if (flags & KateDocument::cfSpaceIndent)
  2647. w = config()->indentationWidth();
  2648. else
  2649. w = config()->tabWidth();
  2650. if (first_char < 0)
  2651. first_char = textline->length();
  2652. int space = textline->cursorX(first_char, config()->tabWidth()) + change * w;
  2653. if (space < 0)
  2654. space = 0;
  2655. if (!(flags & KateDocument::cfKeepExtraSpaces))
  2656. {
  2657. uint extra = space % w;
  2658. space -= extra;
  2659. if (extra && change < 0) {
  2660. // otherwise it unindents too much (e.g. 12 chars when indentation is 8 chars wide)
  2661. space += w;
  2662. }
  2663. }
  2664. //kdDebug(13020) << "replace With Op: " << line << " " << first_char << " " << space << endl;
  2665. replaceWithOptimizedSpace(line, first_char, space, flags);
  2666. }
  2667. void KateDocument::replaceWithOptimizedSpace(uint line, uint upto_column, uint space, int flags)
  2668. {
  2669. uint length;
  2670. TQString new_space;
  2671. if (flags & KateDocument::cfSpaceIndent && ! (flags & KateDocumentConfig::cfMixedIndent) ) {
  2672. length = space;
  2673. new_space.fill(' ', length);
  2674. }
  2675. else {
  2676. length = space / config()->tabWidth();
  2677. new_space.fill('\t', length);
  2678. TQString extra_space;
  2679. extra_space.fill(' ', space % config()->tabWidth());
  2680. length += space % config()->tabWidth();
  2681. new_space += extra_space;
  2682. }
  2683. KateTextLine::Ptr textline = m_buffer->plainLine(line);
  2684. uint change_from;
  2685. for (change_from = 0; change_from < upto_column && change_from < length; change_from++) {
  2686. if (textline->getChar(change_from) != new_space[change_from])
  2687. break;
  2688. }
  2689. editStart();
  2690. if (change_from < upto_column)
  2691. removeText(line, change_from, line, upto_column);
  2692. if (change_from < length)
  2693. insertText(line, change_from, new_space.right(length - change_from));
  2694. editEnd();
  2695. }
  2696. /*
  2697. Remove a given string at the begining
  2698. of the current line.
  2699. */
  2700. bool KateDocument::removeStringFromBegining(int line, TQString &str)
  2701. {
  2702. KateTextLine::Ptr textline = m_buffer->plainLine(line);
  2703. int index = 0;
  2704. bool there = false;
  2705. if (textline->startingWith(str))
  2706. there = true;
  2707. else
  2708. {
  2709. index = textline->firstChar ();
  2710. if ((index >= 0) && (textline->length() >= (index + str.length())) && (textline->string(index, str.length()) == str))
  2711. there = true;
  2712. }
  2713. if (there)
  2714. {
  2715. // Remove some chars
  2716. removeText (line, index, line, index+str.length());
  2717. }
  2718. return there;
  2719. }
  2720. /*
  2721. Remove a given string at the end
  2722. of the current line.
  2723. */
  2724. bool KateDocument::removeStringFromEnd(int line, TQString &str)
  2725. {
  2726. KateTextLine::Ptr textline = m_buffer->plainLine(line);
  2727. int index = 0;
  2728. bool there = false;
  2729. if(textline->endingWith(str))
  2730. {
  2731. index = textline->length() - str.length();
  2732. there = true;
  2733. }
  2734. else
  2735. {
  2736. index = textline->lastChar ()-str.length()+1;
  2737. if ((index >= 0) && (textline->length() >= (index + str.length())) && (textline->string(index, str.length()) == str))
  2738. there = true;
  2739. }
  2740. if (there)
  2741. {
  2742. // Remove some chars
  2743. removeText (line, index, line, index+str.length());
  2744. }
  2745. return there;
  2746. }
  2747. /*
  2748. Add to the current line a comment line mark at
  2749. the begining.
  2750. */
  2751. void KateDocument::addStartLineCommentToSingleLine( int line, int attrib )
  2752. {
  2753. if (highlight()->getCommentSingleLinePosition(attrib)==KateHighlighting::CSLPosColumn0)
  2754. {
  2755. TQString commentLineMark = highlight()->getCommentSingleLineStart( attrib ) + " ";
  2756. insertText (line, 0, commentLineMark);
  2757. }
  2758. else
  2759. {
  2760. TQString commentLineMark=highlight()->getCommentSingleLineStart(attrib);
  2761. KateTextLine::Ptr l = m_buffer->line(line);
  2762. int pos=l->firstChar();
  2763. if (pos >=0)
  2764. insertText(line,pos,commentLineMark);
  2765. }
  2766. }
  2767. /*
  2768. Remove from the current line a comment line mark at
  2769. the begining if there is one.
  2770. */
  2771. bool KateDocument::removeStartLineCommentFromSingleLine( int line, int attrib )
  2772. {
  2773. TQString shortCommentMark = highlight()->getCommentSingleLineStart( attrib );
  2774. TQString longCommentMark = shortCommentMark + " ";
  2775. editStart();
  2776. // Try to remove the long comment mark first
  2777. bool removed = (removeStringFromBegining(line, longCommentMark)
  2778. || removeStringFromBegining(line, shortCommentMark));
  2779. editEnd();
  2780. return removed;
  2781. }
  2782. /*
  2783. Add to the current line a start comment mark at the
  2784. begining and a stop comment mark at the end.
  2785. */
  2786. void KateDocument::addStartStopCommentToSingleLine( int line, int attrib )
  2787. {
  2788. TQString startCommentMark = highlight()->getCommentStart( attrib ) + " ";
  2789. TQString stopCommentMark = " " + highlight()->getCommentEnd( attrib );
  2790. editStart();
  2791. // Add the start comment mark
  2792. insertText (line, 0, startCommentMark);
  2793. // Go to the end of the line
  2794. int col = m_buffer->plainLine(line)->length();
  2795. // Add the stop comment mark
  2796. insertText (line, col, stopCommentMark);
  2797. editEnd();
  2798. }
  2799. /*
  2800. Remove from the current line a start comment mark at
  2801. the begining and a stop comment mark at the end.
  2802. */
  2803. bool KateDocument::removeStartStopCommentFromSingleLine( int line, int attrib )
  2804. {
  2805. TQString shortStartCommentMark = highlight()->getCommentStart( attrib );
  2806. TQString longStartCommentMark = shortStartCommentMark + " ";
  2807. TQString shortStopCommentMark = highlight()->getCommentEnd( attrib );
  2808. TQString longStopCommentMark = " " + shortStopCommentMark;
  2809. editStart();
  2810. #ifdef __GNUC__
  2811. #warning "that's a bad idea, can lead to stray endings, FIXME"
  2812. #endif
  2813. // Try to remove the long start comment mark first
  2814. bool removedStart = (removeStringFromBegining(line, longStartCommentMark)
  2815. || removeStringFromBegining(line, shortStartCommentMark));
  2816. bool removedStop = false;
  2817. if (removedStart)
  2818. {
  2819. // Try to remove the long stop comment mark first
  2820. removedStop = (removeStringFromEnd(line, longStopCommentMark)
  2821. || removeStringFromEnd(line, shortStopCommentMark));
  2822. }
  2823. editEnd();
  2824. return (removedStart || removedStop);
  2825. }
  2826. /*
  2827. Add to the current selection a start comment
  2828. mark at the begining and a stop comment mark
  2829. at the end.
  2830. */
  2831. void KateDocument::addStartStopCommentToSelection( KateView *view, int attrib )
  2832. {
  2833. TQString startComment = highlight()->getCommentStart( attrib );
  2834. TQString endComment = highlight()->getCommentEnd( attrib );
  2835. int sl = view->selStartLine();
  2836. int el = view->selEndLine();
  2837. int sc = view->selStartCol();
  2838. int ec = view->selEndCol();
  2839. if ((ec == 0) && ((el-1) >= 0))
  2840. {
  2841. el--;
  2842. ec = m_buffer->plainLine (el)->length();
  2843. }
  2844. editStart();
  2845. insertText (el, ec, endComment);
  2846. insertText (sl, sc, startComment);
  2847. editEnd ();
  2848. // Set the new selection
  2849. ec += endComment.length() + ( (el == sl) ? startComment.length() : 0 );
  2850. view->setSelection(sl, sc, el, ec);
  2851. }
  2852. /*
  2853. Add to the current selection a comment line
  2854. mark at the begining of each line.
  2855. */
  2856. void KateDocument::addStartLineCommentToSelection( KateView *view, int attrib )
  2857. {
  2858. TQString commentLineMark = highlight()->getCommentSingleLineStart( attrib ) + " ";
  2859. int sl = view->selStartLine();
  2860. int el = view->selEndLine();
  2861. if ((view->selEndCol() == 0) && ((el-1) >= 0))
  2862. {
  2863. el--;
  2864. }
  2865. editStart();
  2866. // For each line of the selection
  2867. for (int z = el; z >= sl; z--) {
  2868. //insertText (z, 0, commentLineMark);
  2869. addStartLineCommentToSingleLine(z, attrib );
  2870. }
  2871. editEnd ();
  2872. // Set the new selection
  2873. KateDocCursor end (view->selEnd());
  2874. end.setCol(view->selEndCol() + ((el == view->selEndLine()) ? commentLineMark.length() : 0) );
  2875. view->setSelection(view->selStartLine(), 0, end.line(), end.col());
  2876. }
  2877. bool KateDocument::nextNonSpaceCharPos(int &line, int &col)
  2878. {
  2879. for(; line < (int)m_buffer->count(); line++) {
  2880. KateTextLine::Ptr textLine = m_buffer->plainLine(line);
  2881. if (!textLine)
  2882. break;
  2883. col = textLine->nextNonSpaceChar(col);
  2884. if(col != -1)
  2885. return true; // Next non-space char found
  2886. col = 0;
  2887. }
  2888. // No non-space char found
  2889. line = -1;
  2890. col = -1;
  2891. return false;
  2892. }
  2893. bool KateDocument::previousNonSpaceCharPos(int &line, int &col)
  2894. {
  2895. while(true)
  2896. {
  2897. KateTextLine::Ptr textLine = m_buffer->plainLine(line);
  2898. if (!textLine)
  2899. break;
  2900. col = textLine->previousNonSpaceChar(col);
  2901. if(col != -1) return true;
  2902. if(line == 0) return false;
  2903. --line;
  2904. col = textLine->length();
  2905. }
  2906. // No non-space char found
  2907. line = -1;
  2908. col = -1;
  2909. return false;
  2910. }
  2911. /*
  2912. Remove from the selection a start comment mark at
  2913. the begining and a stop comment mark at the end.
  2914. */
  2915. bool KateDocument::removeStartStopCommentFromSelection( KateView *view, int attrib )
  2916. {
  2917. TQString startComment = highlight()->getCommentStart( attrib );
  2918. TQString endComment = highlight()->getCommentEnd( attrib );
  2919. int sl = kMax<int> (0, view->selStartLine());
  2920. int el = kMin<int> (view->selEndLine(), lastLine());
  2921. int sc = view->selStartCol();
  2922. int ec = view->selEndCol();
  2923. // The selection ends on the char before selectEnd
  2924. if (ec != 0) {
  2925. ec--;
  2926. } else {
  2927. if (el > 0) {
  2928. el--;
  2929. ec = m_buffer->plainLine(el)->length() - 1;
  2930. }
  2931. }
  2932. int startCommentLen = startComment.length();
  2933. int endCommentLen = endComment.length();
  2934. // had this been perl or sed: s/^\s*$startComment(.+?)$endComment\s*/$1/
  2935. bool remove = nextNonSpaceCharPos(sl, sc)
  2936. && m_buffer->plainLine(sl)->stringAtPos(sc, startComment)
  2937. && previousNonSpaceCharPos(el, ec)
  2938. && ( (ec - endCommentLen + 1) >= 0 )
  2939. && m_buffer->plainLine(el)->stringAtPos(ec - endCommentLen + 1, endComment);
  2940. if (remove) {
  2941. editStart();
  2942. removeText (el, ec - endCommentLen + 1, el, ec + 1);
  2943. removeText (sl, sc, sl, sc + startCommentLen);
  2944. editEnd ();
  2945. // set new selection not necessary, as the selection cursors are KateSuperCursors
  2946. }
  2947. return remove;
  2948. }
  2949. bool KateDocument::removeStartStopCommentFromRegion(const KateTextCursor &start,const KateTextCursor &end,int attrib)
  2950. {
  2951. TQString startComment = highlight()->getCommentStart( attrib );
  2952. TQString endComment = highlight()->getCommentEnd( attrib );
  2953. int startCommentLen = startComment.length();
  2954. int endCommentLen = endComment.length();
  2955. bool remove = m_buffer->plainLine(start.line())->stringAtPos(start.col(), startComment)
  2956. && ( (end.col() - endCommentLen ) >= 0 )
  2957. && m_buffer->plainLine(end.line())->stringAtPos(end.col() - endCommentLen , endComment);
  2958. if (remove) {
  2959. editStart();
  2960. removeText(end.line(),end.col()-endCommentLen,end.line(),end.col());
  2961. removeText(start.line(),start.col(),start.line(),start.col()+startCommentLen);
  2962. editEnd();
  2963. }
  2964. return remove;
  2965. }
  2966. /*
  2967. Remove from the begining of each line of the
  2968. selection a start comment line mark.
  2969. */
  2970. bool KateDocument::removeStartLineCommentFromSelection( KateView *view, int attrib )
  2971. {
  2972. TQString shortCommentMark = highlight()->getCommentSingleLineStart( attrib );
  2973. TQString longCommentMark = shortCommentMark + " ";
  2974. int sl = view->selStartLine();
  2975. int el = view->selEndLine();
  2976. if ((view->selEndCol() == 0) && ((el-1) >= 0))
  2977. {
  2978. el--;
  2979. }
  2980. // Find out how many char will be removed from the last line
  2981. int removeLength = 0;
  2982. if (m_buffer->plainLine(el)->startingWith(longCommentMark))
  2983. removeLength = longCommentMark.length();
  2984. else if (m_buffer->plainLine(el)->startingWith(shortCommentMark))
  2985. removeLength = shortCommentMark.length();
  2986. bool removed = false;
  2987. editStart();
  2988. // For each line of the selection
  2989. for (int z = el; z >= sl; z--)
  2990. {
  2991. // Try to remove the long comment mark first
  2992. removed = (removeStringFromBegining(z, longCommentMark)
  2993. || removeStringFromBegining(z, shortCommentMark)
  2994. || removed);
  2995. }
  2996. editEnd();
  2997. // updating selection already done by the KateSuperCursors
  2998. return removed;
  2999. }
  3000. /*
  3001. Comment or uncomment the selection or the current
  3002. line if there is no selection.
  3003. */
  3004. void KateDocument::comment( KateView *v, uint line,uint column, int change)
  3005. {
  3006. // We need to check that we can sanely comment the selectino or region.
  3007. // It is if the attribute of the first and last character of the range to
  3008. // comment belongs to the same language definition.
  3009. // for lines with no text, we need the attribute for the lines context.
  3010. bool hassel = v->hasSelection();
  3011. int startAttrib, endAttrib;
  3012. if ( hassel )
  3013. {
  3014. KateTextLine::Ptr ln = kateTextLine( v->selStartLine() );
  3015. int l = v->selStartLine(), c = v->selStartCol();
  3016. startAttrib = nextNonSpaceCharPos( l, c ) ? kateTextLine( l )->attribute( c ) : 0;
  3017. ln = kateTextLine( v->selEndLine() );
  3018. l = v->selEndLine(), c = v->selEndCol();
  3019. endAttrib = previousNonSpaceCharPos( l, c ) ? kateTextLine( l )->attribute( c ) : 0;
  3020. }
  3021. else
  3022. {
  3023. KateTextLine::Ptr ln = kateTextLine( line );
  3024. if ( ln->length() )
  3025. {
  3026. startAttrib = ln->attribute( ln->firstChar() );
  3027. endAttrib = ln->attribute( ln->lastChar() );
  3028. }
  3029. else
  3030. {
  3031. int l = line, c = 0;
  3032. if ( nextNonSpaceCharPos( l, c ) || previousNonSpaceCharPos( l, c ) )
  3033. startAttrib = endAttrib = kateTextLine( l )->attribute( c );
  3034. else
  3035. startAttrib = endAttrib = 0;
  3036. }
  3037. }
  3038. if ( ! highlight()->canComment( startAttrib, endAttrib ) )
  3039. {
  3040. kdDebug(13020)<<"canComment( "<<startAttrib<<", "<<endAttrib<<" ) returned false!"<<endl;
  3041. return;
  3042. }
  3043. bool hasStartLineCommentMark = !(highlight()->getCommentSingleLineStart( startAttrib ).isEmpty());
  3044. bool hasStartStopCommentMark = ( !(highlight()->getCommentStart( startAttrib ).isEmpty())
  3045. && !(highlight()->getCommentEnd( endAttrib ).isEmpty()) );
  3046. bool removed = false;
  3047. if (change > 0) // comment
  3048. {
  3049. if ( !hassel )
  3050. {
  3051. if ( hasStartLineCommentMark )
  3052. addStartLineCommentToSingleLine( line, startAttrib );
  3053. else if ( hasStartStopCommentMark )
  3054. addStartStopCommentToSingleLine( line, startAttrib );
  3055. }
  3056. else
  3057. {
  3058. // anders: prefer single line comment to avoid nesting probs
  3059. // If the selection starts after first char in the first line
  3060. // or ends before the last char of the last line, we may use
  3061. // multiline comment markers.
  3062. // TODO We should try to detect nesting.
  3063. // - if selection ends at col 0, most likely she wanted that
  3064. // line ignored
  3065. if ( hasStartStopCommentMark &&
  3066. ( !hasStartLineCommentMark || (
  3067. ( v->selStartCol() > m_buffer->plainLine( v->selStartLine() )->firstChar() ) ||
  3068. ( v->selEndCol() < ((int)m_buffer->plainLine( v->selEndLine() )->length()) )
  3069. ) ) )
  3070. addStartStopCommentToSelection( v, startAttrib );
  3071. else if ( hasStartLineCommentMark )
  3072. addStartLineCommentToSelection( v, startAttrib );
  3073. }
  3074. }
  3075. else // uncomment
  3076. {
  3077. if ( !hassel )
  3078. {
  3079. removed = ( hasStartLineCommentMark
  3080. && removeStartLineCommentFromSingleLine( line, startAttrib ) )
  3081. || ( hasStartStopCommentMark
  3082. && removeStartStopCommentFromSingleLine( line, startAttrib ) );
  3083. if ((!removed) && foldingTree()) {
  3084. kdDebug(13020)<<"easy approach for uncommenting did not work, trying harder (folding tree)"<<endl;
  3085. int commentRegion=(highlight()->commentRegion(startAttrib));
  3086. if (commentRegion){
  3087. KateCodeFoldingNode *n=foldingTree()->findNodeForPosition(line,column);
  3088. if (n) {
  3089. KateTextCursor start,end;
  3090. if ((n->nodeType()==commentRegion) && n->getBegin(foldingTree(), &start) && n->getEnd(foldingTree(), &end)) {
  3091. kdDebug(13020)<<"Enclosing region found:"<<start.col()<<"/"<<start.line()<<"-"<<end.col()<<"/"<<end.line()<<endl;
  3092. removeStartStopCommentFromRegion(start,end,startAttrib);
  3093. } else {
  3094. kdDebug(13020)<<"Enclosing region found, but not valid"<<endl;
  3095. kdDebug(13020)<<"Region found: "<<n->nodeType()<<" region needed: "<<commentRegion<<endl;
  3096. }
  3097. //perhaps nested regions should be hadled here too...
  3098. } else kdDebug(13020)<<"No enclosing region found"<<endl;
  3099. } else kdDebug(13020)<<"No comment region specified for current hl"<<endl;
  3100. }
  3101. }
  3102. else
  3103. {
  3104. // anders: this seems like it will work with above changes :)
  3105. removed = ( hasStartLineCommentMark
  3106. && removeStartLineCommentFromSelection( v, startAttrib ) )
  3107. || ( hasStartStopCommentMark
  3108. && removeStartStopCommentFromSelection( v, startAttrib ) );
  3109. }
  3110. }
  3111. }
  3112. void KateDocument::transform( KateView *v, const KateTextCursor &c,
  3113. KateDocument::TextTransform t )
  3114. {
  3115. editStart();
  3116. uint cl( c.line() ), cc( c.col() );
  3117. bool selectionRestored = false;
  3118. if ( hasSelection() )
  3119. {
  3120. // cache the selection and cursor, so we can be sure to restore.
  3121. KateTextCursor selstart = v->selStart();
  3122. KateTextCursor selend = v->selEnd();
  3123. int ln = v->selStartLine();
  3124. while ( ln <= selend.line() )
  3125. {
  3126. uint start, end;
  3127. start = (ln == selstart.line() || v->blockSelectionMode()) ?
  3128. selstart.col() : 0;
  3129. end = (ln == selend.line() || v->blockSelectionMode()) ?
  3130. selend.col() : lineLength( ln );
  3131. if ( start > end )
  3132. {
  3133. uint t = start;
  3134. start = end;
  3135. end = t;
  3136. }
  3137. TQString s = text( ln, start, ln, end );
  3138. TQString o = s;
  3139. if ( t == Uppercase )
  3140. s = s.upper();
  3141. else if ( t == Lowercase )
  3142. s = s.lower();
  3143. else // Capitalize
  3144. {
  3145. KateTextLine::Ptr l = m_buffer->plainLine( ln );
  3146. uint p ( 0 );
  3147. while( p < s.length() )
  3148. {
  3149. // If bol or the character before is not in a word, up this one:
  3150. // 1. if both start and p is 0, upper char.
  3151. // 2. if blockselect or first line, and p == 0 and start-1 is not in a word, upper
  3152. // 3. if p-1 is not in a word, upper.
  3153. if ( ( ! start && ! p ) ||
  3154. ( ( ln == selstart.line() || v->blockSelectionMode() ) &&
  3155. ! p && ! highlight()->isInWord( l->getChar( start - 1 )) ) ||
  3156. ( p && ! highlight()->isInWord( s.at( p-1 ) ) )
  3157. )
  3158. s[p] = s.at(p).upper();
  3159. p++;
  3160. }
  3161. }
  3162. if ( o != s )
  3163. {
  3164. removeText( ln, start, ln, end );
  3165. insertText( ln, start, s );
  3166. }
  3167. ln++;
  3168. }
  3169. // restore selection
  3170. v->setSelection( selstart, selend );
  3171. selectionRestored = true;
  3172. } else { // no selection
  3173. TQString o = text( cl, cc, cl, cc + 1 );
  3174. TQString s;
  3175. int n ( cc );
  3176. switch ( t ) {
  3177. case Uppercase:
  3178. s = o.upper();
  3179. break;
  3180. case Lowercase:
  3181. s = o.lower();
  3182. break;
  3183. case Capitalize:
  3184. {
  3185. KateTextLine::Ptr l = m_buffer->plainLine( cl );
  3186. while ( n > 0 && highlight()->isInWord( l->getChar( n-1 ), l->attribute( n-1 ) ) )
  3187. n--;
  3188. o = text( cl, n, cl, n + 1 );
  3189. s = o.upper();
  3190. }
  3191. break;
  3192. default:
  3193. break;
  3194. }
  3195. if ( s != o )
  3196. {
  3197. removeText( cl, n, cl, n+1 );
  3198. insertText( cl, n, s );
  3199. }
  3200. }
  3201. editEnd();
  3202. if ( ! selectionRestored )
  3203. v->setCursorPosition( cl, cc );
  3204. }
  3205. void KateDocument::joinLines( uint first, uint last )
  3206. {
  3207. // if ( first == last ) last += 1;
  3208. editStart();
  3209. int line( first );
  3210. while ( first < last )
  3211. {
  3212. // Normalize the whitespace in the joined lines by making sure there's
  3213. // always exactly one space between the joined lines
  3214. // This cannot be done in editUnwrapLine, because we do NOT want this
  3215. // behaviour when deleting from the start of a line, just when explicitly
  3216. // calling the join command
  3217. KateTextLine::Ptr l = m_buffer->line( line );
  3218. KateTextLine::Ptr tl = m_buffer->line( line + 1 );
  3219. if ( !l || !tl )
  3220. {
  3221. editEnd();
  3222. return;
  3223. }
  3224. int pos = tl->firstChar();
  3225. if ( pos >= 0 )
  3226. {
  3227. if (pos != 0)
  3228. editRemoveText( line + 1, 0, pos );
  3229. if ( !( l->length() == 0 || l->getChar( l->length() - 1 ).isSpace() ) )
  3230. editInsertText( line + 1, 0, " " );
  3231. }
  3232. else
  3233. {
  3234. // Just remove the whitespace and let Kate handle the rest
  3235. editRemoveText( line + 1, 0, tl->length() );
  3236. }
  3237. editUnWrapLine( line );
  3238. first++;
  3239. }
  3240. editEnd();
  3241. }
  3242. TQString KateDocument::getWord( const KateTextCursor& cursor ) {
  3243. int start, end, len;
  3244. KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
  3245. len = textLine->length();
  3246. start = end = cursor.col();
  3247. if (start > len) // Probably because of non-wrapping cursor mode.
  3248. return TQString("");
  3249. while (start > 0 && highlight()->isInWord(textLine->getChar(start - 1), textLine->attribute(start - 1))) start--;
  3250. while (end < len && highlight()->isInWord(textLine->getChar(end), textLine->attribute(end))) end++;
  3251. len = end - start;
  3252. return TQString(&textLine->text()[start], len);
  3253. }
  3254. void KateDocument::tagLines(int start, int end)
  3255. {
  3256. for (uint z = 0; z < m_views.count(); z++)
  3257. m_views.at(z)->tagLines (start, end, true);
  3258. }
  3259. void KateDocument::tagLines(KateTextCursor start, KateTextCursor end)
  3260. {
  3261. // May need to switch start/end cols if in block selection mode
  3262. if (blockSelectionMode() && start.col() > end.col()) {
  3263. int sc = start.col();
  3264. start.setCol(end.col());
  3265. end.setCol(sc);
  3266. }
  3267. for (uint z = 0; z < m_views.count(); z++)
  3268. m_views.at(z)->tagLines(start, end, true);
  3269. }
  3270. void KateDocument::repaintViews(bool paintOnlyDirty)
  3271. {
  3272. for (uint z = 0; z < m_views.count(); z++)
  3273. m_views.at(z)->repaintText(paintOnlyDirty);
  3274. }
  3275. void KateDocument::tagAll()
  3276. {
  3277. for (uint z = 0; z < m_views.count(); z++)