some debug messages removed
[kdevelop:kdevelop.git] / kdevelop / kwrite / kwview.cpp
1 #include "kwview.h"
2 #include "kwdoc.h"
3
4 #include <kapp.h>
5 #include <klocale.h>
6 #include <kfiledialog.h>
7 #include <kmessagebox.h>
8 #include <kdebug.h>
9
10 #include <qstring.h>
11 #include <qregexp.h>
12 #include <qwidget.h>
13 #include <qfont.h>
14 #include <qpainter.h>
15 #include <qkeycode.h>
16 #include <qmsgbox.h>
17 #include <qpixmap.h>
18 #include <qfileinf.h>
19 #include <qfile.h>
20 #include <qevent.h>
21 #include <qdir.h>
22 #include <qprinter.h>
23 #include <qprintdialog.h>
24 #include <qpaintdevicemetrics.h>
25 #include <qclipbrd.h>
26
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <string.h>
30
31 #ifdef HAVE_PATHS_H
32 #include <paths.h>
33 #endif
34
35 #ifndef _PATH_TMP
36 #define _PATH_TMP "/tmp/"
37 #endif
38
39 #include <ctype.h>
40 #include <time.h>
41
42 #include <X11/Xlib.h> //used to have XSetTransientForHint()
43
44 int kw_bookmark_keys[] = {Qt::Key_1,Qt::Key_2,Qt::Key_3,Qt::Key_4,Qt::Key_5,Qt::Key_6,Qt::Key_7,Qt::Key_8,Qt::Key_9};
45
46
47 struct BufferInfo {
48   void *user;
49   int w;
50   int h;
51 };
52
53 QList<BufferInfo> bufferInfoList;
54 QPixmap *buffer = 0;
55
56 QPixmap *getBuffer(void *user) {
57   BufferInfo *info;
58
59   if (!buffer) buffer = new QPixmap;
60   info = new BufferInfo;
61   info->user = user;
62   info->w = 0;
63   info->h = 0;
64   bufferInfoList.append(info);
65   return buffer;
66 }
67
68 void resizeBuffer(void *user, int w, int h) {
69   int z;
70   BufferInfo *info;
71   int maxW, maxH;
72
73   maxW = w;
74   maxH = h;
75   for (z = 0; z < (int) bufferInfoList.count(); z++) {
76     info = bufferInfoList.at(z);
77     if (info->user == user) {
78       info->w = w;
79       info->h = h;
80     } else {
81       if (info->w > maxW) maxW = info->w;
82       if (info->h > maxH) maxH = info->h;
83     }
84   }
85   if (maxW != buffer->width() || maxH != buffer->height()) {
86     buffer->resize(maxW,maxH);
87   }
88 }
89
90 void releaseBuffer(void *user) {
91   int z;
92   BufferInfo *info;
93
94   for (z = (int) bufferInfoList.count() -1; z >= 0 ; z--) {
95     info = bufferInfoList.at(z);
96     if (info->user == user) bufferInfoList.remove(z);
97   }
98   resizeBuffer(0,0,0);
99 }
100
101 KIconBorder::KIconBorder(KWrite *write, KWriteDoc *doc, KWriteView *view) :
102   QWidget(write),
103   kWrite(write),
104   kWriteDoc(doc),
105   kWriteView(view),
106   LMBIsBreakpoint(true),
107   cursorOnLine(0),
108   menuId_LMBBrkpoint(0),
109   menuId_LMBBookmark(0),
110   menuId_editBrkpoint(0)
111 {
112   setBackgroundColor(colorGroup().background());
113   setGeometry ( 2, 2, iconBorderWidth, iconBorderHeight);
114
115   selectMenu.insertTitle(i18n("Breakpoints/Bookmarks"));
116   selectMenu.insertItem(i18n("Toggle bookmark"), this, SLOT(slotToggleBookmark()));
117   selectMenu.insertItem(i18n("Clear all bookmarks"), kWrite, SLOT(clearBookmarks()));
118   selectMenu.insertSeparator();
119   selectMenu.insertItem(i18n("Toggle breakpoint"), kWrite, SLOT(slotToggleBreakpoint()));
120   menuId_editBrkpoint   = selectMenu.insertItem(i18n("Edit breakpoint"), this, SLOT(slotEditBreakpoint()));
121   menuId_enableBrkpoint = selectMenu.insertItem(i18n("Enable breakpoint"), this, SLOT(slotToggleBPEnabled()));
122   selectMenu.insertSeparator();
123   selectMenu.insertItem(i18n("Clear all breakpoints"), kWrite, SIGNAL(clearAllBreakpoints()));
124   selectMenu.insertSeparator();
125   menuId_LMBBrkpoint  = selectMenu.insertItem(i18n("LMB sets breakpoints"), this, SLOT(slotLMBMenuToggle()));
126   menuId_LMBBookmark  = selectMenu.insertItem(i18n("LMB sets bookmarks"),   this, SLOT(slotLMBMenuToggle()));
127   selectMenu.setCheckable(true);
128
129   selectMenu.setItemChecked(menuId_LMBBrkpoint, LMBIsBreakpoint);
130   selectMenu.setItemChecked(menuId_LMBBookmark, !LMBIsBreakpoint);
131 }
132
133
134 KIconBorder::~KIconBorder()
135 {
136 }
137
138 /**  */
139 /** Paints an icon to y */
140 void KIconBorder::showIcon(const QPixmap& icon, int y)
141 {
142   QPainter paint;
143
144   paint.begin(this);
145         paint.drawPixmap(2,y,icon);
146   paint.end();
147 }
148
149 void KIconBorder::clearPixelLines(int startPixelLine, int numberPixelLine)
150 {
151         QPainter paint;
152
153         paint.begin(this);
154
155   paint.fillRect(0, startPixelLine, iconBorderWidth-2, numberPixelLine, colorGroup().background());             
156
157   paint.setPen(white);
158   paint.drawLine(iconBorderWidth-2, startPixelLine, iconBorderWidth-2, startPixelLine + numberPixelLine);
159   paint.setPen(QColor(colorGroup().background()).dark());
160   paint.drawLine(iconBorderWidth-1, startPixelLine, iconBorderWidth-1, startPixelLine + numberPixelLine);
161         paint.end();
162 }
163
164 void KIconBorder::clearLine(int line)
165 {
166         int y = line * kWriteDoc->getFontHeight() - kWriteView->getYPos();
167
168         clearPixelLines(y, kWriteDoc->getFontHeight());
169 }
170
171 void KIconBorder::clearAll()
172 {
173         clearPixelLines(0, iconBorderHeight);
174 }
175
176 void KIconBorder::paintBookmark(int line)
177 {
178   if (kWrite->bookmarked(line))
179         {
180     #include "pix/bookmark.xpm"
181                 QPixmap bookmarkPixmap(bookmark_xpm);
182     showIcon(bookmarkPixmap, line * kWriteDoc->getFontHeight() - kWriteView->getYPos());
183         }
184 }
185
186 void KIconBorder::paintBreakpoint(int line)
187 {
188         if (line < 0 || line>kWriteDoc->lastLine())
189                 return;
190
191   // A breakpoint is on this line - draw it
192   TextLine* tLine = kWriteDoc->textLine(line);
193         if (tLine && (tLine->getBPId() != 0))
194         {
195     QPixmap bpPix;
196     if (!tLine->isBPEnabled())
197     {
198       #include "pix/breakpoint_gr.xpm"
199       bpPix = QPixmap(breakpoint_gr_xpm);
200     }
201     else
202     {
203       if (tLine->isBPPending())
204       {
205         #include "pix/breakpoint_bl.xpm"
206         bpPix = QPixmap(breakpoint_bl_xpm);
207       }
208       else
209       {
210         #include "pix/breakpoint.xpm"
211         bpPix = QPixmap(breakpoint_xpm);
212       }
213     }
214
215     showIcon(bpPix, line * kWriteDoc->getFontHeight() - kWriteView->getYPos());
216   }
217 }
218
219 void KIconBorder::paintDbgPosition(int line)
220 {
221   // This line is the position in source the debugger has stopped at.
222   if (kWrite->getStepLine() == line )
223         {
224     #include "pix/ddd.xpm"
225                 QPixmap dddPixmap(ddd_xpm);
226                 showIcon(dddPixmap, line * kWriteDoc->getFontHeight() - kWriteView->getYPos());
227         }
228 }
229
230 void KIconBorder::paintLine(int line)
231 {
232   if (line >= 0 && line < kWriteDoc->getTextLineCount())
233   {
234                 clearLine(line);
235                 paintBookmark(line);
236                 paintBreakpoint(line);
237                 paintDbgPosition(line);
238   }
239 }
240
241 void KIconBorder::paintEvent(QPaintEvent* e)
242 {
243         int lineStart = 0;
244         int lineEnd = 0;
245
246         QRect updateR = e->rect();
247
248         int h = kWriteDoc->getFontHeight();
249         int yPos = kWriteView->getYPos();
250         if (h) {
251         lineStart = (yPos + updateR.y()) / h;
252           lineEnd = (yPos + updateR.y() + updateR.height()) / h;
253         }
254
255         for(int line = lineStart; line <= lineEnd; line++)
256         {
257                 paintLine(line);
258         }
259 }
260
261 /** Checks MouseEvents and executes the popup
262     All slots called from here (including the menu work off the "cursorOnLine" variable
263     set at the line the user has clicked on. We cannot pass the cursorOnLine as a parameter
264     because the menu items cannot have parameters
265 */
266 void KIconBorder::mousePressEvent(QMouseEvent* e)
267 {
268   kWriteView->placeCursor( 0, e->y(), 0 );
269         cursorOnLine = ( e->y() + kWriteView->getYPos() ) / kWriteDoc->getFontHeight();
270
271   switch (e->button())
272   {
273     case LeftButton:
274     {
275       if (LMBIsBreakpoint)
276         kWrite->slotToggleBreakpoint();
277       else
278         slotToggleBookmark();
279       break;
280     }
281     case RightButton:
282     {
283       if (TextLine* tline=kWriteDoc->textLine(cursorOnLine))
284       {
285         if (tline->getBPId())
286         {
287           selectMenu.setItemEnabled (menuId_editBrkpoint, true);
288           selectMenu.setItemEnabled (menuId_enableBrkpoint, true);
289           if (tline->isBPEnabled())
290             selectMenu.changeItem(menuId_enableBrkpoint, i18n("Disable breakpoint"));
291           else
292             selectMenu.changeItem(menuId_enableBrkpoint, i18n("Enable breakpoint"));
293         }
294         else
295         {
296           selectMenu.setItemEnabled (menuId_editBrkpoint, false);
297           selectMenu.setItemEnabled (menuId_enableBrkpoint, false);
298           selectMenu.changeItem(menuId_enableBrkpoint, i18n("Enable breakpoint"));
299         }
300         selectMenu.exec(mapToGlobal(QPoint(e->x()-selectMenu.width(),e->y()-20)));
301       }
302       break;
303     }
304
305     case MidButton:
306     {
307       slotToggleBookmark();
308       break;
309     }
310     default:
311         break;
312   }
313 }
314
315 void KIconBorder::slotLMBMenuToggle()
316 {
317   LMBIsBreakpoint = !LMBIsBreakpoint;
318         selectMenu.setItemChecked(menuId_LMBBrkpoint, LMBIsBreakpoint);
319         selectMenu.setItemChecked(menuId_LMBBookmark, !LMBIsBreakpoint);
320 }
321
322 void KIconBorder::slotEditBreakpoint()
323 {
324   emit kWrite->editBreakpoint(QString(kWriteDoc->fileName()), cursorOnLine+1);
325 }
326
327 void KIconBorder::slotToggleBPEnabled()
328 {
329   emit kWrite->toggleBPEnabled(QString(kWriteDoc->fileName()), cursorOnLine+1);
330 }
331
332 /** toggles a bookmark */
333 void KIconBorder::slotToggleBookmark()
334 {
335         debug("KIconBorder::slotToggleBookmark !\n");
336
337         kWrite->toggleBookmark(cursorOnLine);
338 }
339
340 /** gets the Range of the function the cursor is in */
341 void KIconBorder::slotGetRange()
342 {
343         kWriteView->getRange(kWriteView->cursor.y);
344 }
345
346 KWriteView::KWriteView(KWrite *write, KWriteDoc *doc) : QWidget(write) {
347         m_hasFocus = false;
348   kWrite = write;
349   kWriteDoc = doc;
350   bIsPainting = false;
351
352   QWidget::setCursor(ibeamCursor);
353   setMouseTracking(true);   //dbg
354   setBackgroundMode(NoBackground);
355   setFocusPolicy(ClickFocus);
356 #ifdef QT_I18N
357   setInputMethodEnabled( TRUE );
358   setInputMethodSpotLocation(0, kWriteDoc->fontAscent);
359 #endif
360   move(iconBorderWidth+2,2);
361
362   leftBorder = new KIconBorder(kWrite, kWriteDoc, this);
363
364   xScroll = new QScrollBar(QScrollBar::Horizontal,write);
365   yScroll = new QScrollBar(QScrollBar::Vertical,write);
366   connect(xScroll,SIGNAL(valueChanged(int)),SLOT(changeXPos(int)));
367   connect(yScroll,SIGNAL(valueChanged(int)),SLOT(changeYPos(int)));
368
369   xPos = 0;
370   yPos = 0;
371
372   scrollTimer = 0;
373
374   cursor.x = 0;
375   cursor.y = 0;
376   cursorOn = false;
377   cursorTimer = 0;
378   cXPos = 0;
379   cOldXPos = 0;
380   exposeCursor = false;
381
382   startLine = 0;
383   endLine = 0;
384   updateState = 0;
385
386   drawBuffer = getBuffer(this);
387
388   if (doc)
389     doc->registerView(this);
390 }
391
392 KWriteView::~KWriteView() {
393   if(kWriteDoc) {
394     kWriteDoc->removeView(this);
395   }
396   releaseBuffer(this);
397 }
398
399 bool KWriteView::event( QEvent *e )
400 {
401   if ( e->type() == KeyPress ){
402     QKeyEvent *k = (QKeyEvent *)e;
403     if ( k->key() == Key_Tab ){
404       keyPressEvent( k );
405       return true;
406     }
407   }
408   return QWidget::event( e );
409 }
410
411 bool KWriteView::focusNextPrevChild( bool )
412 {
413   // avoids a focus out event on Tab key
414   return false;
415 }
416
417 void KWriteView::cursorLeft(VConfig &c) {
418
419   cursor.x--;
420 #ifdef QT_I18N
421   if (cursor.x > 0 &&
422       iseucchar(kWriteDoc->textLine(cursor.y)->getChar(cursor.x))) {
423     cursor.x--;
424   }
425 #endif
426   if (c.flags & cfWrapCursor && cursor.x < 0 && cursor.y > 0) {
427     cursor.y--;
428     cursor.x = kWriteDoc->textLength(cursor.y);
429   }
430   cOldXPos = cXPos = kWriteDoc->textWidth(cursor);
431   update(c);
432 }
433
434 void KWriteView::cursorRight(VConfig &c) {
435
436   if (c.flags & cfWrapCursor) {
437     if (cursor.x >= kWriteDoc->textLength(cursor.y)) {
438       if (cursor.y == kWriteDoc->lastLine()) return;
439       cursor.y++;
440       cursor.x = -1;
441     }
442   }  
443 #ifdef QT_I18N
444   if (cursor.x >= 0 &&
445       iseucchar(kWriteDoc->textLine(cursor.y)->getChar(cursor.x))) {
446     cursor.x++;
447   }
448 #endif
449   cursor.x++;
450   cOldXPos = cXPos = kWriteDoc->textWidth(cursor);
451   update(c);
452 }
453
454
455 void KWriteView::cursorLeftWord(VConfig &c) {
456
457   TextLine* CurrLine;
458
459   do{
460     cursor.x--;
461     if (cursor.x < 0) {
462       if (c.flags & cfWrapCursor && cursor.y > 0) {
463         cursor.y--;
464         cursor.x = kWriteDoc->textLength(cursor.y);
465       }else break;  
466     }
467     CurrLine = kWriteDoc->textLine(cursor.y);
468   
469   }while( !isalnum(CurrLine->getChar(cursor.x)) ||
470          isalnum(CurrLine->getChar(cursor.x - 1))
471         );
472
473   cOldXPos = cXPos = kWriteDoc->textWidth(cursor);
474   update(c);
475 }
476
477 void KWriteView::cursorRightWord(VConfig &c) {
478
479   TextLine* CurrLine;
480
481   do{
482     if (cursor.x >= kWriteDoc->textLength(cursor.y)) {
483       if (c.flags & cfWrapCursor) {
484         if (cursor.y == kWriteDoc->lastLine()) break;
485         cursor.y++;
486         cursor.x = -1;
487       }else break;
488     }  
489     
490     cursor.x++;
491     CurrLine = kWriteDoc->textLine(cursor.y);
492   }while( isalnum(CurrLine->getChar(cursor.x - 1)) ||
493          !isalnum(CurrLine->getChar(cursor.x))
494         );
495
496   cOldXPos = cXPos = kWriteDoc->textWidth(cursor);
497   update(c);
498 }
499
500 void KWriteView::cursorUp(VConfig &c) {
501
502   cursor.y--;
503   cXPos = kWriteDoc->textWidth(c.flags & cfWrapCursor,cursor,cOldXPos);
504   update(c);
505 }
506
507 void KWriteView::cursorDown(VConfig &c) {
508   int x;
509   
510   if (cursor.y == kWriteDoc->lastLine()) {
511     x = kWriteDoc->textLength(cursor.y);
512     if (cursor.x >= x) return;
513     cursor.x = x;
514     cXPos = kWriteDoc->textWidth(cursor);
515   } else {
516     cursor.y++;
517     cXPos = kWriteDoc->textWidth(c.flags & cfWrapCursor,cursor,cOldXPos);
518   }  
519   update(c);
520 }
521
522 void KWriteView::home(VConfig &c) {
523
524   cursor.x = 0;
525   cOldXPos = cXPos = 0;
526   update(c);
527 }
528
529 void KWriteView::end(VConfig &c) {
530   
531   cursor.x = kWriteDoc->textLength(cursor.y);
532   cOldXPos = cXPos = kWriteDoc->textWidth(cursor);
533   update(c);
534 }
535
536 void KWriteView::pageUp(VConfig &c) {
537
538   cursor.y -= endLine - startLine;
539   cXPos = kWriteDoc->textWidth(c.flags & cfWrapCursor,cursor,cOldXPos);
540   update(c);
541 }
542
543 void KWriteView::pageDown(VConfig &c) {
544   
545   cursor.y += endLine - startLine;
546   cXPos = kWriteDoc->textWidth(c.flags & cfWrapCursor,cursor,cOldXPos);
547   update(c);
548 }
549
550 void KWriteView::top(VConfig &c) {
551
552   cursor.x = 0;
553   cursor.y = 0;
554   cOldXPos = cXPos = 0;
555   update(c);
556 }
557
558 void KWriteView::bottom(VConfig &c) {
559   
560   cursor.x = 0;
561   cursor.y = kWriteDoc->lastLine();
562   cOldXPos = cXPos = 0;
563   update(c);
564 }
565
566
567 void KWriteView::changeXPos(int p) {
568   int dx;
569
570   dx = xPos - p;
571   xPos = p;
572   if (QABS(dx) < width())
573     scroll(dx,0);
574   else
575     QWidget::update();
576 }
577
578 void KWriteView::changeYPos(int p) {
579   int dy;
580
581   //kdDebug() << "changeYPos1: " << p << " isPainting " << bIsPainting << endl;
582
583   if ( bIsPainting )
584     return;
585   dy = yPos - p;
586   yPos = p;
587   startLine = yPos / kWriteDoc->fontHeight;
588   endLine = (yPos + height() -1) / kWriteDoc->fontHeight;
589   //kdDebug() << "changeYPos2: " << p << " dy " << dy << " height " << height() << endl;
590   if (QABS(dy) < height())
591   {
592     leftBorder->scroll(0,dy);
593     scroll(0,dy);
594   }
595   else
596   {
597     QWidget::update();
598   }
599 }
600
601 void KWriteView::getVConfig(VConfig &c) {
602
603   c.cursor = cursor;
604   c.flags = kWrite->configFlags;
605   c.wrapAt = kWrite->wrapAt;
606 }
607
608 void KWriteView::update(VConfig &c) {
609         
610   if (cursor.x == c.cursor.x && cursor.y == c.cursor.y) return;
611   exposeCursor = true;
612
613   kWriteDoc->unmarkFound();
614   
615   if (cursorOn) {
616     tagLines(c.cursor.y, c.cursor.y);
617     cursorOn = false;
618   }
619 #ifdef QT_I18N
620 #if 0
621   int h, x, y;
622   h = kWriteDoc->fontHeight;
623   y = h*cursor.y - yPos + kWriteDoc->fontAscent;
624   x = cXPos - (xPos-2);
625   setInputMethodSpotLocation(x, y);
626 #endif
627 #endif
628
629   if (bm.sXPos < bm.eXPos) {
630     tagLines(bm.cursor.y, bm.cursor.y);
631   }
632   // make new bracket mark
633   if (c.flags & cfHighlightBrackets) {
634     kWriteDoc->newBracketMark(cursor, bm);
635   }
636
637   if (c.flags & cfMark) {
638     kWriteDoc->selectTo(c.cursor,cursor,c.flags);
639   } else {
640     if (!(c.flags & cfPersistent))
641       kWriteDoc->deselectAll();
642   }
643 }
644
645 void KWriteView::insLine(int line) {
646
647   if (line <= cursor.y) {
648     cursor.y++;
649   }
650   if (line < startLine) {
651     startLine++;
652     endLine++;
653     yPos += kWriteDoc->fontHeight;
654   } else if (line <= endLine) {
655     tagAll();
656   }
657 }
658
659 void KWriteView::delLine(int line)
660 {
661   emit kWrite->deleteLine( line );
662
663   if (line <= cursor.y && cursor.y > 0) {
664     cursor.y--;
665   }
666   if (line < startLine) {
667     startLine--;
668     endLine--;
669     yPos -= kWriteDoc->fontHeight;
670   } else if (line <= endLine) {
671     tagAll();
672   }
673 }
674
675 void KWriteView::wheelEvent(QWheelEvent *e)
676 {
677     e->accept();
678     yScroll->setValue(yScroll->value() - e->delta());
679 //    kdDebug() << yScroll->value() << " - " << e->delta() << " = " << yScroll->value() - e->delta() << endl;
680 }
681 void KWriteView::updateCursor() {
682   cOldXPos = cXPos = kWriteDoc->textWidth(cursor);
683 }
684
685 void KWriteView::updateCursor(PointStruc &newCursor) {
686
687   exposeCursor = true;
688   if (cursorOn) {
689     tagLines(cursor.y,cursor.y);
690     cursorOn = false;
691   }
692   if (bm.sXPos < bm.eXPos) {
693     tagLines(bm.cursor.y, bm.cursor.y);
694   }
695   if (kWrite->configFlags & cfHighlightBrackets) {
696     kWriteDoc->newBracketMark(cursor, bm);
697   }
698
699   cursor = newCursor;
700   cOldXPos = cXPos = kWriteDoc->textWidth(cursor);
701 }
702
703 void KWriteView::updateView(int flags, int newXPos, int newYPos) {
704   int fontHeight;
705   int oldXPos, oldYPos;
706   int w, h;
707   int z;
708   bool b;
709   int xMax, yMax;
710   int cYPos;
711   int cXPosMin, cXPosMax, cYPosMin, cYPosMax;
712   int dx, dy;
713
714   if (exposeCursor || flags & ufDocGeometry) {
715     emit kWrite->newCurPos();
716   } else if (updateState == 0) return;
717
718   if (cursorTimer) {
719     killTimer(cursorTimer);
720     cursorTimer = startTimer(500);
721     cursorOn = true;
722   }
723
724   oldXPos = xPos;
725   oldYPos = yPos;
726   if (flags & ufPos) {
727     xPos = newXPos;
728     yPos = newYPos;
729     exposeCursor = true;//false;
730   }
731
732   fontHeight = kWriteDoc->fontHeight;
733   cYPos = cursor.y*fontHeight;
734
735   z = 0;
736   do {
737     w = kWrite->width() - 4;
738     h = kWrite->height() - 4;
739
740     xMax = kWriteDoc->textWidth() - w + iconBorderWidth;
741     b = (xPos > 0 || xMax > 0);
742     if (b) h -= 16;
743     yMax = kWriteDoc->textHeight() - h;
744     if (yPos > 0 || yMax > 0) {
745       w -= 16;
746       xMax += 16;
747       if (!b && xMax > 0) {
748         h -= 16;
749         yMax += 16;
750       }
751     }
752
753     if (!exposeCursor) break;
754     cXPosMin = xPos + 4;
755     cXPosMax = xPos + w - 8 - iconBorderWidth;
756     cYPosMin = yPos;
757     cYPosMax = yPos + (h - fontHeight);
758
759     if (cXPos < cXPosMin) {
760       xPos -= cXPosMin - cXPos;
761     }
762     if (xPos < 0) xPos = 0;
763     if (cXPos > cXPosMax) {
764       xPos += cXPos - cXPosMax;
765     }
766     if (cYPos < cYPosMin) {
767       yPos -= cYPosMin - cYPos;
768     }
769     if (yPos < 0) yPos = 0;
770     if (cYPos > cYPosMax) {
771       yPos += cYPos - cYPosMax;
772     }
773
774     z++;
775   } while (z < 2);
776
777   if (xMax < xPos) xMax = xPos;
778   if (yMax < yPos) yMax = yPos;
779
780   if (xMax > 0) {
781     xScroll->blockSignals(true);
782     xScroll->setGeometry(2,h + 2,w,16);
783     xScroll->setRange(0,xMax);
784     xScroll->setValue(xPos);
785     xScroll->setSteps(fontHeight,w - 4 - 16);
786     xScroll->blockSignals(false);
787     xScroll->show();
788   } else xScroll->hide();
789
790   if (yMax > 0) {
791     yScroll->blockSignals(true);
792     yScroll->setGeometry(w + 2,2,16,h);
793     yScroll->setRange(0,yMax);
794     yScroll->setValue(yPos);
795     yScroll->setSteps(fontHeight,h - 4 - 16);
796     yScroll->blockSignals(false);
797     yScroll->show();
798   } else yScroll->hide();
799
800   if (fontHeight) {
801     startLine = yPos / fontHeight;
802     endLine = (yPos + h -1) / fontHeight;
803   }
804
805   if (w != width() || h != height()) {
806     resize(w,h);
807   } else {
808     dx = oldXPos - xPos;
809     dy = oldYPos - yPos;
810
811     b = updateState == 3;
812     if (flags & ufUpdateOnScroll) {
813       b |= dx || dy;
814     } else {
815       b |= QABS(dx)*3 > w*2 || QABS(dy)*3 > h*2;
816     }
817
818     if (b) {
819       repaint(0, 0, width(), height(), false);
820     } else {
821       if(dy) leftBorder->scroll(0,dy);
822
823       if (updateState > 0) paintTextLines(oldXPos,oldYPos);
824
825       if (dx || dy) {
826         scroll(dx,dy);
827       } else if (cursorOn) paintCursor();
828       if (bm.eXPos > bm.sXPos) paintBracketMark();
829     }
830   }
831
832   exposeCursor = false;
833   updateState = 0;
834 #ifdef QT_I18N
835   int x, y;
836   h = kWriteDoc->fontHeight;
837   y = h*cursor.y - yPos + kWriteDoc->fontAscent;
838   x = cXPos - (xPos-2);
839   setInputMethodSpotLocation(x, y);
840 #endif
841 }
842
843 void KWriteView::tagLines(int start, int end) {
844   int line, z;
845
846   if (updateState < 3) {
847     if (start < startLine) start = startLine;
848     if (end > endLine) end = endLine;
849
850     if (end - start > 1) {
851       updateState = 3;
852     } else {
853       for (line = start; line <= end; line++) {
854         for (z = 0; z < updateState && updateLines[z] != line; z++);
855         if (z == updateState) {
856           updateState++;
857           if (updateState > 2) break;
858           updateLines[z] = line;
859         }
860       }
861     }
862   }
863 }
864
865 void KWriteView::tagAll() {
866   updateState = 3;
867 }
868
869 void KWriteView::paintTextLines(int xPos, int yPos) {
870   int xStart, xEnd;
871   int line, z;
872   int h;
873
874   QPainter paint;
875   paint.begin(drawBuffer);
876
877   xStart = xPos-2;
878   xEnd = xStart + width();
879   h = kWriteDoc->fontHeight;
880   for (z = 0; z < updateState; z++) {
881     line = updateLines[z];
882     kWriteDoc->paintTextLine(paint,line,xStart,xEnd, kWrite->flags() & cfShowTabs);
883     bitBlt(this,0,line*h - yPos,drawBuffer,0,0,width(),h);
884
885    leftBorder->paintLine(line);
886   }
887   paint.end();
888 }
889
890 void KWriteView::paintCursor() {
891   int h, y, x;
892
893   h = kWriteDoc->fontHeight;
894   y = h*cursor.y - yPos;
895   x = cXPos - (xPos-2);
896
897   QPainter paint;
898   if (cursorOn) {
899     paint.begin(this);
900     paint.setPen(kWriteDoc->cursorCol(cursor.x,cursor.y));
901
902     h += y - 1;
903     paint.drawLine(x,y,x,h);
904     paint.drawLine(x-2,y,x+2,y);
905     paint.drawLine(x-2,h,x+2,h);
906     paint.end();
907   } else {
908     if ( !drawBuffer->isNull() ){
909   //debug("===============================maximus BUG begin");
910       paint.begin(drawBuffer);
911   //debug("===============================maximus BUG end");
912       kWriteDoc->paintTextLine(paint,cursor.y,cXPos - 2, cXPos + 3, kWrite->flags() & cfShowTabs);
913       bitBlt(this,x - 2,y,drawBuffer,0,0,5,h);
914       paint.end();
915     }
916   }
917 }
918
919 void KWriteView::paintBracketMark() {
920
921   if (!(kWrite->configFlags & cfHighlightBrackets)) {
922     return;
923   }
924
925   if ((bm.cursor.x < 0) || (bm.cursor.y < 0)) {
926     return;
927   }
928
929   int y = kWriteDoc->fontHeight*(bm.cursor.y +1) - yPos -1;
930
931   QPainter paint;
932   paint.begin(this);
933   paint.setPen(kWriteDoc->cursorCol(bm.cursor.x, bm.cursor.y));
934
935   paint.drawLine(bm.sXPos - (xPos-2), y, bm.eXPos - (xPos-2) -1, y);
936   paint.end();
937 }
938
939 void KWriteView::placeCursor(int x, int y, int flags) {
940   VConfig c;
941
942   getVConfig(c);
943   c.flags |= flags;
944   cursor.y = (yPos + y)/kWriteDoc->fontHeight;
945   cXPos = cOldXPos = kWriteDoc->textWidth(c.flags & cfWrapCursor, cursor,xPos-2 + x);
946   update(c);
947 }
948
949 void KWriteView::focusInEvent(QFocusEvent *e) {
950   // every widget get a focusInEvent when a popup menu is opened!?! -> maybe bug of QT
951   if (e && ((e->reason())==QFocusEvent::Popup)) {
952     return;
953   }
954   if (m_hasFocus)
955     return;
956   else
957     m_hasFocus = true;
958
959 //  printf("got focus %d\n",cursorTimer);
960
961   QString text=kapp->clipboard()->text();
962   //dbg - start
963   kWrite->newCurPos();
964   kWrite->newStatus();
965   kWrite->newUndo();
966   // dbg - end
967   if (!cursorTimer) {
968     cursorTimer = startTimer(500);
969     cursorOn = true;
970     paintCursor();
971   }
972
973   emit kWrite->clipboardStatus(this, !text.isEmpty());
974 }
975
976 void KWriteView::focusOutEvent(QFocusEvent *) {
977 //  printf("lost focus\n");
978
979   if (cursorTimer) {
980     killTimer(cursorTimer);
981     cursorTimer = 0;
982   }
983
984   if (cursorOn) {
985     cursorOn = false;
986     paintCursor();
987   }
988         m_hasFocus = false;
989 }
990
991 void KWriteView::scroll( int dx, int dy ) {
992   bIsPainting = true;
993   QWidget::scroll( dx, dy );
994   bIsPainting = false;
995 }
996
997 void KWriteView::keyPressEvent(QKeyEvent *e) {
998   VConfig c;
999   bool t;
1000
1001   if (e->state() & AltButton) {
1002     e->ignore();
1003     return;
1004   }
1005
1006 /*
1007 CTRL+
1008 A, <-  : home
1009 B      : <-
1010 C      : copy
1011 D      : del
1012 E, ->  : end
1013 F      : ->
1014 H      : backspace
1015 K      : kill line
1016 N      : down
1017 P      : up
1018 V      : paste
1019 X      : cut
1020 */
1021
1022   getVConfig(c);
1023
1024 #ifdef QT_I18N
1025   if ( (e->key() == 0) && (e->text().length() > 0) ) {
1026     if (c.flags & cfDelOnInput) {
1027       kWriteDoc->delMarkedText(this,c);
1028       getVConfig(c);
1029     }
1030     int i, len;
1031     len = e->text().length();
1032     char* mbuf = e->text().data();
1033     for (i = 0; i < len; i++) {
1034         if (iseucchar(*mbuf)) {
1035             kWriteDoc->insertChar(this,c, mbuf, 2);
1036             mbuf += 2;
1037             i++;
1038         } else {
1039             kWriteDoc->insertChar(this,c, *mbuf++);
1040         }
1041     }
1042   } else
1043 #endif
1044   if ((e->ascii() >= 32 || e->ascii() == '\t')
1045     && e->key() != Key_Delete && e->key() != Key_Backspace) {
1046 //    printf("input %d\n",e->ascii());
1047     if (c.flags & cfDelOnInput) {
1048       kWriteDoc->delMarkedText(this,c);
1049       getVConfig(c);
1050     }
1051     kWriteDoc->insertChar(this,c,e->ascii());
1052   } else {
1053     if (e->state() & ShiftButton) c.flags |= cfMark;
1054
1055     t = false;
1056     if ( e->state() & ControlButton ) {
1057       t = true;
1058       switch ( e->key() ) {
1059 /*
1060         case Key_A:
1061         case Key_Left:
1062             home(c);
1063             break;
1064         case Key_B:
1065             cursorLeft(c);
1066             break; */
1067         case Key_Insert:
1068 //        case Key_C:
1069             kWriteDoc->copy(c.flags);
1070             break;
1071 /*        case Key_D:
1072             kWriteDoc->del(c);
1073             break;
1074         case Key_E:
1075         case Key_Right:
1076             end(c);
1077             break;
1078         case Key_F:
1079             cursorRight(c);
1080             break;
1081         case Key_H:
1082             kWriteDoc->backspace(c);
1083             break;   */
1084         case Key_K:
1085             kWriteDoc->killLine(this,c);
1086             break;
1087 /*        case Key_N:
1088             cursorDown(c);
1089             break;
1090         case Key_P:
1091             cursorUp(c);
1092             break;
1093         case Key_V:
1094             kWriteDoc->paste(c);
1095             break;   */
1096         case Key_Home:
1097             top(c);
1098             home(c);
1099             break;
1100         case Key_End:
1101             bottom(c);
1102             end(c);
1103             break;
1104         case Key_Delete:
1105 //        case Key_X:
1106             kWriteDoc->cut(this,c);
1107             break;
1108         case Key_Left:
1109             cursorLeftWord(c);
1110             break;
1111         case Key_Right:
1112             cursorRightWord(c);
1113             break;
1114         case Key_Next:
1115             bottom(c);
1116             break;
1117         case Key_Prior:
1118             top(c);
1119             break;
1120         default:
1121             t = false;
1122       }
1123     }
1124     if (!t) {
1125       if (e->state() & ControlButton) c.flags |= cfMark | cfKeepSelection;
1126       switch ( e->key() ) {
1127         case Key_Left:
1128             cursorLeft(c);
1129             break;
1130         case Key_Right:
1131             cursorRight(c);
1132             break;
1133         case Key_Up:
1134             cursorUp(c);
1135             break;
1136         case Key_Down:
1137             cursorDown(c);
1138             break;
1139         case Key_Backspace:
1140             if ((c.flags & cfDelOnInput) && kWriteDoc->hasMarkedText())
1141               kWriteDoc->delMarkedText(this,c);
1142             else kWriteDoc->backspace(this,c);
1143             break;
1144         case Key_Home:
1145             home(c);
1146             break;
1147         case Key_End:
1148             end(c);
1149             break;
1150         case Key_Delete:
1151             if (e->state() & ShiftButton) kWriteDoc->cut(this,c);
1152             else if ((c.flags & cfDelOnInput) && kWriteDoc->hasMarkedText())
1153               kWriteDoc->delMarkedText(this,c);
1154             else kWriteDoc->del(this,c);
1155             break;
1156         case Key_Next:
1157             pageDown(c);
1158             break;
1159         case Key_Prior:
1160             pageUp(c);
1161             break;
1162         case Key_Enter:
1163         case Key_Return:
1164             if ((c.flags & cfDelOnInput) && kWriteDoc->hasMarkedText())
1165               kWriteDoc->delMarkedText(this,c);
1166             kWriteDoc->newLine(this,c);
1167             //emit returnPressed();
1168             //e->ignore();
1169             break;
1170         case Key_Insert:
1171             if (e->state() & ShiftButton) kWriteDoc->paste(this,c);
1172               else kWrite->toggleOverwrite();
1173             break;
1174 /*        case Key_F9:
1175             printf("text() %s\n", kWrite->text().data());
1176             break;
1177         case Key_F10:
1178             printf("currentWord() %s\n", kWrite->currentWord().data());
1179             break;*/
1180       }
1181     }
1182   }
1183   kWriteDoc->updateViews();
1184   e->accept();
1185 }
1186
1187 void KWriteView::mousePressEvent(QMouseEvent *e) {
1188
1189   if (e->button() == LeftButton) {
1190     int flags;
1191
1192     flags = 0;
1193     if (e->state() & ShiftButton) {
1194       flags |= cfMark;
1195       if (e->state() & ControlButton) flags |= cfMark | cfKeepSelection;
1196     }
1197     placeCursor(e->x(),e->y(),flags);
1198     scrollX = 0;
1199     scrollY = 0;
1200     if (!scrollTimer) scrollTimer = startTimer(50);
1201     kWriteDoc->updateViews();
1202   }
1203   else if (e->button() == MidButton) {
1204     placeCursor(e->x(),e->y(),0);
1205     kWrite->paste();
1206   }
1207
1208   if (m_hasFocus && (e->button() != RightButton)) {
1209     kWrite->newCurPos();
1210     kWrite->newStatus();
1211     kWrite->newUndo();
1212   }
1213
1214   // Call CEditWidget::mousePressEvent to handle the RightButton case
1215   QMouseEvent ee(QEvent::MouseButtonPress, mapToParent(e->pos()), e->button(), e->state());
1216   kWrite->mousePressEvent(&ee);
1217 }
1218
1219 void KWriteView::mouseDoubleClickEvent(QMouseEvent *e) {
1220
1221   if (e->button() == LeftButton) {
1222     VConfig c;
1223     getVConfig(c);
1224     kWriteDoc->selectWord(c.cursor, c.flags);
1225     kWriteDoc->updateViews();
1226   }
1227 }
1228
1229 void KWriteView::mouseReleaseEvent(QMouseEvent *e) {
1230
1231   if (e->button() == LeftButton) {
1232     VConfig c;
1233     getVConfig(c);
1234
1235     if (c.flags & cfAutoCopy) {
1236       kWrite->copy();
1237     }
1238     killTimer(scrollTimer);
1239     scrollTimer = 0;
1240   }
1241 }
1242
1243 void KWriteView::mouseMoveEvent(QMouseEvent *e) {
1244
1245   if (e->state() & LeftButton) {
1246     int flags;
1247     int d;
1248
1249     mouseX = e->x();
1250     mouseY = e->y();
1251     scrollX = 0;
1252     scrollY = 0;
1253     d = kWriteDoc->fontHeight;
1254     if (mouseX < 0) {
1255       mouseX = 0;
1256       scrollX = -d;
1257     }
1258     if (mouseX > width()) {
1259       mouseX = width();
1260       scrollX = d;
1261     }
1262     if (mouseY < 0) {
1263       mouseY = 0;
1264       scrollY = -d;
1265     }
1266     if (mouseY > height()) {
1267       mouseY = height();
1268       scrollY = d;
1269     }
1270
1271     flags = cfMark;
1272     if (e->state() & ControlButton) flags |= cfKeepSelection;
1273     placeCursor(mouseX,mouseY,flags);
1274     kWriteDoc->updateViews(/*ufNoScroll*/);
1275   }
1276 }
1277
1278 void KWriteView::paintEvent(QPaintEvent *e) {
1279   int xStart, xEnd;
1280   int h, y, yEnd;
1281   int line = 0;
1282   bIsPainting = true;           // toggle scrolling off
1283 //  bool isVisible;
1284
1285   QRect updateR = e->rect();
1286 //  printf("update rect  = ( %i, %i, %i, %i )\n",
1287 //    updateR.x(),updateR.y(), updateR.width(), updateR.height() );
1288
1289   QPainter paint;
1290   paint.begin(drawBuffer);
1291
1292   xStart = xPos-2 + updateR.x();
1293   xEnd = xStart + updateR.width();
1294
1295   h = kWriteDoc->fontHeight;
1296   if (h) {
1297     line = (yPos + updateR.y()) / h;
1298   }
1299   y = line*h - yPos;
1300   yEnd = updateR.y() + updateR.height();
1301
1302   int textLineCount = kWriteDoc->getTextLineCount()-1;
1303   while (y < yEnd)
1304   {
1305     if (textLineCount>line)
1306     {
1307       int ctxNum = 0;
1308       TextLine *textLine = kWriteDoc->textLine(line);
1309       if (line > 0)
1310         ctxNum = kWriteDoc->textLine(line - 1)->getContext();
1311       if ( CTX_UNDEF == ctxNum )
1312         ctxNum = 0;
1313       if (kWriteDoc->highlight)
1314         ctxNum = kWriteDoc->highlight->doHighlight(ctxNum,textLine);
1315       if (textLine)
1316         textLine->setContext(ctxNum);
1317     }
1318
1319     kWriteDoc->paintTextLine(paint,line,xStart,xEnd, kWrite->flags() & cfShowTabs);
1320 //    if (cursorOn && line == cursor.y) paintCursor(paint,cXPos - xStart,h);
1321     bitBlt(this,updateR.x(),y,drawBuffer,0,0,updateR.width(),h);
1322
1323     leftBorder->paintLine(line);
1324
1325     line++;
1326     y += h;
1327     if (!h)
1328       break;  // otherwise there's an infinite loop ;(
1329   }
1330
1331   paint.end();
1332   if (cursorOn) paintCursor();
1333   if (bm.eXPos > bm.sXPos) paintBracketMark();
1334   bIsPainting = false;          // toggle scrolling on
1335 }
1336
1337 void KWriteView::resizeEvent(QResizeEvent *) {
1338 //  printf("KWriteView::resize\n");
1339   resizeBuffer(this,width(),kWriteDoc->fontHeight);
1340   leftBorder->resize(leftBorder->width(), height());
1341   QWidget::update();
1342 }
1343
1344 void KWriteView::timerEvent(QTimerEvent *e) {
1345   if (e->timerId() == cursorTimer) {
1346     cursorOn = !cursorOn;
1347     paintCursor();
1348   }
1349   if (e->timerId() == scrollTimer && (scrollX | scrollY)) {
1350     xScroll->setValue(xPos + scrollX);
1351     yScroll->setValue(yPos + scrollY);
1352
1353     placeCursor(mouseX,mouseY,cfMark);
1354     kWriteDoc->updateViews(/*ufNoScroll*/);
1355   }
1356 }
1357
1358 /** returns the range of a hidden function */
1359 int KWriteView::getRange(int midline){
1360         int counter=0;
1361         int n;
1362         QString textline;
1363         int line=midline;
1364
1365 //      midline=cursor.y;
1366 debug("Midline: %i",midline);
1367
1368         textline=kWriteDoc->contents.at(midline)->getString();
1369
1370 debug(textline);
1371
1372         counter=textline.contains("{")-textline.contains("}");
1373
1374 debug("First Counter: %i",counter);
1375
1376         while (counter<1) {
1377                 line--;
1378                 if (line==0) break;
1379                 textline=kWriteDoc->contents.at(line)->getString();
1380                 counter+=textline.contains("{")-textline.contains("}");
1381                 debug("Line in first while: %i",line);
1382         }
1383
1384         debug("Counter: %i at %i",counter,line);
1385         line++;
1386
1387         while   (counter != 0) {
1388                 textline=kWriteDoc->contents.at(line)->getString();
1389                 counter+=textline.contains("{")-textline.contains("}");
1390                 line++;
1391         }
1392         debug("Range is: %i to %i",midline, line );
1393
1394         for (n=midline;n<=line;n++) {
1395                 kWriteDoc->contents.at(n)->setVisible(false);
1396         }
1397
1398         return line;
1399 }
1400
1401 KWrite::KWrite(KWriteDoc *doc, QWidget *parent, const char *name)
1402   : QWidget(parent, name) {
1403   stepLine = -1;  // dbg
1404   kWriteDoc = doc;
1405   kWriteView = new KWriteView(this,doc);
1406
1407   configFlags = 0;
1408   wrapAt = 78;
1409   searchFlags = 0;
1410   replacePrompt = 0L;
1411
1412   kWriteView->setFocus();
1413 }
1414
1415 KWrite::~KWrite() {
1416   delete kWriteView;
1417 }
1418
1419
1420 int KWrite::currentLine() {
1421   return kWriteView->cursor.y;
1422 }
1423
1424 int KWrite::currentColumn() {
1425   return kWriteDoc->currentColumn(kWriteView->cursor);
1426 }
1427
1428 void KWrite::setCursorPosition(int line, int col) {
1429   PointStruc cursor;
1430
1431   cursor.x = col;
1432   cursor.y = line;
1433   kWriteView->updateCursor(cursor);
1434   kWriteDoc->unmarkFound();
1435   kWriteView->updateView(ufPos, 0, line*kWriteDoc->fontHeight - height()/2);
1436   kWriteDoc->updateViews(kWriteView); //update all other views except this one
1437 }
1438
1439 int KWrite::config() {
1440   return configFlags;
1441 }
1442
1443 void KWrite::setConfig(int flags) {
1444   if (flags != configFlags) {
1445     configFlags = flags;
1446     emit newStatus();
1447   }
1448 }
1449
1450 bool KWrite::isModified() {
1451   return kWriteDoc->modified;//isModified();
1452 }
1453
1454 void KWrite::setModified(bool m) {
1455   kWriteDoc->setModified(m);
1456 }
1457
1458 bool KWrite::isLastView() {
1459   return kWriteDoc->isLastView(1);
1460 }
1461
1462 KWriteDoc *KWrite::doc() {
1463   return kWriteDoc;
1464 }
1465
1466 int KWrite::undoState() {
1467   return kWriteDoc->undoState;
1468 }
1469
1470 void KWrite::copySettings(KWrite *w) {
1471   configFlags = w->configFlags;
1472   wrapAt = w->wrapAt;
1473   searchFlags = w->searchFlags;
1474 }
1475
1476 void KWrite::optDlg() {
1477   SettingsDialog *dlg;
1478
1479   dlg = new SettingsDialog(configFlags,wrapAt,kWriteDoc->tabChars,kWriteDoc->undoSteps,
1480                             topLevelWidget());
1481   if (dlg->exec() == QDialog::Accepted)
1482   {
1483     bool showTabsChanged = (dlg->getFlags() & cfShowTabs) != (configFlags & cfShowTabs);
1484     setConfig(dlg->getFlags() | (configFlags & cfOvr));
1485     wrapAt = dlg->getWrapAt();
1486     kWriteDoc->setTabWidth(dlg->getTabWidth());
1487     kWriteDoc->setUndoSteps(dlg->getUndoSteps());
1488     if (showTabsChanged)
1489       kWriteView->tagAll();
1490     kWriteDoc->updateViews();
1491   }
1492   delete dlg;
1493 }
1494
1495 void KWrite::colDlg() {
1496   ColorDialog *dlg;
1497
1498   dlg = new ColorDialog(kWriteDoc->colors,topLevelWidget());
1499   if (dlg->exec() == QDialog::Accepted) {
1500     dlg->getColors(kWriteDoc->colors);
1501     kWriteDoc->tagAll();
1502     kWriteDoc->updateViews();
1503   }
1504   delete dlg;
1505 }
1506
1507 void KWrite::toggleVertical() {
1508   setConfig(configFlags ^ cfVerticalSelect);
1509   emit statusMsg(configFlags & cfVerticalSelect ? i18n("Vertical Selections On") : i18n("Vertical Selections Off"));
1510 }
1511
1512 void KWrite::toggleOverwrite() {
1513   setConfig(configFlags ^ cfOvr);
1514 }
1515
1516 QCString KWrite::text() {
1517   return kWriteDoc->text();
1518 }
1519
1520 QString KWrite::markedText() {
1521   return kWriteDoc->markedText(configFlags);
1522 }
1523
1524 QString KWrite::currentWord() {
1525   return kWriteDoc->getWord(kWriteView->cursor);
1526 }
1527
1528 QString KWrite::word(int x, int y) {
1529   PointStruc cursor;
1530   cursor.y = (kWriteView->yPos + y)/kWriteDoc->fontHeight;
1531   if (cursor.y < 0 || cursor.y > kWriteDoc->lastLine()) return QString();
1532   cursor.x = kWriteDoc->textPos(kWriteDoc->textLine(cursor.y), kWriteView->xPos-2 + x);
1533   return kWriteDoc->getWord(cursor);
1534 }
1535
1536 void KWrite::setText(const char *s) {
1537   kWriteDoc->setText(s);
1538 }
1539
1540
1541 void KWrite::loadFile(QIODevice &dev, bool insert) {
1542   VConfig c;
1543
1544   if (!insert) {
1545     kWriteDoc->loadFile(dev);
1546   } else {
1547     kWriteView->getVConfig(c);
1548     kWriteDoc->insertFile(kWriteView,c,dev);
1549     kWriteDoc->updateViews();
1550   }
1551 }
1552
1553 void KWrite::writeFile(QIODevice &dev) {
1554   kWriteDoc->writeFile(dev);
1555   kWriteDoc->updateViews();
1556 }
1557
1558
1559 bool KWrite::loadFile(const QString& name, int flags) {
1560   QFileInfo info(name);
1561   if (!info.exists()) {
1562     if (flags & lfNewFile)
1563       return true;
1564     KMessageBox::sorry(this, i18n("The specified File does not exist"));
1565     return false;
1566   }
1567   if (info.isDir()) {
1568     KMessageBox::sorry(this, i18n("You have specified a directory"));
1569     return false;
1570   }
1571   if (!info.isReadable()) {
1572     KMessageBox::sorry(this, i18n("You do not have read permission to this file:\n" + name));
1573     return false;
1574   }
1575
1576   QFile f(name);
1577   if (f.open(IO_ReadOnly)) {
1578     loadFile(f,flags & lfInsert);
1579     f.close();
1580     return true;
1581   }
1582   KMessageBox::sorry(this, i18n("An Error occured while trying to open this Document"));
1583   return false;
1584 }
1585
1586 bool KWrite::writeFile(const QString& name) {
1587
1588   QFileInfo info(name);
1589   if(info.exists() && !info.isWritable()) {
1590     KMessageBox::sorry(this, i18n("You do not have write permission to this file:\n" + name));
1591     return false;
1592   }
1593
1594   QFile f(name);
1595   if (f.open(IO_WriteOnly | IO_Truncate)) {
1596     writeFile(f);
1597     f.close();
1598     return true;//kWriteDoc->setFileName(name);
1599   }
1600   KMessageBox::sorry(this,  i18n("An Error occured while trying to open this Document"));
1601   return false;
1602 }
1603
1604
1605 void KWrite::loadURL(const KURL& url, int flags)
1606 {
1607   if (url.isMalformed())
1608   {
1609     KMessageBox::sorry(this, i18n("Malformed URL\n")+url.prettyURL());
1610     return;
1611   }
1612
1613   if (url.isLocalFile())
1614   {
1615     emit statusMsg(i18n("Loading..."));
1616
1617     QString name(url.path());
1618     if (loadFile(name,flags)) {
1619       name = url.url();
1620       if (flags & lfInsert)
1621       {
1622         name.prepend(i18n("Inserted: "));
1623       }
1624       else
1625       {
1626         if (!(flags & lfNoAutoHl))
1627           kWriteDoc->setFileName(name);
1628         else
1629           kWriteDoc->updateLines();
1630         name.prepend(i18n("Read: "));
1631       }
1632       emit statusMsg(name);
1633     }
1634   }
1635 }
1636
1637
1638 void KWrite::writeURL(const KURL& url, int flags)
1639 {
1640   if (url.isLocalFile())
1641   {
1642     emit statusMsg(i18n("Saving..."));
1643
1644     QString name(url.path());
1645     if (writeFile(name))
1646     {
1647       if (!(flags & lfNoAutoHl))
1648         kWriteDoc->setFileName(url.url());
1649       name.prepend(i18n("Wrote: "));
1650       emit statusMsg(name);
1651       setModified(false);
1652     }
1653   }
1654 }
1655
1656 void KWrite::kfmFinished() {
1657   if (kfmAction == GET ) {
1658
1659     if (loadFile(kfmFile,kfmFlags)) {
1660       if (kfmFlags & lfInsert) {
1661         kfmURL.prepend(": ");
1662         kfmURL.prepend(i18n("Inserted"));
1663       } else {
1664         if (!(kfmFlags & lfNoAutoHl)) {
1665           kWriteDoc->setFileName(kfmURL);
1666         } else {
1667           kWriteDoc->updateLines();
1668           kWriteDoc->updateViews();
1669         }
1670         kfmURL.prepend(": ");
1671         kfmURL.prepend(i18n("Read"));
1672       }
1673       emit statusMsg(kfmURL);
1674     }
1675     //clean up
1676     unlink(kfmFile);
1677   }
1678   if (kfmAction == PUT) {
1679     if (!(kfmFlags & lfNoAutoHl)) kWriteDoc->setFileName(kfmURL);
1680     kfmURL.prepend(": ");
1681     kfmURL.prepend(i18n("Wrote"));
1682     emit statusMsg(kfmURL);
1683     setModified(false);
1684     //clean up
1685     unlink(kfmFile);
1686   }
1687 }
1688
1689 void KWrite::kfmError(int e, const char *s) {
1690   printf("error %d = %s\n",e,s);
1691 }
1692
1693
1694 bool KWrite::hasFileName() {
1695   return kWriteDoc->hasFileName();
1696 }
1697
1698 const char *KWrite::fileName() {
1699   return kWriteDoc->fileName();
1700 }
1701
1702 void KWrite::setFileName(const QString& s) {
1703   kWriteDoc->setFileName(s);
1704 }
1705
1706 bool KWrite::canDiscard() {
1707   int query;
1708
1709   if (isModified()) {
1710     query = KMessageBox::questionYesNo(this,
1711       i18n("The current Document has been modified.\nWould you like to save it?"),
1712       i18n("Warning"));
1713
1714     switch (query)
1715     {
1716       case KMessageBox::Yes:
1717       {
1718         save();
1719         if (isModified())
1720         {
1721           query = KMessageBox::questionYesNo(this,
1722             i18n("Could not save the document.\nOpen a new document anyways?"),
1723             i18n("Sorry"));
1724           if (query == KMessageBox::No)
1725             return false; //no
1726         }
1727         break;
1728       }
1729
1730       default:
1731         return false;
1732     }
1733   }
1734   return true;
1735 }
1736
1737 void KWrite::newDoc() {
1738
1739   if (canDiscard())
1740     clear();
1741 }
1742
1743 void KWrite::open() {
1744   KURL url;
1745
1746   if (!canDiscard()) return;
1747
1748   url = KFileDialog::getOpenURL(kWriteDoc->fileName(),"*");
1749   if (url.isEmpty())
1750     return;
1751
1752   loadURL(url);
1753 }
1754
1755 void KWrite::insertFile() {
1756   KURL url;
1757
1758   url = KFileDialog::getOpenURL(kWriteDoc->fileName(),"*");
1759   if (url.isEmpty())
1760     return;
1761
1762   loadURL(url, lfInsert);
1763 }
1764
1765 void KWrite::save() {
1766   if (isModified()) {
1767     if (kWriteDoc->hasFileName()) {
1768       writeURL(kWriteDoc->fileName(),lfNoAutoHl);
1769     } else saveAs();
1770   } else emit statusMsg(i18n("No changes need to be saved"));
1771 }
1772
1773 void KWrite::saveAs() {
1774   KURL url;
1775   int query;
1776
1777   do {
1778     query = 0;
1779     url = KFileDialog::getSaveURL(kWriteDoc->fileName(),"*");
1780     if (url.isEmpty())
1781       return;
1782
1783     KURL u(url);
1784     if (u.isLocalFile()) {
1785       QFileInfo info;
1786       QString name(u.path());
1787       info.setFile(name);
1788       if (info.exists())
1789       {
1790         query = KMessageBox::questionYesNo(this,
1791           i18n("A Document with this Name already exists.\nDo you want to overwrite it?"),
1792           i18n("Warning"));
1793       }
1794     }
1795   } while (query == KMessageBox::Yes);
1796
1797   writeURL(url);
1798 }
1799
1800 void KWrite::clear() {
1801         // Write bookmarks, breakpoints, ...
1802         kWriteDoc->writeFileConfig();
1803
1804   kWriteDoc->clear();
1805   kWriteDoc->clearFileName();
1806   kWriteDoc->updateViews();
1807 }
1808
1809 void KWrite::cut() {
1810   VConfig c;
1811   kWriteView->getVConfig(c);
1812   kWriteDoc->cut(kWriteView,c);
1813   kWriteDoc->updateViews();
1814 }
1815
1816 void KWrite::copy() {
1817   kWriteDoc->copy(configFlags);
1818 }
1819
1820 void KWrite::paste() {
1821   VConfig c;
1822   kWriteView->getVConfig(c);
1823   kWriteDoc->paste(kWriteView,c);
1824   kWriteDoc->updateViews();
1825 }
1826
1827 void KWrite::undo() {
1828   kWriteDoc->undo(kWriteView,configFlags);
1829   kWriteDoc->updateViews();
1830 }
1831
1832 void KWrite::redo() {
1833   kWriteDoc->redo(kWriteView,configFlags);
1834   kWriteDoc->updateViews();
1835 }
1836
1837 void KWrite::indent() {
1838   VConfig c;
1839   kWriteView->getVConfig(c);
1840   kWriteDoc->indent(kWriteView,c);
1841   kWriteDoc->updateViews();
1842 }
1843
1844 void KWrite::unIndent() {
1845   VConfig c;
1846   kWriteView->getVConfig(c);
1847   kWriteDoc->unIndent(kWriteView,c);
1848   kWriteDoc->updateViews();
1849 }
1850
1851 void KWrite::comment() {
1852   VConfig c;
1853   kWriteView->getVConfig(c);
1854   kWriteDoc->comment(kWriteView,c);
1855   kWriteDoc->updateViews();
1856 }
1857
1858 void KWrite::unComment() {
1859   VConfig c;
1860   kWriteView->getVConfig(c);
1861   kWriteDoc->unComment(kWriteView,c);
1862   kWriteDoc->updateViews();
1863 }
1864
1865 void KWrite::selectAll() {
1866   kWriteDoc->selectAll();
1867   kWriteDoc->updateViews();
1868 }
1869
1870 void KWrite::deselectAll() {
1871   kWriteDoc->deselectAll();
1872   kWriteDoc->updateViews();
1873 }
1874
1875 void KWrite::invertSelection() {
1876   kWriteDoc->invertSelection();
1877   kWriteDoc->updateViews();
1878 }
1879
1880 void addToStrList(QStrList &list, const char *str) {
1881   if (list.find(str) != -1) list.remove();
1882   if (list.count() >= 16) list.removeLast();
1883   list.insert(0, str);
1884 }
1885
1886 void KWrite::search() {
1887   SearchDialog *searchDialog;
1888
1889   searchDialog = new SearchDialog(&searchForList, 0L,
1890     searchFlags & ~sfReplace,topLevelWidget());
1891
1892   // If the user has marked some text we use that otherwise
1893   // use the word under the cursor.
1894   QString str;
1895   if (kWriteDoc && kWriteDoc->hasMarkedText())
1896     str = markedText();
1897   if (str.isEmpty())
1898     str = currentWord();
1899
1900   if (!str.isEmpty()) {
1901     str.replace(QRegExp("^\n"), "");
1902     int pos=str.find("\n");
1903     if (pos>-1)
1904      str=str.left(pos);
1905     searchDialog->setSearchText( str );
1906   }
1907
1908   kWriteView->focusOutEvent(0L);// QT bug ?
1909   if (searchDialog->exec() == QDialog::Accepted) {
1910     addToStrList(searchForList, searchDialog->getSearchFor());
1911     searchFlags = searchDialog->getFlags() | (searchFlags & sfPrompt);
1912     initSearch(s, searchFlags);
1913     searchAgain(s);
1914   }
1915   delete searchDialog;
1916 }
1917
1918 void KWrite::replace() {
1919   SearchDialog *searchDialog;
1920
1921   searchDialog = new SearchDialog(&searchForList, &replaceWithList,
1922     searchFlags | sfReplace,topLevelWidget());
1923   if ( kWriteDoc->hasMarkedText() ) {
1924     QString str = markedText();
1925     str.replace(QRegExp("^\n"), "");
1926     int pos=str.find("\n");
1927     if (pos>-1)
1928      str=str.left(pos);
1929     searchDialog->setSearchText( str );
1930   }
1931
1932   kWriteView->focusOutEvent(0L);// QT bug ?
1933   if (searchDialog->exec() == QDialog::Accepted) {
1934     addToStrList(searchForList, searchDialog->getSearchFor());
1935     addToStrList(replaceWithList, searchDialog->getReplaceWith());
1936     searchFlags = searchDialog->getFlags();
1937     initSearch(s, searchFlags);
1938     replaceAgain();
1939   }
1940   delete searchDialog;
1941 }
1942
1943 void KWrite::searchAgain(bool back) {
1944   bool b= (searchFlags & sfBackward) > 0;
1945   initSearch(s, (searchFlags & ((b==back)?~sfBackward:~0))  // clear flag for forward searching
1946                 | sfFromCursor | sfPrompt | sfAgain | ((b!=back)?sfBackward:0) );
1947   if (s.flags & sfReplace) replaceAgain(); else searchAgain(s);
1948 }
1949
1950 void KWrite::gotoLine() {
1951   GotoLineDialog *dlg;
1952
1953   dlg = new GotoLineDialog(kWriteView->cursor.y + 1,this);
1954   if (dlg->exec() == QDialog::Accepted) {
1955                 gotoPos(0, dlg->getLine() - 1);
1956   }
1957   delete dlg;
1958 }
1959
1960 void KWrite::gotoPos(int cursorXPos, int cursorYPos)
1961 {
1962   PointStruc cursor;
1963   cursor.x = cursorXPos;
1964   cursor.y = cursorYPos;
1965
1966   kWriteView->updateCursor(cursor);
1967   kWriteDoc->unmarkFound();
1968   kWriteView->updateView(ufUpdateOnScroll);
1969   kWriteDoc->updateViews(kWriteView); //uptade all other views except this one
1970 }
1971
1972 void KWrite::initSearch(SConfig &s, int flags) {
1973  const char *searchFor = searchForList.getFirst();
1974   s.flags = flags;
1975   if (s.flags & sfFromCursor) {
1976     s.cursor = kWriteView->cursor;
1977     TextLine *textLine= kWriteDoc->textLine(s.cursor.y);
1978     const char *line = textLine->getText();
1979     int (*cmpfct)(const char *, const char *, unsigned int);
1980     if ( s.flags & sfCaseSensitive )
1981       cmpfct= strncmp;
1982     else
1983       cmpfct= strnicmp;
1984     if ( s.flags & sfBackward )
1985     {
1986       if ( static_cast<int>(s.cursor.x)-static_cast<int>(strlen(searchFor)) >= 0 )
1987         if ( cmpfct(line+s.cursor.x-strlen(searchFor), searchFor, strlen(searchFor)) == 0 )
1988           s.cursor.x-= strlen(searchFor);
1989     }
1990     else 
1991     {
1992       if ( cmpfct(line+s.cursor.x, searchFor, strlen(searchFor)) == 0 )
1993         s.cursor.x+= strlen(searchFor);
1994     }
1995   } else {
1996     if (!(s.flags & sfBackward)) {
1997       s.cursor.x = 0;
1998       s.cursor.y = 0;
1999     } else {
2000       s.cursor.x = -1;
2001       s.cursor.y = kWriteDoc->lastLine();
2002     }
2003     s.flags |= sfFinished;
2004   }
2005   if (!(s.flags & sfBackward)) {
2006     if (!(s.cursor.x || s.cursor.y)) s.flags |= sfFinished;
2007   } else {
2008     s.startCursor.x -= strlen(searchFor);//.length();
2009   }
2010   s.startCursor = s.cursor;
2011 }
2012
2013 void KWrite::continueSearch(SConfig &s) {
2014
2015   if (!(s.flags & sfBackward)) {
2016     s.cursor.x = 0;
2017     s.cursor.y = 0;
2018   } else {
2019     s.cursor.x = -1;
2020     s.cursor.y = kWriteDoc->lastLine();
2021   }
2022   s.flags |= sfFinished;
2023   s.flags &= ~sfAgain;
2024 }
2025
2026 void KWrite::searchAgain(SConfig &s) {
2027   int query;
2028   PointStruc cursor;
2029   int slen;
2030   QString str;
2031
2032  const char *searchFor = searchForList.getFirst();
2033
2034   slen = strlen(searchFor);//.length();
2035   do {
2036     query = 1;
2037     if (kWriteDoc->doSearch(s,searchFor)) {
2038       cursor = s.cursor;
2039       if (!(s.flags & sfBackward)) s.cursor.x += slen;
2040       kWriteView->updateCursor(s.cursor);
2041       exposeFound(cursor,slen,(s.flags & sfAgain) ? 0 : ufUpdateOnScroll,false);
2042     } else {
2043       if (!(s.flags & sfFinished)) {
2044         // ask for continue
2045         if (!(s.flags & sfBackward)) {
2046           // forward search
2047           str.sprintf("%s.\n%s?",
2048             i18n("End of document reached").data(),
2049             i18n("Continue from the beginning").data());
2050           query = QMessageBox::information(this,
2051             i18n("Find"),
2052             str,
2053             i18n("Yes"),
2054             i18n("No"),
2055             "",0,1);
2056         } else {
2057           // backward search
2058           str.sprintf("%s.\n%s?",
2059             i18n("Beginning of document reached").data(),
2060             i18n("Continue from the end").data());
2061           query = QMessageBox::information(this,
2062             i18n("Find"),
2063             str,
2064             i18n("Yes"),
2065             i18n("No"),
2066             "",0,1);
2067         }
2068         continueSearch(s);
2069       } else {
2070         // wrapped
2071         QMessageBox::information(this,
2072           i18n("Find"),
2073           i18n("Search string not found!"),
2074           i18n("OK"),
2075           "",
2076           "",0,0);
2077       }
2078     }
2079   } while (query == 0);
2080 }
2081
2082 void KWrite::replaceAgain() {
2083
2084   replaces = 0;
2085   if (s.flags & sfPrompt) {
2086     doReplaceAction(-1);
2087   } else {
2088     doReplaceAction(srAll);
2089   }
2090 }
2091
2092 void KWrite::doReplaceAction(int result, bool found) {
2093   int slen, rlen;
2094   PointStruc cursor;
2095   bool started;
2096
2097   const char *searchFor = searchForList.getFirst();
2098   const char *replaceWith = replaceWithList.getFirst();
2099   slen = strlen(searchFor);//.length();
2100   rlen = strlen(replaceWith);//replaceWith.length();
2101
2102   switch (result) {
2103     case srYes: //yes
2104       kWriteDoc->recordStart(s.cursor,true);
2105       kWriteDoc->recordReplace(s.cursor,slen,replaceWith,rlen);
2106       replaces++;
2107       if (s.cursor.y == s.startCursor.y && s.cursor.x < s.startCursor.x)
2108         s.startCursor.x += rlen - slen;
2109       if (!(s.flags & sfBackward)) s.cursor.x += rlen;
2110       kWriteDoc->recordEnd(kWriteView,s.cursor,configFlags);
2111       break;
2112     case srNo: //no
2113       if (!(s.flags & sfBackward)) s.cursor.x += slen;
2114       break;
2115     case srAll: //replace all
2116 //      deleteReplacePrompt();
2117       do {
2118         started = false;
2119         while (found || kWriteDoc->doSearch(s,searchFor)) {
2120           if (!started) {
2121             found = false;
2122             kWriteDoc->recordStart(s.cursor);
2123             started = true;
2124           }
2125           kWriteDoc->recordReplace(s.cursor,slen,replaceWith,rlen);
2126           replaces++;
2127           if (s.cursor.y == s.startCursor.y && s.cursor.x < s.startCursor.x)
2128             s.startCursor.x += rlen - slen;
2129           if (!(s.flags & sfBackward)) s.cursor.x += rlen;
2130         }
2131         if (started) kWriteDoc->recordEnd(kWriteView,s.cursor,configFlags);
2132       } while (!askReplaceEnd());
2133       return;
2134     case srCancel: //cancel
2135       deleteReplacePrompt();
2136       return;
2137     default:
2138       replacePrompt = 0L;
2139   }
2140
2141   do {
2142     if (kWriteDoc->doSearch(s,searchFor)) {
2143       cursor = s.cursor;
2144       if (!(s.flags & sfBackward)) cursor.x += slen;
2145       kWriteView->updateCursor(cursor);
2146       exposeFound(s.cursor,slen,(s.flags & sfAgain) ? 0 : ufUpdateOnScroll,true);
2147       if (!replacePrompt) {
2148         replacePrompt = new ReplacePrompt(this);
2149         XSetTransientForHint(qt_xdisplay(),replacePrompt->winId(),topLevelWidget()->winId());
2150         kWriteDoc->setPseudoModal(replacePrompt);//disable();
2151         connect(replacePrompt,SIGNAL(clicked()),this,SLOT(replaceSlot()));
2152         replacePrompt->show();
2153       }
2154       return;
2155     }
2156   } while (!askReplaceEnd());
2157   deleteReplacePrompt();
2158 }
2159
2160 void KWrite::exposeFound(PointStruc &cursor, int slen, int flags, bool replace) {
2161   TextLine *textLine;
2162   int x1, x2, y1, y2, xPos, yPos;
2163
2164   kWriteDoc->markFound(cursor,slen);
2165
2166   textLine = kWriteDoc->textLine(cursor.y);
2167   x1 = kWriteDoc->textWidth(textLine,cursor.x)        -10;
2168   x2 = kWriteDoc->textWidth(textLine,cursor.x + slen) +20;
2169   y1 = kWriteDoc->fontHeight*cursor.y                 -10;
2170   y2 = y1 + kWriteDoc->fontHeight                     +30;
2171
2172   xPos = kWriteView->xPos;
2173   yPos = kWriteView->yPos;
2174
2175
2176   if (x1 < 0) x1 = 0;
2177   if (replace) y2 += 90;
2178
2179   if (x1 < xPos || x2 > xPos + kWriteView->width()) {
2180     xPos = x2 - kWriteView->width();
2181   }
2182   if (y1 < yPos || y2 > yPos + kWriteView->height()) {
2183     xPos = x2 - kWriteView->width();
2184     yPos = kWriteDoc->fontHeight*cursor.y - height()/3;
2185   }
2186
2187         if(xPos < 0) xPos = 0;
2188
2189   kWriteView->updateView(flags | ufPos,xPos,yPos);
2190   kWriteDoc->updateViews(kWriteView);
2191 }
2192
2193 void KWrite::deleteReplacePrompt() {
2194   kWriteDoc->setPseudoModal(0L);
2195 }
2196
2197 bool KWrite::askReplaceEnd() {
2198   QString str;
2199   int query;
2200
2201   kWriteDoc->updateViews();
2202   if (s.flags & sfFinished) {
2203     // replace finished
2204     str.sprintf("%d %s.",
2205       replaces,
2206       (i18n("replace(s) made")).data());
2207     QMessageBox::information(this,
2208       i18n("Replace"),
2209       str,
2210       i18n("OK"),
2211       "",
2212       "",0,0);
2213     return true;
2214   }
2215
2216   // ask for continue
2217   if (!(s.flags & sfBackward)) {
2218     // forward search
2219     str.sprintf("%d %s.\n%s.\n%s?",
2220       replaces,
2221       i18n("replace(s) made").data(),
2222       i18n("End of document reached").data(),
2223       i18n("Continue from the beginning").data());
2224     query = QMessageBox::information(this,
2225       i18n("Replace"),
2226       str,
2227       i18n("Yes"),
2228       i18n("No"),
2229       "",0,1);
2230   } else {
2231     // backward search
2232     str.sprintf("%d %s.\n%s.\n%s?",
2233       replaces,
2234       i18n("replace(s) made").data(),
2235       i18n("Beginning of document reached").data(),
2236       i18n("Continue from the end").data());
2237     query = QMessageBox::information(this,
2238       i18n("Replace"),
2239       str,
2240       i18n("Yes"),
2241       i18n("No"),
2242       "",0,1);
2243   }
2244   replaces = 0;
2245   continueSearch(s);
2246   return query;
2247 }
2248
2249 void KWrite::replaceSlot() {
2250   doReplaceAction(replacePrompt->result(),true);
2251 }
2252
2253 void KWrite::installBMPopup(QPopupMenu *p/*KWBookPopup *p*/)
2254 {
2255   debug("KWrite::installBMPopup");
2256
2257   connect(p,SIGNAL(aboutToShow()),SLOT(updateBMPopup()));
2258   connect(p,SIGNAL(activated(int)),SLOT(gotoBookmark(int)));
2259 }
2260
2261 void KWrite::toggleBookmark()
2262 {
2263         toggleBookmark(kWriteView->cursor.y);
2264 }
2265
2266 void KWrite::toggleBookmark(int line)
2267 {
2268         TextLine* textline = kWriteDoc->textLine(line);
2269         if(textline != NULL) textline->toggleBookmark();
2270
2271   kWriteDoc->tagLines(line, line);
2272   kWriteDoc->updateViews();
2273 }
2274
2275 void KWrite::nextBookmark()
2276 {
2277   int startLine = kWriteView->cursor.y;
2278         int lineCount = kWriteDoc->lastLine();
2279         int line = startLine;
2280         int normalizedLine;
2281         do
2282         {
2283                 line++;
2284                 normalizedLine = line % lineCount;
2285         }
2286         while(normalizedLine != startLine && !bookmarked(normalizedLine));
2287
2288         if(normalizedLine != startLine) gotoPos(0, normalizedLine);
2289 }
2290
2291 void KWrite::previousBookmark()
2292 {
2293   int startLine = kWriteView->cursor.y;
2294         int lineCount = kWriteDoc->lastLine();
2295         int line = startLine + lineCount;
2296         int normalizedLine;
2297         do
2298         {
2299                 line--;
2300                 normalizedLine = line % lineCount;
2301         }
2302         while(normalizedLine != startLine && !bookmarked(normalizedLine));
2303                 
2304         if(normalizedLine != startLine) gotoPos(0, normalizedLine);
2305 }
2306
2307 bool KWrite::bookmarked(int line)
2308 {
2309         TextLine* textline = kWriteDoc->textLine(line);
2310         if(textline != NULL) return (textline->isBookmarked());
2311
2312         return false;
2313 }
2314
2315 void KWrite::gotoBookmark(int n)
2316 {
2317   int currentBookmark = 1;
2318   if(n >= 1)
2319     {
2320       for(int line = 0; line < kWriteDoc->getTextLineCount(); line++)
2321         {
2322           TextLine* textline = kWriteDoc->textLine(line);
2323           if(textline != NULL)
2324             {
2325               if(textline->isBookmarked())
2326                 {
2327                   if(n == currentBookmark)
2328                     {
2329                       gotoPos(0, line);
2330                       return;
2331                     }
2332                   else
2333                     {
2334                       currentBookmark++;
2335                     }
2336                 }
2337             }
2338         }
2339     }
2340 }
2341
2342 void KWrite::clearBookmarks()
2343 {
2344   kWriteDoc->clearBookmarks();
2345 }
2346
2347 void KWrite::updateBMPopup() 
2348 {
2349   QPopupMenu* popup = (QPopupMenu *) sender();
2350
2351   while ((int) popup->count() > 0) {
2352     popup->removeItemAt(popup->count() - 1);
2353   }
2354
2355   popup->insertSeparator();
2356   
2357   for(int line = 0; line < kWriteDoc->getTextLineCount(); line++)
2358     {
2359       TextLine* textline = kWriteDoc->textLine(line);
2360       if(textline != NULL)
2361         if(textline->isBookmarked())
2362           {
2363             char buf[64];
2364             sprintf(buf,"%s %d",i18n("Line").data(), line + 1);
2365             int z = popup->count();
2366             popup->insertItem(buf,z);
2367             if (z < 9) popup->setAccel(ALT+kw_bookmark_keys[z],z);              
2368           }
2369     }
2370 }
2371
2372
2373 void KWrite::readConfig(KConfig *config) {
2374
2375   searchFlags = config->readNumEntry("SearchFlags",sfPrompt);
2376   configFlags = config->readNumEntry("ConfigFlags",
2377     cfPersistent | cfRemoveSpaces) & ~cfMark;
2378   wrapAt = config->readNumEntry("WrapAt",78);
2379 }
2380
2381 void KWrite::writeConfig(KConfig *config) {
2382
2383   config->writeEntry("SearchFlags",searchFlags);
2384   config->writeEntry("ConfigFlags",configFlags);
2385   config->writeEntry("WrapAt",wrapAt);
2386 }
2387
2388 void KWrite::readSessionConfig(KConfig *config) {
2389   PointStruc cursor;
2390   QString s2;
2391
2392   readConfig(config);
2393
2394   kWriteView->xPos = config->readNumEntry("XPos");
2395   kWriteView->yPos = config->readNumEntry("YPos");
2396   cursor.x = config->readNumEntry("CursorX");
2397   cursor.y = config->readNumEntry("CursorY");
2398   kWriteView->updateCursor(cursor);
2399 }
2400
2401 void KWrite::writeSessionConfig(KConfig *config) {
2402   writeConfig(config);
2403
2404   config->writeEntry("XPos",kWriteView->xPos);
2405   config->writeEntry("YPos",kWriteView->yPos);
2406   config->writeEntry("CursorX",kWriteView->cursor.x);
2407   config->writeEntry("CursorY",kWriteView->cursor.y);
2408 }
2409
2410 void KWrite::hlDef() {
2411   DefaultsDialog *dlg;
2412   HlManager *hlManager;
2413   ItemStyleList defaultStyleList;
2414   ItemFont defaultFont;
2415
2416   hlManager = kWriteDoc->hlManager;
2417   defaultStyleList.setAutoDelete(true);
2418
2419   hlManager->getDefaults(defaultStyleList,defaultFont);
2420   dlg = new DefaultsDialog(hlManager,&defaultStyleList,&defaultFont,topLevelWidget());
2421   if (dlg->exec() == QDialog::Accepted) {
2422     hlManager->setDefaults(defaultStyleList,defaultFont);
2423   }
2424   delete dlg;
2425 }
2426
2427
2428 void KWrite::hlDlg() {
2429   HighlightDialog *dlg;
2430   HlManager *hlManager;
2431   HlDataList hlDataList;
2432
2433   hlManager = kWriteDoc->hlManager;
2434   hlDataList.setAutoDelete(true);
2435   hlManager->getHlDataList(hlDataList);
2436   dlg = new HighlightDialog(hlManager,&hlDataList,kWriteDoc->getHighlight(),topLevelWidget());
2437   if (dlg->exec() == QDialog::Accepted) {
2438     hlManager->setHlDataList(hlDataList);
2439   }
2440   delete dlg;
2441 }
2442
2443 int KWrite::getHl() {
2444   return kWriteDoc->getHighlight();
2445 }
2446
2447 void KWrite::setHl(int n) {
2448   kWriteDoc->setPreHighlight(n);
2449   kWriteDoc->updateViews();
2450 }
2451
2452 int KWrite::getEol() {
2453   return kWriteDoc->eolMode;
2454 }
2455
2456 void KWrite::setEol(int eol) {
2457   kWriteDoc->eolMode = eol;
2458   kWriteDoc->setModified(true);
2459 }
2460
2461 void KWrite::print() {
2462   int fontHeight;
2463   int lines, pages;
2464   int line, c, p, l, y;
2465   QPrinter prt;
2466
2467   if (prt.setup()) {
2468     QPaintDeviceMetrics pdm(&prt);
2469     QPainter paint;
2470
2471     paint.begin(&prt);
2472     fontHeight = kWriteDoc->fontHeight;
2473     lines = pdm.height()/fontHeight;
2474     pages = (kWriteDoc->lastLine() +1)/lines;
2475     for (c = 1; c <= prt.numCopies(); c++) {
2476       line = 0;
2477       for (p = 0; p <= pages; p++) {
2478         y = 0;
2479         if (prt.pageOrder() == QPrinter::LastPageFirst) line = (pages - p)*lines;
2480         for (l = 0; l < lines; l++) {
2481           kWriteDoc->printTextLine(paint, line, pdm.width(), y);
2482           line++;
2483           y += fontHeight;
2484         }
2485         if (p < pages || c < prt.numCopies()) {
2486           if (!prt.newPage()) goto abort;
2487         }
2488       }
2489     }
2490     abort:
2491     paint.end();
2492   }
2493 }
2494
2495 void KWrite::keyPressEvent(QKeyEvent *e) {
2496   int z;
2497
2498   if (e->state() & AltButton) {
2499     for (z = 0; z < 9; z++) {
2500       if (kw_bookmark_keys[z] == e->key()) gotoBookmark(z);
2501     }
2502   }
2503 }
2504
2505 void KWrite::paintEvent(QPaintEvent *e) {
2506   int x, y;
2507
2508   QRect updateR = e->rect();                    // update rectangle
2509
2510   int ux1 = updateR.x();
2511   int uy1 = updateR.y();
2512   int ux2 = ux1 + updateR.width();
2513   int uy2 = uy1 + updateR.height();
2514
2515   QPainter paint;
2516   paint.begin(this);
2517
2518   QColorGroup g = colorGroup();
2519   x = width();
2520   y = height();
2521
2522   paint.setPen(g.dark());
2523   if (uy1 <= 0) paint.drawLine(0,0,x-2,0);
2524   if (ux1 <= 0) paint.drawLine(0,1,0,y-2);
2525
2526   paint.setPen(black);
2527   if (uy1 <= 1) paint.drawLine(1,1,x-3,1);
2528   if (ux1 <= 1) paint.drawLine(1,2,1,y-3);
2529
2530   paint.setPen(g.midlight());
2531   if (uy2 >= y-1) paint.drawLine(1,y-2,x-3,y-2);
2532   if (ux2 >= x-1) paint.drawLine(x-2,1,x-2,y-2);
2533
2534   paint.setPen(g.light());
2535   if (uy2 >= y) paint.drawLine(0,y-1,x-2,y-1);
2536   if (ux2 >= x) paint.drawLine(x-1,0,x-1,y-1);
2537
2538   x -= 2 + 16;
2539   y -= 2 + 16;
2540   if (ux2 > x && uy2 > y) {
2541     paint.fillRect(x,y,16,16,g.background());
2542   }
2543   paint.end();
2544 }
2545
2546 void KWrite::resizeEvent(QResizeEvent *) {
2547
2548 //  printf("Resize %d, %d\n",e->size().width(),e->size().height());
2549
2550   kWriteView->tagAll();//updateState = 3;
2551   kWriteView->updateView(0/*ufNoScroll*/);
2552 }
2553
2554 void KWrite::setBreakpoint( int line, int id, bool enabled, bool pending )
2555 {
2556   TextLine *tx = kWriteDoc->textLine( line );
2557   if ( tx == 0L )
2558     return;
2559   tx->setBPId( id, enabled, pending );
2560   kWriteDoc->tagLines( line, line );
2561   kWriteDoc->updateViews();
2562 }
2563
2564 void KWrite::delBreakpoint( int line )
2565 {
2566   TextLine *tx = kWriteDoc->textLine( line );
2567   if ( tx == 0L )
2568     return;
2569   tx->delBPId();
2570   kWriteDoc->tagLines( line, line );
2571   kWriteDoc->updateViews();
2572 }
2573
2574 void KWrite::setStepLine( int line )
2575 {
2576   PointStruc cursor;
2577   cursor.x = 0;
2578   cursor.y = line;
2579   stepLine = line;
2580
2581   kWriteView->updateCursor(cursor);
2582   kWriteDoc->unmarkFound();
2583   kWriteDoc->tagLines( line, line );
2584   kWriteDoc->updateViews();
2585 }
2586
2587 void KWrite::clearStepLine()
2588 {
2589   kWriteDoc->tagLines( stepLine, stepLine );
2590   stepLine = -1;
2591   kWriteDoc->updateViews();
2592 }
2593
2594 void KWrite::slotToggleBreakpoint()
2595 {
2596   emit toggleBreakpoint(QString(kWriteDoc->fileName()), currentLine()+1);
2597 }
2598
2599 void KWrite::pasteStr(QString s)
2600 {
2601   VConfig c;
2602   kWriteView->getVConfig(c);
2603   kWriteDoc->insert(kWriteView,c,s);
2604   kWriteDoc->updateViews();
2605 }
2606
2607 void KWrite::delMarkedText()
2608 {
2609   VConfig c;
2610   kWriteView->getVConfig(c);
2611   kWriteDoc->delMarkedText(kWriteView,c);
2612   kWriteDoc->updateViews();
2613 }
2614
2615 #include "kwview.moc"