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++)
  3278. {
  3279. m_views.at(z)->tagAll();
  3280. m_views.at(z)->updateView (true);
  3281. }
  3282. }
  3283. uint KateDocument::configFlags ()
  3284. {
  3285. return config()->configFlags();
  3286. }
  3287. void KateDocument::setConfigFlags (uint flags)
  3288. {
  3289. config()->setConfigFlags(flags);
  3290. }
  3291. inline bool isStartBracket( const TQChar& c ) { return c == '{' || c == '[' || c == '('; }
  3292. inline bool isEndBracket ( const TQChar& c ) { return c == '}' || c == ']' || c == ')'; }
  3293. inline bool isBracket ( const TQChar& c ) { return isStartBracket( c ) || isEndBracket( c ); }
  3294. /*
  3295. Bracket matching uses the following algorithm:
  3296. If in overwrite mode, match the bracket currently underneath the cursor.
  3297. Otherwise, if the character to the right of the cursor is an starting bracket,
  3298. match it. Otherwise if the character to the left of the cursor is a
  3299. ending bracket, match it. Otherwise, if the the character to the left
  3300. of the cursor is an starting bracket, match it. Otherwise, if the character
  3301. to the right of the cursor is an ending bracket, match it. Otherwise, don't
  3302. match anything.
  3303. */
  3304. void KateDocument::newBracketMark( const KateTextCursor& cursor, KateBracketRange& bm, int maxLines )
  3305. {
  3306. bm.setValid(false);
  3307. bm.start() = cursor;
  3308. if( !findMatchingBracket( bm.start(), bm.end(), maxLines ) )
  3309. return;
  3310. bm.setValid(true);
  3311. const int tw = config()->tabWidth();
  3312. const int indentStart = m_buffer->plainLine(bm.start().line())->indentDepth(tw);
  3313. const int indentEnd = m_buffer->plainLine(bm.end().line())->indentDepth(tw);
  3314. bm.setIndentMin(kMin(indentStart, indentEnd));
  3315. }
  3316. bool KateDocument::findMatchingBracket( KateTextCursor& start, KateTextCursor& end, int maxLines )
  3317. {
  3318. KateTextLine::Ptr textLine = m_buffer->plainLine( start.line() );
  3319. if( !textLine )
  3320. return false;
  3321. TQChar right = textLine->getChar( start.col() );
  3322. TQChar left = textLine->getChar( start.col() - 1 );
  3323. TQChar bracket;
  3324. if ( config()->configFlags() & cfOvr ) {
  3325. if( isBracket( right ) ) {
  3326. bracket = right;
  3327. } else {
  3328. return false;
  3329. }
  3330. } else if ( isStartBracket( right ) ) {
  3331. bracket = right;
  3332. } else if ( isEndBracket( left ) ) {
  3333. start.setCol(start.col() - 1);
  3334. bracket = left;
  3335. } else if ( isBracket( left ) ) {
  3336. start.setCol(start.col() - 1);
  3337. bracket = left;
  3338. } else if ( isBracket( right ) ) {
  3339. bracket = right;
  3340. } else {
  3341. return false;
  3342. }
  3343. TQChar opposite;
  3344. switch( bracket ) {
  3345. case '{': opposite = '}'; break;
  3346. case '}': opposite = '{'; break;
  3347. case '[': opposite = ']'; break;
  3348. case ']': opposite = '['; break;
  3349. case '(': opposite = ')'; break;
  3350. case ')': opposite = '('; break;
  3351. default: return false;
  3352. }
  3353. bool forward = isStartBracket( bracket );
  3354. int startAttr = textLine->attribute( start.col() );
  3355. uint count = 0;
  3356. int lines = 0;
  3357. end = start;
  3358. while( true ) {
  3359. /* Increment or decrement, check base cases */
  3360. if( forward ) {
  3361. end.setCol(end.col() + 1);
  3362. if( end.col() >= lineLength( end.line() ) ) {
  3363. if( end.line() >= (int)lastLine() )
  3364. return false;
  3365. end.setPos(end.line() + 1, 0);
  3366. textLine = m_buffer->plainLine( end.line() );
  3367. lines++;
  3368. }
  3369. } else {
  3370. end.setCol(end.col() - 1);
  3371. if( end.col() < 0 ) {
  3372. if( end.line() <= 0 )
  3373. return false;
  3374. end.setLine(end.line() - 1);
  3375. end.setCol(lineLength( end.line() ) - 1);
  3376. textLine = m_buffer->plainLine( end.line() );
  3377. lines++;
  3378. }
  3379. }
  3380. if ((maxLines != -1) && (lines > maxLines))
  3381. return false;
  3382. /* Easy way to skip comments */
  3383. if( textLine->attribute( end.col() ) != startAttr )
  3384. continue;
  3385. /* Check for match */
  3386. TQChar c = textLine->getChar( end.col() );
  3387. if( c == bracket ) {
  3388. count++;
  3389. } else if( c == opposite ) {
  3390. if( count == 0 )
  3391. return true;
  3392. count--;
  3393. }
  3394. }
  3395. }
  3396. void KateDocument::guiActivateEvent( KParts::GUIActivateEvent *ev )
  3397. {
  3398. KParts::ReadWritePart::guiActivateEvent( ev );
  3399. if ( ev->activated() )
  3400. emit selectionChanged();
  3401. }
  3402. void KateDocument::setDocName (TQString name )
  3403. {
  3404. if ( name == m_docName )
  3405. return;
  3406. if ( !name.isEmpty() )
  3407. {
  3408. // TODO check for similarly named documents
  3409. m_docName = name;
  3410. updateFileType (KateFactory::self()->fileTypeManager()->fileType (this));
  3411. emit nameChanged((Kate::Document *) this);
  3412. return;
  3413. }
  3414. // if the name is set, and starts with FILENAME, it should not be changed!
  3415. if ( ! url().isEmpty() && m_docName.startsWith( url().filename() ) ) return;
  3416. int count = -1;
  3417. for (uint z=0; z < KateFactory::self()->documents()->count(); z++)
  3418. {
  3419. if ( (KateFactory::self()->documents()->at(z) != this) && (KateFactory::self()->documents()->at(z)->url().filename() == url().filename()) )
  3420. if ( KateFactory::self()->documents()->at(z)->m_docNameNumber > count )
  3421. count = KateFactory::self()->documents()->at(z)->m_docNameNumber;
  3422. }
  3423. m_docNameNumber = count + 1;
  3424. m_docName = url().filename();
  3425. if (m_docName.isEmpty())
  3426. m_docName = i18n ("Untitled");
  3427. if (m_docNameNumber > 0)
  3428. m_docName = TQString(m_docName + " (%1)").arg(m_docNameNumber+1);
  3429. updateFileType (KateFactory::self()->fileTypeManager()->fileType (this));
  3430. emit nameChanged ((Kate::Document *) this);
  3431. }
  3432. void KateDocument::slotModifiedOnDisk( Kate::View * /*v*/ )
  3433. {
  3434. if ( m_isasking < 0 )
  3435. {
  3436. m_isasking = 0;
  3437. return;
  3438. }
  3439. if ( !s_fileChangedDialogsActivated || m_isasking )
  3440. return;
  3441. if (m_modOnHd && !url().isEmpty())
  3442. {
  3443. m_isasking = 1;
  3444. KateModOnHdPrompt p( this, m_modOnHdReason, reasonedMOHString(), widget() );
  3445. switch ( p.exec() )
  3446. {
  3447. case KateModOnHdPrompt::Save:
  3448. {
  3449. m_modOnHd = false;
  3450. KEncodingFileDialog::Result res=KEncodingFileDialog::getSaveURLAndEncoding(config()->encoding(),
  3451. url().url(),TQString::null,widget(),i18n("Save File"));
  3452. kdDebug(13020)<<"got "<<res.URLs.count()<<" URLs"<<endl;
  3453. if( ! res.URLs.isEmpty() && ! res.URLs.first().isEmpty() && checkOverwrite( res.URLs.first() ) )
  3454. {
  3455. setEncoding( res.encoding );
  3456. if( ! saveAs( res.URLs.first() ) )
  3457. {
  3458. KMessageBox::error( widget(), i18n("Save failed") );
  3459. m_modOnHd = true;
  3460. }
  3461. else
  3462. emit modifiedOnDisc( this, false, 0 );
  3463. }
  3464. else // the save as dialog was cancelled, we are still modified on disk
  3465. {
  3466. m_modOnHd = true;
  3467. }
  3468. m_isasking = 0;
  3469. break;
  3470. }
  3471. case KateModOnHdPrompt::Reload:
  3472. m_modOnHd = false;
  3473. emit modifiedOnDisc( this, false, 0 );
  3474. reloadFile();
  3475. m_isasking = 0;
  3476. break;
  3477. case KateModOnHdPrompt::Ignore:
  3478. m_modOnHd = false;
  3479. emit modifiedOnDisc( this, false, 0 );
  3480. m_isasking = 0;
  3481. break;
  3482. case KateModOnHdPrompt::Overwrite:
  3483. m_modOnHd = false;
  3484. emit modifiedOnDisc( this, false, 0 );
  3485. m_isasking = 0;
  3486. save();
  3487. break;
  3488. default: // cancel: ignore next focus event
  3489. m_isasking = -1;
  3490. }
  3491. }
  3492. }
  3493. void KateDocument::setModifiedOnDisk( int reason )
  3494. {
  3495. m_modOnHdReason = reason;
  3496. m_modOnHd = (reason > 0);
  3497. emit modifiedOnDisc( this, (reason > 0), reason );
  3498. }
  3499. class KateDocumentTmpMark
  3500. {
  3501. public:
  3502. TQString line;
  3503. KTextEditor::Mark mark;
  3504. };
  3505. void KateDocument::reloadFile()
  3506. {
  3507. if ( !url().isEmpty() )
  3508. {
  3509. if (m_modOnHd && s_fileChangedDialogsActivated)
  3510. {
  3511. int i = KMessageBox::warningYesNoCancel
  3512. (0, reasonedMOHString() + "\n\n" + i18n("What do you want to do?"),
  3513. i18n("File Was Changed on Disk"), i18n("&Reload File"), i18n("&Ignore Changes"));
  3514. if ( i != KMessageBox::Yes)
  3515. {
  3516. if (i == KMessageBox::No)
  3517. {
  3518. m_modOnHd = false;
  3519. m_modOnHdReason = 0;
  3520. emit modifiedOnDisc (this, m_modOnHd, 0);
  3521. }
  3522. return;
  3523. }
  3524. }
  3525. TQValueList<KateDocumentTmpMark> tmp;
  3526. for( TQIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
  3527. {
  3528. KateDocumentTmpMark m;
  3529. m.line = textLine (it.current()->line);
  3530. m.mark = *it.current();
  3531. tmp.append (m);
  3532. }
  3533. uint mode = hlMode ();
  3534. bool byUser = hlSetByUser;
  3535. m_storedVariables.clear();
  3536. m_reloading = true;
  3537. TQValueList<int> lines, cols;
  3538. for ( uint i=0; i < m_views.count(); i++ )
  3539. {
  3540. lines.append( m_views.at( i )->cursorLine() );
  3541. cols.append( m_views.at( i )->cursorColumn() );
  3542. }
  3543. KateDocument::openURL( url() );
  3544. for ( uint i=0; i < m_views.count(); i++ )
  3545. m_views.at( i )->setCursorPositionInternal( lines[ i ], cols[ i ], m_config->tabWidth(), false );
  3546. m_reloading = false;
  3547. for ( TQValueList<int>::size_type z=0; z < tmp.size(); z++ )
  3548. {
  3549. if (z < numLines())
  3550. {
  3551. if (textLine(tmp[z].mark.line) == tmp[z].line)
  3552. setMark (tmp[z].mark.line, tmp[z].mark.type);
  3553. }
  3554. }
  3555. if (byUser)
  3556. setHlMode (mode);
  3557. }
  3558. }
  3559. void KateDocument::flush ()
  3560. {
  3561. closeURL ();
  3562. }
  3563. void KateDocument::setWordWrap (bool on)
  3564. {
  3565. config()->setWordWrap (on);
  3566. }
  3567. bool KateDocument::wordWrap ()
  3568. {
  3569. return config()->wordWrap ();
  3570. }
  3571. void KateDocument::setWordWrapAt (uint col)
  3572. {
  3573. config()->setWordWrapAt (col);
  3574. }
  3575. unsigned int KateDocument::wordWrapAt ()
  3576. {
  3577. return config()->wordWrapAt ();
  3578. }
  3579. void KateDocument::applyWordWrap ()
  3580. {
  3581. // dummy to make the API happy
  3582. }
  3583. void KateDocument::setPageUpDownMovesCursor (bool on)
  3584. {
  3585. config()->setPageUpDownMovesCursor (on);
  3586. }
  3587. bool KateDocument::pageUpDownMovesCursor ()
  3588. {
  3589. return config()->pageUpDownMovesCursor ();
  3590. }
  3591. void KateDocument::dumpRegionTree()
  3592. {
  3593. m_buffer->foldingTree()->debugDump();
  3594. }
  3595. //END
  3596. //BEGIN KTextEditor::CursorInterface stuff
  3597. KTextEditor::Cursor *KateDocument::createCursor ( )
  3598. {
  3599. return new KateSuperCursor (this, false, 0, 0, this);
  3600. }
  3601. void KateDocument::tagArbitraryLines(KateView* view, KateSuperRange* range)
  3602. {
  3603. if (view)
  3604. view->tagLines(range->start(), range->end());
  3605. else
  3606. tagLines(range->start(), range->end());
  3607. }
  3608. void KateDocument::lineInfo (KateLineInfo *info, unsigned int line)
  3609. {
  3610. m_buffer->lineInfo(info,line);
  3611. }
  3612. KateCodeFoldingTree *KateDocument::foldingTree ()
  3613. {
  3614. return m_buffer->foldingTree();
  3615. }
  3616. void KateDocument::setEncoding (const TQString &e)
  3617. {
  3618. if ( m_encodingSticky )
  3619. return;
  3620. TQString ce = m_config->encoding().lower();
  3621. if ( e.lower() == ce )
  3622. return;
  3623. m_config->setEncoding( e );
  3624. if ( ! m_loading )
  3625. reloadFile();
  3626. }
  3627. TQString KateDocument::encoding() const
  3628. {
  3629. return m_config->encoding();
  3630. }
  3631. void KateDocument::updateConfig ()
  3632. {
  3633. emit undoChanged ();
  3634. tagAll();
  3635. for (KateView * view = m_views.first(); view != 0L; view = m_views.next() )
  3636. {
  3637. view->updateDocumentConfig ();
  3638. }
  3639. // switch indenter if needed
  3640. if (m_indenter->modeNumber() != m_config->indentationMode())
  3641. {
  3642. delete m_indenter;
  3643. m_indenter = KateAutoIndent::createIndenter ( this, m_config->indentationMode() );
  3644. }
  3645. m_indenter->updateConfig();
  3646. m_buffer->setTabWidth (config()->tabWidth());
  3647. // plugins
  3648. for (uint i=0; i<KateFactory::self()->plugins().count(); i++)
  3649. {
  3650. if (config()->plugin (i))
  3651. loadPlugin (i);
  3652. else
  3653. unloadPlugin (i);
  3654. }
  3655. }
  3656. //BEGIN Variable reader
  3657. // "local variable" feature by anders, 2003
  3658. /* TODO
  3659. add config options (how many lines to read, on/off)
  3660. add interface for plugins/apps to set/get variables
  3661. add view stuff
  3662. */
  3663. TQRegExp KateDocument::kvLine = TQRegExp("kate:(.*)");
  3664. TQRegExp KateDocument::kvLineWildcard = TQRegExp("kate-wildcard\\((.*)\\):(.*)");
  3665. TQRegExp KateDocument::kvLineMime = TQRegExp("kate-mimetype\\((.*)\\):(.*)");
  3666. TQRegExp KateDocument::kvVar = TQRegExp("([\\w\\-]+)\\s+([^;]+)");
  3667. void KateDocument::readVariables(bool onlyViewAndRenderer)
  3668. {
  3669. if (!onlyViewAndRenderer)
  3670. m_config->configStart();
  3671. // views!
  3672. KateView *v;
  3673. for (v = m_views.first(); v != 0L; v= m_views.next() )
  3674. {
  3675. v->config()->configStart();
  3676. v->renderer()->config()->configStart();
  3677. }
  3678. // read a number of lines in the top/bottom of the document
  3679. for (uint i=0; i < kMin( 9U, numLines() ); ++i )
  3680. {
  3681. readVariableLine( textLine( i ), onlyViewAndRenderer );
  3682. }
  3683. if ( numLines() > 10 )
  3684. {
  3685. for ( uint i = kMax(10U, numLines() - 10); i < numLines(); ++i )
  3686. {
  3687. readVariableLine( textLine( i ), onlyViewAndRenderer );
  3688. }
  3689. }
  3690. if (!onlyViewAndRenderer)
  3691. m_config->configEnd();
  3692. for (v = m_views.first(); v != 0L; v= m_views.next() )
  3693. {
  3694. v->config()->configEnd();
  3695. v->renderer()->config()->configEnd();
  3696. }
  3697. }
  3698. void KateDocument::readVariableLine( TQString t, bool onlyViewAndRenderer )
  3699. {
  3700. // simple check first, no regex
  3701. // no kate inside, no vars, simple...
  3702. if (t.find("kate") < 0)
  3703. return;
  3704. // found vars, if any
  3705. TQString s;
  3706. if ( kvLine.search( t ) > -1 )
  3707. {
  3708. s = kvLine.cap(1);
  3709. kdDebug (13020) << "normal variable line kate: matched: " << s << endl;
  3710. }
  3711. else if (kvLineWildcard.search( t ) > -1) // regex given
  3712. {
  3713. TQStringList wildcards (TQStringList::split(';', kvLineWildcard.cap(1)));
  3714. TQString nameOfFile = url().fileName();
  3715. bool found = false;
  3716. for (TQStringList::size_type i = 0; !found && i < wildcards.size(); ++i)
  3717. {
  3718. TQRegExp wildcard (wildcards[i], true/*Qt::CaseSensitive*/, true/*TQRegExp::Wildcard*/);
  3719. found = wildcard.exactMatch (nameOfFile);
  3720. }
  3721. // nothing usable found...
  3722. if (!found)
  3723. return;
  3724. s = kvLineWildcard.cap(2);
  3725. kdDebug (13020) << "guarded variable line kate-wildcard: matched: " << s << endl;
  3726. }
  3727. else if (kvLineMime.search( t ) > -1) // mime-type given
  3728. {
  3729. TQStringList types (TQStringList::split(';', kvLineMime.cap(1)));
  3730. // no matching type found
  3731. if (!types.contains (mimeType ()))
  3732. return;
  3733. s = kvLineMime.cap(2);
  3734. kdDebug (13020) << "guarded variable line kate-mimetype: matched: " << s << endl;
  3735. }
  3736. else // nothing found
  3737. {
  3738. return;
  3739. }
  3740. TQStringList vvl; // view variable names
  3741. vvl << "dynamic-word-wrap" << "dynamic-word-wrap-indicators"
  3742. << "line-numbers" << "icon-border" << "folding-markers"
  3743. << "bookmark-sorting" << "auto-center-lines"
  3744. << "icon-bar-color"
  3745. // renderer
  3746. << "background-color" << "selection-color"
  3747. << "current-line-color" << "bracket-highlight-color"
  3748. << "word-wrap-marker-color"
  3749. << "font" << "font-size" << "scheme";
  3750. int p( 0 );
  3751. TQString var, val;
  3752. while ( (p = kvVar.search( s, p )) > -1 )
  3753. {
  3754. p += kvVar.matchedLength();
  3755. var = kvVar.cap( 1 );
  3756. val = TQString(kvVar.cap( 2 )).stripWhiteSpace();
  3757. bool state; // store booleans here
  3758. int n; // store ints here
  3759. // only apply view & renderer config stuff
  3760. if (onlyViewAndRenderer)
  3761. {
  3762. if ( vvl.contains( var ) ) // FIXME define above
  3763. setViewVariable( var, val );
  3764. }
  3765. else
  3766. {
  3767. // BOOL SETTINGS
  3768. if ( var == "word-wrap" && checkBoolValue( val, &state ) )
  3769. setWordWrap( state ); // ??? FIXME CHECK
  3770. else if ( var == "block-selection" && checkBoolValue( val, &state ) )
  3771. setBlockSelectionMode( state );
  3772. // KateConfig::configFlags
  3773. // FIXME should this be optimized to only a few calls? how?
  3774. else if ( var == "backspace-indents" && checkBoolValue( val, &state ) )
  3775. m_config->setConfigFlags( KateDocumentConfig::cfBackspaceIndents, state );
  3776. else if ( var == "replace-tabs" && checkBoolValue( val, &state ) )
  3777. m_config->setConfigFlags( KateDocumentConfig::cfReplaceTabsDyn, state );
  3778. else if ( var == "remove-trailing-space" && checkBoolValue( val, &state ) )
  3779. m_config->setConfigFlags( KateDocumentConfig::cfRemoveTrailingDyn, state );
  3780. else if ( var == "wrap-cursor" && checkBoolValue( val, &state ) )
  3781. m_config->setConfigFlags( KateDocumentConfig::cfWrapCursor, state );
  3782. else if ( var == "auto-brackets" && checkBoolValue( val, &state ) )
  3783. m_config->setConfigFlags( KateDocumentConfig::cfAutoBrackets, state );
  3784. else if ( var == "overwrite-mode" && checkBoolValue( val, &state ) )
  3785. m_config->setConfigFlags( KateDocumentConfig::cfOvr, state );
  3786. else if ( var == "keep-indent-profile" && checkBoolValue( val, &state ) )
  3787. m_config->setConfigFlags( KateDocumentConfig::cfKeepIndentProfile, state );
  3788. else if ( var == "keep-extra-spaces" && checkBoolValue( val, &state ) )
  3789. m_config->setConfigFlags( KateDocumentConfig::cfKeepExtraSpaces, state );
  3790. else if ( var == "tab-indents" && checkBoolValue( val, &state ) )
  3791. m_config->setConfigFlags( KateDocumentConfig::cfTabIndents, state );
  3792. else if ( var == "show-tabs" && checkBoolValue( val, &state ) )
  3793. m_config->setConfigFlags( KateDocumentConfig::cfShowTabs, state );
  3794. else if ( var == "space-indent" && checkBoolValue( val, &state ) )
  3795. m_config->setConfigFlags( KateDocumentConfig::cfSpaceIndent, state );
  3796. else if ( var == "smart-home" && checkBoolValue( val, &state ) )
  3797. m_config->setConfigFlags( KateDocumentConfig::cfSmartHome, state );
  3798. else if ( var == "replace-trailing-space-save" && checkBoolValue( val, &state ) )
  3799. m_config->setConfigFlags( KateDocumentConfig::cfRemoveSpaces, state );
  3800. else if ( var == "auto-insert-doxygen" && checkBoolValue( val, &state) )
  3801. m_config->setConfigFlags( KateDocumentConfig::cfDoxygenAutoTyping, state);
  3802. else if ( var == "mixed-indent" && checkBoolValue( val, &state ) )
  3803. m_config->setConfigFlags( KateDocumentConfig::cfMixedIndent, state );
  3804. // INTEGER SETTINGS
  3805. else if ( var == "tab-width" && checkIntValue( val, &n ) )
  3806. m_config->setTabWidth( n );
  3807. else if ( var == "indent-width" && checkIntValue( val, &n ) )
  3808. m_config->setIndentationWidth( n );
  3809. else if ( var == "indent-mode" )
  3810. {
  3811. if ( checkIntValue( val, &n ) )
  3812. m_config->setIndentationMode( n );
  3813. else
  3814. m_config->setIndentationMode( KateAutoIndent::modeNumber( val) );
  3815. }
  3816. else if ( var == "word-wrap-column" && checkIntValue( val, &n ) && n > 0 ) // uint, but hard word wrap at 0 will be no fun ;)
  3817. m_config->setWordWrapAt( n );
  3818. else if ( var == "undo-steps" && checkIntValue( val, &n ) && n >= 0 )
  3819. setUndoSteps( n );
  3820. // STRING SETTINGS
  3821. else if ( var == "eol" || var == "end-of-line" )
  3822. {
  3823. TQStringList l;
  3824. l << "unix" << "dos" << "mac";
  3825. if ( (n = l.findIndex( val.lower() )) != -1 )
  3826. m_config->setEol( n );
  3827. }
  3828. else if ( var == "encoding" )
  3829. m_config->setEncoding( val );
  3830. else if ( var == "syntax" || var == "hl" )
  3831. {
  3832. for ( uint i=0; i < hlModeCount(); i++ )
  3833. {
  3834. if ( hlModeName( i ).lower() == val.lower() )
  3835. {
  3836. setHlMode( i );
  3837. break;
  3838. }
  3839. }
  3840. }
  3841. // VIEW SETTINGS
  3842. else if ( vvl.contains( var ) )
  3843. setViewVariable( var, val );
  3844. else
  3845. {
  3846. m_storedVariables.insert( var, val );
  3847. emit variableChanged( var, val );
  3848. }
  3849. }
  3850. }
  3851. }
  3852. void KateDocument::setViewVariable( TQString var, TQString val )
  3853. {
  3854. KateView *v;
  3855. bool state;
  3856. int n;
  3857. TQColor c;
  3858. for (v = m_views.first(); v != 0L; v= m_views.next() )
  3859. {
  3860. if ( var == "dynamic-word-wrap" && checkBoolValue( val, &state ) )
  3861. v->config()->setDynWordWrap( state );
  3862. else if ( var == "persistent-selection" && checkBoolValue( val, &state ) )
  3863. v->config()->setPersistentSelection( state );
  3864. //else if ( var = "dynamic-word-wrap-indicators" )
  3865. else if ( var == "line-numbers" && checkBoolValue( val, &state ) )
  3866. v->config()->setLineNumbers( state );
  3867. else if (var == "icon-border" && checkBoolValue( val, &state ) )
  3868. v->config()->setIconBar( state );
  3869. else if (var == "folding-markers" && checkBoolValue( val, &state ) )
  3870. v->config()->setFoldingBar( state );
  3871. else if ( var == "auto-center-lines" && checkIntValue( val, &n ) )
  3872. v->config()->setAutoCenterLines( n ); // FIXME uint, > N ??
  3873. else if ( var == "icon-bar-color" && checkColorValue( val, c ) )
  3874. v->renderer()->config()->setIconBarColor( c );
  3875. // RENDERER
  3876. else if ( var == "background-color" && checkColorValue( val, c ) )
  3877. v->renderer()->config()->setBackgroundColor( c );
  3878. else if ( var == "selection-color" && checkColorValue( val, c ) )
  3879. v->renderer()->config()->setSelectionColor( c );
  3880. else if ( var == "current-line-color" && checkColorValue( val, c ) )
  3881. v->renderer()->config()->setHighlightedLineColor( c );
  3882. else if ( var == "bracket-highlight-color" && checkColorValue( val, c ) )
  3883. v->renderer()->config()->setHighlightedBracketColor( c );
  3884. else if ( var == "word-wrap-marker-color" && checkColorValue( val, c ) )
  3885. v->renderer()->config()->setWordWrapMarkerColor( c );
  3886. else if ( var == "font" || ( var == "font-size" && checkIntValue( val, &n ) ) )
  3887. {
  3888. TQFont _f( *v->renderer()->config()->font( ) );
  3889. if ( var == "font" )
  3890. {
  3891. _f.setFamily( val );
  3892. _f.setFixedPitch( TQFont( val ).fixedPitch() );
  3893. }
  3894. else
  3895. _f.setPointSize( n );
  3896. v->renderer()->config()->setFont( _f );
  3897. }
  3898. else if ( var == "scheme" )
  3899. {
  3900. v->renderer()->config()->setSchema( KateFactory::self()->schemaManager()->number( val ) );
  3901. }
  3902. }
  3903. }
  3904. bool KateDocument::checkBoolValue( TQString val, bool *result )
  3905. {
  3906. val = val.stripWhiteSpace().lower();
  3907. TQStringList l;
  3908. l << "1" << "on" << "true";
  3909. if ( l.contains( val ) )
  3910. {
  3911. *result = true;
  3912. return true;
  3913. }
  3914. l.clear();
  3915. l << "0" << "off" << "false";
  3916. if ( l.contains( val ) )
  3917. {
  3918. *result = false;
  3919. return true;
  3920. }
  3921. return false;
  3922. }
  3923. bool KateDocument::checkIntValue( TQString val, int *result )
  3924. {
  3925. bool ret( false );
  3926. *result = val.toInt( &ret );
  3927. return ret;
  3928. }
  3929. bool KateDocument::checkColorValue( TQString val, TQColor &c )
  3930. {
  3931. c.setNamedColor( val );
  3932. return c.isValid();
  3933. }
  3934. // KTextEditor::variable
  3935. TQString KateDocument::variable( const TQString &name ) const
  3936. {
  3937. if ( m_storedVariables.contains( name ) )
  3938. return m_storedVariables[ name ];
  3939. return "";
  3940. }
  3941. //END
  3942. void KateDocument::slotModOnHdDirty (const TQString &path)
  3943. {
  3944. if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 1))
  3945. {
  3946. // compare md5 with the one we have (if we have one)
  3947. if ( ! m_digest.isEmpty() )
  3948. {
  3949. TQCString tmp;
  3950. if ( createDigest( tmp ) && tmp == m_digest )
  3951. return;
  3952. }
  3953. m_modOnHd = true;
  3954. m_modOnHdReason = 1;
  3955. // reenable dialog if not running atm
  3956. if (m_isasking == -1)
  3957. m_isasking = false;
  3958. emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
  3959. }
  3960. }
  3961. void KateDocument::slotModOnHdCreated (const TQString &path)
  3962. {
  3963. if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 2))
  3964. {
  3965. m_modOnHd = true;
  3966. m_modOnHdReason = 2;
  3967. // reenable dialog if not running atm
  3968. if (m_isasking == -1)
  3969. m_isasking = false;
  3970. emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
  3971. }
  3972. }
  3973. void KateDocument::slotModOnHdDeleted (const TQString &path)
  3974. {
  3975. if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 3))
  3976. {
  3977. m_modOnHd = true;
  3978. m_modOnHdReason = 3;
  3979. // reenable dialog if not running atm
  3980. if (m_isasking == -1)
  3981. m_isasking = false;
  3982. emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
  3983. }
  3984. }
  3985. bool KateDocument::createDigest( TQCString &result )
  3986. {
  3987. bool ret = false;
  3988. result = "";
  3989. if ( url().isLocalFile() )
  3990. {
  3991. TQFile f ( url().path() );
  3992. if ( f.open( IO_ReadOnly) )
  3993. {
  3994. KMD5 md5;
  3995. ret = md5.update( TQT_TQIODEVICE_OBJECT(f) );
  3996. md5.hexDigest( result );
  3997. f.close();
  3998. ret = true;
  3999. }
  4000. }
  4001. return ret;
  4002. }
  4003. TQString KateDocument::reasonedMOHString() const
  4004. {
  4005. switch( m_modOnHdReason )
  4006. {
  4007. case 1:
  4008. return i18n("The file '%1' was modified by another program.").arg( url().prettyURL() );
  4009. break;
  4010. case 2:
  4011. return i18n("The file '%1' was created by another program.").arg( url().prettyURL() );
  4012. break;
  4013. case 3:
  4014. return i18n("The file '%1' was deleted by another program.").arg( url().prettyURL() );
  4015. break;
  4016. default:
  4017. return TQString();
  4018. }
  4019. }
  4020. void KateDocument::removeTrailingSpace( uint line )
  4021. {
  4022. // remove trailing spaces from left line if required
  4023. if ( config()->configFlags() & KateDocumentConfig::cfRemoveTrailingDyn )
  4024. {
  4025. KateTextLine::Ptr ln = kateTextLine( line );
  4026. if ( ! ln ) return;
  4027. if ( line == activeView()->cursorLine()
  4028. && activeView()->cursorColumnReal() >= (uint)kMax(0,ln->lastChar()) )
  4029. return;
  4030. if ( ln->length() )
  4031. {
  4032. uint p = ln->lastChar() + 1;
  4033. uint l = ln->length() - p;
  4034. if ( l )
  4035. editRemoveText( line, p, l);
  4036. }
  4037. }
  4038. }
  4039. void KateDocument::updateFileType (int newType, bool user)
  4040. {
  4041. if (user || !m_fileTypeSetByUser)
  4042. {
  4043. const KateFileType *t = 0;
  4044. if ((newType == -1) || (t = KateFactory::self()->fileTypeManager()->fileType (newType)))
  4045. {
  4046. m_fileType = newType;
  4047. if (t)
  4048. {
  4049. m_config->configStart();
  4050. // views!
  4051. KateView *v;
  4052. for (v = m_views.first(); v != 0L; v= m_views.next() )
  4053. {
  4054. v->config()->configStart();
  4055. v->renderer()->config()->configStart();
  4056. }
  4057. readVariableLine( t->varLine );
  4058. m_config->configEnd();
  4059. for (v = m_views.first(); v != 0L; v= m_views.next() )
  4060. {
  4061. v->config()->configEnd();
  4062. v->renderer()->config()->configEnd();
  4063. }
  4064. }
  4065. }
  4066. }
  4067. }
  4068. uint KateDocument::documentNumber () const
  4069. {
  4070. return KTextEditor::Document::documentNumber ();
  4071. }
  4072. long KateDocument::documentListPosition () const
  4073. {
  4074. return KTextEditor::Document::documentListPosition ();
  4075. }
  4076. void KateDocument::setDocumentListPosition (long pos)
  4077. {
  4078. KTextEditor::Document::setDocumentListPosition (pos);
  4079. }
  4080. void KateDocument::slotQueryClose_save(bool *handled, bool* abortClosing) {
  4081. *handled=true;
  4082. *abortClosing=true;
  4083. if (m_url.isEmpty())
  4084. {
  4085. KEncodingFileDialog::Result res=KEncodingFileDialog::getSaveURLAndEncoding(config()->encoding(),
  4086. TQString::null,TQString::null,0,i18n("Save File"));
  4087. if( res.URLs.isEmpty() || !checkOverwrite( res.URLs.first() ) ) {
  4088. *abortClosing=true;
  4089. return;
  4090. }
  4091. setEncoding( res.encoding );
  4092. saveAs( res.URLs.first() );
  4093. *abortClosing=false;
  4094. }
  4095. else
  4096. {
  4097. save();
  4098. *abortClosing=false;
  4099. }
  4100. }
  4101. bool KateDocument::checkOverwrite( KURL u )
  4102. {
  4103. if( !u.isLocalFile() )
  4104. return true;
  4105. TQFileInfo info( u.path() );
  4106. if( !info.exists() )
  4107. return true;
  4108. return KMessageBox::Cancel != KMessageBox::warningContinueCancel( 0,
  4109. i18n( "A file named \"%1\" already exists. "
  4110. "Are you sure you want to overwrite it?" ).arg( info.fileName() ),
  4111. i18n( "Overwrite File?" ),
  4112. i18n( "&Overwrite" ) );
  4113. }
  4114. void KateDocument::setDefaultEncoding (const TQString &encoding)
  4115. {
  4116. s_defaultEncoding = encoding;
  4117. }
  4118. //BEGIN KTextEditor::TemplateInterface
  4119. bool KateDocument::insertTemplateTextImplementation ( uint line, uint column, const TQString &templateString, const TQMap<TQString,TQString> &initialValues, TQWidget *) {
  4120. return (new KateTemplateHandler(this,line,column,templateString,initialValues))->initOk();
  4121. }
  4122. void KateDocument::testTemplateCode() {
  4123. int col=activeView()->cursorColumn();
  4124. int line=activeView()->cursorLine();
  4125. insertTemplateText(line,col,"for ${index} \\${NOPLACEHOLDER} ${index} ${blah} ${fullname} \\$${Placeholder} \\${${PLACEHOLDER2}}\n next line:${ANOTHERPLACEHOLDER} $${DOLLARBEFOREPLACEHOLDER} {NOTHING} {\n${cursor}\n}",TQMap<TQString,TQString>());
  4126. }
  4127. bool KateDocument::invokeTabInterceptor(KKey key) {
  4128. if (m_tabInterceptor) return (*m_tabInterceptor)(key);
  4129. return false;
  4130. }
  4131. bool KateDocument::setTabInterceptor(KateKeyInterceptorFunctor *interceptor) {
  4132. if (m_tabInterceptor) return false;
  4133. m_tabInterceptor=interceptor;
  4134. return true;
  4135. }
  4136. bool KateDocument::removeTabInterceptor(KateKeyInterceptorFunctor *interceptor) {
  4137. if (m_tabInterceptor!=interceptor) return false;
  4138. m_tabInterceptor=0;
  4139. return true;
  4140. }
  4141. //END KTextEditor::TemplateInterface
  4142. //BEGIN DEPRECATED STUFF
  4143. bool KateDocument::setSelection ( uint startLine, uint startCol, uint endLine, uint endCol )
  4144. { if (m_activeView) return m_activeView->setSelection (startLine, startCol, endLine, endCol); return false; }
  4145. bool KateDocument::clearSelection ()
  4146. { if (m_activeView) return m_activeView->clearSelection(); return false; }
  4147. bool KateDocument::hasSelection () const
  4148. { if (m_activeView) return m_activeView->hasSelection (); return false; }
  4149. TQString KateDocument::selection () const
  4150. { if (m_activeView) return m_activeView->selection (); return TQString(""); }
  4151. bool KateDocument::removeSelectedText ()
  4152. { if (m_activeView) return m_activeView->removeSelectedText (); return false; }
  4153. bool KateDocument::selectAll()
  4154. { if (m_activeView) return m_activeView->selectAll (); return false; }
  4155. int KateDocument::selStartLine()
  4156. { if (m_activeView) return m_activeView->selStartLine (); return 0; }
  4157. int KateDocument::selStartCol()
  4158. { if (m_activeView) return m_activeView->selStartCol (); return 0; }
  4159. int KateDocument::selEndLine()
  4160. { if (m_activeView) return m_activeView->selEndLine (); return 0; }
  4161. int KateDocument::selEndCol()
  4162. { if (m_activeView) return m_activeView->selEndCol (); return 0; }
  4163. bool KateDocument::blockSelectionMode ()
  4164. { if (m_activeView) return m_activeView->blockSelectionMode (); return false; }
  4165. bool KateDocument::setBlockSelectionMode (bool on)
  4166. { if (m_activeView) return m_activeView->setBlockSelectionMode (on); return false; }
  4167. bool KateDocument::toggleBlockSelectionMode ()
  4168. { if (m_activeView) return m_activeView->toggleBlockSelectionMode (); return false; }
  4169. //END DEPRECATED
  4170. //END DEPRECATED STUFF
  4171. // kate: space-indent on; indent-width 2; replace-tabs on;