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