OSDN Git Service

remove unused code.
[kita/kita.git] / kita / src / htmlpart.cpp
1 /***************************************************************************
2 *   Copyright (C) 2004 by Kita Developers                                 *
3 *   ikemo@users.sourceforge.jp                                            *
4 *                                                                         *
5 *   This program is free software; you can redistribute it and/or modify  *
6 *   it under the terms of the GNU General Public License as published by  *
7 *   the Free Software Foundation; either version 2 of the License, or     *
8 *   (at your option) any later version.                                   *
9 ***************************************************************************/
10
11 #include <kpopupmenu.h>
12 #include <klocale.h>
13 #include <khtml_events.h>
14 #include <kdebug.h>
15 #include <krun.h>
16
17 #include <dom/html_element.h>
18 #include <dom/html_misc.h>
19
20 #include <qcursor.h>
21 #include <qapplication.h>
22 #include <qclipboard.h>
23 #include <qmessagebox.h>
24 #include <qregexp.h>
25
26 #include "htmlpart.h"
27 #include "domtree.h"
28 #include "respopup.h"
29 #include "viewmediator.h"
30
31 #include "kitaui/htmlview.h"
32
33 #include "libkita/kitaconfig.h"
34 #include "libkita/datmanager.h"
35 #include "libkita/boardmanager.h"
36 #include "libkita/datinfo.h"
37 #include "libkita/kita_misc.h"
38 #include "libkita/signalcollection.h"
39 #include "libkita/config_xt.h"
40 #include "libkita/abone.h"
41
42 /*-------------------------------------------*/
43
44
45 /*-------------------------------------*/
46 /* Don't forget to call setup() later. */
47
48 KitaHTMLPart::KitaHTMLPart( QWidget* parent, const char* name )
49         : KHTMLPart( new KitaHTMLView( this, parent, name ) )
50 {
51     m_mode = HTMLPART_MODE_MAINPART;
52     m_popup = NULL;
53     m_domtree = NULL;
54     m_datURL = QString::null;
55     m_updatedKokoyon = FALSE;
56
57     clearPart();
58     createHTMLDocument();
59     connectSignals();
60 }
61
62
63 KitaHTMLPart::~KitaHTMLPart()
64 {
65     clearPart();
66 }
67
68
69 /* private */
70 void KitaHTMLPart::clearPart()
71 {
72     slotDeletePopup();
73
74     /* delete KitaDomTree */
75     if ( m_domtree ) delete m_domtree;
76     m_domtree = NULL;
77
78     /* update ViewPos */
79     if ( m_mode == HTMLPART_MODE_MAINPART && !m_updatedKokoyon && !m_datURL.isEmpty() ) {
80         int readNum = Kita::DatManager::getReadNum( m_datURL );
81         if ( readNum ) {
82             Kita::DatManager::setViewPos( m_datURL, readNum );
83         }
84     }
85     m_updatedKokoyon = FALSE;
86
87     /* clear variables */
88     m_anchorStack.clear();
89     m_centerNum = 0;
90     m_jumpNumAfterLoading = 0;
91     findTextInit();
92
93     if ( !m_datURL.isEmpty() ) {  /* This part is opened. */
94
95         /* don't forget to unlock previous datURL here. */
96         Kita::DatManager::unlock( m_datURL );
97
98         if ( m_mode == HTMLPART_MODE_MAINPART ) { /* This part is on the main thread view. */
99
100             /* tell Thread class that "thread is closed" */
101             Kita::DatManager::setMainThreadOpened( m_datURL, FALSE );
102
103             /* emit "deactivated all thread view" SIGNAL */
104             ViewMediator::getInstance()->changeWriteTab( QString::null );
105
106             /*  update subject tab. */
107         }
108     }
109
110     m_datURL = QString::null;
111     m_mode = HTMLPART_MODE_MAINPART;
112 }
113
114
115
116 /* public */
117 bool KitaHTMLPart::setup( int mode, const KURL& url )
118 {
119     Q_ASSERT( !url.isEmpty() );
120
121     clearPart();
122
123     m_datURL = Kita::getDatURL( url );
124     m_mode = mode;
125
126     if ( m_mode == HTMLPART_MODE_MAINPART ) { /* This part is on the main thread view. */
127
128         /* create DatInfo explicitly to open new thread.   */
129         /* Usually, DatInfo is NOT created if ReadNum == 0.*/
130         /* See also DatManager::createDatInfo() and        */
131         /*          DatManager::getDatInfo().              */
132         Kita::DatManager::createDatInfo( m_datURL );
133
134         /* tell Thread class that "thread is opend" */
135         Kita::DatManager::setMainThreadOpened( m_datURL, TRUE );
136
137         /* reset abone */
138         Kita::DatManager::resetAbone( m_datURL );
139     }
140
141     /* Lock datURL. Don't forget to unlock it later ! */
142     Kita::DatManager::lock ( m_datURL );
143
144     /* create HTML Document */
145     createHTMLDocument();
146
147     /* create DOM manager */
148     if ( m_mode == HTMLPART_MODE_MAINPART ) {
149         m_domtree = new KitaDomTree( htmlDocument(), m_datURL );
150     }
151
152     return TRUE;
153 }
154
155
156 /* private */
157 void KitaHTMLPart::connectSignals()
158 {
159     Kita::SignalCollection * signalCollection = Kita::SignalCollection::getInstance();
160
161     /* popup */
162     connect( this, SIGNAL( onURL( const QString& ) ), SLOT( slotOnURL( const QString& ) ) );
163
164     connect( view(), SIGNAL( leave() ), SLOT( slotLeave() ) );
165     connect( view(), SIGNAL( verticalSliderReleased() ), SLOT( slotVSliderReleased() ) );
166     connect( view(), SIGNAL( horizontalSliderReleased() ), SLOT( slotHSliderReleased() ) );
167
168     connect( signalCollection, SIGNAL( windowDeactivated() ), SLOT( slotHideChildPopup() ) );
169 }
170
171
172
173 /* private */
174 void KitaHTMLPart::createHTMLDocument()
175 {
176     /* style */
177     QString style = QString( "body { font-size: %1pt; font-family: \"%2\"; color: %3; background-color: %4; }" )
178                     .arg( Kita::Config::threadFont().pointSize() )
179                     .arg( Kita::Config::threadFont().family() )
180                     .arg( Kita::Config::threadColor().name() )
181                     .arg( Kita::Config::threadBackground().name() );
182
183     QString text = "<html><head><style>";
184     text += KitaConfig::defaultStyleSheetText();
185     text += style;
186     if ( Kita::Config::useStyleSheet() ) {
187         text += KitaConfig::styleSheetText();
188     }
189     text += "</style></head><body></body></html>";
190
191     setJScriptEnabled( FALSE );
192     setJavaEnabled( FALSE );
193
194     /* Use dummy URL here, and protocol should be "file:".
195        If protocol is "http:", local image files are not shown
196        (for security reasons ?).
197      */
198     begin( "file:/dummy.htm" );
199     write( text );
200     end();
201 }
202
203 /*---------------------------------------------------------------*/
204 /*---------------------------------------------------------------*/
205 /* direct rendering functions */
206
207 /**
208  * show responses.
209  * @warning don't forget to call updateScreen() later.
210  */
211 void KitaHTMLPart::showResponses( int startnum, int endnum )
212 {
213     if ( !m_domtree ) return ;
214
215     for ( int i = startnum ; i <= endnum; i++ ) m_domtree->appendRes( i );
216 }
217
218
219 /* do parsing only.            */
220 /* call showResponses() later  */ /* public */
221 void KitaHTMLPart::parseResponses( int startnum, int endnum )
222 {
223     if ( !m_domtree ) return ;
224
225     for ( int i = startnum ; i <= endnum; i++ ) m_domtree->createResElement( i );
226 }
227
228
229 /*------------------------------------------------*/
230 /* Show all responses ,header, footer, and etc,
231    if these are not shown.                        */
232
233 /* note that updateScreen() is called internally. */
234 /* So, you need not call it later.                */  /* public slot */
235 void KitaHTMLPart::showAll()
236 {
237     if ( !m_domtree ) return ;
238
239     int bottom = m_domtree->getBottomResNumber();
240     int readNum = Kita::DatManager::getReadNum( m_datURL );
241     if ( bottom != readNum ) {
242
243         QCursor qc; qc.setShape( Qt::WaitCursor );
244         QApplication::setOverrideCursor( qc );
245
246         showResponses( 1, readNum );
247         updateScreen( TRUE, FALSE );
248
249         QApplication::restoreOverrideCursor();
250     }
251 }
252
253 /*
254  * update screen
255  */
256 void KitaHTMLPart::updateScreen( bool showHeaderEtc, bool clock )
257 {
258     if ( !m_domtree ) {
259         view()->setFocus();
260         return ;
261     }
262
263     /* show clock cursor */
264     if ( clock ) {
265         QCursor qc; qc.setShape( Qt::WaitCursor );
266         QApplication::setOverrideCursor( qc );
267     }
268
269     /* show header, footer, and kokomadeyonda, etc. */
270     if ( showHeaderEtc ) {
271         m_domtree->appendKokoyon();
272         m_domtree->appendFooterAndHeader();
273     }
274
275     /* change color of number of the res which is responsed. */
276     if ( m_mode == HTMLPART_MODE_MAINPART ) {
277
278         if ( Kita::Config::checkResponsed() ) {
279             m_domtree->changeColorOfAllResponsedNumber();
280         }
281     }
282
283     /* update display */
284     htmlDocument().applyChanges();
285     view()->layout();
286     view()->setVScrollBarMode( QScrollView::AlwaysOn );
287     view()->setFocus();
288
289     /* restore cursor */
290     if ( clock ) {
291         QApplication::restoreOverrideCursor();
292     }
293 }
294
295
296 /* public */
297 void KitaHTMLPart::setInnerHTML( const QString& innerHTML )
298 {
299     createHTMLDocument();
300     htmlDocument().body().setInnerHTML( innerHTML );
301 }
302
303
304
305 /* redraw screen  */
306 /* These slots are connected to signalCollection.  */ /* public slot */
307 void KitaHTMLPart::redrawHTMLPart( const KURL& datURL, bool force )
308 {
309     if ( m_domtree == NULL ) return ;
310     if ( m_datURL != datURL ) return ;
311
312     m_domtree->redraw( force );
313 }
314
315 /* public slot */
316 void KitaHTMLPart::slotSetFaceOfHTMLPart()
317 {
318     QFont font = Kita::Config::threadFont();
319
320     DOM::CSSStyleDeclaration style = htmlDocument().body().style();
321     style.setProperty( "font-family", font.family(), "" );
322     style.setProperty( "font-size", QString( "%1pt" ).arg( font.pointSize() ), "" );
323     style.setProperty( "color", Kita::Config::threadColor().name(), "" );
324     style.setProperty( "background-color", Kita::Config::threadBackground().name(), "" );
325     htmlDocument().applyChanges();
326 }
327
328 /*---------------------------------------------------------------*/
329 /*---------------------------------------------------------------*/
330 /* cache functions */
331
332
333 /*----------------------------------*/
334 /* load thread from cache & show it */ /* public */
335
336 /*  top = centerNum - preShowNum
337     bottom = centerNum + afterShowNum
338     readNum = Kita::DatManager::getReadNum
339  
340     No.1 <- show -> No.20 <- not show -> No.(top) <- show -> No.(bottom) <- not show -> No.(readNum) */
341
342 bool KitaHTMLPart::load( int centerNum )
343 {
344     m_centerNum = centerNum;
345     m_jumpNumAfterLoading = 0;
346
347     if ( m_mode != HTMLPART_MODE_MAINPART ) return FALSE;
348     if ( !m_domtree ) return FALSE;
349     if ( Kita::DatManager::getReadNum( m_datURL ) == 0 ) return FALSE;
350
351     int endNum = Kita::DatManager::getReadNum( m_datURL );
352     showResponses( 1, endNum );
353     updateScreen( TRUE , FALSE );
354     gotoAnchor( QString().setNum( m_centerNum ), FALSE );
355     view() ->setFocus();
356
357     return TRUE;
358 }
359
360
361
362 /*----------------------------*/
363 /* start reloading            */
364
365 /* see also slotReceiveData()
366    and slotFinishLoad().      */ /* public */
367 bool KitaHTMLPart::reload( int jumpNum )
368 {
369     if ( !m_domtree ) return FALSE;
370     if ( m_mode != HTMLPART_MODE_MAINPART ) {
371         /* If this is not MainPart, then open MainPart.  */
372         ViewMediator::getInstance()->openURL( m_datURL );
373         return FALSE;
374     }
375
376     m_firstReceive = TRUE;
377     if ( m_centerNum == 0 ) m_centerNum = m_domtree->getBottomResNumber();
378     m_jumpNumAfterLoading = jumpNum;
379
380     /* DatManager will call back slotReceiveData and slotFinishLoad. */
381     Kita::DatManager::updateCache( m_datURL , this );
382     view() ->setFocus();
383
384     return TRUE;
385 }
386
387
388
389 /*---------------------------------------------*/
390 /* This slot is called after Kita::DatManager
391    received new data, and emits receiveData()  */ /* !!! "public" slot !!! */
392 void KitaHTMLPart::slotReceiveData()
393 {
394     const int delta = 20;
395
396     if ( m_mode != HTMLPART_MODE_MAINPART ) return ;
397     if ( !m_domtree ) return ;
398
399     int readNum = Kita::DatManager::getReadNum( m_datURL );
400     int bottom = m_domtree->getBottomResNumber();
401
402     /* parsing */
403     parseResponses( bottom + 1, readNum );
404
405     /* rendering */
406     if ( m_firstReceive || bottom + delta < readNum ) {
407         showResponses( bottom + 1, readNum );
408         updateScreen( TRUE, FALSE );
409     }
410
411     if ( m_firstReceive && m_centerNum < readNum ) {
412         gotoAnchor( QString().setNum( m_centerNum ), FALSE );
413         m_firstReceive = FALSE;
414     }
415
416     emit receiveData();
417 }
418
419
420 /*--------------------------------------------*/
421 /* This slot is called after Kita::DatManager
422    finished updating new data,
423    and emits finishReload()                   */ /* !!! "public" slot !!! */
424 void KitaHTMLPart::slotFinishLoad()
425 {
426     if ( m_mode != HTMLPART_MODE_MAINPART ) return ;
427     if ( !m_domtree ) return ;
428
429     int bottom = m_domtree->getBottomResNumber();
430     int shownNum = m_centerNum + 5000;
431
432     showResponses( bottom + 1, shownNum );
433     updateScreen( TRUE, FALSE );
434     //    m_domtree->parseAllRes();
435     m_centerNum = 0;
436
437     if ( m_jumpNumAfterLoading ) gotoAnchor( QString().setNum( m_jumpNumAfterLoading ), FALSE );
438     m_jumpNumAfterLoading = 0;
439
440     emit finishReload();
441 }
442
443
444
445
446 /*---------------------------------------------------------------*/
447 /*---------------------------------------------------------------*/
448 /* goto anchor */
449
450
451 /* public */
452 bool KitaHTMLPart::gotoAnchor( const QString& anc, bool pushPosition )
453 {
454     if ( anc == QString::null ) return FALSE;
455     if ( !m_domtree || m_mode == HTMLPART_MODE_POPUP )
456         return KHTMLPart::gotoAnchor( anc );
457
458     hidePopup();
459
460     QString ancstr = anc;
461     int res = ancstr.toInt();
462
463     if ( res > 1 ) {
464
465         /* is target valid ? */
466         if ( !Kita::DatManager::isResValid( m_datURL, res ) ) return FALSE;
467
468         ancstr = QString().setNum( res );
469     }
470
471     if ( res == 1 ) ancstr = "header";
472     if ( pushPosition ) pushCurrentPosition();
473
474     /* KHTMLPart::gotoAnchor() will fail if the thread is not shown. */
475     /* So KHTMLPart::gotoAnchor() should be called via custom event. */
476     /* See also KitaHTMLPart::customEvent() */
477     GotoAnchorEvent * e = new GotoAnchorEvent( ancstr );
478     QApplication::postEvent( this, e );  // Qt will delete it when done
479
480     return TRUE;
481 }
482
483
484
485 /* jump to kokomade yonda */ /* public slot */
486 void KitaHTMLPart::slotGotoKokoyon()
487 {
488     if ( !m_domtree ) return ;
489     if ( m_mode != HTMLPART_MODE_MAINPART ) return ;
490
491     int kokoyon = Kita::DatManager::getViewPos( m_datURL );
492     gotoAnchor( QString().setNum( kokoyon ), FALSE );
493 }
494
495
496
497 /* public slot  */
498 void KitaHTMLPart::slotGobackAnchor()
499 {
500     if ( m_anchorStack.empty() ) return ;
501
502     QString anc = m_anchorStack.last();
503     m_anchorStack.pop_back();
504     gotoAnchor( anc , FALSE );
505 }
506
507
508
509
510 /* private */
511 void KitaHTMLPart::pushCurrentPosition()
512 {
513     m_anchorStack += getCurrentIDofNode();
514 }
515
516
517 /* find the id of current node */ /* private */
518 QString KitaHTMLPart::getCurrentIDofNode()
519 {
520     DOM::Node node;
521     node = nodeUnderMouse();
522     while ( node != NULL && node.nodeName().string() != "div" ) node = node.parentNode();
523     if ( node == NULL ) return QString::null;
524
525     return static_cast<DOM::Element>( node ).getAttribute( "id" ).string();
526 }
527
528 /* public slot */
529 void KitaHTMLPart::slotClickGotoFooter()
530 {
531     if ( !m_domtree || m_mode != HTMLPART_MODE_MAINPART ) {
532         gotoAnchor( "footer", FALSE );
533         return ;
534     }
535
536     int bottom = m_domtree->getBottomResNumber();
537     int readNum = Kita::DatManager::getReadNum( m_datURL );
538
539     if ( readNum != bottom ) {
540         showResponses( bottom + 1, readNum );
541         updateScreen( TRUE, TRUE );
542     }
543
544     gotoAnchor( "footer", FALSE );
545 }
546
547
548 /*---------------------------------------------------------------*/
549 /*---------------------------------------------------------------*/
550 /* search */
551
552
553 /* private */
554 void KitaHTMLPart::findTextInit()
555 {
556     m_findNode = NULL;
557     m_findPos = -1;
558     m_find_y = 0;
559 }
560
561
562
563 /* public */
564 bool KitaHTMLPart::findText( const QString &query, bool reverse )
565 {
566     if ( m_mode != HTMLPART_MODE_MAINPART ) return FALSE;
567
568     QRegExp regexp( query );
569     regexp.setCaseSensitive( FALSE );
570
571     /* init */
572     if ( m_findNode.isNull() ) {
573
574         m_findNode = htmlDocument().body();
575         m_find_y = 0;
576
577         /* move to the last child node */
578         if ( reverse ) {
579             while ( !m_findNode.lastChild().isNull() ) m_findNode = m_findNode.lastChild();
580             m_find_y = view() ->contentsHeight();
581         }
582     }
583
584     while ( 1 ) {
585
586         if ( m_findNode.nodeType() == DOM::Node::TEXT_NODE
587                 || m_findNode.nodeType() == DOM::Node::CDATA_SECTION_NODE ) {
588
589             /* find the word in the current node */
590             DOM::DOMString nodeText = m_findNode.nodeValue();
591             QString nodestr = nodeText.string();
592             if ( reverse && m_findPos != -1 ) nodestr.setLength( m_findPos );
593
594             if ( reverse ) m_findPos = nodestr.findRev( regexp, m_findPos );
595             else m_findPos = nodestr.find( regexp, m_findPos + 1 );
596
597             /* scroll & select & return */
598             if ( m_findPos != -1 ) {
599                 int matchLen = regexp.matchedLength();
600
601                 QRect qr = m_findNode.getRect();
602                 view() ->setContentsPos( qr.left() - 50, m_find_y - 100 );
603                 DOM::Range rg( m_findNode, m_findPos, m_findNode, m_findPos + matchLen );
604                 setSelection( rg );
605
606                 return TRUE;
607             }
608
609         } else if ( m_findNode.nodeName().string() == "table" ) {
610
611             QRect qr = m_findNode.getRect();
612
613             m_find_y = qr.bottom();
614
615         } else if ( m_findNode.nodeName().string() == "div" ) {
616
617             QRect qr = m_findNode.getRect();
618
619             if ( reverse ) {
620                 m_find_y = qr.bottom();
621             } else {
622                 m_find_y = qr.top();
623             }
624
625         } else if ( m_findNode.nodeName().string() == "br" ) {
626
627             DOM::Node tmpnode = m_findNode.previousSibling();
628
629             if ( tmpnode != NULL ) {
630
631                 QRect qr = tmpnode.getRect();
632                 if ( reverse ) m_find_y -= qr.bottom() - qr.top();
633                 else m_find_y += qr.bottom() - qr.top();
634             }
635         }
636
637         /*------------------------*/
638
639         m_findPos = -1;
640         DOM::Node next;
641
642         /* move to the next node */
643         if ( !reverse ) {
644
645             next = m_findNode.firstChild();
646             if ( next.isNull() ) next = m_findNode.nextSibling();
647
648             while ( !m_findNode.isNull() && next.isNull() ) {
649                 m_findNode = m_findNode.parentNode();
650                 if ( !m_findNode.isNull() ) {
651                     next = m_findNode.nextSibling();
652                 }
653             }
654         }
655         /* revearse */
656         else {
657
658             next = m_findNode.lastChild();
659             if ( next.isNull() ) next = m_findNode.previousSibling();
660
661             while ( !m_findNode.isNull() && next.isNull() ) {
662                 m_findNode = m_findNode.parentNode();
663                 if ( !m_findNode.isNull() ) {
664                     next = m_findNode.previousSibling();
665                 }
666             }
667         }
668
669         m_findNode = next;
670         if ( m_findNode.isNull() ) {
671             m_findNode = NULL;
672             return FALSE;
673         }
674     }
675
676     return FALSE;
677 }
678
679
680
681
682
683
684 /*---------------------------------------------------------------*/
685 /*---------------------------------------------------------------*/
686 /* popup menu */
687
688
689 /* private */
690 void KitaHTMLPart::showPopupMenu( const KURL& kurl )
691 {
692     enum {
693         ID_Home_Link,
694         ID_Koko_Link,
695         ID_End_Link,
696
697         ID_COPY_Link,
698         ID_Copy_Str,
699         ID_Abone_Word,
700         ID_Open_Browser,
701
702         /*-----------------*/
703         ID_Back_Link /* stay bottom */
704     };
705
706     QPoint point = QCursor::pos();
707     QString url = kurl.prettyURL();
708     bool showppm = FALSE;
709     const int ID_Goto_Mark = ID_Back_Link + m_anchorStack.size();
710
711     QString str;
712
713     /* If selected Text is composed of only digits, then show res popup. */
714     if ( !m_pushctrl && showSelectedDigitPopup() ) return ;
715
716     /*-----------------------------------*/
717     /* create menu items                 */
718
719     KPopupMenu* popupMenu = new KPopupMenu( view() );
720     KPopupMenu* backSubMenu = NULL;
721     KPopupMenu* markSubMenu = NULL;
722
723     popupMenu->clear();
724
725     /*------*/
726     /* jump */
727     if ( m_domtree &&
728             ( m_mode == HTMLPART_MODE_MAINPART ) ) {
729
730         showppm = TRUE;
731
732         /* back */
733         if ( !m_anchorStack.empty() ) {
734             backSubMenu = new KPopupMenu( view() );
735             backSubMenu->clear();
736
737             int i = m_anchorStack.size();
738             QStringList::iterator it;
739             for ( it = m_anchorStack.begin(); it != m_anchorStack.end(); it++, i-- ) {
740                 str = ( *it ) + "   " + Kita::DatManager::getPlainBody( m_datURL, ( *it ).toInt() ).left( 10 );
741                 backSubMenu->insertItem( str, ID_Back_Link + ( i - 1 ), 0 );
742             }
743
744             popupMenu->insertItem( i18n( "Back" ), backSubMenu );
745             popupMenu->insertSeparator();
746         }
747
748         /* mark */
749         int readNum = Kita::DatManager::getReadNum( m_datURL );
750         for ( int i = 1; i <= readNum ; i++ ) {
751             if ( Kita::DatManager::isMarked( m_datURL, i ) ) {
752                 if ( !markSubMenu ) {
753                     markSubMenu = new KPopupMenu( view() );
754                     markSubMenu->clear();
755                     popupMenu->insertItem( i18n( "Mark" ), markSubMenu );
756                     popupMenu->insertSeparator();
757                 }
758
759                 str = QString().setNum( i ) + "   " + Kita::DatManager::getPlainBody( m_datURL, i ).left( 10 );
760                 markSubMenu->insertItem( str, ID_Goto_Mark + i );
761             }
762         }
763
764         /* home */
765         popupMenu->insertItem( i18n( "Start" ), ID_Home_Link );
766
767
768         /* template */
769         if ( m_mode == HTMLPART_MODE_MAINPART ) {
770
771             int kokoyon = Kita::DatManager::getViewPos( m_datURL );
772             if ( kokoyon ) {
773                 str = i18n( "Kokomade Yonda (%1)" ).arg( kokoyon );
774                 popupMenu->insertItem( str, ID_Koko_Link );
775             }
776         }
777
778         /* end */
779         popupMenu->insertItem( i18n( "End" ), ID_End_Link );
780     }
781
782
783     /*--------------*/
784     /* copy & abone */
785     if ( hasSelection() ) {
786         if ( showppm ) popupMenu->insertSeparator();
787         showppm = TRUE;
788
789         popupMenu->insertItem( "Copy", ID_Copy_Str );
790
791         // truncated
792         QString selectedStr = selectedText();
793         if ( selectedStr.length() > 20 ) {
794             selectedStr.truncate( 20 );
795             selectedStr.append( "..." );
796         }
797
798         popupMenu->insertItem( i18n( "Add '%1' to abone list" ).arg( selectedStr ), ID_Abone_Word );
799     }
800
801
802     /*-----------*/
803     /* copy link */
804     if ( url != QString::null ) {
805         if ( showppm ) popupMenu->insertSeparator();
806         showppm = TRUE;
807
808         popupMenu->insertItem( i18n( "Open with Web Browser" ), ID_Open_Browser );
809         popupMenu->insertSeparator();
810         popupMenu->insertItem( i18n( "Copy Link Location" ), ID_COPY_Link );
811     }
812
813
814     /*-----------------------------------*/
815
816     /* show menu */
817     if ( showppm ) {
818
819         QClipboard * clipboard = QApplication::clipboard();
820
821         int ret = popupMenu->exec( point );
822         switch ( ret ) {
823         case ID_COPY_Link:
824             clipboard->setText( url , QClipboard::Clipboard );
825             clipboard->setText( url , QClipboard::Selection );
826             break;
827
828         case ID_Open_Browser:
829             KRun::runURL( url, "text/html" );
830             break;
831
832         case ID_Home_Link: gotoAnchor( "header", FALSE ); break;
833
834         case ID_Koko_Link: slotGotoKokoyon(); break;
835
836         case ID_End_Link: slotClickGotoFooter(); break;
837
838         case ID_Copy_Str:
839             clipboard->setText( selectedText(), QClipboard::Clipboard );
840             break;
841
842         case ID_Abone_Word:
843
844             if ( QMessageBox::information( view(), "Kita",
845                                            i18n( "Do you want to add '%1' to abone list ?" ).arg( selectedText() ),
846                                            QMessageBox::Ok, QMessageBox::Cancel | QMessageBox::Default )
847                     == QMessageBox::Ok ) {
848
849                 Kita::AboneConfig::aboneWordList().append( selectedText() );
850                 redrawHTMLPart( m_datURL, FALSE );
851             }
852
853             break;
854
855         default:
856
857             /* mark */
858             if ( ret >= ID_Goto_Mark ) {
859                 gotoAnchor( QString().setNum( ret - ID_Goto_Mark ), FALSE );
860             }
861
862             /* back */
863             else if ( ret >= ID_Back_Link ) {
864                 for ( int i = 0; i < ret - ID_Back_Link; i++ ) m_anchorStack.pop_back();
865                 slotGobackAnchor();
866             }
867
868             break;
869         }
870
871     }
872
873     if ( popupMenu ) delete popupMenu;
874     if ( backSubMenu ) delete backSubMenu;
875     if ( markSubMenu ) delete markSubMenu;
876 }
877
878 /*---------------------------------------------------------------*/
879 /*---------------------------------------------------------------*/
880 /* user event */
881
882
883 /* protected */ /* virtual */
884 void KitaHTMLPart::customEvent( QCustomEvent * e )
885 {
886     if ( e->type() == EVENT_GotoAnchor ) {
887         KHTMLPart::gotoAnchor( static_cast< GotoAnchorEvent* >( e ) ->getAnc() );
888         return ;
889     }
890
891     KHTMLPart::customEvent( e );
892 }
893
894
895 /*---------------------------------------------------------------*/
896 /*---------------------------------------------------------------*/
897 /* mouse event */
898
899
900 /* protected */
901 void KitaHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent* e )
902 {
903     emit mousePressed(); /* to KitaThreadView to focus this view. */
904
905     KURL kurl;
906     if ( e->url().string() != QString::null )
907         kurl = KURL( Kita::BoardManager::boardURL( m_datURL ), e->url().string() );
908
909     m_pushctrl = m_pushmidbt = m_pushrightbt = FALSE;
910     if ( e->qmouseEvent() ->button() & Qt::RightButton ) m_pushrightbt = TRUE;
911     if ( e->qmouseEvent() ->state() & Qt::ControlButton ) m_pushctrl = TRUE;
912     if ( e->qmouseEvent() ->button() & Qt::MidButton ) m_pushmidbt = TRUE;
913
914     if ( e->url() != NULL ) {
915
916         if ( e->url().string().at( 0 ) == '#' ) { /* anchor */
917             kurl = m_datURL;
918             kurl.setRef( e->url().string().mid( 1 ) ) ;
919         }
920
921         clickAnchor( kurl );
922         m_pushctrl = m_pushmidbt = m_pushrightbt = FALSE;
923         return ;
924     }
925
926     /* popup menu */
927     if ( m_pushrightbt ) {
928         showPopupMenu( kurl );
929         m_pushctrl = m_pushmidbt = m_pushrightbt = FALSE;
930         return ;
931     }
932
933     KHTMLPart::khtmlMousePressEvent( e );
934 }
935
936
937
938
939
940 /*-------------------------------------------------------*/
941 /*-------------------------------------------------------*/
942 /* click */
943
944
945
946 /* private slot */
947 void KitaHTMLPart::slotOpenURLRequest( const KURL& urlin, const KParts::URLArgs& )
948 {
949     clickAnchor( urlin );
950 }
951
952
953 /*------------------------------------------------------*/
954 /* This function is called when user clicked res anchor */ /* private */
955 void KitaHTMLPart::clickAnchor( const KURL& urlin )
956 {
957     QString refstr;
958     KURL datURL = Kita::getDatURL( urlin , refstr );
959
960     /*--------------------*/
961     /* Ctrl + right click */
962     if ( m_pushctrl && m_pushrightbt ) {
963         showPopupMenu( urlin );
964         return ;
965     }
966
967     /*--------------------------------*/
968     /* If this is not anchor, then    */
969     /* emit openURLRequest and return */
970
971     if ( datURL.host() != m_datURL.host() || datURL.path() != m_datURL.path() ) {
972
973         /* right click */
974         if ( m_pushrightbt ) {
975
976             /* start multi-popup mode or show popup menu */
977             if ( !startMultiPopup() ) showPopupMenu( urlin );
978
979             return ;
980         }
981         /* right click */
982
983         ViewMediator::getInstance()->openURL( urlin );
984         return ;
985     }
986
987     if ( refstr == QString::null ) return ;
988
989     /*---------------------------*/
990     /* show popupmenu for #write */
991
992     if ( refstr.left( 5 ) == "write" ) {
993         showWritePopupMenu( refstr );
994         return ;
995     }
996
997     /*----------------------------*/
998     /* extract responses by ID    */
999
1000     if ( refstr.left( 5 ) == "idpop" ) {
1001         showIDPopup( refstr );
1002         return ;
1003     }
1004
1005     /*---------------------------*/
1006     /* show popupmenu for #bepop */
1007
1008     if ( refstr.left( 5 ) == "bepop" ) {
1009         showBePopupMenu( refstr );
1010         return ;
1011     }
1012
1013     /*-------------------------*/
1014     /* start multi-popup mdde  */
1015     if ( m_pushrightbt && startMultiPopup() ) return ;
1016
1017
1018     /*----------------------------*/
1019     /* next 100 ,before 100 ,etc. */
1020     if ( m_mode == HTMLPART_MODE_MAINPART ) {
1021         if ( refstr.left( 7 ) == "tosaigo" ) {
1022             slotClickGotoFooter();
1023             return;
1024         }
1025     }
1026
1027     /*-------------------------------*/
1028     /* open Kita Navi or goto anchor */
1029
1030     int refNum, refNum2;
1031
1032     int i = refstr.find( "-" );
1033     if ( i != -1 ) {
1034         refNum = refstr.left( i ).toInt();
1035         refNum2 = refstr.mid( i + 1 ).toInt();
1036         if ( refNum2 < refNum ) {
1037             refNum2 = refNum;
1038         }
1039     } else {
1040         refNum = refNum2 = refstr.toInt();
1041     }
1042
1043     if ( !refNum ) return ;
1044
1045     if ( m_mode == HTMLPART_MODE_POPUP ) {
1046         ViewMediator::getInstance()->openURL( urlin );
1047     } else {
1048         gotoAnchor( QString().setNum( refNum ), TRUE );
1049     }
1050 }
1051
1052
1053
1054 /*---------------------------------------------------------*/
1055 /* popup menu that is opened when user clicked res number. */
1056 /* This funtcion is called in only clickAnchor().          */ /* private */
1057 void KitaHTMLPart::showWritePopupMenu( const QString& refstr )
1058 {
1059     enum{
1060         WRITEMENU_RES,
1061         WRITEMENU_QUOTE,
1062         WRITEMENU_SHOWBROWSER,
1063         WRITEMENU_RESTREE,
1064         WRITEMENU_REVERSERESTREE,
1065         WRITEMENU_EXTRACTNAME,
1066         WRITEMENU_COPY,
1067         WRITEMENU_COPYURL,
1068         WRITEMENU_COPYTHREADNAME,
1069         WRITEMENU_SETKOKOYON,
1070         WRITEMENU_MARK,
1071         WRITEMENU_ABONENAME
1072     };
1073
1074     QClipboard * clipboard = QApplication::clipboard();
1075     QString str, resstr;
1076     int resNum = refstr.mid( 5 ).toInt();
1077     QString namestr = Kita::DatManager::getPlainName( m_datURL, resNum );
1078
1079     /* show res tree */
1080     if ( m_pushrightbt ) {
1081         int num;
1082         QString htmlstr = Kita::DatManager::getTreeByRes( m_datURL, resNum, num );
1083         if ( !num ) return ;
1084         QString tmpstr = QString( "<DIV>No.%1 : [%2]<BR>" ).arg( resNum ).arg( num );
1085         tmpstr += htmlstr + "<BR><BR></DIV>";
1086         showPopup( m_datURL, tmpstr );
1087         startMultiPopup();
1088         return ;
1089     }
1090
1091     /*---------------------*/
1092     /* create popup menu */
1093     QString plainStr;
1094
1095     KPopupMenu *popupMenu = new KPopupMenu( view() );
1096     popupMenu->clear();
1097
1098     /* write */
1099     if ( m_mode == HTMLPART_MODE_MAINPART ) {
1100
1101         popupMenu->insertItem( i18n( "write response" ), WRITEMENU_RES );
1102         popupMenu->insertItem( i18n( "quote this" ), WRITEMENU_QUOTE );
1103         popupMenu->insertSeparator();
1104
1105     }
1106
1107     /* mark */
1108     popupMenu->insertItem( i18n( "Mark" ), WRITEMENU_MARK );
1109     popupMenu->setItemChecked( WRITEMENU_MARK, Kita::DatManager::isMarked( m_datURL, resNum ) );
1110     popupMenu->insertSeparator();
1111
1112     /* open */
1113     popupMenu->insertItem( i18n( "Open with Web Browser" ), WRITEMENU_SHOWBROWSER );
1114     popupMenu->insertSeparator();
1115
1116     /* util */
1117     popupMenu->insertItem( i18n( "res tree" ), WRITEMENU_RESTREE );
1118     popupMenu->insertItem( i18n( "reverse res tree" ), WRITEMENU_REVERSERESTREE );
1119     popupMenu->insertItem( i18n( "extract by name" ), WRITEMENU_EXTRACTNAME );
1120     popupMenu->insertSeparator();
1121
1122     /* copy */
1123     popupMenu->insertItem( i18n( "copy URL" ), WRITEMENU_COPYURL );
1124     popupMenu->insertItem( i18n( "Copy title and URL" ), WRITEMENU_COPYTHREADNAME );
1125     popupMenu->insertItem( i18n( "copy" ), WRITEMENU_COPY );
1126
1127     /* kokkoma de yonda */
1128     if ( m_domtree && m_mode == HTMLPART_MODE_MAINPART ) {
1129         popupMenu->insertSeparator();
1130         popupMenu->insertItem( i18n( "set Kokomade Yonda" ), WRITEMENU_SETKOKOYON );
1131     }
1132
1133     /* abone */
1134     popupMenu->insertSeparator();
1135     popupMenu->insertItem( i18n( "add name to abone list" ), WRITEMENU_ABONENAME );
1136
1137
1138     /*--------------------------------------*/
1139     /* show popup menu */
1140
1141     int ret = popupMenu->exec( QCursor::pos() );
1142     delete popupMenu;
1143     switch ( ret ) {
1144
1145     case WRITEMENU_RES:
1146         resstr = ">>" + QString().setNum( resNum ) + "\n";
1147         ViewMediator::getInstance()->showWriteView( m_datURL, resstr );
1148         break;
1149
1150     case WRITEMENU_QUOTE:
1151         resstr = ">>" + QString().setNum( resNum ) + "\n"
1152                  + "> " + Kita::DatManager::getPlainTitle( m_datURL, resNum ) + "\n"
1153                  + "> " + Kita::DatManager::getPlainBody( m_datURL, resNum ).replace( "\n", "\n> " ) + "\n";
1154         ViewMediator::getInstance()->showWriteView( m_datURL, resstr );
1155         break;
1156
1157     case WRITEMENU_MARK:
1158         Kita::DatManager::setMark( m_datURL, resNum, ! Kita::DatManager::isMarked( m_datURL, resNum ) );
1159         break;
1160
1161     case WRITEMENU_COPY:
1162     case WRITEMENU_COPYURL:
1163     case WRITEMENU_COPYTHREADNAME:
1164         str = QString::null;
1165
1166         /* title */
1167         if ( ret == WRITEMENU_COPYTHREADNAME || ret == WRITEMENU_COPY ) {
1168             str = Kita::DatManager::threadName( m_datURL );
1169         }
1170
1171         /* url */
1172         if ( str != QString::null ) str += "\n";
1173         str += Kita::DatManager::threadURL( m_datURL ) + "/" + QString().setNum( resNum ) + "\n";
1174
1175         /* body */
1176         if ( ret == WRITEMENU_COPY ) {
1177             str += "\n"
1178                    + Kita::DatManager::getPlainTitle( m_datURL, resNum ) + "\n"
1179                    + Kita::DatManager::getPlainBody( m_datURL, resNum ) + "\n";
1180         }
1181
1182         /* copy */
1183         clipboard->setText( str , QClipboard::Clipboard );
1184         clipboard->setText( str , QClipboard::Selection );
1185         break;
1186
1187
1188     case WRITEMENU_SETKOKOYON:
1189         Kita::DatManager::setViewPos( m_datURL, resNum );
1190         ViewMediator::getInstance()->updateBoardView( m_datURL );
1191         m_updatedKokoyon = TRUE;
1192         updateScreen( TRUE, TRUE );
1193         gotoAnchor( QString().setNum( resNum ), FALSE );
1194         break;
1195
1196     case WRITEMENU_SHOWBROWSER:
1197         str = Kita::DatManager::threadURL( m_datURL ) + "/" + QString().setNum( resNum );
1198
1199         KRun::runURL( str, "text/html" );
1200         break;
1201
1202     case WRITEMENU_ABONENAME:
1203         if ( QMessageBox::information( view(), "Kita",
1204                                        i18n( "Do you want to add '%1' to abone list ?" ).arg( namestr ),
1205                                        QMessageBox::Ok, QMessageBox::Cancel | QMessageBox::Default )
1206                 == QMessageBox::Ok ) {
1207
1208             Kita::AboneConfig::aboneNameList().append( namestr );
1209             redrawHTMLPart( m_datURL, FALSE );
1210         }
1211         break;
1212
1213     default:
1214         break;
1215     }
1216
1217 }
1218
1219
1220
1221 /*--------------------------------------------------*/
1222 /* popup that is opened when user clicked ID        */
1223 /* This funtcion is called in only clickAnchor().   */ /* private */
1224 void KitaHTMLPart::showIDPopup( const QString& refstr )
1225 {
1226     QString strid = refstr.mid( 5 )
1227                     .replace( "%2B", "+" )
1228                     .replace( "%2F", "/" );
1229
1230     /* popup */
1231     if ( m_pushrightbt ) {
1232         int num;
1233         QString htmlstr
1234         = Kita::DatManager::getHtmlByID( m_datURL, strid, num );
1235         if ( num <= 1 ) return ;
1236         QString tmpstr = QString( "<DIV>ID:%1:[%2]<BR>" ).arg( strid ).arg( num );
1237         tmpstr += htmlstr + "<BR><BR></DIV>";
1238         showPopup( m_datURL, tmpstr );
1239         startMultiPopup();
1240     }
1241
1242     else {
1243
1244         enum{
1245             IDMENU_ABONE
1246         };
1247
1248         KPopupMenu *popupMenu = new KPopupMenu( view() );
1249         popupMenu->clear();
1250         popupMenu->insertItem( i18n( "add id to abone list" ), IDMENU_ABONE );
1251         int ret = popupMenu->exec( QCursor::pos() );
1252         delete popupMenu;
1253         switch ( ret ) {
1254
1255         case IDMENU_ABONE:
1256             /* add ID to abone list */
1257             if ( QMessageBox::information( view(), "Kita",
1258                                            i18n( "Do you want to add '%1' to abone list ?" ).arg( strid ),
1259                                            QMessageBox::Ok, QMessageBox::Cancel | QMessageBox::Default )
1260                     == QMessageBox::Ok ) {
1261
1262                 Kita::AboneConfig::aboneIDList().append( strid );
1263                 redrawHTMLPart( m_datURL, FALSE );
1264             }
1265             break;
1266
1267         default:
1268             break;
1269         }
1270     }
1271 }
1272
1273
1274
1275 /*---------------------------------------------------------*/
1276 /* popup menu that is opened when user clicked be anchor.  */
1277 /* This funtcion is called in only clickAnchor().          */ /* private */
1278 void KitaHTMLPart::showBePopupMenu( const QString& refstr )
1279 {
1280     QString strURL = "http://be.2ch.net/test/p.php?i=" + refstr.mid( 5 )
1281                     + "&u=d:" + Kita::DatManager::threadURL( m_datURL ) + "/l50";
1282
1283     if ( m_pushrightbt ) {
1284         /*---------------------*/
1285         /* create popup menu */
1286         KPopupMenu *popupMenu = new KPopupMenu( view() );
1287         popupMenu->clear();
1288
1289         enum{
1290             BEMENU_COPYURL,
1291             BEMENU_SHOWBROWSER
1292         };
1293
1294         QClipboard * clipboard = QApplication::clipboard();
1295
1296         popupMenu->insertItem( i18n( "copy URL" ), BEMENU_COPYURL );
1297         popupMenu->insertItem( i18n( "Open with Web Browser" ), BEMENU_SHOWBROWSER );
1298
1299         /*--------------------------------------*/
1300         /* show popup menu */
1301
1302         int ret = popupMenu->exec( QCursor::pos() );
1303         delete popupMenu;
1304         switch ( ret ) {
1305
1306         case BEMENU_COPYURL:
1307             /* copy */
1308             clipboard->setText( strURL, QClipboard::Clipboard );
1309             clipboard->setText( strURL, QClipboard::Selection );
1310             break;
1311
1312         case BEMENU_SHOWBROWSER:
1313             KRun::runURL( strURL, "text/html" );
1314             break;
1315
1316         default:
1317             break;
1318         }
1319     } else {
1320         KRun::runURL( strURL, "text/html" );
1321     }
1322 }
1323
1324 /*-------------------------------------------------------*/
1325 /*-------------------------------------------------------*/
1326 /* popup */
1327
1328
1329 /* public */
1330 bool KitaHTMLPart::isPopupVisible()
1331 {
1332     if ( !m_popup ) return FALSE;
1333     return m_popup->isVisible();
1334 }
1335
1336
1337 /* public slot */
1338 void KitaHTMLPart::slotDeletePopup()
1339 {
1340     if ( m_popup ) delete m_popup;
1341     m_popup = NULL;
1342     m_multiPopup = FALSE;
1343 }
1344
1345
1346 /* for convenience */ /* public slot */
1347 void KitaHTMLPart::slotShowResPopup( QPoint point, int refNum, int refNum2 )
1348 {
1349     QString innerHTML = Kita::DatManager::getHtml( m_datURL, refNum, refNum2 );
1350     if ( innerHTML == QString::null ) return ;
1351
1352     showPopupCore( m_datURL, innerHTML, point );
1353 }
1354
1355
1356 /* for convenience */ /* private */
1357 void KitaHTMLPart::showPopup( const KURL& url, const QString& innerHTML )
1358 {
1359     showPopupCore( url, innerHTML, QCursor::pos() );
1360 }
1361
1362
1363 /* show popup window   */  /* private */
1364 void KitaHTMLPart::showPopupCore( const KURL& url, const QString& innerHTML, QPoint point )
1365 {
1366     slotDeletePopup();
1367     m_multiPopup = FALSE;
1368
1369     m_popup = new Kita::ResPopup( view() , url );
1370
1371     connect( m_popup, SIGNAL( hideChildPopup() ), SLOT( slotHideChildPopup() ) );
1372
1373     m_popup->setText( innerHTML );
1374     m_popup->adjustSize();
1375     m_popup->adjustPos( point );
1376     m_popup->show();
1377 }
1378
1379
1380 /*------------------------*/
1381 /* start multi-popup mode */ /* private */
1382 bool KitaHTMLPart::startMultiPopup()
1383 {
1384
1385     if ( m_popup && m_popup->isVisible() ) {
1386         m_multiPopup = TRUE;
1387         m_popup->moveMouseAbove();
1388     } else {
1389         m_multiPopup = FALSE;
1390     }
1391
1392     return m_multiPopup;
1393 }
1394
1395
1396 /* Is it multi-popup mode now ? */ /* private */
1397 bool KitaHTMLPart::isMultiPopupMode()
1398 {
1399     if ( !m_popup ) {
1400         m_multiPopup = FALSE;
1401     } else if ( m_popup->isHidden() ) {
1402         m_multiPopup = FALSE;
1403     }
1404
1405     return m_multiPopup;
1406 }
1407
1408 /* private */
1409 void KitaHTMLPart::hidePopup()
1410 {
1411     if ( m_popup ) {
1412         m_popup->hide();
1413     }
1414     m_multiPopup = FALSE;
1415 }
1416
1417 /* return TRUE if this view is under mouse. */ /* private */
1418 bool KitaHTMLPart::isUnderMouse( int mrgwd, int mrght )
1419 {
1420     QPoint pos = QCursor::pos();
1421     int cx = pos.x(), cy = pos.y();
1422
1423     QPoint viewpos = view() ->mapToGlobal( QPoint( 0, 0 ) );
1424     int px = viewpos.x(), py = viewpos.y();
1425     int wd = view() ->visibleWidth(), ht = view() ->visibleHeight();
1426
1427     if ( ( px < cx && cx < px + wd + mrgwd )
1428             && ( py < cy && cy < py + ht + mrght ) ) {
1429         return TRUE;
1430     }
1431
1432     return FALSE;
1433 }
1434
1435 /* private slot */
1436 void KitaHTMLPart::slotLeave()
1437 {
1438     if ( isMultiPopupMode() ) return ;
1439     if ( view() ->isHorizontalSliderPressed() ) return ;
1440     if ( view() ->isVerticalSliderPressed () ) return ;
1441
1442     hidePopup();
1443
1444     /* emit signal to have parent hide this if this is popup . */
1445     if ( m_mode == HTMLPART_MODE_POPUP && !isUnderMouse( 0, 0 ) ) {
1446         emit hideChildPopup();
1447     }
1448 }
1449
1450 /* private slot */
1451 void KitaHTMLPart::slotVSliderReleased()
1452 {
1453     QScrollBar * bar = view() ->verticalScrollBar();
1454     QRect rt = bar->sliderRect();
1455     int mrg = rt.right() - rt.left();
1456
1457     hidePopup();
1458
1459     /* emit signal to have parent hide this if this is popup . */
1460     if ( m_mode == HTMLPART_MODE_POPUP && !isUnderMouse( mrg, 0 ) ) {
1461         emit hideChildPopup();
1462     }
1463 }
1464
1465
1466 /* private slot */
1467 void KitaHTMLPart::slotHSliderReleased()
1468 {
1469     QScrollBar * bar = view() ->horizontalScrollBar();
1470     QRect rt = bar->sliderRect();
1471     int mrg = rt.bottom() - rt.top();
1472
1473     hidePopup();
1474
1475     /* emit signal to have parent hide this if this is popup . */
1476     if ( m_mode == HTMLPART_MODE_POPUP && !isUnderMouse( 0, mrg ) ) {
1477         emit hideChildPopup();
1478     }
1479 }
1480
1481
1482
1483 /* private slot */
1484 void KitaHTMLPart::slotHideChildPopup()
1485 {
1486     hidePopup();
1487
1488     /* emit signal to have parent hide this if this is popup . */
1489     if ( m_mode == HTMLPART_MODE_POPUP && !isUnderMouse( 0, 0 ) ) {
1490         emit hideChildPopup();
1491     }
1492 }
1493
1494
1495 /*---------------------------------------------------*/
1496 /* This slot is called when mouse moves onto the URL */ /* private slot */
1497 void KitaHTMLPart::slotOnURL( const QString& url )
1498 {
1499     /* config */
1500
1501     const int maxpopup = 10;  /* max number of responses shown in the popup window */
1502
1503     /*----------------------------*/
1504
1505     if ( isMultiPopupMode() ) return ;
1506
1507     slotDeletePopup();
1508
1509     if ( url.isEmpty() ) return ;
1510     if ( url.left( 7 ) == "mailto:" ) return ;
1511
1512     /* Is Kita active now ? */
1513     if( ViewMediator::getInstance()->isKitaActive() == FALSE ) return;
1514
1515     /* get reference */
1516     QString refstr;
1517     KURL datURL = m_datURL;
1518     if ( url.at( 0 ) == '#' ) {
1519         refstr = url.mid( 1 );
1520     } else {
1521         datURL = Kita::getDatURL( KURL( m_datURL, url ) , refstr );
1522     }
1523
1524     /*------------------------*/
1525     /* id popup               */
1526
1527     if ( url.left( 6 ) == "#idpop" ) {
1528         int num = Kita::DatManager::getNumByID( m_datURL, url.mid( 6 ) );
1529         QString tmpstr;
1530         if ( num >= 2 ) {
1531             tmpstr = QString( "<DIV>ID:%1:[%2]</DIV>" ).arg( url.mid( 6 ) ).arg( num );
1532         } else {
1533             tmpstr = "<DIV>" + i18n( "None" ) + "</DIV>";
1534         }
1535         showPopup( m_datURL, tmpstr );
1536         return ;
1537     }
1538
1539
1540     /*------------------------*/
1541     /* show reffered num      */
1542
1543     if ( refstr.left( 5 ) == "write" ) {
1544         int no = refstr.mid( 5 ).toInt();
1545         int num = 0;
1546         Kita::DatManager::getTreeByRes( m_datURL, no, num );
1547         QString tmpstr;
1548         if ( num ) {
1549             tmpstr = QString( "<DIV>No.%1 : [%2]</DIV>" ).arg( no ).arg( num );
1550         } else {
1551             tmpstr = "<DIV>" + i18n( "None" ) + "</DIV>";
1552         }
1553         showPopup( m_datURL, tmpstr );
1554         return ;
1555     }
1556
1557
1558     /*------------------------*/
1559     /* abone                  */
1560
1561     if ( url.left( 6 ) == "#abone" ) {
1562         int no = url.mid( 6 ).toInt();
1563         QString tmpstr = Kita::DatManager::getHtml( m_datURL, no, no, FALSE );
1564         showPopup( m_datURL, tmpstr );
1565         return ;
1566     }
1567
1568     /*-------------------------*/
1569     /* popup for anchor        */
1570
1571     QString innerHTML = QString::null;
1572     int refNum;
1573     int refNum2;
1574
1575     int i = refstr.find( "-" );
1576     if ( i != -1 ) { /* >>refNum-refNum2 */
1577
1578         refNum = refstr.left( i ).toInt();
1579         refNum2 = refstr.mid( i + 1 ).toInt();
1580
1581         if ( refNum ) {
1582             if ( refNum2 < refNum ) refNum2 = refNum;
1583             if ( refNum2 - refNum > maxpopup - 1 ) refNum2 = refNum + maxpopup - 1;
1584         }
1585
1586     } else { /* >>refNum */
1587         refNum = refstr.toInt();
1588         refNum2 = refNum;
1589     }
1590
1591     /* another thread ? */
1592     if ( datURL.host() != m_datURL.host() || datURL.path() != m_datURL.path() ) {
1593
1594         /* get board name */
1595         QString boardName = Kita::BoardManager::boardName( datURL );
1596         if ( boardName != QString::null ) innerHTML += "[" + boardName + "] ";
1597
1598         /* If idx file of datURL is not read, thread name cannot be obtained.
1599            so, create DatInfo if cache exists, and read idx file in DatInfo::DatInfo(). */
1600         Kita::DatManager::getDatInfoPointer( datURL );
1601
1602         /* get thread Name */
1603         QString subName = Kita::DatManager::threadName( datURL );
1604         if ( subName != QString::null ) innerHTML += subName + "<br><br>";
1605
1606         if ( !refNum ) refNum = refNum2 = 1;
1607     }
1608
1609     /* get HTML and show it */
1610     if ( !refNum ) return ;
1611     innerHTML += Kita::DatManager::getHtml( datURL, refNum, refNum2 );
1612
1613     if ( innerHTML != QString::null ) showPopup( datURL, innerHTML );
1614 }
1615
1616
1617
1618 /* If selected Text is composed of only digits,
1619    then show res popup.                          */ /* private */
1620 bool KitaHTMLPart::showSelectedDigitPopup()
1621 {
1622     if ( !hasSelection() ) return FALSE;
1623
1624     QString linkstr;
1625     int refNum;
1626     QString selectText = selectedText();
1627     const QChar *chpt = selectText.unicode();
1628     unsigned int length = selectText.length();
1629
1630     if ( ( refNum = Kita::stringToPositiveNum( chpt, length ) ) != -1 ) {
1631         QString innerHTML = Kita::DatManager::getHtml( m_datURL, refNum, refNum );
1632         if ( innerHTML != QString::null ) {
1633             showPopup( m_datURL, innerHTML );
1634             startMultiPopup();
1635             return TRUE;
1636         }
1637     }
1638
1639     return FALSE;
1640 }