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.

kateviewinternal.cpp 95KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496
  1. /* This file is part of the KDE libraries
  2. Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org>
  3. Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
  4. Copyright (C) 2002,2003 Christoph Cullmann <cullmann@kde.org>
  5. Copyright (C) 2002,2003 Hamish Rodda <rodda@kde.org>
  6. Copyright (C) 2003 Anakim Border <aborder@sources.sourceforge.net>
  7. Based on:
  8. KWriteView : Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
  9. This library is free software; you can redistribute it and/or
  10. modify it under the terms of the GNU Library General Public
  11. License version 2 as published by the Free Software Foundation.
  12. This library is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. Library General Public License for more details.
  16. You should have received a copy of the GNU Library General Public License
  17. along with this library; see the file COPYING.LIB. If not, write to
  18. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  19. Boston, MA 02110-1301, USA.
  20. */
  21. #include "kateviewinternal.h"
  22. #include "kateviewinternal.moc"
  23. #include "kateview.h"
  24. #include "katecodefoldinghelpers.h"
  25. #include "kateviewhelpers.h"
  26. #include "katehighlight.h"
  27. #include "katesupercursor.h"
  28. #include "katerenderer.h"
  29. #include "katecodecompletion.h"
  30. #include "kateconfig.h"
  31. #include <kcursor.h>
  32. #include <kdebug.h>
  33. #include <tdeapplication.h>
  34. #include <tdeglobalsettings.h>
  35. #include <kurldrag.h>
  36. #include <tqstyle.h>
  37. #include <tqdragobject.h>
  38. #include <tqpopupmenu.h>
  39. #include <tqdropsite.h>
  40. #include <tqpainter.h>
  41. #include <tqlayout.h>
  42. #include <tqclipboard.h>
  43. #include <tqpixmap.h>
  44. #include <tqvbox.h>
  45. KateViewInternal::KateViewInternal(KateView *view, KateDocument *doc)
  46. : TQWidget (view, "", (WFlags)(WStaticContents | WRepaintNoErase | WResizeNoErase) )
  47. , editSessionNumber (0)
  48. , editIsRunning (false)
  49. , m_view (view)
  50. , m_doc (doc)
  51. , cursor (doc, true, 0, 0, TQT_TQOBJECT(this))
  52. , possibleTripleClick (false)
  53. , m_dummy (0)
  54. , m_startPos(doc, true, 0,0)
  55. , m_madeVisible(false)
  56. , m_shiftKeyPressed (false)
  57. , m_autoCenterLines (false)
  58. , m_selChangedByUser (false)
  59. , selectAnchor (-1, -1)
  60. , m_selectionMode( Default )
  61. , m_preserveMaxX(false)
  62. , m_currentMaxX(0)
  63. , m_usePlainLines(false)
  64. , m_updatingView(true)
  65. , m_cachedMaxStartPos(-1, -1)
  66. , m_dragScrollTimer(this)
  67. , m_scrollTimer (this)
  68. , m_cursorTimer (this)
  69. , m_textHintTimer (this)
  70. , m_textHintEnabled(false)
  71. , m_textHintMouseX(-1)
  72. , m_textHintMouseY(-1)
  73. , m_imPreeditStartLine(0)
  74. , m_imPreeditStart(0)
  75. , m_imPreeditLength(0)
  76. , m_imPreeditSelStart(0)
  77. {
  78. setMinimumSize (0,0);
  79. // cursor
  80. cursor.setMoveOnInsert (true);
  81. // invalidate selStartCached, or keyb selection is screwed initially
  82. selStartCached.setLine( -1 );
  83. //
  84. // scrollbar for lines
  85. //
  86. m_lineScroll = new KateScrollBar(Qt::Vertical, this);
  87. m_lineScroll->show();
  88. m_lineScroll->setTracking (true);
  89. m_lineLayout = new TQVBoxLayout();
  90. m_colLayout = new TQHBoxLayout();
  91. m_colLayout->addWidget(m_lineScroll);
  92. m_lineLayout->addLayout(m_colLayout);
  93. // bottom corner box
  94. m_dummy = new TQWidget(m_view);
  95. m_dummy->setFixedHeight(style().scrollBarExtent().width());
  96. if (m_view->dynWordWrap())
  97. m_dummy->hide();
  98. else
  99. m_dummy->show();
  100. m_lineLayout->addWidget(m_dummy);
  101. // Hijack the line scroller's controls, so we can scroll nicely for word-wrap
  102. connect(m_lineScroll, TQT_SIGNAL(prevPage()), TQT_SLOT(scrollPrevPage()));
  103. connect(m_lineScroll, TQT_SIGNAL(nextPage()), TQT_SLOT(scrollNextPage()));
  104. connect(m_lineScroll, TQT_SIGNAL(prevLine()), TQT_SLOT(scrollPrevLine()));
  105. connect(m_lineScroll, TQT_SIGNAL(nextLine()), TQT_SLOT(scrollNextLine()));
  106. connect(m_lineScroll, TQT_SIGNAL(sliderMoved(int)), TQT_SLOT(scrollLines(int)));
  107. connect(m_lineScroll, TQT_SIGNAL(sliderMMBMoved(int)), TQT_SLOT(scrollLines(int)));
  108. // catch wheel events, completing the hijack
  109. m_lineScroll->installEventFilter(this);
  110. //
  111. // scrollbar for columns
  112. //
  113. m_columnScroll = new TQScrollBar(Qt::Horizontal,m_view);
  114. // hide the column scrollbar in the dynamic word wrap mode
  115. if (m_view->dynWordWrap())
  116. m_columnScroll->hide();
  117. else
  118. m_columnScroll->show();
  119. m_columnScroll->setTracking(true);
  120. m_startX = 0;
  121. connect( m_columnScroll, TQT_SIGNAL( valueChanged (int) ),
  122. this, TQT_SLOT( scrollColumns (int) ) );
  123. //
  124. // iconborder ;)
  125. //
  126. leftBorder = new KateIconBorder( this, m_view );
  127. leftBorder->show ();
  128. connect( leftBorder, TQT_SIGNAL(toggleRegionVisibility(unsigned int)),
  129. m_doc->foldingTree(), TQT_SLOT(toggleRegionVisibility(unsigned int)));
  130. connect( doc->foldingTree(), TQT_SIGNAL(regionVisibilityChangedAt(unsigned int)),
  131. this, TQT_SLOT(slotRegionVisibilityChangedAt(unsigned int)));
  132. connect( doc, TQT_SIGNAL(codeFoldingUpdated()),
  133. this, TQT_SLOT(slotCodeFoldingChanged()) );
  134. displayCursor.setPos(0, 0);
  135. cursor.setPos(0, 0);
  136. cXPos = 0;
  137. setAcceptDrops( true );
  138. setBackgroundMode( NoBackground );
  139. // event filter
  140. installEventFilter(this);
  141. // im
  142. setInputMethodEnabled(true);
  143. // set initial cursor
  144. setCursor( KCursor::ibeamCursor() );
  145. m_mouseCursor = TQt::IbeamCursor;
  146. // call mouseMoveEvent also if no mouse button is pressed
  147. setMouseTracking(true);
  148. dragInfo.state = diNone;
  149. // timers
  150. connect( &m_dragScrollTimer, TQT_SIGNAL( timeout() ),
  151. this, TQT_SLOT( doDragScroll() ) );
  152. connect( &m_scrollTimer, TQT_SIGNAL( timeout() ),
  153. this, TQT_SLOT( scrollTimeout() ) );
  154. connect( &m_cursorTimer, TQT_SIGNAL( timeout() ),
  155. this, TQT_SLOT( cursorTimeout() ) );
  156. connect( &m_textHintTimer, TQT_SIGNAL( timeout() ),
  157. this, TQT_SLOT( textHintTimeout() ) );
  158. // selection changed to set anchor
  159. connect( m_view, TQT_SIGNAL( selectionChanged() ),
  160. this, TQT_SLOT( viewSelectionChanged() ) );
  161. // this is a work arround for RTL desktops
  162. // should be changed in kde 3.3
  163. // BTW: this comment has been "ported" from 3.1.X tree
  164. // any hacker with BIDI knowlege is welcomed to fix kate problems :)
  165. if (TQApplication::reverseLayout()){
  166. m_view->m_grid->addMultiCellWidget(leftBorder, 0, 1, 2, 2);
  167. m_view->m_grid->addMultiCellWidget(m_columnScroll, 1, 1, 0, 1);
  168. m_view->m_grid->addMultiCellLayout(m_lineLayout, 0, 0, 0, 0);
  169. }
  170. else{
  171. m_view->m_grid->addMultiCellLayout(m_lineLayout, 0, 1, 2, 2);
  172. m_view->m_grid->addMultiCellWidget(m_columnScroll, 1, 1, 0, 1);
  173. m_view->m_grid->addWidget(leftBorder, 0, 0);
  174. }
  175. updateView ();
  176. }
  177. KateViewInternal::~KateViewInternal ()
  178. {
  179. }
  180. void KateViewInternal::prepareForDynWrapChange()
  181. {
  182. // Which is the current view line?
  183. m_wrapChangeViewLine = displayViewLine(displayCursor, true);
  184. }
  185. void KateViewInternal::dynWrapChanged()
  186. {
  187. if (m_view->dynWordWrap())
  188. {
  189. m_columnScroll->hide();
  190. m_dummy->hide ();
  191. }
  192. else
  193. {
  194. m_columnScroll->show();
  195. m_dummy->show ();
  196. }
  197. tagAll();
  198. updateView();
  199. if (m_view->dynWordWrap())
  200. scrollColumns(0);
  201. // Determine where the cursor should be to get the cursor on the same view line
  202. if (m_wrapChangeViewLine != -1) {
  203. KateTextCursor newStart = viewLineOffset(displayCursor, -m_wrapChangeViewLine);
  204. makeVisible(newStart, newStart.col(), true);
  205. } else {
  206. update();
  207. }
  208. }
  209. KateTextCursor KateViewInternal::endPos() const
  210. {
  211. int viewLines = linesDisplayed() - 1;
  212. if (viewLines < 0) {
  213. kdDebug(13030) << "WARNING: viewLines wrong!" << endl;
  214. viewLines = 0;
  215. }
  216. // Check to make sure that lineRanges isn't invalid
  217. if (!lineRanges.count() || lineRanges[0].line == -1 || viewLines >= (int)lineRanges.count()) {
  218. // Switch off use of the cache
  219. return KateTextCursor(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
  220. }
  221. for (int i = viewLines; i >= 0; i--) {
  222. KateLineRange& thisRange = lineRanges[i];
  223. if (thisRange.line == -1) continue;
  224. if (thisRange.virtualLine >= (int)m_doc->numVisLines()) {
  225. // Cache is too out of date
  226. return KateTextCursor(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
  227. }
  228. return KateTextCursor(thisRange.virtualLine, thisRange.wrap ? thisRange.endCol - 1 : thisRange.endCol);
  229. }
  230. Q_ASSERT(false);
  231. kdDebug(13030) << "WARNING: could not find a lineRange at all" << endl;
  232. return KateTextCursor(-1, -1);
  233. }
  234. uint KateViewInternal::endLine() const
  235. {
  236. return endPos().line();
  237. }
  238. KateLineRange KateViewInternal::yToKateLineRange(uint y) const
  239. {
  240. uint range = y / m_view->renderer()->fontHeight();
  241. // lineRanges is always bigger than 0, after the initial updateView call
  242. if (range >= lineRanges.size())
  243. return lineRanges[lineRanges.size()-1];
  244. return lineRanges[range];
  245. }
  246. int KateViewInternal::lineToY(uint viewLine) const
  247. {
  248. return (viewLine-startLine()) * m_view->renderer()->fontHeight();
  249. }
  250. void KateViewInternal::slotIncFontSizes()
  251. {
  252. m_view->renderer()->increaseFontSizes();
  253. }
  254. void KateViewInternal::slotDecFontSizes()
  255. {
  256. m_view->renderer()->decreaseFontSizes();
  257. }
  258. /**
  259. * Line is the real line number to scroll to.
  260. */
  261. void KateViewInternal::scrollLines ( int line )
  262. {
  263. KateTextCursor newPos(line, 0);
  264. scrollPos(newPos);
  265. }
  266. // This can scroll less than one true line
  267. void KateViewInternal::scrollViewLines(int offset)
  268. {
  269. KateTextCursor c = viewLineOffset(startPos(), offset);
  270. scrollPos(c);
  271. m_lineScroll->blockSignals(true);
  272. m_lineScroll->setValue(startLine());
  273. m_lineScroll->blockSignals(false);
  274. }
  275. void KateViewInternal::scrollNextPage()
  276. {
  277. scrollViewLines(kMax( (int)linesDisplayed() - 1, 0 ));
  278. }
  279. void KateViewInternal::scrollPrevPage()
  280. {
  281. scrollViewLines(-kMax( (int)linesDisplayed() - 1, 0 ));
  282. }
  283. void KateViewInternal::scrollPrevLine()
  284. {
  285. scrollViewLines(-1);
  286. }
  287. void KateViewInternal::scrollNextLine()
  288. {
  289. scrollViewLines(1);
  290. }
  291. KateTextCursor KateViewInternal::maxStartPos(bool changed)
  292. {
  293. m_usePlainLines = true;
  294. if (m_cachedMaxStartPos.line() == -1 || changed)
  295. {
  296. KateTextCursor end(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
  297. m_cachedMaxStartPos = viewLineOffset(end, -((int)linesDisplayed() - 1));
  298. }
  299. m_usePlainLines = false;
  300. return m_cachedMaxStartPos;
  301. }
  302. // c is a virtual cursor
  303. void KateViewInternal::scrollPos(KateTextCursor& c, bool force, bool calledExternally)
  304. {
  305. if (!force && ((!m_view->dynWordWrap() && c.line() == (int)startLine()) || c == startPos()))
  306. return;
  307. if (c.line() < 0)
  308. c.setLine(0);
  309. KateTextCursor limit = maxStartPos();
  310. if (c > limit) {
  311. c = limit;
  312. // Re-check we're not just scrolling to the same place
  313. if (!force && ((!m_view->dynWordWrap() && c.line() == (int)startLine()) || c == startPos()))
  314. return;
  315. }
  316. int viewLinesScrolled = 0;
  317. // only calculate if this is really used and usefull, could be wrong here, please recheck
  318. // for larger scrolls this makes 2-4 seconds difference on my xeon with dyn. word wrap on
  319. // try to get it really working ;)
  320. bool viewLinesScrolledUsable = !force
  321. && (c.line() >= (int)startLine()-(int)linesDisplayed()-1)
  322. && (c.line() <= (int)endLine()+(int)linesDisplayed()+1);
  323. if (viewLinesScrolledUsable)
  324. viewLinesScrolled = displayViewLine(c);
  325. m_startPos.setPos(c);
  326. // set false here but reversed if we return to makeVisible
  327. m_madeVisible = false;
  328. if (viewLinesScrolledUsable)
  329. {
  330. int lines = linesDisplayed();
  331. if ((int)m_doc->numVisLines() < lines) {
  332. KateTextCursor end(m_doc->numVisLines() - 1, m_doc->lineLength(m_doc->getRealLine(m_doc->numVisLines() - 1)));
  333. lines = kMin((int)linesDisplayed(), displayViewLine(end) + 1);
  334. }
  335. Q_ASSERT(lines >= 0);
  336. if (!calledExternally && QABS(viewLinesScrolled) < lines)
  337. {
  338. updateView(false, viewLinesScrolled);
  339. int scrollHeight = -(viewLinesScrolled * (int)m_view->renderer()->fontHeight());
  340. int scrollbarWidth = style().scrollBarExtent().width();
  341. //
  342. // updates are for working around the scrollbar leaving blocks in the view
  343. //
  344. scroll(0, scrollHeight);
  345. update(0, height()+scrollHeight-scrollbarWidth, width(), 2*scrollbarWidth);
  346. leftBorder->scroll(0, scrollHeight);
  347. leftBorder->update(0, leftBorder->height()+scrollHeight-scrollbarWidth, leftBorder->width(), 2*scrollbarWidth);
  348. return;
  349. }
  350. }
  351. updateView();
  352. update();
  353. leftBorder->update();
  354. }
  355. void KateViewInternal::scrollColumns ( int x )
  356. {
  357. if (x == m_startX)
  358. return;
  359. if (x < 0)
  360. x = 0;
  361. int dx = m_startX - x;
  362. m_startX = x;
  363. if (QABS(dx) < width())
  364. scroll(dx, 0);
  365. else
  366. update();
  367. m_columnScroll->blockSignals(true);
  368. m_columnScroll->setValue(m_startX);
  369. m_columnScroll->blockSignals(false);
  370. }
  371. // If changed is true, the lines that have been set dirty have been updated.
  372. void KateViewInternal::updateView(bool changed, int viewLinesScrolled)
  373. {
  374. m_updatingView = true;
  375. uint contentLines = m_doc->visibleLines();
  376. m_lineScroll->blockSignals(true);
  377. KateTextCursor maxStart = maxStartPos(changed);
  378. int maxLineScrollRange = maxStart.line();
  379. if (m_view->dynWordWrap() && maxStart.col() != 0)
  380. maxLineScrollRange++;
  381. m_lineScroll->setRange(0, maxLineScrollRange);
  382. m_lineScroll->setValue(startPos().line());
  383. m_lineScroll->setSteps(1, height() / m_view->renderer()->fontHeight());
  384. m_lineScroll->blockSignals(false);
  385. uint oldSize = lineRanges.size ();
  386. uint newSize = (height() / m_view->renderer()->fontHeight()) + 1;
  387. if (oldSize != newSize) {
  388. lineRanges.resize((height() / m_view->renderer()->fontHeight()) + 1);
  389. if (newSize > oldSize) {
  390. static KateLineRange blank;
  391. for (uint i = oldSize; i < newSize; i++) {
  392. lineRanges[i] = blank;
  393. }
  394. }
  395. }
  396. if (oldSize < lineRanges.size ())
  397. {
  398. for (uint i=oldSize; i < lineRanges.size(); i++)
  399. lineRanges[i].dirty = true;
  400. }
  401. // Move the lineRanges data if we've just scrolled...
  402. if (viewLinesScrolled != 0) {
  403. // loop backwards if we've just scrolled up...
  404. bool forwards = viewLinesScrolled >= 0 ? true : false;
  405. for (uint z = forwards ? 0 : lineRanges.count() - 1; z < lineRanges.count(); forwards ? z++ : z--) {
  406. uint oldZ = z + viewLinesScrolled;
  407. if (oldZ < lineRanges.count()) {
  408. lineRanges[z] = lineRanges[oldZ];
  409. } else {
  410. lineRanges[z].dirty = true;
  411. }
  412. }
  413. }
  414. if (m_view->dynWordWrap())
  415. {
  416. KateTextCursor realStart = startPos();
  417. realStart.setLine(m_doc->getRealLine(realStart.line()));
  418. KateLineRange startRange = range(realStart);
  419. uint line = startRange.virtualLine;
  420. int realLine = startRange.line;
  421. uint oldLine = line;
  422. int startCol = startRange.startCol;
  423. int startX = startRange.startX;
  424. int endX = startRange.startX;
  425. int shiftX = startRange.startCol ? startRange.shiftX : 0;
  426. bool wrap = false;
  427. int newViewLine = startRange.viewLine;
  428. // z is the current display view line
  429. KateTextLine::Ptr text = textLine(realLine);
  430. bool alreadyDirty = false;
  431. for (uint z = 0; z < lineRanges.size(); z++)
  432. {
  433. if (oldLine != line) {
  434. realLine = (int)m_doc->getRealLine(line);
  435. if (z)
  436. lineRanges[z-1].startsInvisibleBlock = (realLine != lineRanges[z-1].line + 1);
  437. text = textLine(realLine);
  438. startCol = 0;
  439. startX = 0;
  440. endX = 0;
  441. shiftX = 0;
  442. newViewLine = 0;
  443. oldLine = line;
  444. }
  445. if (line >= contentLines || !text)
  446. {
  447. if (lineRanges[z].line != -1)
  448. lineRanges[z].dirty = true;
  449. lineRanges[z].clear();
  450. line++;
  451. }
  452. else
  453. {
  454. if (lineRanges[z].line != realLine || lineRanges[z].startCol != startCol)
  455. alreadyDirty = lineRanges[z].dirty = true;
  456. if (lineRanges[z].dirty || changed || alreadyDirty) {
  457. alreadyDirty = true;
  458. lineRanges[z].virtualLine = line;
  459. lineRanges[z].line = realLine;
  460. lineRanges[z].startsInvisibleBlock = false;
  461. int tempEndX = 0;
  462. int endCol = m_view->renderer()->textWidth(text, startCol, width() - shiftX, &wrap, &tempEndX);
  463. endX += tempEndX;
  464. if (wrap)
  465. {
  466. if (m_view->config()->dynWordWrapAlignIndent() > 0)
  467. {
  468. if (startX == 0)
  469. {
  470. int pos = text->nextNonSpaceChar(0);
  471. if (pos > 0)
  472. shiftX = m_view->renderer()->textWidth(text, pos);
  473. if (shiftX > ((double)width() / 100 * m_view->config()->dynWordWrapAlignIndent()))
  474. shiftX = 0;
  475. }
  476. }
  477. if ((lineRanges[z].startX != startX) || (lineRanges[z].endX != endX) ||
  478. (lineRanges[z].startCol != startCol) || (lineRanges[z].endCol != endCol) ||
  479. (lineRanges[z].shiftX != shiftX))
  480. lineRanges[z].dirty = true;
  481. lineRanges[z].startCol = startCol;
  482. lineRanges[z].endCol = endCol;
  483. lineRanges[z].startX = startX;
  484. lineRanges[z].endX = endX;
  485. lineRanges[z].viewLine = newViewLine;
  486. lineRanges[z].wrap = true;
  487. startCol = endCol;
  488. startX = endX;
  489. }
  490. else
  491. {
  492. if ((lineRanges[z].startX != startX) || (lineRanges[z].endX != endX) ||
  493. (lineRanges[z].startCol != startCol) || (lineRanges[z].endCol != endCol))
  494. lineRanges[z].dirty = true;
  495. lineRanges[z].startCol = startCol;
  496. lineRanges[z].endCol = endCol;
  497. lineRanges[z].startX = startX;
  498. lineRanges[z].endX = endX;
  499. lineRanges[z].viewLine = newViewLine;
  500. lineRanges[z].wrap = false;
  501. line++;
  502. }
  503. lineRanges[z].shiftX = shiftX;
  504. } else {
  505. // The cached data is still intact
  506. if (lineRanges[z].wrap) {
  507. startCol = lineRanges[z].endCol;
  508. startX = lineRanges[z].endX;
  509. endX = lineRanges[z].endX;
  510. } else {
  511. line++;
  512. }
  513. shiftX = lineRanges[z].shiftX;
  514. }
  515. }
  516. newViewLine++;
  517. }
  518. }
  519. else
  520. {
  521. uint z = 0;
  522. for(; (z + startLine() < contentLines) && (z < lineRanges.size()); z++)
  523. {
  524. if (lineRanges[z].dirty || lineRanges[z].line != (int)m_doc->getRealLine(z + startLine())) {
  525. lineRanges[z].dirty = true;
  526. lineRanges[z].line = m_doc->getRealLine( z + startLine() );
  527. if (z)
  528. lineRanges[z-1].startsInvisibleBlock = (lineRanges[z].line != lineRanges[z-1].line + 1);
  529. lineRanges[z].virtualLine = z + startLine();
  530. lineRanges[z].startCol = 0;
  531. lineRanges[z].endCol = m_doc->lineLength(lineRanges[z].line);
  532. lineRanges[z].startX = 0;
  533. lineRanges[z].endX = m_view->renderer()->textWidth( textLine( lineRanges[z].line ), -1 );
  534. lineRanges[z].shiftX = 0;
  535. lineRanges[z].viewLine = 0;
  536. lineRanges[z].wrap = false;
  537. }
  538. else if (z && lineRanges[z-1].dirty)
  539. {
  540. lineRanges[z-1].startsInvisibleBlock = (lineRanges[z].line != lineRanges[z-1].line + 1);
  541. }
  542. }
  543. for (; z < lineRanges.size(); z++)
  544. {
  545. if (lineRanges[z].line != -1)
  546. lineRanges[z].dirty = true;
  547. lineRanges[z].clear();
  548. }
  549. int max = maxLen(startLine()) - width();
  550. if (max < 0)
  551. max = 0;
  552. // if we lose the ability to scroll horizontally, move view to the far-left
  553. if (max == 0)
  554. {
  555. scrollColumns(0);
  556. }
  557. m_columnScroll->blockSignals(true);
  558. // disable scrollbar
  559. m_columnScroll->setDisabled (max == 0);
  560. m_columnScroll->setRange(0, max);
  561. m_columnScroll->setValue(m_startX);
  562. // Approximate linescroll
  563. m_columnScroll->setSteps(m_view->renderer()->config()->fontMetrics()->width('a'), width());
  564. m_columnScroll->blockSignals(false);
  565. }
  566. m_updatingView = false;
  567. if (changed)
  568. paintText(0, 0, width(), height(), true);
  569. }
  570. void KateViewInternal::paintText (int x, int y, int width, int height, bool paintOnlyDirty)
  571. {
  572. //kdDebug() << k_funcinfo << x << " " << y << " " << width << " " << height << " " << paintOnlyDirty << endl;
  573. int xStart = startX() + x;
  574. int xEnd = xStart + width;
  575. uint h = m_view->renderer()->fontHeight();
  576. uint startz = (y / h);
  577. uint endz = startz + 1 + (height / h);
  578. uint lineRangesSize = lineRanges.size();
  579. static TQPixmap drawBuffer;
  580. if (drawBuffer.width() < KateViewInternal::width() || drawBuffer.height() < (int)h)
  581. drawBuffer.resize(KateViewInternal::width(), (int)h);
  582. if (drawBuffer.isNull())
  583. return;
  584. TQPainter paint(this);
  585. TQPainter paintDrawBuffer(&drawBuffer);
  586. // TODO put in the proper places
  587. m_view->renderer()->setCaretStyle(m_view->isOverwriteMode() ? KateRenderer::Replace : KateRenderer::Insert);
  588. m_view->renderer()->setShowTabs(m_doc->configFlags() & KateDocument::cfShowTabs);
  589. for (uint z=startz; z <= endz; z++)
  590. {
  591. if ( (z >= lineRangesSize) || ((lineRanges[z].line == -1) && (!paintOnlyDirty || lineRanges[z].dirty)) )
  592. {
  593. if (!(z >= lineRangesSize))
  594. lineRanges[z].dirty = false;
  595. paint.fillRect( x, z * h, width, h, m_view->renderer()->config()->backgroundColor() );
  596. }
  597. else if (!paintOnlyDirty || lineRanges[z].dirty)
  598. {
  599. lineRanges[z].dirty = false;
  600. m_view->renderer()->paintTextLine(paintDrawBuffer, &lineRanges[z], xStart, xEnd, &cursor, &bm);
  601. paint.drawPixmap (x, z * h, drawBuffer, 0, 0, width, h);
  602. }
  603. }
  604. }
  605. /**
  606. * this function ensures a certain location is visible on the screen.
  607. * if endCol is -1, ignore making the columns visible.
  608. */
  609. void KateViewInternal::makeVisible (const KateTextCursor& c, uint endCol, bool force, bool center, bool calledExternally)
  610. {
  611. //kdDebug() << "MakeVisible start [" << startPos().line << "," << startPos().col << "] end [" << endPos().line << "," << endPos().col << "] -> request: [" << c.line << "," << c.col << "]" <<endl;// , new start [" << scroll.line << "," << scroll.col << "] lines " << (linesDisplayed() - 1) << " height " << height() << endl;
  612. // if the line is in a folded region, unfold all the way up
  613. //if ( m_doc->foldingTree()->findNodeForLine( c.line )->visible )
  614. // kdDebug()<<"line ("<<c.line<<") should be visible"<<endl;
  615. if ( force )
  616. {
  617. KateTextCursor scroll = c;
  618. scrollPos(scroll, force, calledExternally);
  619. }
  620. else if (center && (c < startPos() || c > endPos()))
  621. {
  622. KateTextCursor scroll = viewLineOffset(c, -int(linesDisplayed()) / 2);
  623. scrollPos(scroll, false, calledExternally);
  624. }
  625. else if ( c > viewLineOffset(endPos(), -m_minLinesVisible) )
  626. {
  627. KateTextCursor scroll = viewLineOffset(c, -((int)linesDisplayed() - m_minLinesVisible - 1));
  628. scrollPos(scroll, false, calledExternally);
  629. }
  630. else if ( c < viewLineOffset(startPos(), m_minLinesVisible) )
  631. {
  632. KateTextCursor scroll = viewLineOffset(c, -m_minLinesVisible);
  633. scrollPos(scroll, false, calledExternally);
  634. }
  635. else
  636. {
  637. // Check to see that we're not showing blank lines
  638. KateTextCursor max = maxStartPos();
  639. if (startPos() > max) {
  640. scrollPos(max, max.col(), calledExternally);
  641. }
  642. }
  643. if (!m_view->dynWordWrap() && endCol != (uint)-1)
  644. {
  645. int sX = (int)m_view->renderer()->textWidth (textLine( m_doc->getRealLine( c.line() ) ), c.col() );
  646. int sXborder = sX-8;
  647. if (sXborder < 0)
  648. sXborder = 0;
  649. if (sX < m_startX)
  650. scrollColumns (sXborder);
  651. else if (sX > m_startX + width())
  652. scrollColumns (sX - width() + 8);
  653. }
  654. m_madeVisible = !force;
  655. }
  656. void KateViewInternal::slotRegionVisibilityChangedAt(unsigned int)
  657. {
  658. kdDebug(13030) << "slotRegionVisibilityChangedAt()" << endl;
  659. m_cachedMaxStartPos.setLine(-1);
  660. KateTextCursor max = maxStartPos();
  661. if (startPos() > max)
  662. scrollPos(max);
  663. updateView();
  664. update();
  665. leftBorder->update();
  666. }
  667. void KateViewInternal::slotCodeFoldingChanged()
  668. {
  669. leftBorder->update();
  670. }
  671. void KateViewInternal::slotRegionBeginEndAddedRemoved(unsigned int)
  672. {
  673. kdDebug(13030) << "slotRegionBeginEndAddedRemoved()" << endl;
  674. // FIXME: performance problem
  675. leftBorder->update();
  676. }
  677. void KateViewInternal::showEvent ( TQShowEvent *e )
  678. {
  679. updateView ();
  680. TQWidget::showEvent (e);
  681. }
  682. uint KateViewInternal::linesDisplayed() const
  683. {
  684. int h = height();
  685. int fh = m_view->renderer()->fontHeight();
  686. return (h - (h % fh)) / fh;
  687. }
  688. TQPoint KateViewInternal::cursorCoordinates()
  689. {
  690. int viewLine = displayViewLine(displayCursor, true);
  691. if (viewLine == -1)
  692. return TQPoint(-1, -1);
  693. uint y = viewLine * m_view->renderer()->fontHeight();
  694. uint x = cXPos - m_startX - lineRanges[viewLine].startX + leftBorder->width() + lineRanges[viewLine].xOffset();
  695. return TQPoint(x, y);
  696. }
  697. void KateViewInternal::updateMicroFocusHint()
  698. {
  699. int line = displayViewLine(displayCursor, true);
  700. /* Check for hasFocus() to avoid crashes in QXIMInputContext as in bug #131266.
  701. This is only a workaround until somebody can find the real reason of the crash
  702. (probably it's in Qt). */
  703. if (line == -1 || !hasFocus())
  704. return;
  705. KateRenderer *renderer = m_view->renderer();
  706. // Cursor placement code is changed for Asian input method that
  707. // shows candidate window. This behavior is same as Qt/E 2.3.7
  708. // which supports Asian input methods. Asian input methods need
  709. // start point of IM selection text to place candidate window as
  710. // adjacent to the selection text.
  711. uint preeditStrLen = renderer->textWidth(textLine(m_imPreeditStartLine), cursor.col()) - renderer->textWidth(textLine(m_imPreeditStartLine), m_imPreeditSelStart);
  712. uint x = cXPos - m_startX - lineRanges[line].startX + lineRanges[line].xOffset() - preeditStrLen;
  713. uint y = line * renderer->fontHeight();
  714. setMicroFocusHint(x, y, 0, renderer->fontHeight());
  715. }
  716. void KateViewInternal::doReturn()
  717. {
  718. KateTextCursor c = cursor;
  719. m_doc->newLine( c, this );
  720. updateCursor( c );
  721. updateView();
  722. }
  723. void KateViewInternal::doDelete()
  724. {
  725. m_doc->del( m_view, cursor );
  726. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  727. m_view->m_codeCompletion->updateBox();
  728. }
  729. }
  730. void KateViewInternal::doBackspace()
  731. {
  732. m_doc->backspace( m_view, cursor );
  733. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  734. m_view->m_codeCompletion->updateBox();
  735. }
  736. }
  737. void KateViewInternal::doTranspose()
  738. {
  739. m_doc->transpose( cursor );
  740. }
  741. void KateViewInternal::doDeleteWordLeft()
  742. {
  743. wordLeft( true );
  744. m_view->removeSelectedText();
  745. update();
  746. }
  747. void KateViewInternal::doDeleteWordRight()
  748. {
  749. wordRight( true );
  750. m_view->removeSelectedText();
  751. update();
  752. }
  753. class CalculatingCursor : public KateTextCursor {
  754. public:
  755. CalculatingCursor(KateViewInternal* vi)
  756. : KateTextCursor()
  757. , m_vi(vi)
  758. {
  759. Q_ASSERT(valid());
  760. }
  761. CalculatingCursor(KateViewInternal* vi, const KateTextCursor& c)
  762. : KateTextCursor(c)
  763. , m_vi(vi)
  764. {
  765. Q_ASSERT(valid());
  766. }
  767. // This one constrains its arguments to valid positions
  768. CalculatingCursor(KateViewInternal* vi, uint line, uint col)
  769. : KateTextCursor(line, col)
  770. , m_vi(vi)
  771. {
  772. makeValid();
  773. }
  774. virtual CalculatingCursor& operator+=( int n ) = 0;
  775. virtual CalculatingCursor& operator-=( int n ) = 0;
  776. CalculatingCursor& operator++() { return operator+=( 1 ); }
  777. CalculatingCursor& operator--() { return operator-=( 1 ); }
  778. void makeValid() {
  779. m_line = kMax( 0, kMin( int( m_vi->m_doc->numLines() - 1 ), line() ) );
  780. if (m_vi->m_view->wrapCursor())
  781. m_col = kMax( 0, kMin( m_vi->m_doc->lineLength( line() ), col() ) );
  782. else
  783. m_col = kMax( 0, col() );
  784. Q_ASSERT( valid() );
  785. }
  786. void toEdge( Bias bias ) {
  787. if( bias == left_b ) m_col = 0;
  788. else if( bias == right_b ) m_col = m_vi->m_doc->lineLength( line() );
  789. }
  790. bool atEdge() const { return atEdge( left_b ) || atEdge( right_b ); }
  791. bool atEdge( Bias bias ) const {
  792. switch( bias ) {
  793. case left_b: return col() == 0;
  794. case none: return atEdge();
  795. case right_b: return col() == m_vi->m_doc->lineLength( line() );
  796. default: Q_ASSERT(false); return false;
  797. }
  798. }
  799. protected:
  800. bool valid() const {
  801. return line() >= 0 &&
  802. uint( line() ) < m_vi->m_doc->numLines() &&
  803. col() >= 0 &&
  804. (!m_vi->m_view->wrapCursor() || col() <= m_vi->m_doc->lineLength( line() ));
  805. }
  806. KateViewInternal* m_vi;
  807. };
  808. class BoundedCursor : public CalculatingCursor {
  809. public:
  810. BoundedCursor(KateViewInternal* vi)
  811. : CalculatingCursor( vi ) {};
  812. BoundedCursor(KateViewInternal* vi, const KateTextCursor& c )
  813. : CalculatingCursor( vi, c ) {};
  814. BoundedCursor(KateViewInternal* vi, uint line, uint col )
  815. : CalculatingCursor( vi, line, col ) {};
  816. virtual CalculatingCursor& operator+=( int n ) {
  817. m_col += n;
  818. if (n > 0 && m_vi->m_view->dynWordWrap()) {
  819. // Need to constrain to current visible text line for dynamic wrapping mode
  820. if (m_col > m_vi->m_doc->lineLength(m_line)) {
  821. KateLineRange currentRange = m_vi->range(*this);
  822. int endX;
  823. bool crap;
  824. m_vi->m_view->renderer()->textWidth(m_vi->textLine(m_line), currentRange.startCol, m_vi->width() - currentRange.xOffset(), &crap, &endX);
  825. endX += (m_col - currentRange.endCol + 1) * m_vi->m_view->renderer()->spaceWidth();
  826. // Constraining if applicable NOTE: some code duplication in KateViewInternal::resize()
  827. if (endX >= m_vi->width() - currentRange.xOffset()) {
  828. m_col -= n;
  829. if ( uint( line() ) < m_vi->m_doc->numLines() - 1 ) {
  830. m_line++;
  831. m_col = 0;
  832. }
  833. }
  834. }
  835. } else if (n < 0 && col() < 0 && line() > 0 ) {
  836. m_line--;
  837. m_col = m_vi->m_doc->lineLength( line() );
  838. }
  839. m_col = kMax( 0, col() );
  840. Q_ASSERT( valid() );
  841. return *this;
  842. }
  843. virtual CalculatingCursor& operator-=( int n ) {
  844. return operator+=( -n );
  845. }
  846. };
  847. class WrappingCursor : public CalculatingCursor {
  848. public:
  849. WrappingCursor(KateViewInternal* vi)
  850. : CalculatingCursor( vi) {};
  851. WrappingCursor(KateViewInternal* vi, const KateTextCursor& c )
  852. : CalculatingCursor( vi, c ) {};
  853. WrappingCursor(KateViewInternal* vi, uint line, uint col )
  854. : CalculatingCursor( vi, line, col ) {};
  855. virtual CalculatingCursor& operator+=( int n ) {
  856. if( n < 0 ) return operator-=( -n );
  857. int len = m_vi->m_doc->lineLength( line() );
  858. if( col() + n <= len ) {
  859. m_col += n;
  860. } else if( uint( line() ) < m_vi->m_doc->numLines() - 1 ) {
  861. n -= len - col() + 1;
  862. m_col = 0;
  863. m_line++;
  864. operator+=( n );
  865. } else {
  866. m_col = len;
  867. }
  868. Q_ASSERT( valid() );
  869. return *this;
  870. }
  871. virtual CalculatingCursor& operator-=( int n ) {
  872. if( n < 0 ) return operator+=( -n );
  873. if( col() - n >= 0 ) {
  874. m_col -= n;
  875. } else if( line() > 0 ) {
  876. n -= col() + 1;
  877. m_line--;
  878. m_col = m_vi->m_doc->lineLength( line() );
  879. operator-=( n );
  880. } else {
  881. m_col = 0;
  882. }
  883. Q_ASSERT( valid() );
  884. return *this;
  885. }
  886. };
  887. void KateViewInternal::moveChar( Bias bias, bool sel )
  888. {
  889. KateTextCursor c;
  890. if ( m_view->wrapCursor() ) {
  891. c = WrappingCursor( this, cursor ) += bias;
  892. } else {
  893. c = BoundedCursor( this, cursor ) += bias;
  894. }
  895. updateSelection( c, sel );
  896. updateCursor( c );
  897. }
  898. void KateViewInternal::cursorLeft( bool sel )
  899. {
  900. if ( ! m_view->wrapCursor() && cursor.col() == 0 )
  901. return;
  902. moveChar( left_b, sel );
  903. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  904. m_view->m_codeCompletion->updateBox();
  905. }
  906. }
  907. void KateViewInternal::cursorRight( bool sel )
  908. {
  909. moveChar( right_b, sel );
  910. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  911. m_view->m_codeCompletion->updateBox();
  912. }
  913. }
  914. void KateViewInternal::wordLeft ( bool sel )
  915. {
  916. WrappingCursor c( this, cursor );
  917. // First we skip backwards all space.
  918. // Then we look up into which category the current position falls:
  919. // 1. a "word" character
  920. // 2. a "non-word" character (except space)
  921. // 3. the beginning of the line
  922. // and skip all preceding characters that fall into this class.
  923. // The code assumes that space is never part of the word character class.
  924. KateHighlighting* h = m_doc->highlight();
  925. if( !c.atEdge( left_b ) ) {
  926. while( !c.atEdge( left_b ) && m_doc->textLine( c.line() )[ c.col() - 1 ].isSpace() )
  927. --c;
  928. }
  929. if( c.atEdge( left_b ) )
  930. {
  931. --c;
  932. }
  933. else if( h->isInWord( m_doc->textLine( c.line() )[ c.col() - 1 ] ) )
  934. {
  935. while( !c.atEdge( left_b ) && h->isInWord( m_doc->textLine( c.line() )[ c.col() - 1 ] ) )
  936. --c;
  937. }
  938. else
  939. {
  940. while( !c.atEdge( left_b )
  941. && !h->isInWord( m_doc->textLine( c.line() )[ c.col() - 1 ] )
  942. // in order to stay symmetric to wordLeft()
  943. // we must not skip space preceding a non-word sequence
  944. && !m_doc->textLine( c.line() )[ c.col() - 1 ].isSpace() )
  945. {
  946. --c;
  947. }
  948. }
  949. updateSelection( c, sel );
  950. updateCursor( c );
  951. }
  952. void KateViewInternal::wordRight( bool sel )
  953. {
  954. WrappingCursor c( this, cursor );
  955. // We look up into which category the current position falls:
  956. // 1. a "word" character
  957. // 2. a "non-word" character (except space)
  958. // 3. the end of the line
  959. // and skip all following characters that fall into this class.
  960. // If the skipped characters are followed by space, we skip that too.
  961. // The code assumes that space is never part of the word character class.
  962. KateHighlighting* h = m_doc->highlight();
  963. if( c.atEdge( right_b ) )
  964. {
  965. ++c;
  966. }
  967. else if( h->isInWord( m_doc->textLine( c.line() )[ c.col() ] ) )
  968. {
  969. while( !c.atEdge( right_b ) && h->isInWord( m_doc->textLine( c.line() )[ c.col() ] ) )
  970. ++c;
  971. }
  972. else
  973. {
  974. while( !c.atEdge( right_b )
  975. && !h->isInWord( m_doc->textLine( c.line() )[ c.col() ] )
  976. // we must not skip space, because if that space is followed
  977. // by more non-word characters, we would skip them, too
  978. && !m_doc->textLine( c.line() )[ c.col() ].isSpace() )
  979. {
  980. ++c;
  981. }
  982. }
  983. while( !c.atEdge( right_b ) && m_doc->textLine( c.line() )[ c.col() ].isSpace() )
  984. ++c;
  985. updateSelection( c, sel );
  986. updateCursor( c );
  987. }
  988. void KateViewInternal::moveEdge( Bias bias, bool sel )
  989. {
  990. BoundedCursor c( this, cursor );
  991. c.toEdge( bias );
  992. updateSelection( c, sel );
  993. updateCursor( c );
  994. }
  995. void KateViewInternal::home( bool sel )
  996. {
  997. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  998. TQKeyEvent e(TQEvent::KeyPress, Qt::Key_Home, 0, 0);
  999. m_view->m_codeCompletion->handleKey(&e);
  1000. return;
  1001. }
  1002. if (m_view->dynWordWrap() && currentRange().startCol) {
  1003. // Allow us to go to the real start if we're already at the start of the view line
  1004. if (cursor.col() != currentRange().startCol) {
  1005. KateTextCursor c(cursor.line(), currentRange().startCol);
  1006. updateSelection( c, sel );
  1007. updateCursor( c );
  1008. return;
  1009. }
  1010. }
  1011. if( !(m_doc->configFlags() & KateDocument::cfSmartHome) ) {
  1012. moveEdge( left_b, sel );
  1013. return;
  1014. }
  1015. KateTextLine::Ptr l = textLine( cursor.line() );
  1016. if (!l)
  1017. return;
  1018. KateTextCursor c = cursor;
  1019. int lc = l->firstChar();
  1020. if( lc < 0 || c.col() == lc ) {
  1021. c.setCol(0);
  1022. } else {
  1023. c.setCol(lc);
  1024. }
  1025. updateSelection( c, sel );
  1026. updateCursor( c, true );
  1027. }
  1028. void KateViewInternal::end( bool sel )
  1029. {
  1030. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  1031. TQKeyEvent e(TQEvent::KeyPress, Qt::Key_End, 0, 0);
  1032. m_view->m_codeCompletion->handleKey(&e);
  1033. return;
  1034. }
  1035. KateLineRange range = currentRange();
  1036. if (m_view->dynWordWrap() && range.wrap) {
  1037. // Allow us to go to the real end if we're already at the end of the view line
  1038. if (cursor.col() < range.endCol - 1) {
  1039. KateTextCursor c(cursor.line(), range.endCol - 1);
  1040. updateSelection( c, sel );
  1041. updateCursor( c );
  1042. return;
  1043. }
  1044. }
  1045. if( !(m_doc->configFlags() & KateDocument::cfSmartHome) ) {
  1046. moveEdge( right_b, sel );
  1047. return;
  1048. }
  1049. KateTextLine::Ptr l = textLine( cursor.line() );
  1050. if (!l)
  1051. return;
  1052. // "Smart End", as requested in bugs #78258 and #106970
  1053. KateTextCursor c = cursor;
  1054. // If the cursor is already the real end, jump to last non-space character.
  1055. // Otherwise, go to the real end ... obviously.
  1056. if (c.col() == m_doc->lineLength(c.line())) {
  1057. c.setCol(l->lastChar() + 1);
  1058. updateSelection(c, sel);
  1059. updateCursor(c, true);
  1060. } else {
  1061. moveEdge(right_b, sel);
  1062. }
  1063. }
  1064. KateLineRange KateViewInternal::range(int realLine, const KateLineRange* previous)
  1065. {
  1066. // look at the cache first
  1067. if (!m_updatingView && realLine >= lineRanges[0].line && realLine <= lineRanges[lineRanges.count() - 1].line)
  1068. for (uint i = 0; i < lineRanges.count(); i++)
  1069. if (realLine == lineRanges[i].line)
  1070. if (!m_view->dynWordWrap() || (!previous && lineRanges[i].startCol == 0) || (previous && lineRanges[i].startCol == previous->endCol))
  1071. return lineRanges[i];
  1072. // Not in the cache, we have to create it
  1073. KateLineRange ret;
  1074. KateTextLine::Ptr text = textLine(realLine);
  1075. if (!text) {
  1076. return KateLineRange();
  1077. }
  1078. if (!m_view->dynWordWrap()) {
  1079. Q_ASSERT(!previous);
  1080. ret.line = realLine;
  1081. ret.virtualLine = m_doc->getVirtualLine(realLine);
  1082. ret.startCol = 0;
  1083. ret.endCol = m_doc->lineLength(realLine);
  1084. ret.startX = 0;
  1085. ret.endX = m_view->renderer()->textWidth(text, -1);
  1086. ret.viewLine = 0;
  1087. ret.wrap = false;
  1088. return ret;
  1089. }
  1090. ret.endCol = (int)m_view->renderer()->textWidth(text, previous ? previous->endCol : 0, width() - (previous ? previous->shiftX : 0), &ret.wrap, &ret.endX);
  1091. Q_ASSERT(ret.endCol > ret.startCol);
  1092. ret.line = realLine;
  1093. if (previous) {
  1094. ret.virtualLine = previous->virtualLine;
  1095. ret.startCol = previous->endCol;
  1096. ret.startX = previous->endX;
  1097. ret.endX += previous->endX;
  1098. ret.shiftX = previous->shiftX;
  1099. ret.viewLine = previous->viewLine + 1;
  1100. } else {
  1101. // TODO worthwhile optimising this to get the data out of the initial textWidth call?
  1102. if (m_view->config()->dynWordWrapAlignIndent() > 0) {
  1103. int pos = text->nextNonSpaceChar(0);
  1104. if (pos > 0)
  1105. ret.shiftX = m_view->renderer()->textWidth(text, pos);
  1106. if (ret.shiftX > ((double)width() / 100 * m_view->config()->dynWordWrapAlignIndent()))
  1107. ret.shiftX = 0;
  1108. }
  1109. ret.virtualLine = m_doc->getVirtualLine(realLine);
  1110. ret.startCol = 0;
  1111. ret.startX = 0;
  1112. ret.viewLine = 0;
  1113. }
  1114. return ret;
  1115. }
  1116. KateLineRange KateViewInternal::currentRange()
  1117. {
  1118. // Q_ASSERT(m_view->dynWordWrap());
  1119. return range(cursor);
  1120. }
  1121. KateLineRange KateViewInternal::previousRange()
  1122. {
  1123. uint currentViewLine = viewLine(cursor);
  1124. if (currentViewLine)
  1125. return range(cursor.line(), currentViewLine - 1);
  1126. else
  1127. return range(m_doc->getRealLine(displayCursor.line() - 1), -1);
  1128. }
  1129. KateLineRange KateViewInternal::nextRange()
  1130. {
  1131. uint currentViewLine = viewLine(cursor) + 1;
  1132. if (currentViewLine >= viewLineCount(cursor.line())) {
  1133. currentViewLine = 0;
  1134. return range(cursor.line() + 1, currentViewLine);
  1135. } else {
  1136. return range(cursor.line(), currentViewLine);
  1137. }
  1138. }
  1139. KateLineRange KateViewInternal::range(const KateTextCursor& realCursor)
  1140. {
  1141. // Q_ASSERT(m_view->dynWordWrap());
  1142. KateLineRange thisRange;
  1143. bool first = true;
  1144. do {
  1145. thisRange = range(realCursor.line(), first ? 0L : &thisRange);
  1146. first = false;
  1147. } while (thisRange.wrap && !(realCursor.col() >= thisRange.startCol && realCursor.col() < thisRange.endCol) && thisRange.startCol != thisRange.endCol);
  1148. return thisRange;
  1149. }
  1150. KateLineRange KateViewInternal::range(uint realLine, int viewLine)
  1151. {
  1152. // Q_ASSERT(m_view->dynWordWrap());
  1153. KateLineRange thisRange;
  1154. bool first = true;
  1155. do {
  1156. thisRange = range(realLine, first ? 0L : &thisRange);
  1157. first = false;
  1158. } while (thisRange.wrap && viewLine != thisRange.viewLine && thisRange.startCol != thisRange.endCol);
  1159. if (viewLine != -1 && viewLine != thisRange.viewLine)
  1160. kdDebug(13030) << "WARNING: viewLine " << viewLine << " of line " << realLine << " does not exist." << endl;
  1161. return thisRange;
  1162. }
  1163. /**
  1164. * This returns the view line upon which realCursor is situated.
  1165. * The view line is the number of lines in the view from the first line
  1166. * The supplied cursor should be in real lines.
  1167. */
  1168. uint KateViewInternal::viewLine(const KateTextCursor& realCursor)
  1169. {
  1170. if (!m_view->dynWordWrap()) return 0;
  1171. if (realCursor.col() == 0) return 0;
  1172. KateLineRange thisRange;
  1173. bool first = true;
  1174. do {
  1175. thisRange = range(realCursor.line(), first ? 0L : &thisRange);
  1176. first = false;
  1177. } while (thisRange.wrap && !(realCursor.col() >= thisRange.startCol && realCursor.col() < thisRange.endCol) && thisRange.startCol != thisRange.endCol);
  1178. return thisRange.viewLine;
  1179. }
  1180. int KateViewInternal::displayViewLine(const KateTextCursor& virtualCursor, bool limitToVisible)
  1181. {
  1182. KateTextCursor work = startPos();
  1183. int limit = linesDisplayed();
  1184. // Efficient non-word-wrapped path
  1185. if (!m_view->dynWordWrap()) {
  1186. int ret = virtualCursor.line() - startLine();
  1187. if (limitToVisible && (ret < 0 || ret > limit))
  1188. return -1;
  1189. else
  1190. return ret;
  1191. }
  1192. if (work == virtualCursor) {
  1193. return 0;
  1194. }
  1195. int ret = -(int)viewLine(work);
  1196. bool forwards = (work < virtualCursor) ? true : false;
  1197. // FIXME switch to using ranges? faster?
  1198. if (forwards) {
  1199. while (work.line() != virtualCursor.line()) {
  1200. ret += viewLineCount(m_doc->getRealLine(work.line()));
  1201. work.setLine(work.line() + 1);
  1202. if (limitToVisible && ret > limit)
  1203. return -1;
  1204. }
  1205. } else {
  1206. while (work.line() != virtualCursor.line()) {
  1207. work.setLine(work.line() - 1);
  1208. ret -= viewLineCount(m_doc->getRealLine(work.line()));
  1209. if (limitToVisible && ret < 0)
  1210. return -1;
  1211. }
  1212. }
  1213. // final difference
  1214. KateTextCursor realCursor = virtualCursor;
  1215. realCursor.setLine(m_doc->getRealLine(realCursor.line()));
  1216. if (realCursor.col() == -1) realCursor.setCol(m_doc->lineLength(realCursor.line()));
  1217. ret += viewLine(realCursor);
  1218. if (limitToVisible && (ret < 0 || ret > limit))
  1219. return -1;
  1220. return ret;
  1221. }
  1222. uint KateViewInternal::lastViewLine(uint realLine)
  1223. {
  1224. if (!m_view->dynWordWrap()) return 0;
  1225. KateLineRange thisRange;
  1226. bool first = true;
  1227. do {
  1228. thisRange = range(realLine, first ? 0L : &thisRange);
  1229. first = false;
  1230. } while (thisRange.wrap && thisRange.startCol != thisRange.endCol);
  1231. return thisRange.viewLine;
  1232. }
  1233. uint KateViewInternal::viewLineCount(uint realLine)
  1234. {
  1235. return lastViewLine(realLine) + 1;
  1236. }
  1237. /*
  1238. * This returns the cursor which is offset by (offset) view lines.
  1239. * This is the main function which is called by code not specifically dealing with word-wrap.
  1240. * The opposite conversion (cursor to offset) can be done with displayViewLine.
  1241. *
  1242. * The cursors involved are virtual cursors (ie. equivalent to displayCursor)
  1243. */
  1244. KateTextCursor KateViewInternal::viewLineOffset(const KateTextCursor& virtualCursor, int offset, bool keepX)
  1245. {
  1246. if (!m_view->dynWordWrap()) {
  1247. KateTextCursor ret(kMin((int)m_doc->visibleLines() - 1, virtualCursor.line() + offset), 0);
  1248. if (ret.line() < 0)
  1249. ret.setLine(0);
  1250. if (keepX) {
  1251. int realLine = m_doc->getRealLine(ret.line());
  1252. ret.setCol(m_doc->lineLength(realLine) - 1);
  1253. if (m_currentMaxX > cXPos)
  1254. cXPos = m_currentMaxX;
  1255. if (m_view->wrapCursor())
  1256. cXPos = kMin(cXPos, (int)m_view->renderer()->textWidth(textLine(realLine), m_doc->lineLength(realLine)));
  1257. m_view->renderer()->textWidth(ret, cXPos);
  1258. }
  1259. return ret;
  1260. }
  1261. KateTextCursor realCursor = virtualCursor;
  1262. realCursor.setLine(m_doc->getRealLine(virtualCursor.line()));
  1263. uint cursorViewLine = viewLine(realCursor);
  1264. int currentOffset = 0;
  1265. int virtualLine = 0;
  1266. bool forwards = (offset > 0) ? true : false;
  1267. if (forwards) {
  1268. currentOffset = lastViewLine(realCursor.line()) - cursorViewLine;
  1269. if (offset <= currentOffset) {
  1270. // the answer is on the same line
  1271. KateLineRange thisRange = range(realCursor.line(), cursorViewLine + offset);
  1272. Q_ASSERT(thisRange.virtualLine == virtualCursor.line());
  1273. return KateTextCursor(virtualCursor.line(), thisRange.startCol);
  1274. }
  1275. virtualLine = virtualCursor.line() + 1;
  1276. } else {
  1277. offset = -offset;
  1278. currentOffset = cursorViewLine;
  1279. if (offset <= currentOffset) {
  1280. // the answer is on the same line
  1281. KateLineRange thisRange = range(realCursor.line(), cursorViewLine - offset);
  1282. Q_ASSERT(thisRange.virtualLine == virtualCursor.line());
  1283. return KateTextCursor(virtualCursor.line(), thisRange.startCol);
  1284. }
  1285. virtualLine = virtualCursor.line() - 1;
  1286. }
  1287. currentOffset++;
  1288. while (virtualLine >= 0 && virtualLine < (int)m_doc->visibleLines())
  1289. {
  1290. KateLineRange thisRange;
  1291. bool first = true;
  1292. int realLine = m_doc->getRealLine(virtualLine);
  1293. do {
  1294. thisRange = range(realLine, first ? 0L : &thisRange);
  1295. first = false;
  1296. if (offset == currentOffset) {
  1297. if (!forwards) {
  1298. // We actually want it the other way around
  1299. int requiredViewLine = lastViewLine(realLine) - thisRange.viewLine;
  1300. if (requiredViewLine != thisRange.viewLine) {
  1301. thisRange = range(realLine, requiredViewLine);
  1302. }
  1303. }
  1304. KateTextCursor ret(virtualLine, thisRange.startCol);
  1305. // keep column position
  1306. if (keepX) {
  1307. ret.setCol(thisRange.endCol - 1);
  1308. KateTextCursor realCursorTemp(m_doc->getRealLine(virtualCursor.line()), virtualCursor.col());
  1309. int visibleX = m_view->renderer()->textWidth(realCursorTemp) - range(realCursorTemp).startX;
  1310. int xOffset = thisRange.startX;
  1311. if (m_currentMaxX > visibleX)
  1312. visibleX = m_currentMaxX;
  1313. cXPos = xOffset + visibleX;
  1314. cXPos = kMin(cXPos, lineMaxCursorX(thisRange));
  1315. m_view->renderer()->textWidth(ret, cXPos);
  1316. }
  1317. return ret;
  1318. }
  1319. currentOffset++;
  1320. } while (thisRange.wrap);
  1321. if (forwards)
  1322. virtualLine++;
  1323. else
  1324. virtualLine--;
  1325. }
  1326. // Looks like we were asked for something a bit exotic.
  1327. // Return the max/min valid position.
  1328. if (forwards)
  1329. return KateTextCursor(m_doc->visibleLines() - 1, m_doc->lineLength(m_doc->visibleLines() - 1));
  1330. else
  1331. return KateTextCursor(0, 0);
  1332. }
  1333. int KateViewInternal::lineMaxCursorX(const KateLineRange& range)
  1334. {
  1335. if (!m_view->wrapCursor() && !range.wrap)
  1336. return INT_MAX;
  1337. int maxX = range.endX;
  1338. if (maxX && range.wrap) {
  1339. TQChar lastCharInLine = textLine(range.line)->getChar(range.endCol - 1);
  1340. if (lastCharInLine == TQChar('\t')) {
  1341. int lineSize = 0;
  1342. int lastTabSize = 0;
  1343. for(int i = range.startCol; i < range.endCol; i++) {
  1344. if (textLine(range.line)->getChar(i) == TQChar('\t')) {
  1345. lastTabSize = m_view->tabWidth() - (lineSize % m_view->tabWidth());
  1346. lineSize += lastTabSize;
  1347. } else {
  1348. lineSize++;
  1349. }
  1350. }
  1351. maxX -= lastTabSize * m_view->renderer()->spaceWidth();
  1352. } else {
  1353. maxX -= m_view->renderer()->config()->fontMetrics()->width(lastCharInLine);
  1354. }
  1355. }
  1356. return maxX;
  1357. }
  1358. int KateViewInternal::lineMaxCol(const KateLineRange& range)
  1359. {
  1360. int maxCol = range.endCol;
  1361. if (maxCol && range.wrap)
  1362. maxCol--;
  1363. return maxCol;
  1364. }
  1365. void KateViewInternal::cursorUp(bool sel)
  1366. {
  1367. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  1368. TQKeyEvent e(TQEvent::KeyPress, Qt::Key_Up, 0, 0);
  1369. m_view->m_codeCompletion->handleKey(&e);
  1370. return;
  1371. }
  1372. if (displayCursor.line() == 0 && (!m_view->dynWordWrap() || viewLine(cursor) == 0))
  1373. return;
  1374. int newLine = cursor.line(), newCol = 0, xOffset = 0, startCol = 0;
  1375. m_preserveMaxX = true;
  1376. if (m_view->dynWordWrap()) {
  1377. // Dynamic word wrapping - navigate on visual lines rather than real lines
  1378. KateLineRange thisRange = currentRange();
  1379. // This is not the first line because that is already simplified out above
  1380. KateLineRange pRange = previousRange();
  1381. // Ensure we're in the right spot
  1382. Q_ASSERT((cursor.line() == thisRange.line) &&
  1383. (cursor.col() >= thisRange.startCol) &&
  1384. (!thisRange.wrap || cursor.col() < thisRange.endCol));
  1385. // VisibleX is the distance from the start of the text to the cursor on the current line.
  1386. int visibleX = m_view->renderer()->textWidth(cursor) - thisRange.startX;
  1387. int currentLineVisibleX = visibleX;
  1388. // Translate to new line
  1389. visibleX += thisRange.xOffset();
  1390. visibleX -= pRange.xOffset();
  1391. // Limit to >= 0
  1392. visibleX = kMax(0, visibleX);
  1393. startCol = pRange.startCol;
  1394. xOffset = pRange.startX;
  1395. newLine = pRange.line;
  1396. // Take into account current max X (ie. if the current line was smaller
  1397. // than the last definitely specified width)
  1398. if (thisRange.xOffset() && !pRange.xOffset() && currentLineVisibleX == 0) // Special case for where xOffset may be > m_currentMaxX
  1399. visibleX = m_currentMaxX;
  1400. else if (visibleX < m_currentMaxX - pRange.xOffset())
  1401. visibleX = m_currentMaxX - pRange.xOffset();
  1402. cXPos = xOffset + visibleX;
  1403. cXPos = kMin(cXPos, lineMaxCursorX(pRange));
  1404. newCol = kMin((int)m_view->renderer()->textPos(newLine, visibleX, startCol), lineMaxCol(pRange));
  1405. } else {
  1406. newLine = m_doc->getRealLine(displayCursor.line() - 1);
  1407. if ((m_view->wrapCursor()) && m_currentMaxX > cXPos)
  1408. cXPos = m_currentMaxX;
  1409. }
  1410. KateTextCursor c(newLine, newCol);
  1411. m_view->renderer()->textWidth(c, cXPos);
  1412. updateSelection( c, sel );
  1413. updateCursor( c );
  1414. }
  1415. void KateViewInternal::cursorDown(bool sel)
  1416. {
  1417. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  1418. TQKeyEvent e(TQEvent::KeyPress, Qt::Key_Down, 0, 0);
  1419. m_view->m_codeCompletion->handleKey(&e);
  1420. return;
  1421. }
  1422. if ((displayCursor.line() >= (int)m_doc->numVisLines() - 1) && (!m_view->dynWordWrap() || viewLine(cursor) == lastViewLine(cursor.line())))
  1423. return;
  1424. int newLine = cursor.line(), newCol = 0, xOffset = 0, startCol = 0;
  1425. m_preserveMaxX = true;
  1426. if (m_view->dynWordWrap()) {
  1427. // Dynamic word wrapping - navigate on visual lines rather than real lines
  1428. KateLineRange thisRange = currentRange();
  1429. // This is not the last line because that is already simplified out above
  1430. KateLineRange nRange = nextRange();
  1431. // Ensure we're in the right spot
  1432. Q_ASSERT((cursor.line() == thisRange.line) &&
  1433. (cursor.col() >= thisRange.startCol) &&
  1434. (!thisRange.wrap || cursor.col() < thisRange.endCol));
  1435. // VisibleX is the distance from the start of the text to the cursor on the current line.
  1436. int visibleX = m_view->renderer()->textWidth(cursor) - thisRange.startX;
  1437. int currentLineVisibleX = visibleX;
  1438. // Translate to new line
  1439. visibleX += thisRange.xOffset();
  1440. visibleX -= nRange.xOffset();
  1441. // Limit to >= 0
  1442. visibleX = kMax(0, visibleX);
  1443. if (!thisRange.wrap) {
  1444. newLine = m_doc->getRealLine(displayCursor.line() + 1);
  1445. } else {
  1446. startCol = thisRange.endCol;
  1447. xOffset = thisRange.endX;
  1448. }
  1449. // Take into account current max X (ie. if the current line was smaller
  1450. // than the last definitely specified width)
  1451. if (thisRange.xOffset() && !nRange.xOffset() && currentLineVisibleX == 0) // Special case for where xOffset may be > m_currentMaxX
  1452. visibleX = m_currentMaxX;
  1453. else if (visibleX < m_currentMaxX - nRange.xOffset())
  1454. visibleX = m_currentMaxX - nRange.xOffset();
  1455. cXPos = xOffset + visibleX;
  1456. cXPos = kMin(cXPos, lineMaxCursorX(nRange));
  1457. newCol = kMin((int)m_view->renderer()->textPos(newLine, visibleX, startCol), lineMaxCol(nRange));
  1458. } else {
  1459. newLine = m_doc->getRealLine(displayCursor.line() + 1);
  1460. if ((m_view->wrapCursor()) && m_currentMaxX > cXPos)
  1461. cXPos = m_currentMaxX;
  1462. }
  1463. KateTextCursor c(newLine, newCol);
  1464. m_view->renderer()->textWidth(c, cXPos);
  1465. updateSelection(c, sel);
  1466. updateCursor(c);
  1467. }
  1468. void KateViewInternal::cursorToMatchingBracket( bool sel )
  1469. {
  1470. KateTextCursor start( cursor ), end;
  1471. if( !m_doc->findMatchingBracket( start, end ) )
  1472. return;
  1473. // The cursor is now placed just to the left of the matching bracket.
  1474. // If it's an ending bracket, put it to the right (so we can easily
  1475. // get back to the original bracket).
  1476. if( end > start )
  1477. end.setCol(end.col() + 1);
  1478. updateSelection( end, sel );
  1479. updateCursor( end );
  1480. }
  1481. void KateViewInternal::topOfView( bool sel )
  1482. {
  1483. KateTextCursor c = viewLineOffset(startPos(), m_minLinesVisible);
  1484. updateSelection( c, sel );
  1485. updateCursor( c );
  1486. }
  1487. void KateViewInternal::bottomOfView( bool sel )
  1488. {
  1489. // FIXME account for wordwrap
  1490. KateTextCursor c = viewLineOffset(endPos(), -m_minLinesVisible);
  1491. updateSelection( c, sel );
  1492. updateCursor( c );
  1493. }
  1494. // lines is the offset to scroll by
  1495. void KateViewInternal::scrollLines( int lines, bool sel )
  1496. {
  1497. KateTextCursor c = viewLineOffset(displayCursor, lines, true);
  1498. // Fix the virtual cursor -> real cursor
  1499. c.setLine(m_doc->getRealLine(c.line()));
  1500. updateSelection( c, sel );
  1501. updateCursor( c );
  1502. }
  1503. // This is a bit misleading... it's asking for the view to be scrolled, not the cursor
  1504. void KateViewInternal::scrollUp()
  1505. {
  1506. KateTextCursor newPos = viewLineOffset(m_startPos, -1);
  1507. scrollPos(newPos);
  1508. }
  1509. void KateViewInternal::scrollDown()
  1510. {
  1511. KateTextCursor newPos = viewLineOffset(m_startPos, 1);
  1512. scrollPos(newPos);
  1513. }
  1514. void KateViewInternal::setAutoCenterLines(int viewLines, bool updateView)
  1515. {
  1516. m_autoCenterLines = viewLines;
  1517. m_minLinesVisible = kMin(int((linesDisplayed() - 1)/2), m_autoCenterLines);
  1518. if (updateView)
  1519. KateViewInternal::updateView();
  1520. }
  1521. void KateViewInternal::pageUp( bool sel )
  1522. {
  1523. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  1524. TQKeyEvent e(TQEvent::KeyPress, Qt::Key_PageUp, 0, 0);
  1525. m_view->m_codeCompletion->handleKey(&e);
  1526. return;
  1527. }
  1528. // remember the view line and x pos
  1529. int viewLine = displayViewLine(displayCursor);
  1530. bool atTop = (startPos().line() == 0 && startPos().col() == 0);
  1531. // Adjust for an auto-centering cursor
  1532. int lineadj = 2 * m_minLinesVisible;
  1533. int cursorStart = (linesDisplayed() - 1) - viewLine;
  1534. if (cursorStart < m_minLinesVisible)
  1535. lineadj -= m_minLinesVisible - cursorStart;
  1536. int linesToScroll = -kMax( ((int)linesDisplayed() - 1) - lineadj, 0 );
  1537. m_preserveMaxX = true;
  1538. if (!m_doc->pageUpDownMovesCursor () && !atTop) {
  1539. int xPos = m_view->renderer()->textWidth(cursor) - currentRange().startX;
  1540. KateTextCursor newStartPos = viewLineOffset(startPos(), linesToScroll - 1);
  1541. scrollPos(newStartPos);
  1542. // put the cursor back approximately where it was
  1543. KateTextCursor newPos = viewLineOffset(newStartPos, viewLine, true);
  1544. newPos.setLine(m_doc->getRealLine(newPos.line()));
  1545. KateLineRange newLine = range(newPos);
  1546. if (m_currentMaxX - newLine.xOffset() > xPos)
  1547. xPos = m_currentMaxX - newLine.xOffset();
  1548. cXPos = kMin(newLine.startX + xPos, lineMaxCursorX(newLine));
  1549. m_view->renderer()->textWidth( newPos, cXPos );
  1550. m_preserveMaxX = true;
  1551. updateSelection( newPos, sel );
  1552. updateCursor(newPos);
  1553. } else {
  1554. scrollLines( linesToScroll, sel );
  1555. }
  1556. }
  1557. void KateViewInternal::pageDown( bool sel )
  1558. {
  1559. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  1560. TQKeyEvent e(TQEvent::KeyPress, Qt::Key_PageDown, 0, 0);
  1561. m_view->m_codeCompletion->handleKey(&e);
  1562. return;
  1563. }
  1564. // remember the view line
  1565. int viewLine = displayViewLine(displayCursor);
  1566. bool atEnd = startPos() >= m_cachedMaxStartPos;
  1567. // Adjust for an auto-centering cursor
  1568. int lineadj = 2 * m_minLinesVisible;
  1569. int cursorStart = m_minLinesVisible - viewLine;
  1570. if (cursorStart > 0)
  1571. lineadj -= cursorStart;
  1572. int linesToScroll = kMax( ((int)linesDisplayed() - 1) - lineadj, 0 );
  1573. m_preserveMaxX = true;
  1574. if (!m_doc->pageUpDownMovesCursor () && !atEnd) {
  1575. int xPos = m_view->renderer()->textWidth(cursor) - currentRange().startX;
  1576. KateTextCursor newStartPos = viewLineOffset(startPos(), linesToScroll + 1);
  1577. scrollPos(newStartPos);
  1578. // put the cursor back approximately where it was
  1579. KateTextCursor newPos = viewLineOffset(newStartPos, viewLine, true);
  1580. newPos.setLine(m_doc->getRealLine(newPos.line()));
  1581. KateLineRange newLine = range(newPos);
  1582. if (m_currentMaxX - newLine.xOffset() > xPos)
  1583. xPos = m_currentMaxX - newLine.xOffset();
  1584. cXPos = kMin(newLine.startX + xPos, lineMaxCursorX(newLine));
  1585. m_view->renderer()->textWidth( newPos, cXPos );
  1586. m_preserveMaxX = true;
  1587. updateSelection( newPos, sel );
  1588. updateCursor(newPos);
  1589. } else {
  1590. scrollLines( linesToScroll, sel );
  1591. }
  1592. }
  1593. int KateViewInternal::maxLen(uint startLine)
  1594. {
  1595. // Q_ASSERT(!m_view->dynWordWrap());
  1596. int displayLines = (m_view->height() / m_view->renderer()->fontHeight()) + 1;
  1597. int maxLen = 0;
  1598. for (int z = 0; z < displayLines; z++) {
  1599. int virtualLine = startLine + z;
  1600. if (virtualLine < 0 || virtualLine >= (int)m_doc->visibleLines())
  1601. break;
  1602. KateLineRange thisRange = range((int)m_doc->getRealLine(virtualLine));
  1603. maxLen = kMax(maxLen, thisRange.endX);
  1604. }
  1605. return maxLen;
  1606. }
  1607. void KateViewInternal::top( bool sel )
  1608. {
  1609. KateTextCursor c( 0, cursor.col() );
  1610. m_view->renderer()->textWidth( c, cXPos );
  1611. updateSelection( c, sel );
  1612. updateCursor( c );
  1613. }
  1614. void KateViewInternal::bottom( bool sel )
  1615. {
  1616. KateTextCursor c( m_doc->lastLine(), cursor.col() );
  1617. m_view->renderer()->textWidth( c, cXPos );
  1618. updateSelection( c, sel );
  1619. updateCursor( c );
  1620. }
  1621. void KateViewInternal::top_home( bool sel )
  1622. {
  1623. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  1624. TQKeyEvent e(TQEvent::KeyPress, Qt::Key_Home, 0, 0);
  1625. m_view->m_codeCompletion->handleKey(&e);
  1626. return;
  1627. }
  1628. KateTextCursor c( 0, 0 );
  1629. updateSelection( c, sel );
  1630. updateCursor( c );
  1631. }
  1632. void KateViewInternal::bottom_end( bool sel )
  1633. {
  1634. if (m_view->m_codeCompletion->codeCompletionVisible()) {
  1635. TQKeyEvent e(TQEvent::KeyPress, Qt::Key_End, 0, 0);
  1636. m_view->m_codeCompletion->handleKey(&e);
  1637. return;
  1638. }
  1639. KateTextCursor c( m_doc->lastLine(), m_doc->lineLength( m_doc->lastLine() ) );
  1640. updateSelection( c, sel );
  1641. updateCursor( c );
  1642. }
  1643. void KateViewInternal::updateSelection( const KateTextCursor& _newCursor, bool keepSel )
  1644. {
  1645. KateTextCursor newCursor = _newCursor;
  1646. if( keepSel )
  1647. {
  1648. if ( !m_view->hasSelection() || (selectAnchor.line() == -1)
  1649. || (m_view->config()->persistentSelection()
  1650. && ((cursor < m_view->selectStart) || (cursor > m_view->selectEnd))) )
  1651. {
  1652. selectAnchor = cursor;
  1653. m_view->setSelection( cursor, newCursor );
  1654. }
  1655. else
  1656. {
  1657. bool doSelect = true;
  1658. switch (m_selectionMode)
  1659. {
  1660. case Word:
  1661. {
  1662. // Restore selStartCached if needed. It gets nuked by
  1663. // viewSelectionChanged if we drag the selection into non-existence,
  1664. // which can legitimately happen if a shift+DC selection is unable to
  1665. // set a "proper" (i.e. non-empty) cached selection, e.g. because the
  1666. // start was on something that isn't a word. Word select mode relies
  1667. // on the cached selection being set properly, even if it is empty
  1668. // (i.e. selStartCached == selEndCached).
  1669. if ( selStartCached.line() == -1 )
  1670. selStartCached = selEndCached;
  1671. int c;
  1672. if ( newCursor > selEndCached )
  1673. {
  1674. selectAnchor = selStartCached;
  1675. KateTextLine::Ptr l = m_doc->kateTextLine( newCursor.line() );
  1676. c = newCursor.col();
  1677. if ( c > 0 && m_doc->highlight()->isInWord( l->getChar( c-1 ) ) ) {
  1678. for (; c < l->length(); c++ )
  1679. if ( !m_doc->highlight()->isInWord( l->getChar( c ) ) )
  1680. break;
  1681. }
  1682. newCursor.setCol( c );
  1683. }
  1684. else if ( newCursor < selStartCached )
  1685. {
  1686. selectAnchor = selEndCached;
  1687. KateTextLine::Ptr l = m_doc->kateTextLine( newCursor.line() );
  1688. c = newCursor.col();
  1689. if ( c > 0 && c < m_doc->textLine( newCursor.line() ).length()
  1690. && m_doc->highlight()->isInWord( l->getChar( c ) )
  1691. && m_doc->highlight()->isInWord( l->getChar( c-1 ) ) ) {
  1692. for ( c -= 2; c >= 0; c-- )
  1693. if ( !m_doc->highlight()->isInWord( l->getChar( c ) ) )
  1694. break;
  1695. newCursor.setCol( c+1 );
  1696. }
  1697. }
  1698. else
  1699. doSelect = false;
  1700. }
  1701. break;
  1702. case Line:
  1703. if ( newCursor.line() > selStartCached.line() )
  1704. {
  1705. if ( newCursor.line()+1 >= m_doc->numLines() )
  1706. newCursor.setCol( m_doc->textLine( newCursor.line() ).length() );
  1707. else
  1708. newCursor.setPos( newCursor.line() + 1, 0 );
  1709. // Grow to include entire line
  1710. selectAnchor = selStartCached;
  1711. selectAnchor.setCol( 0 );
  1712. }
  1713. else if ( newCursor.line() < selStartCached.line() )
  1714. {
  1715. newCursor.setCol( 0 );
  1716. // Grow to include entire line
  1717. selectAnchor = selEndCached;
  1718. if ( selectAnchor.col() > 0 )
  1719. {
  1720. if ( selectAnchor.line()+1 >= m_doc->numLines() )
  1721. selectAnchor.setCol( m_doc->textLine( selectAnchor.line() ).length() );
  1722. else
  1723. selectAnchor.setPos( selectAnchor.line() + 1, 0 );
  1724. }
  1725. }
  1726. else // same line, ignore
  1727. doSelect = false;
  1728. break;
  1729. case Mouse:
  1730. {
  1731. if ( selStartCached.line() < 0 ) // invalid
  1732. break;
  1733. if ( newCursor > selEndCached )
  1734. selectAnchor = selStartCached;
  1735. else if ( newCursor < selStartCached )
  1736. selectAnchor = selEndCached;
  1737. else
  1738. doSelect = false;
  1739. }
  1740. break;
  1741. default:
  1742. {
  1743. if ( selectAnchor.line() < 0 ) // invalid
  1744. break;
  1745. }
  1746. }
  1747. if ( doSelect )
  1748. m_view->setSelection( selectAnchor, newCursor);
  1749. else if ( selStartCached.line() >= 0 ) // we have a cached selection, so we restore that
  1750. m_view->setSelection( selStartCached, selEndCached );
  1751. }
  1752. m_selChangedByUser = true;
  1753. }
  1754. else if ( !m_view->config()->persistentSelection() )
  1755. {
  1756. m_view->clearSelection();
  1757. selStartCached.setLine( -1 );
  1758. selectAnchor.setLine( -1 );
  1759. }
  1760. }
  1761. void KateViewInternal::updateCursor( const KateTextCursor& newCursor, bool force, bool center, bool calledExternally )
  1762. {
  1763. if ( !force && (cursor == newCursor) )
  1764. {
  1765. if ( !m_madeVisible && m_view == m_doc->activeView() )
  1766. {
  1767. // unfold if required
  1768. m_doc->foldingTree()->ensureVisible( newCursor.line() );
  1769. makeVisible ( displayCursor, displayCursor.col(), false, center, calledExternally );
  1770. }
  1771. return;
  1772. }
  1773. // unfold if required
  1774. m_doc->foldingTree()->ensureVisible( newCursor.line() );
  1775. KateTextCursor oldDisplayCursor = displayCursor;
  1776. cursor.setPos (newCursor);
  1777. displayCursor.setPos (m_doc->getVirtualLine(cursor.line()), cursor.col());
  1778. cXPos = m_view->renderer()->textWidth( cursor );
  1779. if (m_view == m_doc->activeView())
  1780. makeVisible ( displayCursor, displayCursor.col(), false, center, calledExternally );
  1781. updateBracketMarks();
  1782. // It's efficient enough to just tag them both without checking to see if they're on the same view line
  1783. tagLine(oldDisplayCursor);
  1784. tagLine(displayCursor);
  1785. updateMicroFocusHint();
  1786. if (m_cursorTimer.isActive ())
  1787. {
  1788. if ( TDEApplication::cursorFlashTime() > 0 )
  1789. m_cursorTimer.start( TDEApplication::cursorFlashTime() / 2 );
  1790. m_view->renderer()->setDrawCaret(true);
  1791. }
  1792. // Remember the maximum X position if requested
  1793. if (m_preserveMaxX)
  1794. m_preserveMaxX = false;
  1795. else
  1796. if (m_view->dynWordWrap())
  1797. m_currentMaxX = m_view->renderer()->textWidth(displayCursor) - currentRange().startX + currentRange().xOffset();
  1798. else
  1799. m_currentMaxX = cXPos;
  1800. //kdDebug() << "m_currentMaxX: " << m_currentMaxX << " (was "<< oldmaxx << "), cXPos: " << cXPos << endl;
  1801. //kdDebug(13030) << "Cursor now located at real " << cursor.line << "," << cursor.col << ", virtual " << displayCursor.line << ", " << displayCursor.col << "; Top is " << startLine() << ", " << startPos().col << endl;
  1802. paintText(0, 0, width(), height(), true);
  1803. emit m_view->cursorPositionChanged();
  1804. }
  1805. void KateViewInternal::updateBracketMarks()
  1806. {
  1807. if ( bm.isValid() ) {
  1808. KateTextCursor bmStart(m_doc->getVirtualLine(bm.start().line()), bm.start().col());
  1809. KateTextCursor bmEnd(m_doc->getVirtualLine(bm.end().line()), bm.end().col());
  1810. if( bm.getMinIndent() != 0 )
  1811. {
  1812. // @@ Do this only when cursor near start/end.
  1813. if( bmStart > bmEnd )
  1814. {
  1815. tagLines(bmEnd, bmStart);
  1816. }
  1817. else
  1818. {
  1819. tagLines(bmStart, bmEnd);
  1820. }
  1821. }
  1822. else
  1823. {
  1824. tagLine(bmStart);
  1825. tagLine(bmEnd);
  1826. }
  1827. }
  1828. // add some limit to this, this is really endless on big files without limit
  1829. int maxLines = linesDisplayed () * 3;
  1830. m_doc->newBracketMark( cursor, bm, maxLines );
  1831. if ( bm.isValid() ) {
  1832. KateTextCursor bmStart(m_doc->getVirtualLine(bm.start().line()), bm.start().col());
  1833. KateTextCursor bmEnd(m_doc->getVirtualLine(bm.end().line()), bm.end().col());
  1834. if( bm.getMinIndent() != 0 )
  1835. {
  1836. // @@ Do this only when cursor near start/end.
  1837. if( bmStart > bmEnd )
  1838. {
  1839. tagLines(bmEnd, bmStart);
  1840. }
  1841. else
  1842. {
  1843. tagLines(bmStart, bmEnd);
  1844. }
  1845. }
  1846. else
  1847. {
  1848. tagLine(bmStart);
  1849. tagLine(bmEnd);
  1850. }
  1851. }
  1852. }
  1853. bool KateViewInternal::tagLine(const KateTextCursor& virtualCursor)
  1854. {
  1855. int viewLine = displayViewLine(virtualCursor, true);
  1856. if (viewLine >= 0 && viewLine < (int)lineRanges.count()) {
  1857. lineRanges[viewLine].dirty = true;
  1858. leftBorder->update (0, lineToY(viewLine), leftBorder->width(), m_view->renderer()->fontHeight());
  1859. return true;
  1860. }
  1861. return false;
  1862. }
  1863. bool KateViewInternal::tagLines( int start, int end, bool realLines )
  1864. {
  1865. return tagLines(KateTextCursor(start, 0), KateTextCursor(end, -1), realLines);
  1866. }
  1867. bool KateViewInternal::tagLines(KateTextCursor start, KateTextCursor end, bool realCursors)
  1868. {
  1869. if (realCursors)
  1870. {
  1871. //kdDebug()<<"realLines is true"<<endl;
  1872. start.setLine(m_doc->getVirtualLine( start.line() ));
  1873. end.setLine(m_doc->getVirtualLine( end.line() ));
  1874. }
  1875. if (end.line() < (int)startLine())
  1876. {
  1877. //kdDebug()<<"end<startLine"<<endl;
  1878. return false;
  1879. }
  1880. if (start.line() > (int)endLine())
  1881. {
  1882. //kdDebug()<<"start> endLine"<<start<<" "<<((int)endLine())<<endl;
  1883. return false;
  1884. }
  1885. //kdDebug(13030) << "tagLines( [" << start.line << "," << start.col << "], [" << end.line << "," << end.col << "] )\n";
  1886. bool ret = false;
  1887. for (uint z = 0; z < lineRanges.size(); z++)
  1888. {
  1889. if ((lineRanges[z].virtualLine > start.line() || (lineRanges[z].virtualLine == start.line() && lineRanges[z].endCol >= start.col() && start.col() != -1)) && (lineRanges[z].virtualLine < end.line() || (lineRanges[z].virtualLine == end.line() && (lineRanges[z].startCol <= end.col() || end.col() == -1)))) {
  1890. ret = lineRanges[z].dirty = true;
  1891. //kdDebug() << "Tagged line " << lineRanges[z].line << endl;
  1892. }
  1893. }
  1894. if (!m_view->dynWordWrap())
  1895. {
  1896. int y = lineToY( start.line() );
  1897. // FIXME is this enough for when multiple lines are deleted
  1898. int h = (end.line() - start.line() + 2) * m_view->renderer()->fontHeight();
  1899. if (end.line() == (int)m_doc->numVisLines() - 1)
  1900. h = height();
  1901. leftBorder->update (0, y, leftBorder->width(), h);
  1902. }
  1903. else
  1904. {
  1905. // FIXME Do we get enough good info in editRemoveText to optimise this more?
  1906. //bool justTagged = false;
  1907. for (uint z = 0; z < lineRanges.size(); z++)
  1908. {
  1909. if ((lineRanges[z].virtualLine > start.line() || (lineRanges[z].virtualLine == start.line() && lineRanges[z].endCol >= start.col() && start.col() != -1)) && (lineRanges[z].virtualLine < end.line() || (lineRanges[z].virtualLine == end.line() && (lineRanges[z].startCol <= end.col() || end.col() == -1))))
  1910. {
  1911. //justTagged = true;
  1912. leftBorder->update (0, z * m_view->renderer()->fontHeight(), leftBorder->width(), leftBorder->height());
  1913. break;
  1914. }
  1915. /*else if (justTagged)
  1916. {
  1917. justTagged = false;
  1918. leftBorder->update (0, z * m_doc->viewFont.fontHeight, leftBorder->width(), m_doc->viewFont.fontHeight);
  1919. break;
  1920. }*/
  1921. }
  1922. }
  1923. return ret;
  1924. }
  1925. void KateViewInternal::tagAll()
  1926. {
  1927. //kdDebug(13030) << "tagAll()" << endl;
  1928. for (uint z = 0; z < lineRanges.size(); z++)
  1929. {
  1930. lineRanges[z].dirty = true;
  1931. }
  1932. leftBorder->updateFont();
  1933. leftBorder->update ();
  1934. }
  1935. void KateViewInternal::paintCursor()
  1936. {
  1937. if (tagLine(displayCursor))
  1938. paintText (0,0,width(), height(), true);
  1939. }
  1940. // Point in content coordinates
  1941. void KateViewInternal::placeCursor( const TQPoint& p, bool keepSelection, bool updateSelection )
  1942. {
  1943. KateLineRange thisRange = yToKateLineRange(p.y());
  1944. if (thisRange.line == -1) {
  1945. for (int i = (p.y() / m_view->renderer()->fontHeight()); i >= 0; i--) {
  1946. thisRange = lineRanges[i];
  1947. if (thisRange.line != -1)
  1948. break;
  1949. }
  1950. Q_ASSERT(thisRange.line != -1);
  1951. }
  1952. int realLine = thisRange.line;
  1953. int visibleLine = thisRange.virtualLine;
  1954. uint startCol = thisRange.startCol;
  1955. visibleLine = kMax( 0, kMin( visibleLine, int(m_doc->numVisLines()) - 1 ) );
  1956. KateTextCursor c(realLine, 0);
  1957. int x = kMin(kMax(-m_startX, p.x() - thisRange.xOffset()), lineMaxCursorX(thisRange) - thisRange.startX);
  1958. m_view->renderer()->textWidth( c, startX() + x, startCol);
  1959. if (updateSelection)
  1960. KateViewInternal::updateSelection( c, keepSelection );
  1961. updateCursor( c );
  1962. }
  1963. // Point in content coordinates
  1964. bool KateViewInternal::isTargetSelected( const TQPoint& p )
  1965. {
  1966. KateLineRange thisRange = yToKateLineRange(p.y());
  1967. KateTextLine::Ptr l = textLine( thisRange.line );
  1968. if( !l )
  1969. return false;
  1970. int col = m_view->renderer()->textPos( l, startX() + p.x() - thisRange.xOffset(), thisRange.startCol, false );
  1971. return m_view->lineColSelected( thisRange.line, col );
  1972. }
  1973. //BEGIN EVENT HANDLING STUFF
  1974. bool KateViewInternal::eventFilter( TQObject *obj, TQEvent *e )
  1975. {
  1976. if (TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(m_lineScroll))
  1977. {
  1978. // the second condition is to make sure a scroll on the vertical bar doesn't cause a horizontal scroll ;)
  1979. if (e->type() == TQEvent::Wheel && m_lineScroll->minValue() != m_lineScroll->maxValue())
  1980. {
  1981. wheelEvent((TQWheelEvent*)e);
  1982. return true;
  1983. }
  1984. // continue processing
  1985. return TQWidget::eventFilter( obj, e );
  1986. }
  1987. switch( e->type() )
  1988. {
  1989. case TQEvent::KeyPress:
  1990. {
  1991. TQKeyEvent *k = (TQKeyEvent *)e;
  1992. if (m_view->m_codeCompletion->codeCompletionVisible ())
  1993. {
  1994. kdDebug (13030) << "hint around" << endl;
  1995. if( k->key() == Key_Escape )
  1996. m_view->m_codeCompletion->abortCompletion();
  1997. }
  1998. if ((k->key() == Qt::Key_Escape) && !m_view->config()->persistentSelection() )
  1999. {
  2000. m_view->clearSelection();
  2001. return true;
  2002. }
  2003. else if ( !((k->state() & ControlButton) || (k->state() & AltButton)) )
  2004. {
  2005. keyPressEvent( k );
  2006. return k->isAccepted();
  2007. }
  2008. } break;
  2009. case TQEvent::DragMove:
  2010. {
  2011. TQPoint currentPoint = ((TQDragMoveEvent*) e)->pos();
  2012. TQRect doNotScrollRegion( scrollMargin, scrollMargin,
  2013. width() - scrollMargin * 2,
  2014. height() - scrollMargin * 2 );
  2015. if ( !doNotScrollRegion.contains( currentPoint ) )
  2016. {
  2017. startDragScroll();
  2018. // Keep sending move events
  2019. ( (TQDragMoveEvent*)e )->accept( TQRect(0,0,0,0) );
  2020. }
  2021. dragMoveEvent((TQDragMoveEvent*)e);
  2022. } break;
  2023. case TQEvent::DragLeave:
  2024. // happens only when pressing ESC while dragging
  2025. stopDragScroll();
  2026. break;
  2027. case TQEvent::WindowBlocked:
  2028. // next focus originates from an internal dialog:
  2029. // don't show the modonhd prompt
  2030. m_doc->m_isasking = -1;
  2031. break;
  2032. default:
  2033. break;
  2034. }
  2035. return TQWidget::eventFilter( obj, e );
  2036. }
  2037. void KateViewInternal::keyPressEvent( TQKeyEvent* e )
  2038. {
  2039. KKey key(e);
  2040. bool codeComp = m_view->m_codeCompletion->codeCompletionVisible ();
  2041. if (codeComp)
  2042. {
  2043. kdDebug (13030) << "hint around" << endl;
  2044. if( e->key() == Key_Enter || e->key() == Key_Return ||
  2045. (key == SHIFT + Qt::Key_Return) || (key == SHIFT + Qt::Key_Enter)) {
  2046. m_view->m_codeCompletion->doComplete();
  2047. e->accept();
  2048. return;
  2049. }
  2050. }
  2051. if( !m_doc->isReadWrite() )
  2052. {
  2053. e->ignore();
  2054. return;
  2055. }
  2056. if ((key == Qt::Key_Return) || (key == Qt::Key_Enter))
  2057. {
  2058. m_view->keyReturn();
  2059. e->accept();
  2060. return;
  2061. }
  2062. if ((key == SHIFT + Qt::Key_Return) || (key == SHIFT + Qt::Key_Enter))
  2063. {
  2064. uint ln = cursor.line();
  2065. int col = cursor.col();
  2066. KateTextLine::Ptr line = m_doc->kateTextLine( ln );
  2067. int pos = line->firstChar();
  2068. if (pos > cursor.col()) pos = cursor.col();
  2069. if (pos != -1) {
  2070. while ((int)line->length() > pos &&
  2071. !line->getChar(pos).isLetterOrNumber() &&
  2072. pos < cursor.col()) ++pos;
  2073. } else {
  2074. pos = line->length(); // stay indented
  2075. }
  2076. m_doc->editStart();
  2077. m_doc->insertText( cursor.line(), line->length(), "\n" + line->string(0, pos)
  2078. + line->string().right( line->length() - cursor.col() ) );
  2079. cursor.setPos(ln + 1, pos);
  2080. if (col < int(line->length()))
  2081. m_doc->editRemoveText(ln, col, line->length() - col);
  2082. m_doc->editEnd();
  2083. updateCursor(cursor, true);
  2084. updateView();
  2085. e->accept();
  2086. return;
  2087. }
  2088. if (key == Qt::Key_Backspace || key == SHIFT + Qt::Key_Backspace)
  2089. {
  2090. m_view->backspace();
  2091. e->accept();
  2092. if (codeComp)
  2093. m_view->m_codeCompletion->updateBox ();
  2094. return;
  2095. }
  2096. if (key == Qt::Key_Tab || key == SHIFT+Qt::Key_Backtab || key == Qt::Key_Backtab)
  2097. {
  2098. if (m_doc->invokeTabInterceptor(key)) {
  2099. e->accept();
  2100. return;
  2101. } else
  2102. if (m_doc->configFlags() & KateDocumentConfig::cfTabIndents)
  2103. {
  2104. if( key == Qt::Key_Tab )
  2105. {
  2106. if (m_view->hasSelection() || (m_doc->configFlags() & KateDocumentConfig::cfTabIndentsMode))
  2107. m_doc->indent( m_view, cursor.line(), 1 );
  2108. else if (m_doc->configFlags() & KateDocumentConfig::cfTabInsertsTab)
  2109. m_doc->typeChars ( m_view, TQString ("\t") );
  2110. else
  2111. m_doc->insertIndentChars ( m_view );
  2112. e->accept();
  2113. if (codeComp)
  2114. m_view->m_codeCompletion->updateBox ();
  2115. return;
  2116. }
  2117. if (key == SHIFT+Qt::Key_Backtab || key == Qt::Key_Backtab)
  2118. {
  2119. m_doc->indent( m_view, cursor.line(), -1 );
  2120. e->accept();
  2121. if (codeComp)
  2122. m_view->m_codeCompletion->updateBox ();
  2123. return;
  2124. }
  2125. }
  2126. }
  2127. if ( !(e->state() & ControlButton) && !(e->state() & AltButton)
  2128. && m_doc->typeChars ( m_view, e->text() ) )
  2129. {
  2130. e->accept();
  2131. if (codeComp)
  2132. m_view->m_codeCompletion->updateBox ();
  2133. return;
  2134. }
  2135. e->ignore();
  2136. }
  2137. void KateViewInternal::keyReleaseEvent( TQKeyEvent* e )
  2138. {
  2139. KKey key(e);
  2140. if (key == SHIFT)
  2141. m_shiftKeyPressed = true;
  2142. else
  2143. {
  2144. if (m_shiftKeyPressed)
  2145. {
  2146. m_shiftKeyPressed = false;
  2147. if (m_selChangedByUser)
  2148. {
  2149. TQApplication::clipboard()->setSelectionMode( true );
  2150. m_view->copy();
  2151. TQApplication::clipboard()->setSelectionMode( false );
  2152. m_selChangedByUser = false;
  2153. }
  2154. }
  2155. }
  2156. e->ignore();
  2157. return;
  2158. }
  2159. void KateViewInternal::contextMenuEvent ( TQContextMenuEvent * e )
  2160. {
  2161. // try to show popup menu
  2162. TQPoint p = e->pos();
  2163. if ( m_view->m_doc->browserView() )
  2164. {
  2165. m_view->contextMenuEvent( e );
  2166. return;
  2167. }
  2168. if ( e->reason() == TQContextMenuEvent::Keyboard )
  2169. {
  2170. makeVisible( cursor, 0 );
  2171. p = cursorCoordinates();
  2172. }
  2173. else if ( ! m_view->hasSelection() || m_view->config()->persistentSelection() )
  2174. placeCursor( e->pos() );
  2175. // popup is a qguardedptr now
  2176. if (m_view->popup()) {
  2177. m_view->popup()->popup( mapToGlobal( p ) );
  2178. e->accept ();
  2179. }
  2180. }
  2181. void KateViewInternal::mousePressEvent( TQMouseEvent* e )
  2182. {
  2183. switch (e->button())
  2184. {
  2185. case Qt::LeftButton:
  2186. m_selChangedByUser = false;
  2187. if (possibleTripleClick)
  2188. {
  2189. possibleTripleClick = false;
  2190. m_selectionMode = Line;
  2191. if ( e->state() & TQt::ShiftButton )
  2192. {
  2193. updateSelection( cursor, true );
  2194. }
  2195. else
  2196. {
  2197. m_view->selectLine( cursor );
  2198. }
  2199. TQApplication::clipboard()->setSelectionMode( true );
  2200. m_view->copy();
  2201. TQApplication::clipboard()->setSelectionMode( false );
  2202. // Keep the line at the select anchor selected during further
  2203. // mouse selection
  2204. if ( selectAnchor.line() > m_view->selectStart.line() )
  2205. {
  2206. // Preserve the last selected line
  2207. if ( selectAnchor == m_view->selectEnd && selectAnchor.col() == 0 )
  2208. selStartCached = KateTextCursor( selectAnchor.line()-1, 0 );
  2209. else
  2210. selStartCached = KateTextCursor( selectAnchor.line(), 0 );
  2211. selEndCached = m_view->selectEnd;
  2212. }
  2213. else
  2214. {
  2215. // Preserve the first selected line
  2216. selStartCached = m_view->selectStart;
  2217. if ( m_view->selectEnd.line() > m_view->selectStart.line() )
  2218. selEndCached = KateTextCursor( m_view->selectStart.line()+1, 0 );
  2219. else
  2220. selEndCached = m_view->selectEnd;
  2221. }
  2222. // Set cursor to edge of selection... which edge depends on what
  2223. // "direction" the selection was made in
  2224. if ( m_view->selectStart < selectAnchor
  2225. && selectAnchor.line() != m_view->selectStart.line() )
  2226. updateCursor( m_view->selectStart );
  2227. else
  2228. updateCursor( m_view->selectEnd );
  2229. e->accept ();
  2230. return;
  2231. }
  2232. else if (m_selectionMode == Default)
  2233. {
  2234. m_selectionMode = Mouse;
  2235. }
  2236. if ( e->state() & TQt::ShiftButton )
  2237. {
  2238. if (selectAnchor.line() < 0)
  2239. selectAnchor = cursor;
  2240. }
  2241. else
  2242. {
  2243. selStartCached.setLine( -1 ); // invalidate
  2244. }
  2245. if( !( e->state() & TQt::ShiftButton ) && isTargetSelected( e->pos() ) )
  2246. {
  2247. dragInfo.state = diPending;
  2248. dragInfo.start = e->pos();
  2249. }
  2250. else
  2251. {
  2252. dragInfo.state = diNone;
  2253. if ( e->state() & TQt::ShiftButton )
  2254. {
  2255. placeCursor( e->pos(), true, false );
  2256. if ( selStartCached.line() >= 0 )
  2257. {
  2258. if ( cursor > selEndCached )
  2259. {
  2260. m_view->setSelection( selStartCached, cursor );
  2261. selectAnchor = selStartCached;
  2262. }
  2263. else if ( cursor < selStartCached )
  2264. {
  2265. m_view->setSelection( cursor, selEndCached );
  2266. selectAnchor = selEndCached;
  2267. }
  2268. else
  2269. {
  2270. m_view->setSelection( selStartCached, cursor );
  2271. }
  2272. }
  2273. else
  2274. {
  2275. m_view->setSelection( selectAnchor, cursor );
  2276. }
  2277. }
  2278. else
  2279. {
  2280. placeCursor( e->pos() );
  2281. }
  2282. scrollX = 0;
  2283. scrollY = 0;
  2284. m_scrollTimer.start (50);
  2285. }
  2286. e->accept ();
  2287. break;
  2288. default:
  2289. e->ignore ();
  2290. break;
  2291. }
  2292. }
  2293. void KateViewInternal::mouseDoubleClickEvent(TQMouseEvent *e)
  2294. {
  2295. switch (e->button())
  2296. {
  2297. case Qt::LeftButton:
  2298. m_selectionMode = Word;
  2299. if ( e->state() & TQt::ShiftButton )
  2300. {
  2301. KateTextCursor oldSelectStart = m_view->selectStart;
  2302. KateTextCursor oldSelectEnd = m_view->selectEnd;
  2303. // Now select the word under the select anchor
  2304. int cs, ce;
  2305. KateTextLine::Ptr l = m_doc->kateTextLine( selectAnchor.line() );
  2306. ce = selectAnchor.col();
  2307. if ( ce > 0 && m_doc->highlight()->isInWord( l->getChar( ce ) ) ) {
  2308. for (; ce < l->length(); ce++ )
  2309. if ( !m_doc->highlight()->isInWord( l->getChar( ce ) ) )
  2310. break;
  2311. }
  2312. cs = selectAnchor.col() - 1;
  2313. if ( cs < m_doc->textLine( selectAnchor.line() ).length()
  2314. && m_doc->highlight()->isInWord( l->getChar( cs ) ) ) {
  2315. for ( cs--; cs >= 0; cs-- )
  2316. if ( !m_doc->highlight()->isInWord( l->getChar( cs ) ) )
  2317. break;
  2318. }
  2319. // ...and keep it selected
  2320. if (cs+1 < ce)
  2321. {
  2322. selStartCached = KateTextCursor( selectAnchor.line(), cs+1 );
  2323. selEndCached = KateTextCursor( selectAnchor.line(), ce );
  2324. }
  2325. else
  2326. {
  2327. selStartCached = selectAnchor;
  2328. selEndCached = selectAnchor;
  2329. }
  2330. // Now word select to the mouse cursor
  2331. placeCursor( e->pos(), true );
  2332. }
  2333. else
  2334. {
  2335. // first clear the selection, otherwise we run into bug #106402
  2336. // ...and set the cursor position, for the same reason (otherwise there
  2337. // are *other* idiosyncrasies we can't fix without reintroducing said
  2338. // bug)
  2339. // Parameters: 1st false: don't redraw
  2340. // 2nd false: don't emit selectionChanged signals, as
  2341. // selectWord() emits this already
  2342. m_view->clearSelection( false, false );
  2343. placeCursor( e->pos() );
  2344. m_view->selectWord( cursor );
  2345. if (m_view->hasSelection())
  2346. {
  2347. selectAnchor = selStartCached = m_view->selectStart;
  2348. selEndCached = m_view->selectEnd;
  2349. }
  2350. else
  2351. {
  2352. // if we didn't actually select anything, restore the selection mode
  2353. // -- see bug #131369 (kling)
  2354. m_selectionMode = Default;
  2355. }
  2356. }
  2357. // Move cursor to end (or beginning) of selected word
  2358. if (m_view->hasSelection())
  2359. {
  2360. TQApplication::clipboard()->setSelectionMode( true );
  2361. m_view->copy();
  2362. TQApplication::clipboard()->setSelectionMode( false );
  2363. // Shift+DC before the "cached" word should move the cursor to the
  2364. // beginning of the selection, not the end
  2365. if (m_view->selectStart < selStartCached)
  2366. updateCursor( m_view->selectStart );
  2367. else
  2368. updateCursor( m_view->selectEnd );
  2369. }
  2370. possibleTripleClick = true;
  2371. TQTimer::singleShot ( TQApplication::doubleClickInterval(), this, TQT_SLOT(tripleClickTimeout()) );
  2372. scrollX = 0;
  2373. scrollY = 0;
  2374. m_scrollTimer.start (50);
  2375. e->accept ();
  2376. break;
  2377. default:
  2378. e->ignore ();
  2379. break;
  2380. }
  2381. }
  2382. void KateViewInternal::tripleClickTimeout()
  2383. {
  2384. possibleTripleClick = false;
  2385. }
  2386. void KateViewInternal::mouseReleaseEvent( TQMouseEvent* e )
  2387. {
  2388. switch (e->button())
  2389. {
  2390. case Qt::LeftButton:
  2391. m_selectionMode = Default;
  2392. // selStartCached.setLine( -1 );
  2393. if (m_selChangedByUser)
  2394. {
  2395. TQApplication::clipboard()->setSelectionMode( true );
  2396. m_view->copy();
  2397. TQApplication::clipboard()->setSelectionMode( false );
  2398. // Set cursor to edge of selection... which edge depends on what
  2399. // "direction" the selection was made in
  2400. if ( m_view->selectStart < selectAnchor )
  2401. updateCursor( m_view->selectStart );
  2402. else
  2403. updateCursor( m_view->selectEnd );
  2404. m_selChangedByUser = false;
  2405. }
  2406. if (dragInfo.state == diPending)
  2407. placeCursor( e->pos(), e->state() & ShiftButton );
  2408. else if (dragInfo.state == diNone)
  2409. m_scrollTimer.stop ();
  2410. dragInfo.state = diNone;
  2411. e->accept ();
  2412. break;
  2413. case Qt::MidButton:
  2414. placeCursor( e->pos() );
  2415. if( m_doc->isReadWrite() )
  2416. {
  2417. TQApplication::clipboard()->setSelectionMode( true );
  2418. m_view->paste ();
  2419. TQApplication::clipboard()->setSelectionMode( false );
  2420. }
  2421. e->accept ();
  2422. break;
  2423. default:
  2424. e->ignore ();
  2425. break;
  2426. }
  2427. }
  2428. void KateViewInternal::mouseMoveEvent( TQMouseEvent* e )
  2429. {
  2430. if( e->state() & Qt::LeftButton )
  2431. {
  2432. if (dragInfo.state == diPending)
  2433. {
  2434. // we had a mouse down, but haven't confirmed a drag yet
  2435. // if the mouse has moved sufficiently, we will confirm
  2436. TQPoint p( e->pos() - dragInfo.start );
  2437. // we've left the drag square, we can start a real drag operation now
  2438. if( p.manhattanLength() > TDEGlobalSettings::dndEventDelay() )
  2439. doDrag();
  2440. return;
  2441. }
  2442. else if (dragInfo.state == diDragging)
  2443. {
  2444. // Don't do anything after a canceled drag until the user lets go of
  2445. // the mouse button!
  2446. return;
  2447. }
  2448. mouseX = e->x();
  2449. mouseY = e->y();
  2450. scrollX = 0;
  2451. scrollY = 0;
  2452. int d = m_view->renderer()->fontHeight();
  2453. if (mouseX < 0)
  2454. scrollX = -d;
  2455. if (mouseX > width())
  2456. scrollX = d;
  2457. if (mouseY < 0)
  2458. {
  2459. mouseY = 0;
  2460. scrollY = -d;
  2461. }
  2462. if (mouseY > height())
  2463. {
  2464. mouseY = height();
  2465. scrollY = d;
  2466. }
  2467. placeCursor( TQPoint( mouseX, mouseY ), true );
  2468. }
  2469. else
  2470. {
  2471. if (isTargetSelected( e->pos() ) ) {
  2472. // mouse is over selected text. indicate that the text is draggable by setting
  2473. // the arrow cursor as other Qt text editing widgets do
  2474. if (m_mouseCursor != ArrowCursor) {
  2475. setCursor( KCursor::arrowCursor() );
  2476. m_mouseCursor = TQt::ArrowCursor;
  2477. }
  2478. } else {
  2479. // normal text cursor
  2480. if (m_mouseCursor != IbeamCursor) {
  2481. setCursor( KCursor::ibeamCursor() );
  2482. m_mouseCursor = TQt::IbeamCursor;
  2483. }
  2484. }
  2485. if (m_textHintEnabled)
  2486. {
  2487. m_textHintTimer.start(m_textHintTimeout);
  2488. m_textHintMouseX=e->x();
  2489. m_textHintMouseY=e->y();
  2490. }
  2491. }
  2492. }
  2493. void KateViewInternal::paintEvent(TQPaintEvent *e)
  2494. {
  2495. paintText(e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height());
  2496. }
  2497. void KateViewInternal::resizeEvent(TQResizeEvent* e)
  2498. {
  2499. bool expandedHorizontally = width() > e->oldSize().width();
  2500. bool expandedVertically = height() > e->oldSize().height();
  2501. bool heightChanged = height() != e->oldSize().height();
  2502. m_madeVisible = false;
  2503. if (heightChanged) {
  2504. setAutoCenterLines(m_autoCenterLines, false);
  2505. m_cachedMaxStartPos.setPos(-1, -1);
  2506. }
  2507. if (m_view->dynWordWrap()) {
  2508. bool dirtied = false;
  2509. for (uint i = 0; i < lineRanges.count(); i++) {
  2510. // find the first dirty line
  2511. // the word wrap updateView algorithm is forced to check all lines after a dirty one
  2512. if (lineRanges[i].wrap ||
  2513. (!expandedHorizontally && (lineRanges[i].endX - lineRanges[i].startX) > width())) {
  2514. dirtied = lineRanges[i].dirty = true;
  2515. break;
  2516. }
  2517. }
  2518. if (dirtied || heightChanged) {
  2519. updateView(true);
  2520. leftBorder->update();
  2521. }
  2522. if (width() < e->oldSize().width()) {
  2523. if (!m_view->wrapCursor()) {
  2524. // May have to restrain cursor to new smaller width...
  2525. if (cursor.col() > m_doc->lineLength(cursor.line())) {
  2526. KateLineRange thisRange = currentRange();
  2527. KateTextCursor newCursor(cursor.line(), thisRange.endCol + ((width() - thisRange.xOffset() - (thisRange.endX - thisRange.startX)) / m_view->renderer()->spaceWidth()) - 1);
  2528. updateCursor(newCursor);
  2529. }
  2530. }
  2531. }
  2532. } else {
  2533. updateView();
  2534. if (expandedHorizontally && startX() > 0)
  2535. scrollColumns(startX() - (width() - e->oldSize().width()));
  2536. }
  2537. if (expandedVertically) {
  2538. KateTextCursor max = maxStartPos();
  2539. if (startPos() > max)
  2540. scrollPos(max);
  2541. }
  2542. }
  2543. void KateViewInternal::scrollTimeout ()
  2544. {
  2545. if (scrollX || scrollY)
  2546. {
  2547. scrollLines (startPos().line() + (scrollY / (int)m_view->renderer()->fontHeight()));
  2548. placeCursor( TQPoint( mouseX, mouseY ), true );
  2549. }
  2550. }
  2551. void KateViewInternal::cursorTimeout ()
  2552. {
  2553. m_view->renderer()->setDrawCaret(!m_view->renderer()->drawCaret());
  2554. paintCursor();
  2555. }
  2556. void KateViewInternal::textHintTimeout ()
  2557. {
  2558. m_textHintTimer.stop ();
  2559. KateLineRange thisRange = yToKateLineRange(m_textHintMouseY);
  2560. if (thisRange.line == -1) return;
  2561. if (m_textHintMouseX> (lineMaxCursorX(thisRange) - thisRange.startX)) return;
  2562. int realLine = thisRange.line;
  2563. int startCol = thisRange.startCol;
  2564. KateTextCursor c(realLine, 0);
  2565. m_view->renderer()->textWidth( c, startX() + m_textHintMouseX, startCol);
  2566. TQString tmp;
  2567. emit m_view->needTextHint(c.line(), c.col(), tmp);
  2568. if (!tmp.isEmpty()) kdDebug(13030)<<"Hint text: "<<tmp<<endl;
  2569. }
  2570. void KateViewInternal::focusInEvent (TQFocusEvent *)
  2571. {
  2572. if (TDEApplication::cursorFlashTime() > 0)
  2573. m_cursorTimer.start ( TDEApplication::cursorFlashTime() / 2 );
  2574. if (m_textHintEnabled)
  2575. m_textHintTimer.start( m_textHintTimeout );
  2576. paintCursor();
  2577. m_doc->setActiveView( m_view );
  2578. emit m_view->gotFocus( m_view );
  2579. }
  2580. void KateViewInternal::focusOutEvent (TQFocusEvent *)
  2581. {
  2582. if( m_view->renderer() && ! m_view->m_codeCompletion->codeCompletionVisible() )
  2583. {
  2584. m_cursorTimer.stop();
  2585. m_view->renderer()->setDrawCaret(true);
  2586. paintCursor();
  2587. emit m_view->lostFocus( m_view );
  2588. }
  2589. m_textHintTimer.stop();
  2590. }
  2591. void KateViewInternal::doDrag()
  2592. {
  2593. dragInfo.state = diDragging;
  2594. dragInfo.dragObject = new TQTextDrag(m_view->selection(), this);
  2595. dragInfo.dragObject->drag();
  2596. }
  2597. void KateViewInternal::dragEnterEvent( TQDragEnterEvent* event )
  2598. {
  2599. event->accept( (TQTextDrag::canDecode(event) && m_doc->isReadWrite()) ||
  2600. KURLDrag::canDecode(event) );
  2601. }
  2602. void KateViewInternal::dragMoveEvent( TQDragMoveEvent* event )
  2603. {
  2604. // track the cursor to the current drop location
  2605. placeCursor( event->pos(), true, false );
  2606. // important: accept action to switch between copy and move mode
  2607. // without this, the text will always be copied.
  2608. event->acceptAction();
  2609. }
  2610. void KateViewInternal::dropEvent( TQDropEvent* event )
  2611. {
  2612. if ( KURLDrag::canDecode(event) ) {
  2613. emit dropEventPass(event);
  2614. } else if ( TQTextDrag::canDecode(event) && m_doc->isReadWrite() ) {
  2615. TQString text;
  2616. if (!TQTextDrag::decode(event, text))
  2617. return;
  2618. // is the source our own document?
  2619. bool priv = false;
  2620. if (event->source() && event->source()->inherits("KateViewInternal"))
  2621. priv = m_doc->ownedView( ((KateViewInternal*)(event->source()))->m_view );
  2622. // dropped on a text selection area?
  2623. bool selected = isTargetSelected( event->pos() );
  2624. if( priv && selected ) {
  2625. // this is a drag that we started and dropped on our selection
  2626. // ignore this case
  2627. return;
  2628. }
  2629. // use one transaction
  2630. m_doc->editStart ();
  2631. // on move: remove selected text; on copy: duplicate text
  2632. if ( event->action() != TQDropEvent::Copy )
  2633. m_view->removeSelectedText();
  2634. m_doc->insertText( cursor.line(), cursor.col(), text );
  2635. m_doc->editEnd ();
  2636. placeCursor( event->pos() );
  2637. event->acceptAction();
  2638. updateView();
  2639. }
  2640. // finally finish drag and drop mode
  2641. dragInfo.state = diNone;
  2642. // important, because the eventFilter`s DragLeave does not occur
  2643. stopDragScroll();
  2644. }
  2645. //END EVENT HANDLING STUFF
  2646. void KateViewInternal::clear()
  2647. {
  2648. cursor.setPos(0, 0);
  2649. displayCursor.setPos(0, 0);
  2650. }
  2651. void KateViewInternal::wheelEvent(TQWheelEvent* e)
  2652. {
  2653. if (m_lineScroll->minValue() != m_lineScroll->maxValue() && e->orientation() != Qt::Horizontal) {
  2654. // React to this as a vertical event
  2655. if ( ( e->state() & ControlButton ) || ( e->state() & ShiftButton ) ) {
  2656. if (e->delta() > 0)
  2657. scrollPrevPage();
  2658. else
  2659. scrollNextPage();
  2660. } else {
  2661. scrollViewLines(-((e->delta() / 120) * TQApplication::wheelScrollLines()));
  2662. // maybe a menu was opened or a bubbled window title is on us -> we shall erase it
  2663. update();
  2664. leftBorder->update();
  2665. }
  2666. } else if (columnScrollingPossible()) {
  2667. TQWheelEvent copy = *e;
  2668. TQApplication::sendEvent(m_columnScroll, &copy);
  2669. } else {
  2670. e->ignore();
  2671. }
  2672. }
  2673. void KateViewInternal::startDragScroll()
  2674. {
  2675. if ( !m_dragScrollTimer.isActive() ) {
  2676. m_dragScrollTimer.start( scrollTime );
  2677. }
  2678. }
  2679. void KateViewInternal::stopDragScroll()
  2680. {
  2681. m_dragScrollTimer.stop();
  2682. updateView();
  2683. }
  2684. void KateViewInternal::doDragScroll()
  2685. {
  2686. TQPoint p = this->mapFromGlobal( TQCursor::pos() );
  2687. int dx = 0, dy = 0;
  2688. if ( p.y() < scrollMargin ) {
  2689. dy = p.y() - scrollMargin;
  2690. } else if ( p.y() > height() - scrollMargin ) {
  2691. dy = scrollMargin - (height() - p.y());
  2692. }
  2693. if ( p.x() < scrollMargin ) {
  2694. dx = p.x() - scrollMargin;
  2695. } else if ( p.x() > width() - scrollMargin ) {
  2696. dx = scrollMargin - (width() - p.x());
  2697. }
  2698. dy /= 4;
  2699. if (dy)
  2700. scrollLines(startPos().line() + dy);
  2701. if (columnScrollingPossible () && dx)
  2702. scrollColumns(kMin (m_startX + dx, m_columnScroll->maxValue()));
  2703. if (!dy && !dx)
  2704. stopDragScroll();
  2705. }
  2706. void KateViewInternal::enableTextHints(int timeout)
  2707. {
  2708. m_textHintTimeout=timeout;
  2709. m_textHintEnabled=true;
  2710. m_textHintTimer.start(timeout);
  2711. }
  2712. void KateViewInternal::disableTextHints()
  2713. {
  2714. m_textHintEnabled=false;
  2715. m_textHintTimer.stop ();
  2716. }
  2717. bool KateViewInternal::columnScrollingPossible ()
  2718. {
  2719. return !m_view->dynWordWrap() && m_columnScroll->isEnabled() && (m_columnScroll->maxValue() > 0);
  2720. }
  2721. //BEGIN EDIT STUFF
  2722. void KateViewInternal::editStart()
  2723. {
  2724. editSessionNumber++;
  2725. if (editSessionNumber > 1)
  2726. return;
  2727. editIsRunning = true;
  2728. editOldCursor = cursor;
  2729. }
  2730. void KateViewInternal::editEnd(int editTagLineStart, int editTagLineEnd, bool tagFrom)
  2731. {
  2732. if (editSessionNumber == 0)
  2733. return;
  2734. editSessionNumber--;
  2735. if (editSessionNumber > 0)
  2736. return;
  2737. if (tagFrom && (editTagLineStart <= int(m_doc->getRealLine(startLine()))))
  2738. tagAll();
  2739. else
  2740. tagLines (editTagLineStart, tagFrom ? m_doc->lastLine() : editTagLineEnd, true);
  2741. if (editOldCursor == cursor)
  2742. updateBracketMarks();
  2743. if (m_imPreeditLength <= 0)
  2744. updateView(true);
  2745. if ((editOldCursor != cursor) && (m_imPreeditLength <= 0))
  2746. {
  2747. m_madeVisible = false;
  2748. updateCursor ( cursor, true );
  2749. }
  2750. else if ( m_view == m_doc->activeView() )
  2751. {
  2752. makeVisible(displayCursor, displayCursor.col());
  2753. }
  2754. editIsRunning = false;
  2755. }
  2756. void KateViewInternal::editSetCursor (const KateTextCursor &cursor)
  2757. {
  2758. if (this->cursor != cursor)
  2759. {
  2760. this->cursor.setPos (cursor);
  2761. }
  2762. }
  2763. //END
  2764. void KateViewInternal::viewSelectionChanged ()
  2765. {
  2766. if (!m_view->hasSelection())
  2767. {
  2768. selectAnchor.setPos (-1, -1);
  2769. selStartCached.setPos (-1, -1);
  2770. }
  2771. }
  2772. //BEGIN IM INPUT STUFF
  2773. void KateViewInternal::imStartEvent( TQIMEvent *e )
  2774. {
  2775. if ( m_doc->m_bReadOnly ) {
  2776. e->ignore();
  2777. return;
  2778. }
  2779. if ( m_view->hasSelection() )
  2780. m_view->removeSelectedText();
  2781. m_imPreeditStartLine = cursor.line();
  2782. m_imPreeditStart = cursor.col();
  2783. m_imPreeditLength = 0;
  2784. m_imPreeditSelStart = m_imPreeditStart;
  2785. m_view->setIMSelectionValue( m_imPreeditStartLine, m_imPreeditStart, 0, 0, 0, true );
  2786. }
  2787. void KateViewInternal::imComposeEvent( TQIMEvent *e )
  2788. {
  2789. if ( m_doc->m_bReadOnly ) {
  2790. e->ignore();
  2791. return;
  2792. }
  2793. // remove old preedit
  2794. if ( m_imPreeditLength > 0 ) {
  2795. cursor.setPos( m_imPreeditStartLine, m_imPreeditStart );
  2796. m_doc->removeText( m_imPreeditStartLine, m_imPreeditStart,
  2797. m_imPreeditStartLine, m_imPreeditStart + m_imPreeditLength );
  2798. }
  2799. m_imPreeditLength = e->text().length();
  2800. m_imPreeditSelStart = m_imPreeditStart + e->cursorPos();
  2801. // update selection
  2802. m_view->setIMSelectionValue( m_imPreeditStartLine, m_imPreeditStart, m_imPreeditStart + m_imPreeditLength,
  2803. m_imPreeditSelStart, m_imPreeditSelStart + e->selectionLength(),
  2804. true );
  2805. // insert new preedit
  2806. m_doc->insertText( m_imPreeditStartLine, m_imPreeditStart, e->text() );
  2807. // update cursor
  2808. cursor.setPos( m_imPreeditStartLine, m_imPreeditSelStart );
  2809. updateCursor( cursor, true );
  2810. updateView( true );
  2811. }
  2812. void KateViewInternal::imEndEvent( TQIMEvent *e )
  2813. {
  2814. if ( m_doc->m_bReadOnly ) {
  2815. e->ignore();
  2816. return;
  2817. }
  2818. if ( m_imPreeditLength > 0 ) {
  2819. cursor.setPos( m_imPreeditStartLine, m_imPreeditStart );
  2820. m_doc->removeText( m_imPreeditStartLine, m_imPreeditStart,
  2821. m_imPreeditStartLine, m_imPreeditStart + m_imPreeditLength );
  2822. }
  2823. m_view->setIMSelectionValue( m_imPreeditStartLine, m_imPreeditStart, 0, 0, 0, false );
  2824. if ( e->text().length() > 0 ) {
  2825. m_doc->insertText( cursor.line(), cursor.col(), e->text() );
  2826. if ( !m_cursorTimer.isActive() && TDEApplication::cursorFlashTime() > 0 )
  2827. m_cursorTimer.start ( TDEApplication::cursorFlashTime() / 2 );
  2828. updateView( true );
  2829. updateCursor( cursor, true );
  2830. }
  2831. m_imPreeditStart = 0;
  2832. m_imPreeditLength = 0;
  2833. m_imPreeditSelStart = 0;
  2834. }
  2835. //END IM INPUT STUFF
  2836. // kate: space-indent on; indent-width 2; replace-tabs on;