]> git.lyx.org Git - lyx.git/blob - src/text3.C
removing update calls
[lyx.git] / src / text3.C
1 /**
2  * \file text3.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger Alstrup
7  * \author Lars Gullik Bjønnes
8  * \author Alfredo Braunstein
9  * \author Angus Leeming
10  * \author John Levon
11  * \author André Pönitz
12  *
13  * Full author contact details are available in file CREDITS.
14  */
15
16 #include <config.h>
17
18 #include "lyxtext.h"
19
20 #include "buffer.h"
21 #include "bufferparams.h"
22 #include "BufferView.h"
23 #include "cursor.h"
24 #include "debug.h"
25 #include "dispatchresult.h"
26 #include "factory.h"
27 #include "funcrequest.h"
28 #include "gettext.h"
29 #include "intl.h"
30 #include "language.h"
31 #include "lyxrc.h"
32 #include "lyxrow.h"
33 #include "paragraph.h"
34 #include "paragraph_funcs.h"
35 #include "ParagraphParameters.h"
36 #include "undo.h"
37 #include "vspace.h"
38
39 #include "frontends/Dialogs.h"
40 #include "frontends/LyXView.h"
41
42 #include "insets/insetcommand.h"
43 #include "insets/insetnewline.h"
44 #include "insets/insetspecialchar.h"
45 #include "insets/insettext.h"
46
47 #include "support/lstrings.h"
48 #include "support/tostr.h"
49 #include "support/std_sstream.h"
50
51 #include "mathed/formulabase.h"
52
53 #include <clocale>
54
55 using bv_funcs::replaceSelection;
56
57 using lyx::pos_type;
58
59 using lyx::support::isStrUnsignedInt;
60 using lyx::support::strToUnsignedInt;
61
62 using std::endl;
63 using std::find;
64 using std::string;
65 using std::istringstream;
66 using std::vector;
67
68
69 extern string current_layout;
70 extern int bibitemMaxWidth(BufferView *, LyXFont const &);
71
72 // the selection possible is needed, that only motion events are
73 // used, where the bottom press event was on the drawing area too
74 bool selection_possible = false;
75
76
77 namespace {
78
79         // globals...
80         LyXFont freefont(LyXFont::ALL_IGNORE);
81         bool toggleall = false;
82
83
84         void toggleAndShow(BufferView * bv, LyXText * text,
85                 LyXFont const & font, bool toggleall = true)
86         {
87                 if (!bv->available())
88                         return;
89
90                 text->toggleFree(font, toggleall);
91                 bv->update();
92
93                 if (font.language() != ignore_language ||
94                                 font.number() != LyXFont::IGNORE) {
95                         LyXCursor & cursor = text->cursor;
96                         Paragraph & par = *text->cursorPar();
97                         text->bidi.computeTables(par, *bv->buffer(),
98                                 *par.getRow(cursor.pos()));
99                         if (cursor.boundary() !=
100                                         text->bidi.isBoundary(*bv->buffer(), par,
101                                                         cursor.pos(),
102                                                         text->real_current_font))
103                                 text->setCursor(cursor.par(), cursor.pos(),
104                                                 false, !cursor.boundary());
105                 }
106         }
107
108
109         /// Apply the contents of freefont at the current cursor location.
110         void apply_freefont(BufferView * bv, LyXText * text)
111         {
112                 toggleAndShow(bv, text, freefont, toggleall);
113                 bv->owner()->view_state_changed();
114                 bv->owner()->message(_("Character set"));
115         }
116
117
118         /** Set the freefont using the contents of \param data dispatched from
119          *  the frontends and apply it at the current cursor location.
120          */
121         void update_and_apply_freefont(BufferView * bv, LyXText * text,
122                 string const & data)
123         {
124                 LyXFont font;
125                 bool toggle;
126                 if (bv_funcs::string2font(data, font, toggle)) {
127                         freefont = font;
128                         toggleall = toggle;
129                         apply_freefont(bv, text);
130                 }
131         }
132
133
134         void emph(BufferView * bv, LyXText * text)
135         {
136                 LyXFont font(LyXFont::ALL_IGNORE);
137                 font.setEmph(LyXFont::TOGGLE);
138                 toggleAndShow(bv, text, font);
139         }
140
141
142         void bold(BufferView * bv, LyXText * text)
143         {
144                 LyXFont font(LyXFont::ALL_IGNORE);
145                 font.setSeries(LyXFont::BOLD_SERIES);
146                 toggleAndShow(bv, text, font);
147         }
148
149
150         void noun(BufferView * bv, LyXText * text)
151         {
152                 LyXFont font(LyXFont::ALL_IGNORE);
153                 font.setNoun(LyXFont::TOGGLE);
154                 toggleAndShow(bv, text, font);
155         }
156
157
158         void lang(BufferView * bv, string const & l, LyXText * text)
159         {
160                 Language const * lang = languages.getLanguage(l);
161                 if (!lang)
162                         return;
163
164                 LyXFont font(LyXFont::ALL_IGNORE);
165                 font.setLanguage(lang);
166                 toggleAndShow(bv, text, font);
167         }
168
169
170         void code(BufferView * bv, LyXText * text)
171         {
172                 LyXFont font(LyXFont::ALL_IGNORE);
173                 font.setFamily(LyXFont::TYPEWRITER_FAMILY); // no good
174                 toggleAndShow(bv, text, font);
175         }
176
177
178         void sans(BufferView * bv, LyXText * text)
179         {
180                 LyXFont font(LyXFont::ALL_IGNORE);
181                 font.setFamily(LyXFont::SANS_FAMILY);
182                 toggleAndShow(bv, text, font);
183         }
184
185
186         void roman(BufferView * bv, LyXText * text)
187         {
188                 LyXFont font(LyXFont::ALL_IGNORE);
189                 font.setFamily(LyXFont::ROMAN_FAMILY);
190                 toggleAndShow(bv, text, font);
191         }
192
193
194         void styleReset(BufferView * bv, LyXText * text)
195         {
196                 LyXFont font(LyXFont::ALL_INHERIT, ignore_language);
197                 toggleAndShow(bv, text, font);
198         }
199
200
201         void underline(BufferView * bv, LyXText * text)
202         {
203                 LyXFont font(LyXFont::ALL_IGNORE);
204                 font.setUnderbar(LyXFont::TOGGLE);
205                 toggleAndShow(bv, text, font);
206         }
207
208
209         void fontSize(BufferView * bv, string const & size, LyXText * text)
210         {
211                 LyXFont font(LyXFont::ALL_IGNORE);
212                 font.setLyXSize(size);
213                 toggleAndShow(bv, text, font);
214         }
215
216
217         void moveCursorUpdate(BufferView * bv, bool selecting)
218         {
219                 LyXText * lt = bv->getLyXText();
220
221 //              if (!lt->selection.set())
222 //                      lt->selection.cursor = lt->cursor;
223
224                 if (selecting || lt->selection.mark())
225                         lt->setSelection();
226
227                 if (!lt->selection.set())
228                         bv->haveSelection(false);
229
230                 bv->update();
231                 bv->switchKeyMap();
232         }
233
234
235         void finishChange(BufferView * bv, bool selecting = false)
236         {
237                 finishUndo();
238                 moveCursorUpdate(bv, selecting);
239                 bv->owner()->view_state_changed();
240         }
241
242 } // anon namespace
243
244
245 namespace bv_funcs {
246
247 string const freefont2string()
248 {
249         string data;
250         if (font2string(freefont, toggleall, data))
251                 return data;
252         return string();
253 }
254
255 }
256
257
258
259 InsetOld * LyXText::checkInsetHit(int x, int y)
260 {
261         ParagraphList::iterator pit;
262         ParagraphList::iterator end;
263
264         getParsInRange(ownerParagraphs(),
265                        bv()->top_y(), bv()->top_y() + bv()->workHeight(),
266                        pit, end);
267         
268         lyxerr << "checkInsetHit: x: " << x << " y: " << y << endl;
269         for ( ; pit != end; ++pit) {
270                 InsetList::iterator iit = pit->insetlist.begin();
271                 InsetList::iterator iend = pit->insetlist.end();
272                 for ( ; iit != iend; ++iit) {
273                         InsetOld * inset = iit->inset;
274                         //lyxerr << "examining inset " << inset
275                         //      << " xy: " << inset->x() << "/" << inset->y()
276                         //      << " x: " << inset->x() << "..." << inset->x() + inset->width()
277                         //      << " y: " << inset->y() - inset->ascent() << "..."
278                         //      << inset->y() + inset->descent()
279                         //      << endl;
280                         if (x >= inset->x()
281                             && x <= inset->x() + inset->width()
282                             && y >= inset->y() - inset->ascent()
283                             && y <= inset->y() + inset->descent())
284                         {
285                                 lyxerr << "Hit inset: " << inset << endl;
286                                 return inset;
287                         }
288                 }
289         }
290         lyxerr << "No inset hit. " << endl;
291         return 0;
292 }
293
294
295 bool LyXText::gotoNextInset(vector<InsetOld::Code> const & codes,
296                             string const & contents)
297 {
298         ParagraphList::iterator end = ownerParagraphs().end();
299         ParagraphList::iterator pit = cursorPar();
300         pos_type pos = cursor.pos();
301
302         InsetOld * inset;
303         do {
304                 if (pos + 1 < pit->size()) {
305                         ++pos;
306                 } else  {
307                         ++pit;
308                         pos = 0;
309                 }
310
311         } while (pit != end &&
312                  !(pit->isInset(pos) &&
313                    (inset = pit->getInset(pos)) != 0 &&
314                    find(codes.begin(), codes.end(), inset->lyxCode()) != codes.end() &&
315                    (contents.empty() ||
316                     static_cast<InsetCommand *>(pit->getInset(pos))->getContents()
317                     == contents)));
318
319         if (pit == end)
320                 return false;
321
322         setCursor(parOffset(pit), pos, false);
323         return true;
324 }
325
326
327 void LyXText::gotoInset(vector<InsetOld::Code> const & codes,
328                         bool same_content)
329 {
330         clearSelection();
331
332         string contents;
333         if (same_content && cursor.pos() < cursorPar()->size()
334             && cursorPar()->isInset(cursor.pos())) {
335                 InsetOld const * inset = cursorPar()->getInset(cursor.pos());
336                 if (find(codes.begin(), codes.end(), inset->lyxCode())
337                     != codes.end())
338                         contents = static_cast<InsetCommand const *>(inset)->getContents();
339         }
340
341         if (!gotoNextInset(codes, contents)) {
342                 if (cursor.pos() || cursorPar() != ownerParagraphs().begin()) {
343                         LyXCursor tmp = cursor;
344                         cursor.par(0);
345                         cursor.pos(0);
346                         if (!gotoNextInset(codes, contents)) {
347                                 cursor = tmp;
348                                 bv()->owner()->message(_("No more insets"));
349                         }
350                 } else {
351                         bv()->owner()->message(_("No more insets"));
352                 }
353         }
354         bv()->update();
355         selection.cursor = cursor;
356 }
357
358
359 void LyXText::gotoInset(InsetOld::Code code, bool same_content)
360 {
361         gotoInset(vector<InsetOld::Code>(1, code), same_content);
362 }
363
364
365 void LyXText::cursorPrevious()
366 {
367         int y = bv()->top_y();
368
369         ParagraphList::iterator cpit = cursorPar();
370         RowList::iterator crit = cpit->getRow(cursor.pos());
371
372         if (isFirstRow(cpit, *crit)) {
373                 if (y > 0)
374                         bv()->updateScrollbar();
375                 return;
376         }
377
378         setCursorFromCoordinates(bv()->x_target(), y);
379         finishUndo();
380
381         if (crit == bv()->text->cursorRow()) {
382                 // we have a row which is taller than the workarea. The
383                 // simplest solution is to move to the previous row instead.
384                 cursorUp(true);
385                 return;
386         }
387
388         int new_y = + crit->height() - bv()->workHeight() + 1;
389
390         if (inset_owner) {
391                 new_y += bv()->text->cursor.y()
392                         + bv()->cursor().innerInset()->insetInInsetY()
393                         + y;
394         } else {
395                 new_y += cursor.y() - crit->baseline();
396         }
397
398         previousRow(cpit, crit);
399         LyXCursor cur;
400         setCursor(cur, parOffset(cpit), crit->pos(), false);
401         if (cur.y() > bv()->top_y())
402                 cursorUp(true);
403         bv()->updateScrollbar();
404 }
405
406
407 void LyXText::cursorNext()
408 {
409         int topy = bv()->top_y();
410
411         ParagraphList::iterator cpit = cursorPar();
412         RowList::iterator crit = cpit->getRow(cursor.pos());
413
414         if (isLastRow(cpit, *crit)) {
415                 int y = cursor.y() - crit->baseline() + crit->height();
416                 if (y > topy + bv()->workHeight())
417                         bv()->updateScrollbar();
418                 return;
419         }
420
421         int y = topy + bv()->workHeight();
422         if (inset_owner && !topy) {
423                 y += - bv()->text->cursor.y()
424                            + bv()->top_y()
425                            - bv()->cursor().innerInset()->insetInInsetY();
426         }
427
428         ParagraphList::iterator dummypit;
429         Row const & row = *getRowNearY(y, dummypit);
430         y = dummypit->y + row.y_offset();
431
432         setCursorFromCoordinates(bv()->x_target(), y);
433         // + bv->workHeight());
434         finishUndo();
435
436         int new_y;
437         if (crit == bv()->text->cursorRow()) {
438                 // we have a row which is taller than the workarea. The
439                 // simplest solution is to move to the next row instead.
440                 cursorDown(true);
441                 return;
442                 // This is what we used to do, so we wouldn't skip right past
443                 // tall rows, but it's not working right now.
444 #if 0
445                 new_y = bv->top_y() + bv->workHeight();
446 #endif
447         }
448
449         if (inset_owner) {
450                 new_y = bv()->text->cursor.y()
451                         + bv()->cursor().innerInset()->insetInInsetY()
452                         + y - crit->baseline();
453         } else {
454                 new_y = cursor.y() - crit->baseline();
455         }
456
457
458         nextRow(cpit, crit);
459         LyXCursor cur;
460         setCursor(cur, parOffset(cpit), crit->pos(), false);
461         if (cur.y() < bv()->top_y() + bv()->workHeight())
462                 cursorDown(true);
463         bv()->updateScrollbar();
464 }
465
466
467 namespace {
468
469 void specialChar(LyXText * lt, BufferView * bv, InsetSpecialChar::Kind kind)
470 {
471         bv->update();
472         InsetSpecialChar * new_inset = new InsetSpecialChar(kind);
473         replaceSelection(lt);
474         if (!bv->insertInset(new_inset))
475                 delete new_inset;
476         else
477                 bv->update();
478 }
479
480
481 void doInsertInset(LyXText * lt, FuncRequest const & cmd,
482                    bool edit, bool pastesel)
483 {
484         InsetOld * inset = createInset(cmd);
485         BufferView * bv = cmd.view();
486
487         if (inset) {
488                 bool gotsel = false;
489                 if (lt->selection.set()) {
490                         bv->owner()->dispatch(FuncRequest(LFUN_CUT));
491                         gotsel = true;
492                 }
493                 if (bv->insertInset(inset)) {
494                         if (edit)
495                                 inset->edit(bv, true);
496                         if (gotsel && pastesel)
497                                 bv->owner()->dispatch(FuncRequest(LFUN_PASTE));
498                 }
499                 else
500                         delete inset;
501         }
502 }
503
504 } // anon namespace
505
506
507 void LyXText::number()
508 {
509         LyXFont font(LyXFont::ALL_IGNORE);
510         font.setNumber(LyXFont::TOGGLE);
511         toggleAndShow(bv(), this, font);
512 }
513
514
515 bool LyXText::rtl() const
516 {
517         return cursorPar()->isRightToLeftPar(bv()->buffer()->params());
518 }
519
520
521 DispatchResult LyXText::dispatch(FuncRequest const & cmd)
522 {
523         //lyxerr[Debug::ACTION] << "LyXText::dispatch: cmd: " << cmd << endl;
524         lyxerr << "LyXText::dispatch: cmd: " << cmd << endl;
525
526         BufferView * bv = cmd.view();
527
528         switch (cmd.action) {
529
530         case LFUN_APPENDIX: {
531                 ParagraphList::iterator pit = cursorPar();
532                 bool start = !pit->params().startOfAppendix();
533
534                 // ensure that we have only one start_of_appendix in this document
535                 ParagraphList::iterator tmp = ownerParagraphs().begin();
536                 ParagraphList::iterator end = ownerParagraphs().end();
537
538                 for (; tmp != end; ++tmp) {
539                         if (tmp->params().startOfAppendix()) {
540                                 recUndo(parOffset(tmp));
541                                 tmp->params().startOfAppendix(false);
542                                 redoParagraph(tmp);
543                                 break;
544                         }
545                 }
546
547                 recUndo(parOffset(pit));
548                 pit->params().startOfAppendix(start);
549
550                 // we can set the refreshing parameters now
551                 updateCounters();
552                 redoParagraph(cursorPar());
553                 setCursor(cursorPar(), cursor.pos());
554                 bv->update();
555                 break;
556         }
557
558         case LFUN_DELETE_WORD_FORWARD:
559                 clearSelection();
560                 deleteWordForward();
561                 finishChange(bv);
562                 break;
563
564         case LFUN_DELETE_WORD_BACKWARD:
565                 clearSelection();
566                 deleteWordBackward();
567                 finishChange(bv);
568                 break;
569
570         case LFUN_DELETE_LINE_FORWARD:
571                 clearSelection();
572                 deleteLineForward();
573                 finishChange(bv);
574                 break;
575
576         case LFUN_WORDRIGHT:
577                 if (!selection.mark())
578                         clearSelection();
579                 if (rtl())
580                         cursorLeftOneWord();
581                 else
582                         cursorRightOneWord();
583                 finishChange(bv);
584                 break;
585
586         case LFUN_WORDLEFT:
587                 if (!selection.mark())
588                         clearSelection();
589                 if (rtl())
590                         cursorRightOneWord();
591                 else
592                         cursorLeftOneWord();
593                 finishChange(bv);
594                 break;
595
596         case LFUN_BEGINNINGBUF:
597                 if (!selection.mark())
598                         clearSelection();
599                 cursorTop();
600                 finishChange(bv);
601                 break;
602
603         case LFUN_ENDBUF:
604                 if (selection.mark())
605                         clearSelection();
606                 cursorBottom();
607                 finishChange(bv);
608                 break;
609
610         case LFUN_RIGHTSEL:
611                 if (!selection.set())
612                         selection.cursor = cursor;
613                 if (rtl())
614                         cursorLeft(bv);
615                 else
616                         cursorRight(bv);
617                 finishChange(bv, true);
618                 break;
619
620         case LFUN_LEFTSEL:
621                 if (!selection.set())
622                         selection.cursor = cursor;
623                 if (rtl())
624                         cursorRight(bv);
625                 else
626                         cursorLeft(bv);
627                 finishChange(bv, true);
628                 break;
629
630         case LFUN_UPSEL:
631                 if (!selection.set())
632                         selection.cursor = cursor;
633                 cursorUp(true);
634                 finishChange(bv, true);
635                 break;
636
637         case LFUN_DOWNSEL:
638                 if (!selection.set())
639                         selection.cursor = cursor;
640                 cursorDown(true);
641                 finishChange(bv, true);
642                 break;
643
644         case LFUN_UP_PARAGRAPHSEL:
645                 if (!selection.set())
646                         selection.cursor = cursor;
647                 cursorUpParagraph();
648                 finishChange(bv, true);
649                 break;
650
651         case LFUN_DOWN_PARAGRAPHSEL:
652                 if (!selection.set())
653                         selection.cursor = cursor;
654                 cursorDownParagraph();
655                 finishChange(bv, true);
656                 break;
657
658         case LFUN_PRIORSEL:
659                 if (!selection.set())
660                         selection.cursor = cursor;
661                 cursorPrevious();
662                 finishChange(bv, true);
663                 break;
664
665         case LFUN_NEXTSEL:
666                 if (!selection.set())
667                         selection.cursor = cursor;
668                 cursorNext();
669                 finishChange(bv, true);
670                 break;
671
672         case LFUN_HOMESEL:
673                 if (!selection.set())
674                         selection.cursor = cursor;
675                 cursorHome();
676                 finishChange(bv, true);
677                 break;
678
679         case LFUN_ENDSEL:
680                 if (!selection.set())
681                         selection.cursor = cursor;
682                 cursorEnd();
683                 finishChange(bv, true);
684                 break;
685
686         case LFUN_WORDRIGHTSEL:
687                 if (rtl())
688                         cursorLeftOneWord();
689                 else
690                         cursorRightOneWord();
691                 finishChange(bv, true);
692                 break;
693
694         case LFUN_WORDLEFTSEL:
695                 if (rtl())
696                         cursorRightOneWord();
697                 else
698                         cursorLeftOneWord();
699                 finishChange(bv, true);
700                 break;
701
702         case LFUN_WORDSEL: {
703                 LyXCursor cur1 = cursor;
704                 LyXCursor cur2;
705                 getWord(cur1, cur2, lyx::WHOLE_WORD);
706                 setCursor(cur1.par(), cur1.pos());
707                 clearSelection();
708                 setCursor(cur2.par(), cur2.pos());
709                 finishChange(bv, true);
710                 break;
711         }
712
713         case LFUN_RIGHT: {
714                 bool is_rtl = rtl();
715                 if (!selection.mark())
716                         clearSelection();
717                 if (is_rtl)
718                         cursorLeft(false);
719                 if (cursor.pos() < cursorPar()->size()
720                     && cursorPar()->isInset(cursor.pos())
721                     && isHighlyEditableInset(cursorPar()->getInset(cursor.pos()))) {
722                         InsetOld * tmpinset = cursorPar()->getInset(cursor.pos());
723                         cmd.message(tmpinset->editMessage());
724                         tmpinset->edit(bv, !is_rtl);
725                         break;
726                 }
727                 if (!is_rtl)
728                         cursorRight(false);
729                 finishChange(bv);
730                 break;
731         }
732
733         case LFUN_LEFT: {
734                 // This is soooo ugly. Isn't it possible to make
735                 // it simpler? (Lgb)
736                 bool const is_rtl = rtl();
737                 if (!selection.mark())
738                         clearSelection();
739                 LyXCursor const cur = cursor;
740                 if (!is_rtl)
741                         cursorLeft(false);
742                 if ((is_rtl || cur != cursor) && // only if really moved!
743                     cursor.pos() < cursorPar()->size() &&
744                     cursorPar()->isInset(cursor.pos()) &&
745                     isHighlyEditableInset(cursorPar()->getInset(cursor.pos()))) {
746                         InsetOld * tmpinset = cursorPar()->getInset(cursor.pos());
747                         cmd.message(tmpinset->editMessage());
748                         tmpinset->edit(bv, is_rtl);
749                         break;
750                 }
751                 if (is_rtl)
752                         cursorRight(false);
753                 finishChange(bv);
754                 break;
755         }
756
757         case LFUN_UP:
758                 if (!selection.mark())
759                         clearSelection();
760                 cursorUp(false);
761                 finishChange(bv);
762                 break;
763
764         case LFUN_DOWN:
765                 if (!selection.mark())
766                         clearSelection();
767                 cursorDown(false);
768                 finishChange(bv);
769                 break;
770
771         case LFUN_UP_PARAGRAPH:
772                 if (!selection.mark())
773                         clearSelection();
774                 cursorUpParagraph();
775                 finishChange(bv);
776                 break;
777
778         case LFUN_DOWN_PARAGRAPH:
779                 if (!selection.mark())
780                         clearSelection();
781                 cursorDownParagraph();
782                 finishChange(bv, false);
783                 break;
784
785         case LFUN_PRIOR:
786                 if (!selection.mark())
787                         clearSelection();
788                 cursorPrevious();
789                 finishChange(bv, false);
790                 break;
791
792         case LFUN_NEXT:
793                 if (!selection.mark())
794                         clearSelection();
795                 cursorNext();
796                 finishChange(bv, false);
797                 break;
798
799         case LFUN_HOME:
800                 if (!selection.mark())
801                         clearSelection();
802                 cursorHome();
803                 finishChange(bv, false);
804                 break;
805
806         case LFUN_END:
807                 if (!selection.mark())
808                         clearSelection();
809                 cursorEnd();
810                 finishChange(bv, false);
811                 break;
812
813         case LFUN_BREAKLINE: {
814                 lyx::pos_type body = cursorPar()->beginningOfBody();
815
816                 // Not allowed by LaTeX (labels or empty par)
817                 if (cursor.pos() <= body)
818                         break;
819
820                 replaceSelection(bv->getLyXText());
821                 insertInset(new InsetNewline);
822                 setCursor(cursorPar(), cursor.pos());
823                 moveCursorUpdate(bv, false);
824                 break;
825         }
826
827         case LFUN_DELETE:
828                 if (!selection.set()) {
829                         Delete();
830                         selection.cursor = cursor;
831                         // It is possible to make it a lot faster still
832                         // just comment out the line below...
833                 } else {
834                         cutSelection(true, false);
835                 }
836                 moveCursorUpdate(bv, false);
837                 bv->owner()->view_state_changed();
838                 break;
839
840         case LFUN_DELETE_SKIP:
841                 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
842                 if (!selection.set()) {
843                         if (cursor.pos() == cursorPar()->size()) {
844                                 cursorRight(bv);
845                                 ParagraphParameters & params = cursorPar()->params();
846                                 if (cursor.pos() == 0
847                                     && !(params.spaceTop() == VSpace (VSpace::NONE))) {
848                                         setParagraph(
849                                                  VSpace(VSpace::NONE),
850                                                  params.spaceBottom(),
851                                                  params.spacing(),
852                                                  params.align(),
853                                                  params.labelWidthString(), 0);
854                                         cursorLeft(bv);
855                                 } else {
856                                         cursorLeft(bv);
857                                         Delete();
858                                         selection.cursor = cursor;
859                                 }
860                         } else {
861                                 Delete();
862                                 selection.cursor = cursor;
863                         }
864                 } else {
865                         cutSelection(true, false);
866                 }
867                 bv->update();
868                 break;
869
870
871         case LFUN_BACKSPACE:
872                 if (!selection.set()) {
873                         if (bv->owner()->getIntl().getTransManager().backspace()) {
874                                 backspace();
875                                 selection.cursor = cursor;
876                                 // It is possible to make it a lot faster still
877                                 // just comment out the line below...
878                         }
879                 } else {
880                         cutSelection(true, false);
881                 }
882                 bv->owner()->view_state_changed();
883                 bv->switchKeyMap();
884                 bv->update();
885                 break;
886
887         case LFUN_BACKSPACE_SKIP:
888                 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
889                 if (!selection.set()) {
890                         ParagraphParameters & params = cursorPar()->params();
891                         if (cursor.pos() == 0 && !(params.spaceTop() == VSpace(VSpace::NONE))) {
892                                 setParagraph(
893                                          VSpace(VSpace::NONE),
894                                    params.spaceBottom(),
895                                          params.spacing(),
896                                          params.align(),
897                                          params.labelWidthString(), 0);
898                         } else {
899                                 LyXCursor cur = cursor;
900                                 backspace();
901                                 selection.cursor = cur;
902                         }
903                 } else {
904                         cutSelection(true, false);
905                 }
906                 bv->update();
907                 break;
908
909         case LFUN_BREAKPARAGRAPH:
910                 replaceSelection(bv->getLyXText());
911                 breakParagraph(bv->buffer()->paragraphs(), 0);
912                 bv->update();
913                 selection.cursor = cursor;
914                 bv->switchKeyMap();
915                 bv->owner()->view_state_changed();
916                 break;
917
918         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
919                 replaceSelection(bv->getLyXText());
920                 breakParagraph(bv->buffer()->paragraphs(), 1);
921                 bv->update();
922                 selection.cursor = cursor;
923                 bv->switchKeyMap();
924                 bv->owner()->view_state_changed();
925                 break;
926
927         case LFUN_BREAKPARAGRAPH_SKIP: {
928                 // When at the beginning of a paragraph, remove
929                 // indentation and add a "defskip" at the top.
930                 // Otherwise, do the same as LFUN_BREAKPARAGRAPH.
931                 LyXCursor cur = cursor;
932                 replaceSelection(bv->getLyXText());
933                 if (cur.pos() == 0) {
934                         ParagraphParameters & params = getPar(cur)->params();
935                         if (params.spaceTop() == VSpace(VSpace::NONE)) {
936                                 setParagraph(
937                                          VSpace(VSpace::DEFSKIP), params.spaceBottom(),
938                                          params.spacing(),
939                                          params.align(),
940                                          params.labelWidthString(), 1);
941                         }
942                 }
943                 else {
944                         breakParagraph(bv->buffer()->paragraphs(), 0);
945                 }
946                 bv->update();
947                 selection.cursor = cur;
948                 bv->switchKeyMap();
949                 bv->owner()->view_state_changed();
950                 break;
951         }
952
953         case LFUN_PARAGRAPH_SPACING: {
954                 ParagraphList::iterator pit = cursorPar();
955                 Spacing::Space cur_spacing = pit->params().spacing().getSpace();
956                 float cur_value = 1.0;
957                 if (cur_spacing == Spacing::Other)
958                         cur_value = pit->params().spacing().getValue();
959
960                 istringstream is(cmd.argument);
961                 string tmp;
962                 is >> tmp;
963                 Spacing::Space new_spacing = cur_spacing;
964                 float new_value = cur_value;
965                 if (tmp.empty()) {
966                         lyxerr << "Missing argument to `paragraph-spacing'"
967                                << endl;
968                 } else if (tmp == "single") {
969                         new_spacing = Spacing::Single;
970                 } else if (tmp == "onehalf") {
971                         new_spacing = Spacing::Onehalf;
972                 } else if (tmp == "double") {
973                         new_spacing = Spacing::Double;
974                 } else if (tmp == "other") {
975                         new_spacing = Spacing::Other;
976                         float tmpval = 0.0;
977                         is >> tmpval;
978                         lyxerr << "new_value = " << tmpval << endl;
979                         if (tmpval != 0.0)
980                                 new_value = tmpval;
981                 } else if (tmp == "default") {
982                         new_spacing = Spacing::Default;
983                 } else {
984                         lyxerr << _("Unknown spacing argument: ")
985                                << cmd.argument << endl;
986                 }
987                 if (cur_spacing != new_spacing || cur_value != new_value) {
988                         pit->params().spacing(Spacing(new_spacing, new_value));
989                         redoParagraph();
990                         bv->update();
991                 }
992                 break;
993         }
994
995         case LFUN_INSET_SETTINGS:
996                 bv->cursor().innerInset()->showInsetDialog(bv);
997                 break;
998
999         case LFUN_INSET_TOGGLE:
1000                 clearSelection();
1001                 toggleInset();
1002                 bv->update();
1003                 bv->switchKeyMap();
1004                 break;
1005
1006         case LFUN_SPACE_INSERT:
1007                 if (cursorPar()->layout()->free_spacing)
1008                         insertChar(' ');
1009                 else
1010                         doInsertInset(this, cmd, false, false);
1011                 moveCursorUpdate(bv, false);
1012                 break;
1013
1014         case LFUN_HYPHENATION:
1015                 specialChar(this, bv, InsetSpecialChar::HYPHENATION);
1016                 break;
1017
1018         case LFUN_LIGATURE_BREAK:
1019                 specialChar(this, bv, InsetSpecialChar::LIGATURE_BREAK);
1020                 break;
1021
1022         case LFUN_LDOTS:
1023                 specialChar(this, bv, InsetSpecialChar::LDOTS);
1024                 break;
1025
1026         case LFUN_END_OF_SENTENCE:
1027                 specialChar(this, bv, InsetSpecialChar::END_OF_SENTENCE);
1028                 break;
1029
1030         case LFUN_MENU_SEPARATOR:
1031                 specialChar(this, bv, InsetSpecialChar::MENU_SEPARATOR);
1032                 break;
1033
1034         case LFUN_MARK_OFF:
1035                 clearSelection();
1036                 bv->update();
1037                 selection.cursor = cursor;
1038                 cmd.message(N_("Mark off"));
1039                 break;
1040
1041         case LFUN_MARK_ON:
1042                 clearSelection();
1043                 selection.mark(true);
1044                 bv->update();
1045                 selection.cursor = cursor;
1046                 cmd.message(N_("Mark on"));
1047                 break;
1048
1049         case LFUN_SETMARK:
1050                 clearSelection();
1051                 if (selection.mark()) {
1052                         cmd.message(N_("Mark removed"));
1053                 } else {
1054                         selection.mark(true);
1055                         cmd.message(N_("Mark set"));
1056                 }
1057                 selection.cursor = cursor;
1058                 bv->update();
1059                 break;
1060
1061         case LFUN_UPCASE_WORD:
1062                 changeCase(LyXText::text_uppercase);
1063                 bv->update();
1064                 break;
1065
1066         case LFUN_LOWCASE_WORD:
1067                 changeCase(LyXText::text_lowercase);
1068                 bv->update();
1069                 break;
1070
1071         case LFUN_CAPITALIZE_WORD:
1072                 changeCase(LyXText::text_capitalization);
1073                 bv->update();
1074                 break;
1075
1076         case LFUN_TRANSPOSE_CHARS:
1077                 recUndo(cursor.par());
1078                 redoParagraph();
1079                 bv->update();
1080                 break;
1081
1082         case LFUN_PASTE:
1083                 cmd.message(_("Paste"));
1084                 replaceSelection(bv->getLyXText());
1085 #warning FIXME Check if the arg is in the domain of available selections.
1086                 if (isStrUnsignedInt(cmd.argument))
1087                         pasteSelection(strToUnsignedInt(cmd.argument));
1088                 else
1089                         pasteSelection(0);
1090                 clearSelection(); // bug 393
1091                 bv->update();
1092                 bv->switchKeyMap();
1093                 finishUndo();
1094                 break;
1095
1096         case LFUN_CUT:
1097                 cutSelection(true, true);
1098                 cmd.message(_("Cut"));
1099                 bv->update();
1100                 break;
1101
1102         case LFUN_COPY:
1103                 copySelection();
1104                 cmd.message(_("Copy"));
1105                 break;
1106
1107         case LFUN_BEGINNINGBUFSEL:
1108                 if (inset_owner)
1109                         return DispatchResult(false);
1110                 cursorTop();
1111                 finishChange(bv, true);
1112                 break;
1113
1114         case LFUN_ENDBUFSEL:
1115                 if (inset_owner)
1116                         return DispatchResult(false);
1117                 cursorBottom();
1118                 finishChange(bv, true);
1119                 break;
1120
1121         case LFUN_GETXY:
1122                 cmd.message(tostr(cursor.x()) + ' ' + tostr(cursor.y()));
1123                 break;
1124
1125         case LFUN_SETXY: {
1126                 int x = 0;
1127                 int y = 0;
1128                 istringstream is(cmd.argument);
1129                 is >> x >> y;
1130                 if (!is)
1131                         lyxerr << "SETXY: Could not parse coordinates in '"
1132                                << cmd.argument << std::endl;
1133                 else
1134                         setCursorFromCoordinates(x, y);
1135                 break;
1136         }
1137
1138         case LFUN_GETFONT:
1139                 if (current_font.shape() == LyXFont::ITALIC_SHAPE)
1140                         cmd.message("E");
1141                 else if (current_font.shape() == LyXFont::SMALLCAPS_SHAPE)
1142                         cmd.message("N");
1143                 else
1144                         cmd.message("0");
1145                 break;
1146
1147         case LFUN_GETLAYOUT:
1148                 cmd.message(tostr(cursorPar()->layout()));
1149                 break;
1150
1151         case LFUN_LAYOUT: {
1152                 lyxerr[Debug::INFO] << "LFUN_LAYOUT: (arg) "
1153                   << cmd.argument << endl;
1154
1155                 // This is not the good solution to the empty argument
1156                 // problem, but it will hopefully suffice for 1.2.0.
1157                 // The correct solution would be to augument the
1158                 // function list/array with information about what
1159                 // functions needs arguments and their type.
1160                 if (cmd.argument.empty()) {
1161                         cmd.errorMessage(_("LyX function 'layout' needs an argument."));
1162                         break;
1163                 }
1164
1165                 // Derive layout number from given argument (string)
1166                 // and current buffer's textclass (number)
1167                 LyXTextClass const & tclass = bv->buffer()->params().getLyXTextClass();
1168                 bool hasLayout = tclass.hasLayout(cmd.argument);
1169                 string layout = cmd.argument;
1170
1171                 // If the entry is obsolete, use the new one instead.
1172                 if (hasLayout) {
1173                         string const & obs = tclass[layout]->obsoleted_by();
1174                         if (!obs.empty())
1175                                 layout = obs;
1176                 }
1177
1178                 if (!hasLayout) {
1179                         cmd.errorMessage(string(N_("Layout ")) + cmd.argument +
1180                                 N_(" not known"));
1181                         break;
1182                 }
1183
1184                 bool change_layout = (current_layout != layout);
1185
1186                 if (!change_layout && selection.set() &&
1187                         selection.start.par() != selection.end.par())
1188                 {
1189                         ParagraphList::iterator spit = getPar(selection.start);
1190                         ParagraphList::iterator epit = boost::next(getPar(selection.end));
1191                         while (spit != epit) {
1192                                 if (spit->layout()->name() != current_layout) {
1193                                         change_layout = true;
1194                                         break;
1195                                 }
1196                                 ++spit;
1197                         }
1198                 }
1199
1200                 if (change_layout) {
1201                         current_layout = layout;
1202                         setLayout(layout);
1203                         bv->owner()->setLayout(layout);
1204                         bv->update();
1205                         bv->switchKeyMap();
1206                 }
1207                 break;
1208         }
1209
1210         case LFUN_PASTESELECTION: {
1211                 // this was originally a bv->text->clearSelection(), i.e
1212                 // the outermost LyXText!
1213                 clearSelection();
1214                 string const clip = bv->getClipboard();
1215                 if (!clip.empty()) {
1216                         if (cmd.argument == "paragraph")
1217                                 insertStringAsParagraphs(clip);
1218                         else
1219                                 insertStringAsLines(clip);
1220                         bv->update();
1221                 }
1222                 break;
1223         }
1224
1225         case LFUN_GOTOERROR:
1226                 gotoInset(InsetOld::ERROR_CODE, false);
1227                 break;
1228
1229         case LFUN_GOTONOTE:
1230                 gotoInset(InsetOld::NOTE_CODE, false);
1231                 break;
1232
1233         case LFUN_REFERENCE_GOTO: {
1234                 vector<InsetOld::Code> tmp;
1235                 tmp.push_back(InsetOld::LABEL_CODE);
1236                 tmp.push_back(InsetOld::REF_CODE);
1237                 gotoInset(tmp, true);
1238                 break;
1239         }
1240
1241         case LFUN_QUOTE: {
1242                 replaceSelection(bv->getLyXText());
1243                 ParagraphList::iterator pit = cursorPar();
1244                 lyx::pos_type pos = cursor.pos();
1245                 char c;
1246                 if (!pos)
1247                         c = ' ';
1248                 else if (pit->isInset(pos - 1) && pit->getInset(pos - 1)->isSpace())
1249                         c = ' ';
1250                 else
1251                         c = pit->getChar(pos - 1);
1252
1253                 LyXLayout_ptr const & style = pit->layout();
1254
1255                 BufferParams const & bufparams = bv->buffer()->params();
1256                 if (style->pass_thru ||
1257                     pit->getFontSettings(bufparams,pos).language()->lang() == "hebrew" ||
1258                     !bv->insertInset(new InsetQuotes(c, bufparams)))
1259                         bv->owner()->dispatch(FuncRequest(LFUN_SELFINSERT, "\""));
1260                 break;
1261         }
1262
1263         case LFUN_DATE_INSERT: {
1264                 replaceSelection(bv->getLyXText());
1265                 time_t now_time_t = time(NULL);
1266                 struct tm * now_tm = localtime(&now_time_t);
1267                 setlocale(LC_TIME, "");
1268                 string arg;
1269                 if (!cmd.argument.empty())
1270                         arg = cmd.argument;
1271                 else
1272                         arg = lyxrc.date_insert_format;
1273                 char datetmp[32];
1274                 int const datetmp_len =
1275                         ::strftime(datetmp, 32, arg.c_str(), now_tm);
1276
1277                 for (int i = 0; i < datetmp_len; i++)
1278                         insertChar(datetmp[i]);
1279
1280                 selection.cursor = cursor;
1281                 moveCursorUpdate(bv, false);
1282                 break;
1283         }
1284
1285         case LFUN_MOUSE_TRIPLE:
1286                 if (!bv->buffer())
1287                         break;
1288                 if (cmd.button() == mouse_button::button1) {
1289                         cursorHome();
1290                         selection.cursor = cursor;
1291                         cursorEnd();
1292                         setSelection();
1293                         bv->update();
1294                         bv->haveSelection(selection.set());
1295                 }
1296                 break;
1297
1298         case LFUN_MOUSE_DOUBLE:
1299                 if (!bv->buffer())
1300                         break;
1301                 if (cmd.button() == mouse_button::button1) {
1302                         selectWord(lyx::WHOLE_WORD_STRICT);
1303                         bv->update();
1304                         bv->haveSelection(selection.set());
1305                 }
1306                 break;
1307
1308         case LFUN_MOUSE_MOTION: {
1309                 // Only use motion with button 1
1310                 //if (ev.button() != mouse_button::button1)
1311                 //      return false;
1312
1313                 if (!bv->buffer())
1314                         break;
1315
1316                 // Check for inset locking
1317 #ifdef LOCK
1318                 if (bv->innerInset()) {
1319                         InsetOld * tli = bv->innerInset();
1320                         LyXCursor cursor = bv->text->cursor;
1321                         LyXFont font = bv->text->getFont(bv->text->cursorPar(), cursor.pos());
1322                         int width = tli->width();
1323                         int inset_x = font.isVisibleRightToLeft()
1324                                 ? cursor.x() - width : cursor.x();
1325                         int start_x = inset_x + tli->scroll();
1326                         FuncRequest cmd1 = cmd;
1327                         cmd1.x = cmd.x - start_x;
1328                         cmd1.y = cmd.y - cursor.y() + bv->top_y();
1329                         tli->dispatch(cmd1);
1330                         break;
1331                 }
1332 #endif
1333
1334                 // The test for not selection possible is needed, that only motion
1335                 // events are used, where the bottom press event was on
1336                 //  the drawing area too
1337                 if (!selection_possible) {
1338                         lyxerr[Debug::ACTION]
1339                                 << "BufferView::Pimpl::Dispatch: no selection possible\n";
1340                         break;
1341                 }
1342
1343                 RowList::iterator cursorrow = bv->text->cursorRow();
1344                 bv->text->setCursorFromCoordinates(cmd.x, cmd.y + bv->top_y());
1345         #if 0
1346                 // sorry for this but I have a strange error that the y value jumps at
1347                 // a certain point. This seems like an error in my xforms library or
1348                 // in some other local environment, but I would like to leave this here
1349                 // for the moment until I can remove this (Jug 20020418)
1350                 if (y_before < bv->text->cursor.y())
1351                         lyxerr << y_before << ':'
1352                                << bv->text->cursor.y() << endl;
1353         #endif
1354                 // This is to allow jumping over large insets
1355                 if (cursorrow == bv->text->cursorRow()) {
1356                         if (cmd.y >= bv->workHeight())
1357                                 bv->text->cursorDown(false);
1358                         else if (cmd.y < 0)
1359                                 bv->text->cursorUp(false);
1360                 }
1361
1362                 bv->text->setSelection();
1363                 bv->update();
1364                 break;
1365         }
1366
1367         // Single-click on work area
1368         case LFUN_MOUSE_PRESS: {
1369                 if (!bv->buffer())
1370                         break;
1371
1372                 // ok ok, this is a hack (for xforms)
1373                 // We shouldn't go further down as we really should only do the
1374                 // scrolling and be done with this. Otherwise we may open some
1375                 // dialogs (Jug 20020424).
1376                 if (cmd.button() == mouse_button::button4) {
1377                         bv->scroll(-lyxrc.wheel_jump);
1378                         break;
1379                 }
1380                 if (cmd.button() == mouse_button::button5) {
1381                         bv->scroll(lyxrc.wheel_jump);
1382                         break;
1383                 }
1384
1385                 // Middle button press pastes if we have a selection
1386                 // We do this here as if the selection was inside an inset
1387                 // it could get cleared on the unlocking of the inset so
1388                 // we have to check this first
1389                 bool paste_internally = false;
1390                 if (cmd.button() == mouse_button::button2 && selection.set()) {
1391                         bv->owner()->dispatch(FuncRequest(LFUN_COPY));
1392                         paste_internally = true;
1393                 }
1394
1395                 int const screen_first = bv->top_y();
1396                 selection_possible = true;
1397
1398                 // Clear the selection
1399                 bv->text->clearSelection();
1400                 bv->update();
1401                 bv->updateScrollbar();
1402
1403                 // Right click on a footnote flag opens float menu
1404                 if (cmd.button() == mouse_button::button3) {
1405                         selection_possible = false;
1406                         break;
1407                 }
1408
1409                 bv->text->setCursorFromCoordinates(cmd.x, cmd.y + screen_first);
1410                 finishUndo();
1411                 bv->text->selection.cursor = bv->text->cursor;
1412                 bv->x_target(bv->text->cursor.x());
1413
1414                 if (bv->fitCursor())
1415                         selection_possible = false;
1416
1417                 // Insert primary selection with middle mouse
1418                 // if there is a local selection in the current buffer,
1419                 // insert this
1420                 if (cmd.button() == mouse_button::button2) {
1421                         if (paste_internally)
1422                                 bv->owner()->dispatch(FuncRequest(LFUN_PASTE));
1423                         else
1424                                 bv->owner()->dispatch(FuncRequest(LFUN_PASTESELECTION, "paragraph"));
1425                         selection_possible = false;
1426                 }
1427                 break;
1428         }
1429
1430         case LFUN_MOUSE_RELEASE: {
1431                 // do nothing if we used the mouse wheel
1432                 if (!bv->buffer())
1433                         break;
1434
1435                 if (cmd.button() == mouse_button::button4
1436                  || cmd.button() == mouse_button::button5)
1437                         break;
1438
1439                 selection_possible = false;
1440
1441                 if (cmd.button() == mouse_button::button2)
1442                         break;
1443
1444                 // finish selection
1445                 if (cmd.button() == mouse_button::button1)
1446                         bv->haveSelection(selection.set());
1447
1448                 bv->switchKeyMap();
1449                 bv->owner()->view_state_changed();
1450                 bv->owner()->updateMenubar();
1451                 bv->owner()->updateToolbar();
1452                 break;
1453         }
1454
1455         case LFUN_SELFINSERT: {
1456                 if (cmd.argument.empty())
1457                         break;
1458
1459                 // Automatically delete the currently selected
1460                 // text and replace it with what is being
1461                 // typed in now. Depends on lyxrc settings
1462                 // "auto_region_delete", which defaults to
1463                 // true (on).
1464
1465                 if (lyxrc.auto_region_delete) {
1466                         if (selection.set())
1467                                 cutSelection(false, false);
1468                         bv->haveSelection(false);
1469                 }
1470
1471                 clearSelection();
1472                 LyXFont const old_font = real_current_font;
1473
1474                 string::const_iterator cit = cmd.argument.begin();
1475                 string::const_iterator end = cmd.argument.end();
1476                 for (; cit != end; ++cit)
1477                         bv->owner()->getIntl().getTransManager().
1478                                 TranslateAndInsert(*cit, this);
1479
1480                 selection.cursor = cursor;
1481                 moveCursorUpdate(bv, false);
1482
1483                 // real_current_font.number can change so we need to
1484                 // update the minibuffer
1485                 if (old_font != real_current_font)
1486                         bv->owner()->view_state_changed();
1487                 bv->updateScrollbar();
1488                 break;
1489         }
1490
1491         case LFUN_HTMLURL: {
1492                 InsetCommandParams p("htmlurl");
1493                 string const data = InsetCommandMailer::params2string("url", p);
1494                 bv->owner()->getDialogs().show("url", data, 0);
1495                 break;
1496         }
1497
1498         case LFUN_URL: {
1499                 InsetCommandParams p("url");
1500                 string const data = InsetCommandMailer::params2string("url", p);
1501                 bv->owner()->getDialogs().show("url", data, 0);
1502                 break;
1503         }
1504
1505
1506 #if 0
1507         case LFUN_INSET_LIST:
1508         case LFUN_INSET_THEOREM:
1509         case LFUN_INSET_CAPTION:
1510 #endif
1511         case LFUN_INSERT_NOTE:
1512         case LFUN_INSERT_BOX:
1513         case LFUN_INSERT_BRANCH:
1514         case LFUN_INSERT_BIBITEM:
1515         case LFUN_INSET_ERT:
1516         case LFUN_INSET_FLOAT:
1517         case LFUN_INSET_FOOTNOTE:
1518         case LFUN_INSET_MARGINAL:
1519         case LFUN_INSET_MINIPAGE:
1520         case LFUN_INSET_OPTARG:
1521         case LFUN_INSET_WIDE_FLOAT:
1522         case LFUN_INSET_WRAP:
1523         case LFUN_TABULAR_INSERT:
1524         case LFUN_ENVIRONMENT_INSERT:
1525                 // Open the inset, and move the current selection
1526                 // inside it.
1527                 doInsertInset(this, cmd, true, true);
1528                 break;
1529
1530         case LFUN_INDEX_INSERT:
1531                 // Just open the inset
1532                 doInsertInset(this, cmd, true, false);
1533                 break;
1534
1535         case LFUN_INDEX_PRINT:
1536         case LFUN_TOC_INSERT:
1537         case LFUN_HFILL:
1538         case LFUN_INSERT_LINE:
1539         case LFUN_INSERT_PAGEBREAK:
1540                 // do nothing fancy
1541                 doInsertInset(this, cmd, false, false);
1542                 break;
1543
1544         case LFUN_DEPTH_MIN:
1545                 clearSelection();
1546                 bv_funcs::changeDepth(bv, this, bv_funcs::DEC_DEPTH, false);
1547                 bv->update();
1548                 break;
1549
1550         case LFUN_DEPTH_PLUS:
1551                 clearSelection();
1552                 bv_funcs::changeDepth(bv, this, bv_funcs::INC_DEPTH, false);
1553                 bv->update();
1554                 break;
1555
1556         case LFUN_MATH_DELIM:
1557         case LFUN_MATH_DISPLAY:
1558         case LFUN_INSERT_MATH:
1559         case LFUN_MATH_LIMITS:
1560         case LFUN_MATH_MACRO:
1561         case LFUN_MATH_MUTATE:
1562         case LFUN_MATH_SPACE:
1563         case LFUN_MATH_IMPORT_SELECTION:
1564         case LFUN_MATH_MODE:
1565         case LFUN_MATH_NONUMBER:
1566         case LFUN_MATH_NUMBER:
1567         case LFUN_MATH_EXTERN:
1568         case LFUN_MATH_SIZE:
1569                 mathDispatch(cmd);
1570                 break;
1571
1572         case LFUN_EMPH:
1573                 emph(bv, this);
1574                 bv->owner()->view_state_changed();
1575                 break;
1576
1577         case LFUN_BOLD:
1578                 bold(bv, this);
1579                 bv->owner()->view_state_changed();
1580                 break;
1581
1582         case LFUN_NOUN:
1583                 noun(bv, this);
1584                 bv->owner()->view_state_changed();
1585                 break;
1586
1587         case LFUN_CODE:
1588                 code(bv, this);
1589                 bv->owner()->view_state_changed();
1590                 break;
1591
1592         case LFUN_SANS:
1593                 sans(bv, this);
1594                 bv->owner()->view_state_changed();
1595                 break;
1596
1597         case LFUN_ROMAN:
1598                 roman(bv, this);
1599                 bv->owner()->view_state_changed();
1600                 break;
1601
1602         case LFUN_DEFAULT:
1603                 styleReset(bv, this);
1604                 bv->owner()->view_state_changed();
1605                 break;
1606
1607         case LFUN_UNDERLINE:
1608                 underline(bv, this);
1609                 bv->owner()->view_state_changed();
1610                 break;
1611
1612         case LFUN_FONT_SIZE:
1613                 fontSize(bv, cmd.argument, this);
1614                 bv->owner()->view_state_changed();
1615                 break;
1616
1617         case LFUN_LANGUAGE:
1618                 lang(bv, cmd.argument, this);
1619                 bv->switchKeyMap();
1620                 bv->owner()->view_state_changed();
1621                 break;
1622
1623         case LFUN_FREEFONT_APPLY:
1624                 apply_freefont(bv, this);
1625                 break;
1626
1627         case LFUN_FREEFONT_UPDATE:
1628                 update_and_apply_freefont(bv, this, cmd.argument);
1629                 break;
1630         
1631         case LFUN_FINISHED_LEFT:
1632                 lyxerr << "swallow LFUN_FINISHED_LEFT" << endl;
1633                 if (rtl())
1634                         cursorRight(bv);
1635                 break;
1636
1637         case LFUN_FINISHED_RIGHT:
1638                 lyxerr << "swallow LFUN_FINISHED_RIGHT" << endl;
1639                 if (!rtl())
1640                         cursorRight(bv);
1641                 break;
1642
1643         case LFUN_FINISHED_UP:
1644                 lyxerr << "swallow LFUN_FINISHED_UP" << endl;
1645                 break;
1646
1647         case LFUN_FINISHED_DOWN:
1648                 lyxerr << "swallow LFUN_FINISHED_DOWN" << endl;
1649                 cursorRight(bv);
1650                 break;
1651
1652         default:
1653                 return DispatchResult(false);
1654         }
1655
1656         return DispatchResult(true, true);
1657 }