]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiView.cpp
fix crash.
[lyx.git] / src / frontends / qt4 / GuiView.cpp
1 /**
2  * \file GuiView.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author John Levon
8  * \author Abdelrazak Younes
9  * \author Peter Kümmel
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #include <config.h>
15
16 #include "GuiView.h"
17 #include "Dialog.h"
18
19 #include "GuiApplication.h"
20 #include "GuiWorkArea.h"
21 #include "GuiKeySymbol.h"
22 #include "GuiMenubar.h"
23 #include "GuiToolbar.h"
24 #include "GuiToolbars.h"
25
26 #include "qt_helpers.h"
27
28 #include "buffer_funcs.h"
29 #include "Buffer.h"
30 #include "BufferList.h"
31 #include "BufferParams.h"
32 #include "BufferView.h"
33 #include "Cursor.h"
34 #include "support/debug.h"
35 #include "ErrorList.h"
36 #include "FuncRequest.h"
37 #include "support/gettext.h"
38 #include "Intl.h"
39 #include "Layout.h"
40 #include "Lexer.h"
41 #include "LyXFunc.h"
42 #include "LyX.h"
43 #include "LyXRC.h"
44 #include "LyXVC.h"
45 #include "MenuBackend.h"
46 #include "Paragraph.h"
47 #include "TextClass.h"
48 #include "Text.h"
49 #include "ToolbarBackend.h"
50 #include "version.h"
51
52 #include "support/FileName.h"
53 #include "support/lstrings.h"
54 #include "support/os.h"
55 #include "support/Timeout.h"
56
57 #include <QAction>
58 #include <QApplication>
59 #include <QCloseEvent>
60 #include <QDebug>
61 #include <QDesktopWidget>
62 #include <QDragEnterEvent>
63 #include <QDropEvent>
64 #include <QList>
65 #include <QMenu>
66 #include <QPainter>
67 #include <QPixmap>
68 #include <QPoint>
69 #include <QPushButton>
70 #include <QSettings>
71 #include <QShowEvent>
72 #include <QSplitter>
73 #include <QStackedWidget>
74 #include <QStatusBar>
75 #include <QTimer>
76 #include <QToolBar>
77 #include <QUrl>
78
79 #include <boost/assert.hpp>
80 #include <boost/bind.hpp>
81
82 #ifdef HAVE_SYS_TIME_H
83 # include <sys/time.h>
84 #endif
85 #ifdef HAVE_UNISTD_H
86 # include <unistd.h>
87 #endif
88
89 using std::endl;
90 using std::string;
91 using std::vector;
92
93 namespace lyx {
94
95 extern bool quitting;
96
97 namespace frontend {
98
99 using support::bformat;
100 using support::FileName;
101 using support::trim;
102
103 namespace {
104
105 class BackgroundWidget : public QWidget
106 {
107 public:
108         BackgroundWidget()
109         {
110                 LYXERR(Debug::GUI, "show banner: " << lyxrc.show_banner);
111                 /// The text to be written on top of the pixmap
112                 QString const text = lyx_version ? lyx_version : qt_("unknown version");
113                 splash_ = QPixmap(":/images/banner.png");
114
115                 QPainter pain(&splash_);
116                 pain.setPen(QColor(255, 255, 0));
117                 QFont font;
118                 // The font used to display the version info
119                 font.setStyleHint(QFont::SansSerif);
120                 font.setWeight(QFont::Bold);
121                 font.setPointSize(int(toqstr(lyxrc.font_sizes[FONT_SIZE_LARGE]).toDouble()));
122                 pain.setFont(font);
123                 pain.drawText(260, 270, text);
124         }
125
126         void paintEvent(QPaintEvent *)
127         {
128                 int x = (width() - splash_.width()) / 2;
129                 int y = (height() - splash_.height()) / 2;
130                 QPainter pain(this);
131                 pain.drawPixmap(x, y, splash_);
132         }
133
134 private:
135         QPixmap splash_;
136 };
137
138 } // namespace anon
139
140
141 typedef boost::shared_ptr<Dialog> DialogPtr;
142
143 struct GuiView::GuiViewPrivate
144 {
145         GuiViewPrivate()
146                 : current_work_area_(0), layout_(0),
147                 quitting_by_menu_(false), autosave_timeout_(5000), in_show_(false)
148         {
149                 // hardcode here the platform specific icon size
150                 smallIconSize = 14;     // scaling problems
151                 normalIconSize = 20;    // ok, default
152                 bigIconSize = 26;               // better for some math icons
153
154                 splitter_ = new QSplitter;
155                 bg_widget_ = new BackgroundWidget;
156                 stack_widget_ = new QStackedWidget;
157                 stack_widget_->addWidget(bg_widget_);
158                 stack_widget_->addWidget(splitter_);
159                 setBackground();
160         }
161
162         ~GuiViewPrivate()
163         {
164                 delete splitter_;
165                 delete bg_widget_;
166                 delete stack_widget_;
167                 delete menubar_;
168                 delete toolbars_;
169         }
170
171         QMenu * toolBarPopup(GuiView * parent)
172         {
173                 // FIXME: translation
174                 QMenu * menu = new QMenu(parent);
175                 QActionGroup * iconSizeGroup = new QActionGroup(parent);
176
177                 QAction * smallIcons = new QAction(iconSizeGroup);
178                 smallIcons->setText(qt_("Small-sized icons"));
179                 smallIcons->setCheckable(true);
180                 QObject::connect(smallIcons, SIGNAL(triggered()),
181                         parent, SLOT(smallSizedIcons()));
182                 menu->addAction(smallIcons);
183
184                 QAction * normalIcons = new QAction(iconSizeGroup);
185                 normalIcons->setText(qt_("Normal-sized icons"));
186                 normalIcons->setCheckable(true);
187                 QObject::connect(normalIcons, SIGNAL(triggered()),
188                         parent, SLOT(normalSizedIcons()));
189                 menu->addAction(normalIcons);
190
191                 QAction * bigIcons = new QAction(iconSizeGroup);
192                 bigIcons->setText(qt_("Big-sized icons"));
193                 bigIcons->setCheckable(true);
194                 QObject::connect(bigIcons, SIGNAL(triggered()),
195                         parent, SLOT(bigSizedIcons()));
196                 menu->addAction(bigIcons);
197
198                 unsigned int cur = parent->iconSize().width();
199                 if ( cur == parent->d.smallIconSize)
200                         smallIcons->setChecked(true);
201                 else if (cur == parent->d.normalIconSize)
202                         normalIcons->setChecked(true);
203                 else if (cur == parent->d.bigIconSize)
204                         bigIcons->setChecked(true);
205
206                 return menu;
207         }
208
209         void setBackground()
210         {
211                 stack_widget_->setCurrentWidget(bg_widget_);
212                 bg_widget_->setUpdatesEnabled(true);
213         }
214
215         TabWorkArea * tabWorkArea(int i)
216         {
217                 return dynamic_cast<TabWorkArea *>(splitter_->widget(i));
218         }
219
220         TabWorkArea * currentTabWorkArea()
221         {
222                 if (splitter_->count() == 1)
223                         // The first TabWorkArea is always the first one, if any.
224                         return tabWorkArea(0);
225
226                 TabWorkArea * tab_widget = 0;
227                 for (int i = 0; i != splitter_->count(); ++i) {
228                         QWidget * w = splitter_->widget(i);
229                         if (!w->hasFocus())
230                                 continue;
231                         tab_widget = dynamic_cast<TabWorkArea *>(w);
232                         if (tab_widget)
233                                 break;
234                 }
235
236                 return tab_widget;
237         }
238
239 public:
240         GuiWorkArea * current_work_area_;
241         QSplitter * splitter_;
242         QStackedWidget * stack_widget_;
243         BackgroundWidget * bg_widget_;
244         /// view's menubar
245         GuiMenubar * menubar_;
246         /// view's toolbars
247         GuiToolbars * toolbars_;
248         /// The main layout box.
249         /** 
250          * \warning Don't Delete! The layout box is actually owned by
251          * whichever toolbar contains it. All the GuiView class needs is a
252          * means of accessing it.
253          *
254          * FIXME: replace that with a proper model so that we are not limited
255          * to only one dialog.
256          */
257         GuiLayoutBox * layout_;
258
259         ///
260         std::map<std::string, Inset *> open_insets_;
261
262         ///
263         std::map<std::string, DialogPtr> dialogs_;
264
265         unsigned int smallIconSize;
266         unsigned int normalIconSize;
267         unsigned int bigIconSize;
268         ///
269         QTimer statusbar_timer_;
270         /// are we quitting by the menu?
271         bool quitting_by_menu_;
272         /// auto-saving of buffers
273         Timeout autosave_timeout_;
274         /// flag against a race condition due to multiclicks, see bug #1119
275         bool in_show_;
276 };
277
278
279 GuiView::GuiView(int id)
280         : d(*new GuiViewPrivate), id_(id)
281 {
282         // GuiToolbars *must* be initialised before GuiMenubar.
283         d.toolbars_ = new GuiToolbars(*this);
284         d.menubar_ = new GuiMenubar(this, menubackend);
285
286         setCentralWidget(d.stack_widget_);
287
288         // Start autosave timer
289         if (lyxrc.autosave) {
290                 d.autosave_timeout_.timeout.connect(boost::bind(&GuiView::autoSave, this));
291                 d.autosave_timeout_.setTimeout(lyxrc.autosave * 1000);
292                 d.autosave_timeout_.start();
293         }
294         connect(&d.statusbar_timer_, SIGNAL(timeout()),
295                 this, SLOT(clearMessage()));
296
297         // Qt bug? signal lastWindowClosed does not work
298         setAttribute(Qt::WA_QuitOnClose, false);
299         setAttribute(Qt::WA_DeleteOnClose, true);
300 #ifndef Q_WS_MACX
301         // assign an icon to main form. We do not do it under Qt/Mac,
302         // since the icon is provided in the application bundle.
303         setWindowIcon(QPixmap(":/images/lyx.png"));
304 #endif
305
306         // For Drag&Drop.
307         setAcceptDrops(true);
308
309         statusBar()->setSizeGripEnabled(true);
310
311         // Forbid too small unresizable window because it can happen
312         // with some window manager under X11.
313         setMinimumSize(300, 200);
314
315         if (!lyxrc.allow_geometry_session)
316                 // No session handling, default to a sane size.
317                 setGeometry(50, 50, 690, 510);
318
319         // Now take care of session management.
320         QSettings settings;
321         QString const key = "view-" + QString::number(id_);
322 #ifdef Q_WS_X11
323         QPoint pos = settings.value(key + "/pos", QPoint(50, 50)).toPoint();
324         QSize size = settings.value(key + "/size", QSize(690, 510)).toSize();
325         resize(size);
326         move(pos);
327 #else
328         if (!restoreGeometry(settings.value(key + "/geometry").toByteArray()))
329                 setGeometry(50, 50, 690, 510);
330 #endif
331         setIconSize(settings.value(key + "/icon_size").toSize());
332 }
333
334
335 GuiView::~GuiView()
336 {
337         delete &d;
338 }
339
340
341 void GuiView::close()
342 {
343         d.quitting_by_menu_ = true;
344         d.current_work_area_ = 0;
345         for (int i = 0; i != d.splitter_->count(); ++i) {
346                 TabWorkArea * twa = d.tabWorkArea(i);
347                 if (twa)
348                         twa->closeAll();
349         }
350         QMainWindow::close();
351         d.quitting_by_menu_ = false;
352 }
353
354
355 void GuiView::setFocus()
356 {
357         if (d.current_work_area_)
358                 d.current_work_area_->setFocus();
359         else
360                 QWidget::setFocus();
361 }
362
363
364 QMenu * GuiView::createPopupMenu()
365 {
366         return d.toolBarPopup(this);
367 }
368
369
370 void GuiView::showEvent(QShowEvent * e)
371 {
372         LYXERR(Debug::GUI, "Passed Geometry "
373                 << size().height() << "x" << size().width()
374                 << "+" << pos().x() << "+" << pos().y());
375
376         if (d.splitter_->count() == 0)
377                 // No work area, switch to the background widget.
378                 d.setBackground();
379
380         QMainWindow::showEvent(e);
381 }
382
383
384 void GuiView::closeEvent(QCloseEvent * close_event)
385 {
386         // we may have been called through the close window button
387         // which bypasses the LFUN machinery.
388         if (!d.quitting_by_menu_ && guiApp->viewCount() == 1) {
389                 if (!theBufferList().quitWriteAll()) {
390                         close_event->ignore();
391                         return;
392                 }
393         }
394
395         // Make sure that no LFUN use this close to be closed View.
396         theLyXFunc().setLyXView(0);
397         // Make sure the timer time out will not trigger a statusbar update.
398         d.statusbar_timer_.stop();
399
400         if (lyxrc.allow_geometry_session) {
401                 QSettings settings;
402                 QString const key = "view-" + QString::number(id_);
403 #ifdef Q_WS_X11
404                 settings.setValue(key + "/pos", pos());
405                 settings.setValue(key + "/size", size());
406 #else
407                 settings.setValue(key + "/geometry", saveGeometry());
408 #endif
409                 settings.setValue(key + "/icon_size", iconSize());
410                 d.toolbars_->saveToolbarInfo();
411         }
412
413         guiApp->unregisterView(id_);
414         if (guiApp->viewCount() > 0) {
415                 // Just close the window and do nothing else if this is not the
416                 // last window.
417                 close_event->accept();
418                 return;
419         }
420
421         quitting = true;
422
423         // this is the place where we leave the frontend.
424         // it is the only point at which we start quitting.
425         close_event->accept();
426         // quit the event loop
427         qApp->quit();
428 }
429
430
431 void GuiView::dragEnterEvent(QDragEnterEvent * event)
432 {
433         if (event->mimeData()->hasUrls())
434                 event->accept();
435         /// \todo Ask lyx-devel is this is enough:
436         /// if (event->mimeData()->hasFormat("text/plain"))
437         ///     event->acceptProposedAction();
438 }
439
440
441 void GuiView::dropEvent(QDropEvent* event)
442 {
443         QList<QUrl> files = event->mimeData()->urls();
444         if (files.isEmpty())
445                 return;
446
447         LYXERR(Debug::GUI, "GuiView::dropEvent: got URLs!");
448         for (int i = 0; i != files.size(); ++i) {
449                 string const file = support::os::internal_path(fromqstr(
450                         files.at(i).toLocalFile()));
451                 if (!file.empty())
452                         dispatch(FuncRequest(LFUN_FILE_OPEN, file));
453         }
454 }
455
456
457 void GuiView::message(docstring const & str)
458 {
459         statusBar()->showMessage(toqstr(str));
460         d.statusbar_timer_.stop();
461         d.statusbar_timer_.start(3000);
462 }
463
464
465 void GuiView::smallSizedIcons()
466 {
467         setIconSize(QSize(d.smallIconSize, d.smallIconSize));
468 }
469
470
471 void GuiView::normalSizedIcons()
472 {
473         setIconSize(QSize(d.normalIconSize, d.normalIconSize));
474 }
475
476
477 void GuiView::bigSizedIcons()
478 {
479         setIconSize(QSize(d.bigIconSize, d.bigIconSize));
480 }
481
482
483 void GuiView::clearMessage()
484 {
485         if (!hasFocus())
486                 return;
487         theLyXFunc().setLyXView(this);
488         statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
489         d.statusbar_timer_.stop();
490 }
491
492
493 void GuiView::updateWindowTitle(GuiWorkArea * wa)
494 {
495         if (wa != d.current_work_area_)
496                 return;
497         setWindowTitle(qt_("LyX: ") + wa->windowTitle());
498         setWindowIconText(wa->windowIconText());
499 }
500
501
502 void GuiView::on_currentWorkAreaChanged(GuiWorkArea * wa)
503 {
504         disconnectBuffer();
505         disconnectBufferView();
506         connectBufferView(wa->bufferView());
507         connectBuffer(wa->bufferView().buffer());
508         d.current_work_area_ = wa;
509         QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
510                 this, SLOT(updateWindowTitle(GuiWorkArea *)));
511         updateWindowTitle(wa);
512
513         updateToc();
514         // Buffer-dependent dialogs should be updated or
515         // hidden. This should go here because some dialogs (eg ToC)
516         // require bv_->text.
517         updateBufferDependent(true);
518         updateToolbars();
519         updateLayoutList();
520         updateStatusBar();
521 }
522
523
524 void GuiView::updateStatusBar()
525 {
526         // let the user see the explicit message
527         if (d.statusbar_timer_.isActive())
528                 return;
529
530         statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
531 }
532
533
534 bool GuiView::hasFocus() const
535 {
536         return qApp->activeWindow() == this;
537 }
538
539
540 bool GuiView::event(QEvent * e)
541 {
542         switch (e->type())
543         {
544         // Useful debug code:
545         //case QEvent::ActivationChange:
546         //case QEvent::WindowDeactivate:
547         //case QEvent::Paint:
548         //case QEvent::Enter:
549         //case QEvent::Leave:
550         //case QEvent::HoverEnter:
551         //case QEvent::HoverLeave:
552         //case QEvent::HoverMove:
553         //case QEvent::StatusTip:
554         //case QEvent::DragEnter:
555         //case QEvent::DragLeave:
556         //case QEvent::Drop:
557         //      break;
558
559         case QEvent::WindowActivate: {
560                 guiApp->setCurrentView(*this);
561                 if (d.current_work_area_) {
562                         BufferView & bv = d.current_work_area_->bufferView();
563                         connectBufferView(bv);
564                         connectBuffer(bv.buffer());
565                         // The document structure, name and dialogs might have
566                         // changed in another view.
567                         updateBufferDependent(true);
568                 } else {
569                         setWindowTitle(qt_("LyX"));
570                         setWindowIconText(qt_("LyX"));
571                 }
572                 return QMainWindow::event(e);
573         }
574         case QEvent::ShortcutOverride: {
575                 QKeyEvent * ke = static_cast<QKeyEvent*>(e);
576                 if (!d.current_work_area_) {
577                         theLyXFunc().setLyXView(this);
578                         KeySymbol sym;
579                         setKeySymbol(&sym, ke);
580                         theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
581                         e->accept();
582                         return true;
583                 }
584                 if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
585                         KeySymbol sym;
586                         setKeySymbol(&sym, ke);
587                         d.current_work_area_->processKeySym(sym, NoModifier);
588                         e->accept();
589                         return true;
590                 }
591         }
592         default:
593                 return QMainWindow::event(e);
594         }
595 }
596
597
598 bool GuiView::focusNextPrevChild(bool /*next*/)
599 {
600         setFocus();
601         return true;
602 }
603
604
605 void GuiView::setBusy(bool yes)
606 {
607         if (d.current_work_area_) {
608                 d.current_work_area_->setUpdatesEnabled(!yes);
609                 if (yes)
610                         d.current_work_area_->stopBlinkingCursor();
611                 else
612                         d.current_work_area_->startBlinkingCursor();
613         }
614
615         if (yes)
616                 QApplication::setOverrideCursor(Qt::WaitCursor);
617         else
618                 QApplication::restoreOverrideCursor();
619 }
620
621
622 GuiToolbar * GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newline)
623 {
624         GuiToolbar * toolBar = new GuiToolbar(tbinfo, *this);
625
626         if (tbinfo.flags & ToolbarInfo::TOP) {
627                 if (newline)
628                         addToolBarBreak(Qt::TopToolBarArea);
629                 addToolBar(Qt::TopToolBarArea, toolBar);
630         }
631
632         if (tbinfo.flags & ToolbarInfo::BOTTOM) {
633 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
634 #if (QT_VERSION >= 0x040202)
635                 if (newline)
636                         addToolBarBreak(Qt::BottomToolBarArea);
637 #endif
638                 addToolBar(Qt::BottomToolBarArea, toolBar);
639         }
640
641         if (tbinfo.flags & ToolbarInfo::LEFT) {
642 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
643 #if (QT_VERSION >= 0x040202)
644                 if (newline)
645                         addToolBarBreak(Qt::LeftToolBarArea);
646 #endif
647                 addToolBar(Qt::LeftToolBarArea, toolBar);
648         }
649
650         if (tbinfo.flags & ToolbarInfo::RIGHT) {
651 // Qt < 4.2.2 cannot handle ToolBarBreak on non-TOP dock.
652 #if (QT_VERSION >= 0x040202)
653                 if (newline)
654                         addToolBarBreak(Qt::RightToolBarArea);
655 #endif
656                 addToolBar(Qt::RightToolBarArea, toolBar);
657         }
658
659         // The following does not work so I cannot restore to exact toolbar location
660         /*
661         ToolbarSection::ToolbarInfo & tbinfo = LyX::ref().session().toolbars().load(tbinfo.name);
662         toolBar->move(tbinfo.posx, tbinfo.posy);
663         */
664
665         return toolBar;
666 }
667
668
669 GuiWorkArea * GuiView::workArea(Buffer & buffer)
670 {
671         for (int i = 0; i != d.splitter_->count(); ++i) {
672                 GuiWorkArea * wa = d.tabWorkArea(i)->workArea(buffer);
673                 if (wa)
674                         return wa;
675         }
676         return 0;
677 }
678
679
680 GuiWorkArea * GuiView::addWorkArea(Buffer & buffer)
681 {
682
683         // Automatically create a TabWorkArea if there are none yet.
684         if (!d.splitter_->count())
685                 addTabWorkArea();
686
687         TabWorkArea * tab_widget = d.currentTabWorkArea();
688         return tab_widget->addWorkArea(buffer, *this);
689 }
690
691
692 void GuiView::addTabWorkArea()
693 {
694         TabWorkArea * twa = new TabWorkArea;
695         QObject::connect(twa, SIGNAL(currentWorkAreaChanged(GuiWorkArea *)),
696                 this, SLOT(on_currentWorkAreaChanged(GuiWorkArea *)));
697         d.splitter_->addWidget(twa);
698         d.stack_widget_->setCurrentWidget(d.splitter_);
699 }
700
701
702 GuiWorkArea const * GuiView::currentWorkArea() const
703 {
704         return d.current_work_area_;
705 }
706
707
708 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
709 {
710         BOOST_ASSERT(wa);
711
712         // Changing work area can result from opening a file so
713         // update the toc in any case.
714         updateToc();
715
716         d.current_work_area_ = wa;
717         for (int i = 0; i != d.splitter_->count(); ++i) {
718                 if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
719                         return;
720         }
721 }
722
723
724 void GuiView::removeWorkArea(GuiWorkArea * wa)
725 {
726         BOOST_ASSERT(wa);
727         if (wa == d.current_work_area_) {
728                 disconnectBuffer();
729                 disconnectBufferView();
730                 hideBufferDependent();
731                 d.current_work_area_ = 0;
732         }
733
734         for (int i = 0; i != d.splitter_->count(); ++i) {
735                 TabWorkArea * twa = d.tabWorkArea(i);
736                 if (!twa->removeWorkArea(wa))
737                         // Not found in this tab group.
738                         continue;
739
740                 // We found and removed the GuiWorkArea.
741                 if (!twa->count()) {
742                         // No more WorkAreas in this tab group, so delete it.
743                         delete twa;
744                         break;
745                 }
746
747                 if (d.current_work_area_)
748                         // This means that we are not closing the current GuiWorkArea;
749                         break;
750
751                 // Switch to the next GuiWorkArea in the found TabWorkArea.
752                 d.current_work_area_ = twa->currentWorkArea();
753                 break;
754         }
755
756         if (d.splitter_->count() == 0)
757                 // No more work area, switch to the background widget.
758                 d.setBackground();
759 }
760
761
762 void GuiView::setLayoutDialog(GuiLayoutBox * layout)
763 {
764         d.layout_ = layout;
765 }
766
767
768 void GuiView::updateLayoutList()
769 {
770         if (d.layout_)
771                 d.layout_->updateContents(false);
772 }
773
774
775 void GuiView::updateToolbars()
776 {
777         if (d.current_work_area_) {
778                 bool const math =
779                         d.current_work_area_->bufferView().cursor().inMathed();
780                 bool const table =
781                         lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
782                 bool const review =
783                         lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
784                         lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
785
786                 d.toolbars_->update(math, table, review);
787         } else
788                 d.toolbars_->update(false, false, false);
789
790         // update read-only status of open dialogs.
791         checkStatus();
792 }
793
794
795 Buffer * GuiView::buffer()
796 {
797         if (d.current_work_area_)
798                 return &d.current_work_area_->bufferView().buffer();
799         return 0;
800 }
801
802
803 Buffer const * GuiView::buffer() const
804 {
805         if (d.current_work_area_)
806                 return &d.current_work_area_->bufferView().buffer();
807         return 0;
808 }
809
810
811 void GuiView::setBuffer(Buffer * newBuffer)
812 {
813         BOOST_ASSERT(newBuffer);
814         setBusy(true);
815
816         GuiWorkArea * wa = workArea(*newBuffer);
817         if (wa == 0) {
818                 updateLabels(*newBuffer->masterBuffer());
819                 wa = addWorkArea(*newBuffer);
820         } else {
821                 //Disconnect the old buffer...there's no new one.
822                 disconnectBuffer();
823         }
824         connectBuffer(*newBuffer);
825         connectBufferView(wa->bufferView());
826         setCurrentWorkArea(wa);
827
828         setBusy(false);
829 }
830
831
832 void GuiView::connectBuffer(Buffer & buf)
833 {
834         buf.setGuiDelegate(this);
835 }
836
837
838 void GuiView::disconnectBuffer()
839 {
840         if (d.current_work_area_)
841                 d.current_work_area_->bufferView().setGuiDelegate(0);
842 }
843
844
845 void GuiView::connectBufferView(BufferView & bv)
846 {
847         bv.setGuiDelegate(this);
848 }
849
850
851 void GuiView::disconnectBufferView()
852 {
853         if (d.current_work_area_)
854                 d.current_work_area_->bufferView().setGuiDelegate(0);
855 }
856
857
858 void GuiView::errors(string const & error_type)
859 {
860         ErrorList & el = buffer()->errorList(error_type);
861         if (!el.empty())
862                 showDialog("errorlist", error_type);
863 }
864
865
866 void GuiView::updateDialog(string const & name, string const & data)
867 {
868         if (!isDialogVisible(name))
869                 return;
870
871         std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
872         if (it == d.dialogs_.end())
873                 return;
874
875         Dialog * const dialog = it->second.get();
876         if (dialog->isVisibleView())
877                 dialog->updateData(data);
878 }
879
880
881 BufferView * GuiView::view()
882 {
883         return d.current_work_area_ ? &d.current_work_area_->bufferView() : 0;
884 }
885
886
887 void GuiView::updateToc()
888 {
889         updateDialog("toc", "");
890 }
891
892
893 void GuiView::updateEmbeddedFiles()
894 {
895         updateDialog("embedding", "");
896 }
897
898
899 void GuiView::autoSave()
900 {
901         LYXERR(Debug::INFO, "Running autoSave()");
902
903         if (buffer())
904                 view()->buffer().autoSave();
905 }
906
907
908 void GuiView::resetAutosaveTimers()
909 {
910         if (lyxrc.autosave)
911                 d.autosave_timeout_.restart();
912 }
913
914
915 FuncStatus GuiView::getStatus(FuncRequest const & cmd)
916 {
917         FuncStatus flag;
918         bool enable = true;
919         Buffer * buf = buffer();
920
921         /* In LyX/Mac, when a dialog is open, the menus of the
922            application can still be accessed without giving focus to
923            the main window. In this case, we want to disable the menu
924            entries that are buffer-related.
925
926            Note that this code is not perfect, as bug 1941 attests:
927            http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
928         */
929         if (cmd.origin == FuncRequest::MENU && !hasFocus())
930                 buf = 0;
931
932         switch(cmd.action) {
933         case LFUN_TOOLBAR_TOGGLE:
934                 flag.setOnOff(d.toolbars_->visible(cmd.getArg(0)));
935                 break;
936
937         case LFUN_DIALOG_TOGGLE:
938                 flag.setOnOff(isDialogVisible(cmd.getArg(0)));
939                 // fall through to set "enable"
940         case LFUN_DIALOG_SHOW: {
941                 string const name = cmd.getArg(0);
942                 if (!buf)
943                         enable = name == "aboutlyx"
944                                 || name == "file" //FIXME: should be removed.
945                                 || name == "prefs"
946                                 || name == "texinfo";
947                 else if (name == "print")
948                         enable = buf->isExportable("dvi")
949                                 && lyxrc.print_command != "none";
950                 else if (name == "character") {
951                         if (!view())
952                                 enable = false;
953                         else {
954                                 InsetCode ic = view()->cursor().inset().lyxCode();
955                                 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
956                         }
957                 }
958                 else if (name == "latexlog")
959                         enable = FileName(buf->logName()).isReadableFile();
960                 else if (name == "spellchecker")
961 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
962                         enable = !buf->isReadonly();
963 #else
964                         enable = false;
965 #endif
966                 else if (name == "vclog")
967                         enable = buf->lyxvc().inUse();
968                 break;
969         }
970
971         case LFUN_DIALOG_UPDATE: {
972                 string const name = cmd.getArg(0);
973                 if (!buf)
974                         enable = name == "prefs";
975                 break;
976         }
977
978         case LFUN_INSET_APPLY: {
979                 if (!buf) {
980                         enable = false;
981                         break;
982                 }
983                 string const name = cmd.getArg(0);
984                 Inset * inset = getOpenInset(name);
985                 if (inset) {
986                         FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
987                         FuncStatus fs;
988                         if (!inset->getStatus(view()->cursor(), fr, fs)) {
989                                 // Every inset is supposed to handle this
990                                 BOOST_ASSERT(false);
991                         }
992                         flag |= fs;
993                 } else {
994                         FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
995                         flag |= getStatus(fr);
996                 }
997                 enable = flag.enabled();
998                 break;
999         }
1000
1001         default:
1002                 if (!view()) {
1003                         enable = false;
1004                         break;
1005                 }
1006         }
1007
1008         if (!enable)
1009                 flag.enabled(false);
1010
1011         return flag;
1012 }
1013
1014
1015 bool GuiView::dispatch(FuncRequest const & cmd)
1016 {
1017         BufferView * bv = view();       
1018         // By default we won't need any update.
1019         if (bv)
1020                 bv->cursor().updateFlags(Update::None);
1021
1022         switch(cmd.action) {
1023                 case LFUN_BUFFER_SWITCH:
1024                         setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
1025                         break;
1026
1027                 case LFUN_BUFFER_NEXT:
1028                         setBuffer(theBufferList().next(buffer()));
1029                         break;
1030
1031                 case LFUN_BUFFER_PREVIOUS:
1032                         setBuffer(theBufferList().previous(buffer()));
1033                         break;
1034
1035                 case LFUN_COMMAND_EXECUTE: {
1036                         bool const show_it = cmd.argument() != "off";
1037                         d.toolbars_->showCommandBuffer(show_it);
1038                         break;
1039                 }
1040                 case LFUN_DROP_LAYOUTS_CHOICE:
1041                         if (d.layout_)
1042                                 d.layout_->showPopup();
1043                         break;
1044
1045                 case LFUN_MENU_OPEN:
1046                         d.menubar_->openByName(toqstr(cmd.argument()));
1047                         break;
1048
1049                 case LFUN_TOOLBAR_TOGGLE: {
1050                         string const name = cmd.getArg(0);
1051                         bool const allowauto = cmd.getArg(1) == "allowauto";
1052                         // it is possible to get current toolbar status like this,...
1053                         // but I decide to obey the order of ToolbarBackend::flags
1054                         // and disregard real toolbar status.
1055                         // toolbars_->saveToolbarInfo();
1056                         //
1057                         // toggle state on/off/auto
1058                         d.toolbars_->toggleToolbarState(name, allowauto);
1059                         // update toolbar
1060                         updateToolbars();
1061
1062                         ToolbarInfo * tbi = d.toolbars_->getToolbarInfo(name);
1063                         if (!tbi) {
1064                                 message(bformat(_("Unknown toolbar \"%1$s\""), from_utf8(name)));
1065                                 break;
1066                         }
1067                         docstring state;
1068                         if (tbi->flags & ToolbarInfo::ON)
1069                                 state = _("on");
1070                         else if (tbi->flags & ToolbarInfo::OFF)
1071                                 state = _("off");
1072                         else if (tbi->flags & ToolbarInfo::AUTO)
1073                                 state = _("auto");
1074
1075                         message(bformat(_("Toolbar \"%1$s\" state set to %2$s"), 
1076                                            _(tbi->gui_name), state));
1077                         break;
1078                 }
1079
1080                 case LFUN_DIALOG_UPDATE: {
1081                         string const name = to_utf8(cmd.argument());
1082                         // Can only update a dialog connected to an existing inset
1083                         Inset * inset = getOpenInset(name);
1084                         if (inset) {
1085                                 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1086                                 inset->dispatch(view()->cursor(), fr);
1087                         } else if (name == "paragraph") {
1088                                 lyx::dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1089                         } else if (name == "prefs") {
1090                                 updateDialog(name, string());
1091                         }
1092                         break;
1093                 }
1094
1095                 case LFUN_DIALOG_TOGGLE: {
1096                         if (isDialogVisible(cmd.getArg(0)))
1097                                 dispatch(FuncRequest(LFUN_DIALOG_HIDE, cmd.argument()));
1098                         else
1099                                 dispatch(FuncRequest(LFUN_DIALOG_SHOW, cmd.argument()));
1100                         break;
1101                 }
1102
1103                 case LFUN_DIALOG_DISCONNECT_INSET:
1104                         disconnectDialog(to_utf8(cmd.argument()));
1105                         break;
1106
1107                 case LFUN_DIALOG_HIDE: {
1108                         if (quitting)
1109                                 break;
1110                         guiApp->hideDialogs(to_utf8(cmd.argument()), 0);
1111                         break;
1112                 }
1113
1114                 case LFUN_DIALOG_SHOW: {
1115                         string const name = cmd.getArg(0);
1116                         string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1117
1118                         if (name == "character") {
1119                                 data = freefont2string();
1120                                 if (!data.empty())
1121                                         showDialog("character", data);
1122                         } else if (name == "latexlog") {
1123                                 Buffer::LogType type; 
1124                                 string const logfile = buffer()->logName(&type);
1125                                 switch (type) {
1126                                 case Buffer::latexlog:
1127                                         data = "latex ";
1128                                         break;
1129                                 case Buffer::buildlog:
1130                                         data = "literate ";
1131                                         break;
1132                                 }
1133                                 data += Lexer::quoteString(logfile);
1134                                 showDialog("log", data);
1135                         } else if (name == "vclog") {
1136                                 string const data = "vc " +
1137                                         Lexer::quoteString(buffer()->lyxvc().getLogFile());
1138                                 showDialog("log", data);
1139                         } else
1140                                 showDialog(name, data);
1141                         break;
1142                 }
1143
1144                 case LFUN_INSET_APPLY: {
1145                         string const name = cmd.getArg(0);
1146                         Inset * inset = getOpenInset(name);
1147                         if (inset) {
1148                                 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
1149                                 inset->dispatch(view()->cursor(), fr);
1150                         } else {
1151                                 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
1152                                 lyx::dispatch(fr);
1153                         }
1154                         break;
1155                 }
1156
1157                 default:
1158                         return false;
1159         }
1160
1161         return true;
1162 }
1163
1164
1165 Buffer const * GuiView::updateInset(Inset const * inset)
1166 {
1167         if (!d.current_work_area_)
1168                 return 0;
1169
1170         if (inset)
1171                 d.current_work_area_->scheduleRedraw();
1172
1173         return &d.current_work_area_->bufferView().buffer();
1174 }
1175
1176
1177 void GuiView::restartCursor()
1178 {
1179         /* When we move around, or type, it's nice to be able to see
1180          * the cursor immediately after the keypress.
1181          */
1182         if (d.current_work_area_)
1183                 d.current_work_area_->startBlinkingCursor();
1184
1185         // Take this occasion to update the toobars and layout list.
1186         updateLayoutList();
1187         updateToolbars();
1188 }
1189
1190 namespace {
1191
1192 // This list should be kept in sync with the list of insets in
1193 // src/insets/Inset.cpp.  I.e., if a dialog goes with an inset, the
1194 // dialog should have the same name as the inset.
1195
1196 char const * const dialognames[] = {
1197 "aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
1198 "citation", "document", "embedding", "errorlist", "ert", "external", "file",
1199 "findreplace", "float", "graphics", "include", "index", "nomenclature", "label", "log",
1200 "mathdelimiter", "mathmatrix", "note", "paragraph",
1201 "prefs", "print", "ref", "sendto", "spellchecker","tabular", "tabularcreate",
1202
1203 #ifdef HAVE_LIBAIKSAURUS
1204 "thesaurus",
1205 #endif
1206
1207 "texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
1208
1209 char const * const * const end_dialognames =
1210         dialognames + (sizeof(dialognames) / sizeof(char *));
1211
1212 class cmpCStr {
1213 public:
1214         cmpCStr(char const * name) : name_(name) {}
1215         bool operator()(char const * other) {
1216                 return strcmp(other, name_) == 0;
1217         }
1218 private:
1219         char const * name_;
1220 };
1221
1222
1223 bool isValidName(string const & name)
1224 {
1225         return std::find_if(dialognames, end_dialognames,
1226                             cmpCStr(name.c_str())) != end_dialognames;
1227 }
1228
1229 } // namespace anon
1230
1231
1232 void GuiView::resetDialogs()
1233 {
1234         // Make sure that no LFUN uses any LyXView.
1235         theLyXFunc().setLyXView(0);
1236         d.toolbars_->init();
1237         d.menubar_->init();
1238         if (d.layout_)
1239                 d.layout_->updateContents(true);
1240         // Now update controls with current buffer.
1241         theLyXFunc().setLyXView(this);
1242         restartCursor();
1243 }
1244
1245
1246 Dialog * GuiView::find_or_build(string const & name)
1247 {
1248         if (!isValidName(name))
1249                 return 0;
1250
1251         std::map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
1252
1253         if (it != d.dialogs_.end())
1254                 return it->second.get();
1255
1256         d.dialogs_[name].reset(build(name));
1257         return d.dialogs_[name].get();
1258 }
1259
1260
1261 void GuiView::showDialog(string const & name, string const & data,
1262         Inset * inset)
1263 {
1264         if (d.in_show_)
1265                 return;
1266
1267         d.in_show_ = true;
1268         Dialog * dialog = find_or_build(name);
1269         if (dialog) {
1270                 dialog->showData(data);
1271                 if (inset)
1272                         d.open_insets_[name] = inset;
1273         }
1274         d.in_show_ = false;
1275 }
1276
1277
1278 bool GuiView::isDialogVisible(string const & name) const
1279 {
1280         std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1281         if (it == d.dialogs_.end())
1282                 return false;
1283         return it->second.get()->isVisibleView();
1284 }
1285
1286
1287 void GuiView::hideDialog(string const & name, Inset * inset)
1288 {
1289         // Don't send the signal if we are quitting, because on MSVC it is
1290         // destructed before the cut stack in CutAndPaste.cpp, and this method
1291         // is called from some inset destructor if the cut stack is not empty
1292         // on exit.
1293         if (quitting)
1294                 return;
1295
1296         std::map<string, DialogPtr>::const_iterator it = d.dialogs_.find(name);
1297         if (it == d.dialogs_.end())
1298                 return;
1299
1300         if (inset && inset != getOpenInset(name))
1301                 return;
1302
1303         Dialog * const dialog = it->second.get();
1304         if (dialog->isVisibleView())
1305                 dialog->hide();
1306         d.open_insets_[name] = 0;
1307 }
1308
1309
1310 void GuiView::disconnectDialog(string const & name)
1311 {
1312         if (!isValidName(name))
1313                 return;
1314
1315         if (d.open_insets_.find(name) != d.open_insets_.end())
1316                 d.open_insets_[name] = 0;
1317 }
1318
1319
1320 Inset * GuiView::getOpenInset(string const & name) const
1321 {
1322         if (!isValidName(name))
1323                 return 0;
1324
1325         std::map<string, Inset *>::const_iterator it = d.open_insets_.find(name);
1326         return it == d.open_insets_.end() ? 0 : it->second;
1327 }
1328
1329
1330 void GuiView::hideAll() const
1331 {
1332         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1333         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1334
1335         for(; it != end; ++it)
1336                 it->second->hide();
1337 }
1338
1339
1340 void GuiView::hideBufferDependent() const
1341 {
1342         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1343         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1344
1345         for(; it != end; ++it) {
1346                 Dialog * dialog = it->second.get();
1347                 if (dialog->isBufferDependent())
1348                         dialog->hide();
1349         }
1350 }
1351
1352
1353 void GuiView::updateBufferDependent(bool switched) const
1354 {
1355         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1356         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1357
1358         for(; it != end; ++it) {
1359                 Dialog * dialog = it->second.get();
1360                 if (switched && dialog->isBufferDependent()) {
1361                         if (dialog->isVisibleView() && dialog->initialiseParams(""))
1362                                 dialog->updateView();
1363                         else
1364                                 dialog->hide();
1365                 } else {
1366                         // A bit clunky, but the dialog will request
1367                         // that the kernel provides it with the necessary
1368                         // data.
1369                         dialog->updateDialog();
1370                 }
1371         }
1372 }
1373
1374
1375 void GuiView::checkStatus()
1376 {
1377         std::map<string, DialogPtr>::const_iterator it  = d.dialogs_.begin();
1378         std::map<string, DialogPtr>::const_iterator end = d.dialogs_.end();
1379
1380         for(; it != end; ++it) {
1381                 Dialog * const dialog = it->second.get();
1382                 if (dialog && dialog->isVisibleView())
1383                         dialog->checkStatus();
1384         }
1385 }
1386
1387
1388
1389 // will be replaced by a proper factory...
1390 Dialog * createGuiAbout(GuiView & lv);
1391 Dialog * createGuiBibitem(GuiView & lv);
1392 Dialog * createGuiBibtex(GuiView & lv);
1393 Dialog * createGuiBox(GuiView & lv);
1394 Dialog * createGuiBranch(GuiView & lv);
1395 Dialog * createGuiChanges(GuiView & lv);
1396 Dialog * createGuiCharacter(GuiView & lv);
1397 Dialog * createGuiCitation(GuiView & lv);
1398 Dialog * createGuiDelimiter(GuiView & lv);
1399 Dialog * createGuiDocument(GuiView & lv);
1400 Dialog * createGuiErrorList(GuiView & lv);
1401 Dialog * createGuiERT(GuiView & lv);
1402 Dialog * createGuiExternal(GuiView & lv);
1403 Dialog * createGuiFloat(GuiView & lv);
1404 Dialog * createGuiGraphics(GuiView & lv);
1405 Dialog * createGuiInclude(GuiView & lv);
1406 Dialog * createGuiIndex(GuiView & lv);
1407 Dialog * createGuiLabel(GuiView & lv);
1408 Dialog * createGuiListings(GuiView & lv);
1409 Dialog * createGuiLog(GuiView & lv);
1410 Dialog * createGuiMathMatrix(GuiView & lv);
1411 Dialog * createGuiNomenclature(GuiView & lv);
1412 Dialog * createGuiNote(GuiView & lv);
1413 Dialog * createGuiParagraph(GuiView & lv);
1414 Dialog * createGuiPreferences(GuiView & lv);
1415 Dialog * createGuiPrint(GuiView & lv);
1416 Dialog * createGuiRef(GuiView & lv);
1417 Dialog * createGuiSearch(GuiView & lv);
1418 Dialog * createGuiSendTo(GuiView & lv);
1419 Dialog * createGuiShowFile(GuiView & lv);
1420 Dialog * createGuiSpellchecker(GuiView & lv);
1421 Dialog * createGuiTabularCreate(GuiView & lv);
1422 Dialog * createGuiTabular(GuiView & lv);
1423 Dialog * createGuiTexInfo(GuiView & lv);
1424 Dialog * createGuiToc(GuiView & lv);
1425 Dialog * createGuiThesaurus(GuiView & lv);
1426 Dialog * createGuiHyperlink(GuiView & lv);
1427 Dialog * createGuiVSpace(GuiView & lv);
1428 Dialog * createGuiViewSource(GuiView & lv);
1429 Dialog * createGuiWrap(GuiView & lv);
1430
1431
1432 Dialog * GuiView::build(string const & name)
1433 {
1434         BOOST_ASSERT(isValidName(name));
1435
1436         if (name == "aboutlyx")
1437                 return createGuiAbout(*this);
1438         if (name == "bibitem")
1439                 return createGuiBibitem(*this);
1440         if (name == "bibtex")
1441                 return createGuiBibtex(*this);
1442         if (name == "box")
1443                 return createGuiBox(*this);
1444         if (name == "branch")
1445                 return createGuiBranch(*this);
1446         if (name == "changes")
1447                 return createGuiChanges(*this);
1448         if (name == "character")
1449                 return createGuiCharacter(*this);
1450         if (name == "citation")
1451                 return createGuiCitation(*this);
1452         if (name == "document")
1453                 return createGuiDocument(*this);
1454         if (name == "errorlist")
1455                 return createGuiErrorList(*this);
1456         if (name == "ert")
1457                 return createGuiERT(*this);
1458         if (name == "external")
1459                 return createGuiExternal(*this);
1460         if (name == "file")
1461                 return createGuiShowFile(*this);
1462         if (name == "findreplace")
1463                 return createGuiSearch(*this);
1464         if (name == "float")
1465                 return createGuiFloat(*this);
1466         if (name == "graphics")
1467                 return createGuiGraphics(*this);
1468         if (name == "include")
1469                 return createGuiInclude(*this);
1470         if (name == "index")
1471                 return createGuiIndex(*this);
1472         if (name == "nomenclature")
1473                 return createGuiNomenclature(*this);
1474         if (name == "label")
1475                 return createGuiLabel(*this);
1476         if (name == "log")
1477                 return createGuiLog(*this);
1478         if (name == "view-source")
1479                 return createGuiViewSource(*this);
1480         if (name == "mathdelimiter")
1481                 return createGuiDelimiter(*this);
1482         if (name == "mathmatrix")
1483                 return createGuiMathMatrix(*this);
1484         if (name == "note")
1485                 return createGuiNote(*this);
1486         if (name == "paragraph")
1487                 return createGuiParagraph(*this);
1488         if (name == "prefs")
1489                 return createGuiPreferences(*this);
1490         if (name == "print")
1491                 return createGuiPrint(*this);
1492         if (name == "ref")
1493                 return createGuiRef(*this);
1494         if (name == "sendto")
1495                 return createGuiSendTo(*this);
1496         if (name == "spellchecker")
1497                 return createGuiSpellchecker(*this);
1498         if (name == "tabular")
1499                 return createGuiTabular(*this);
1500         if (name == "tabularcreate")
1501                 return createGuiTabularCreate(*this);
1502         if (name == "texinfo")
1503                 return createGuiTexInfo(*this);
1504 #ifdef HAVE_LIBAIKSAURUS
1505         if (name == "thesaurus")
1506                 return createGuiThesaurus(*this);
1507 #endif
1508         if (name == "toc")
1509                 return createGuiToc(*this);
1510         if (name == "href")
1511                 return createGuiHyperlink(*this);
1512         if (name == "vspace")
1513                 return createGuiVSpace(*this);
1514         if (name == "wrap")
1515                 return createGuiWrap(*this);
1516         if (name == "listings")
1517                 return createGuiListings(*this);
1518
1519         return 0;
1520 }
1521
1522
1523 } // namespace frontend
1524 } // namespace lyx
1525
1526 #include "GuiView_moc.cpp"