]> git.lyx.org Git - lyx.git/blob - src/text3.C
remove part of old texted<->mathed interface
[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 "FloatList.h"
21 #include "FuncStatus.h"
22 #include "buffer.h"
23 #include "bufferparams.h"
24 #include "BufferView.h"
25 #include "cursor.h"
26 #include "debug.h"
27 #include "dispatchresult.h"
28 #include "factory.h"
29 #include "funcrequest.h"
30 #include "gettext.h"
31 #include "intl.h"
32 #include "language.h"
33 #include "lyxfunc.h"
34 #include "lyxlex.h"
35 #include "lyxrc.h"
36 #include "lyxrow.h"
37 #include "paragraph.h"
38 #include "paragraph_funcs.h"
39 #include "ParagraphParameters.h"
40 #include "undo.h"
41 #include "vspace.h"
42
43 #include "frontends/Dialogs.h"
44 #include "frontends/LyXView.h"
45
46 #include "insets/insetcommand.h"
47 #include "insets/insetfloatlist.h"
48 #include "insets/insetnewline.h"
49 #include "insets/insetquotes.h"
50 #include "insets/insetspecialchar.h"
51 #include "insets/insettext.h"
52
53 #include "support/lstrings.h"
54 #include "support/lyxlib.h"
55 #include "support/tostr.h"
56 #include "support/std_sstream.h"
57
58 #include "mathed/math_hullinset.h"
59 #include "mathed/formulamacro.h"
60
61 #include <clocale>
62
63 using lyx::pos_type;
64
65 using lyx::support::isStrUnsignedInt;
66 using lyx::support::strToUnsignedInt;
67 using lyx::support::atoi;
68 using lyx::support::token;
69
70 using std::endl;
71 using std::find;
72 using std::string;
73 using std::istringstream;
74 using std::vector;
75
76
77 extern string current_layout;
78
79 // the selection possible is needed, that only motion events are
80 // used, where the button press event was on the drawing area too
81 bool selection_possible = false;
82
83
84 namespace {
85
86         // globals...
87         LyXFont freefont(LyXFont::ALL_IGNORE);
88         bool toggleall = false;
89
90
91         void toggleAndShow(LCursor & cur, LyXText * text,
92                 LyXFont const & font, bool toggleall = true)
93         {
94                 text->toggleFree(cur, font, toggleall);
95
96                 if (font.language() != ignore_language ||
97                                 font.number() != LyXFont::IGNORE) {
98                         Paragraph & par = cur.paragraph();
99                         text->bidi.computeTables(par, *cur.bv().buffer(), cur.textRow());
100                         if (cur.boundary() !=
101                                         text->bidi.isBoundary(*cur.bv().buffer(), par,
102                                                         cur.pos(),
103                                                         text->real_current_font))
104                                 text->setCursor(cur, cur.par(), cur.pos(),
105                                                 false, !cur.boundary());
106                 }
107         }
108
109
110         void moveCursor(LCursor & cur, bool selecting)
111         {
112                 if (selecting || cur.mark())
113                         cur.setSelection();
114                 if (!cur.selection())
115                         cur.bv().haveSelection(false);
116                 cur.bv().switchKeyMap();
117         }
118
119
120         void finishChange(LCursor & cur, bool selecting)
121         {
122                 finishUndo();
123                 moveCursor(cur, selecting);
124         }
125
126
127         void mathDispatch(LCursor & cur, LyXText * text,
128                 FuncRequest const & cmd, bool display)
129         {
130                 recordUndo(cur);
131                 string sel = cur.selectionAsString(false);
132                 lyxerr << "selection is: '" << sel << "'" << endl;
133
134                 if (sel.empty()) {
135                         cur.insert(new MathHullInset);
136                         cur.dispatch(FuncRequest(LFUN_RIGHT));
137                         cur.dispatch(FuncRequest(LFUN_MATH_MUTATE, "simple"));
138                         // don't do that also for LFUN_MATH_MODE unless you want end up with
139                         // always changing to mathrm when opening an inlined inset
140                         // -- I really hate "LyXfunc overloading"...
141                         if (display)
142                                 cur.dispatch(FuncRequest(LFUN_MATH_DISPLAY));
143                         cur.dispatch(FuncRequest(LFUN_INSERT_MATH, cmd.argument));
144                 } else {
145                         // create a macro if we see "\\newcommand" somewhere, and an ordinary
146                         // formula otherwise
147                         text->cutSelection(cur, true, true);
148                         if (sel.find("\\newcommand") == string::npos
149                             && sel.find("\\def") == string::npos)
150                         {
151                                 cur.insert(new MathHullInset);
152                                 cur.dispatch(FuncRequest(LFUN_RIGHT));
153                                 cur.dispatch(FuncRequest(LFUN_MATH_MUTATE, "simple"));
154                                 cur.dispatch(FuncRequest(LFUN_INSERT_MATH, sel));
155                         } else {
156                                 cur.insert(new InsetFormulaMacro(sel));
157                                 cur.dispatch(FuncRequest(LFUN_RIGHT));
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                                 cur.top() = 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         recordUndo(cur);
345         bool gotsel = false;
346         if (cur.selection()) {
347                 cur.bv().owner()->dispatch(FuncRequest(LFUN_CUT));
348                 gotsel = true;
349         }
350         text->insertInset(cur, inset);
351         if (edit)
352                 inset->edit(cur, true);
353         if (gotsel && pastesel)
354                 cur.bv().owner()->dispatch(FuncRequest(LFUN_PASTE));
355 }
356
357 } // anon namespace
358
359
360 void LyXText::number(LCursor & cur)
361 {
362         LyXFont font(LyXFont::ALL_IGNORE);
363         font.setNumber(LyXFont::TOGGLE);
364         toggleAndShow(cur, this, font);
365 }
366
367
368 bool LyXText::isRTL(Paragraph const & par) const
369 {
370         return par.isRightToLeftPar(bv()->buffer()->params());
371 }
372
373
374 void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
375 {
376         lyxerr[Debug::ACTION] << "LyXText::dispatch: cmd: " << cmd << endl;
377         //lyxerr << "*** LyXText::dispatch: cmd: " << cmd << endl;
378
379         BOOST_ASSERT(cur.text() == this);
380         BufferView * bv = &cur.bv();
381         CursorSlice sl = cur.top();
382
383         switch (cmd.action) {
384
385         case LFUN_APPENDIX: {
386                 Paragraph & par = cur.paragraph();
387                 bool start = !par.params().startOfAppendix();
388
389                 // ensure that we have only one start_of_appendix in this document
390                 ParagraphList::iterator tmp = paragraphs().begin();
391                 ParagraphList::iterator end = paragraphs().end();
392
393                 for (; tmp != end; ++tmp) {
394                         if (tmp->params().startOfAppendix()) {
395                                 recUndo(parOffset(tmp));
396                                 tmp->params().startOfAppendix(false);
397                                 redoParagraph(tmp);
398                                 break;
399                         }
400                 }
401
402                 recordUndo(cur);
403                 par.params().startOfAppendix(start);
404
405                 // we can set the refreshing parameters now
406                 updateCounters();
407                 redoParagraph(cur);
408                 cur.update();
409                 break;
410         }
411
412         case LFUN_DELETE_WORD_FORWARD:
413                 cur.clearSelection();
414                 deleteWordForward(cur);
415                 finishChange(cur, false);
416                 break;
417
418         case LFUN_DELETE_WORD_BACKWARD:
419                 cur.clearSelection();
420                 deleteWordBackward(cur);
421                 finishChange(cur, false);
422                 break;
423
424         case LFUN_DELETE_LINE_FORWARD:
425                 cur.clearSelection();
426                 deleteLineForward(cur);
427                 finishChange(cur, false);
428                 break;
429
430         case LFUN_WORDRIGHT:
431                 if (!cur.mark())
432                         cur.clearSelection();
433                 if (isRTL(cur.paragraph()))
434                         cursorLeftOneWord(cur);
435                 else
436                         cursorRightOneWord(cur);
437                 finishChange(cur, false);
438                 break;
439
440         case LFUN_WORDLEFT:
441                 if (!cur.mark())
442                         cur.clearSelection();
443                 if (isRTL(cur.paragraph()))
444                         cursorRightOneWord(cur);
445                 else
446                         cursorLeftOneWord(cur);
447                 finishChange(cur, false);
448                 break;
449
450         case LFUN_BEGINNINGBUF:
451                 if (!cur.mark())
452                         cur.clearSelection();
453                 cursorTop(cur);
454                 finishChange(cur, false);
455                 break;
456
457         case LFUN_ENDBUF:
458                 if (!cur.mark())
459                         cur.clearSelection();
460                 cursorBottom(cur);
461                 finishChange(cur, false);
462                 break;
463
464         case LFUN_RIGHT:
465         case LFUN_RIGHTSEL:
466                 cur.selHandle(cmd.action == LFUN_RIGHTSEL);
467                 if (isRTL(cur.paragraph()))
468                         cursorLeft(cur);
469                 else
470                         cursorRight(cur);
471                 if (sl == cur.top())
472                         cmd = FuncRequest(LFUN_FINISHED_RIGHT);
473                 break;
474
475         case LFUN_LEFT:
476         case LFUN_LEFTSEL:
477                 cur.selHandle(cmd.action == LFUN_LEFTSEL);
478                 if (isRTL(cur.paragraph()))
479                         cursorRight(cur);
480                 else
481                         cursorLeft(cur);
482                 if (sl == cur.top())
483                         cmd = FuncRequest(LFUN_FINISHED_LEFT);
484                 break;
485
486         case LFUN_UP:
487         case LFUN_UPSEL:
488                 cur.selHandle(cmd.action == LFUN_UPSEL);
489                 cursorUp(cur);
490                 if (sl == cur.top())
491                         cmd = FuncRequest(LFUN_FINISHED_UP);
492                 break;
493
494         case LFUN_DOWN:
495         case LFUN_DOWNSEL:
496                 cur.selHandle(cmd.action == LFUN_DOWNSEL);
497                 cursorDown(cur);
498                 if (sl == cur.top())
499                         cmd = FuncRequest(LFUN_FINISHED_DOWN);
500                 break;
501
502         case LFUN_UP_PARAGRAPHSEL:
503                 if (!cur.selection())
504                         cur.resetAnchor();
505                 cursorUpParagraph(cur);
506                 finishChange(cur, true);
507                 break;
508
509         case LFUN_DOWN_PARAGRAPHSEL:
510                 if (!cur.selection())
511                         cur.resetAnchor();
512                 cursorDownParagraph(cur);
513                 finishChange(cur, true);
514                 break;
515
516         case LFUN_PRIORSEL:
517                 if (!cur.selection())
518                         cur.resetAnchor();
519                 cursorPrevious(cur);
520                 finishChange(cur, true);
521                 break;
522
523         case LFUN_NEXTSEL:
524                 if (!cur.selection())
525                         cur.resetAnchor();
526                 cursorNext(cur);
527                 finishChange(cur, true);
528                 break;
529
530         case LFUN_HOMESEL:
531                 if (!cur.selection())
532                         cur.resetAnchor();
533                 cursorHome(cur);
534                 finishChange(cur, true);
535                 break;
536
537         case LFUN_ENDSEL:
538                 if (!cur.selection())
539                         cur.resetAnchor();
540                 cursorEnd(cur);
541                 finishChange(cur, true);
542                 break;
543
544         case LFUN_WORDRIGHTSEL:
545                 if (!cur.selection())
546                         cur.resetAnchor();
547                 if (isRTL(cur.paragraph()))
548                         cursorLeftOneWord(cur);
549                 else
550                         cursorRightOneWord(cur);
551                 finishChange(cur, true);
552                 break;
553
554         case LFUN_WORDLEFTSEL:
555                 if (!cur.selection())
556                         cur.resetAnchor();
557                 if (isRTL(cur.paragraph()))
558                         cursorRightOneWord(cur);
559                 else
560                         cursorLeftOneWord(cur);
561                 finishChange(cur, true);
562                 break;
563
564         case LFUN_WORDSEL: {
565                 selectWord(cur, lyx::WHOLE_WORD);
566                 finishChange(cur, true);
567                 break;
568         }
569
570         case LFUN_UP_PARAGRAPH:
571                 if (!cur.mark())
572                         cur.clearSelection();
573                 cursorUpParagraph(cur);
574                 finishChange(cur, false);
575                 break;
576
577         case LFUN_DOWN_PARAGRAPH:
578                 if (!cur.mark())
579                         cur.clearSelection();
580                 cursorDownParagraph(cur);
581                 finishChange(cur, false);
582                 break;
583
584         case LFUN_PRIOR:
585                 if (!cur.mark())
586                         cur.clearSelection();
587                 finishChange(cur, false);
588                 if (cur.par() == 0 && cur.textRow().pos() == 0)
589                         cmd = FuncRequest(LFUN_FINISHED_UP);
590                 else
591                         cursorPrevious(cur);
592                 break;
593
594         case LFUN_NEXT:
595                 if (!cur.mark())
596                         cur.clearSelection();
597                 finishChange(cur, false);
598                 if (cur.par() == cur.lastpar()
599                           && cur.textRow().endpos() == cur.lastpos())
600                         cmd = FuncRequest(LFUN_FINISHED_DOWN);
601                 else
602                         cursorNext(cur);
603                 break;
604
605         case LFUN_HOME:
606                 if (!cur.mark())
607                         cur.clearSelection();
608                 cursorHome(cur);
609                 finishChange(cur, false);
610                 break;
611
612         case LFUN_END:
613                 if (!cur.mark())
614                         cur.clearSelection();
615                 cursorEnd(cur);
616                 finishChange(cur, false);
617                 break;
618
619         case LFUN_BREAKLINE: {
620                 // Not allowed by LaTeX (labels or empty par)
621                 if (cur.pos() > cur.paragraph().beginOfBody()) {
622                         replaceSelection(cur);
623                         cur.insert(new InsetNewline);
624                         moveCursor(cur, false);
625                 }
626                 break;
627         }
628
629         case LFUN_DELETE:
630                 if (!cur.selection()) {
631                         Delete(cur);
632                         cur.resetAnchor();
633                         // It is possible to make it a lot faster still
634                         // just comment out the line below...
635                 } else {
636                         cutSelection(cur, true, false);
637                 }
638                 moveCursor(cur, false);
639                 break;
640
641         case LFUN_DELETE_SKIP:
642                 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
643                 if (!cur.selection()) {
644                         if (cur.pos() == cur.lastpos()) {
645                                 cursorRight(cur);
646                                 cursorLeft(cur);
647                         }
648                         Delete(cur);
649                         cur.resetAnchor();
650                 } else {
651                         cutSelection(cur, true, false);
652                 }
653                 cur.update();
654                 break;
655
656
657         case LFUN_BACKSPACE:
658                 if (!cur.selection()) {
659                         if (bv->owner()->getIntl().getTransManager().backspace()) {
660                                 backspace(cur);
661                                 cur.resetAnchor();
662                                 // It is possible to make it a lot faster still
663                                 // just comment out the line below...
664                         }
665                 } else {
666                         cutSelection(cur, true, false);
667                 }
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                 break;
692
693         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
694                 replaceSelection(cur);
695                 breakParagraph(cur, 1);
696                 cur.update();
697                 cur.resetAnchor();
698                 bv->switchKeyMap();
699                 break;
700
701         case LFUN_BREAKPARAGRAPH_SKIP: {
702                 // When at the beginning of a paragraph, remove
703                 // indentation and add a "defskip" at the top.
704                 // Otherwise, do the same as LFUN_BREAKPARAGRAPH.
705                 replaceSelection(cur);
706                 if (cur.pos() == 0) {
707                         ParagraphParameters & params = cur.paragraph().params();
708                         setParagraph(cur,
709                                         params.spacing(),
710                                         params.align(),
711                                         params.labelWidthString(), 1);
712                 } else {
713                         breakParagraph(cur, 0);
714                 }
715                 cur.update();
716 //      anchor() = cur;
717                 bv->switchKeyMap();
718                 break;
719         }
720
721         case LFUN_PARAGRAPH_SPACING: {
722                 Paragraph & par = cur.paragraph();
723                 Spacing::Space cur_spacing = par.params().spacing().getSpace();
724                 float cur_value = 1.0;
725                 if (cur_spacing == Spacing::Other)
726                         cur_value = par.params().spacing().getValue();
727
728                 istringstream is(cmd.argument);
729                 string tmp;
730                 is >> tmp;
731                 Spacing::Space new_spacing = cur_spacing;
732                 float new_value = cur_value;
733                 if (tmp.empty()) {
734                         lyxerr << "Missing argument to `paragraph-spacing'"
735                                << endl;
736                 } else if (tmp == "single") {
737                         new_spacing = Spacing::Single;
738                 } else if (tmp == "onehalf") {
739                         new_spacing = Spacing::Onehalf;
740                 } else if (tmp == "double") {
741                         new_spacing = Spacing::Double;
742                 } else if (tmp == "other") {
743                         new_spacing = Spacing::Other;
744                         float tmpval = 0.0;
745                         is >> tmpval;
746                         lyxerr << "new_value = " << tmpval << endl;
747                         if (tmpval != 0.0)
748                                 new_value = tmpval;
749                 } else if (tmp == "default") {
750                         new_spacing = Spacing::Default;
751                 } else {
752                         lyxerr << _("Unknown spacing argument: ")
753                                << cmd.argument << endl;
754                 }
755                 if (cur_spacing != new_spacing || cur_value != new_value) {
756                         par.params().spacing(Spacing(new_spacing, new_value));
757                         redoParagraph(cur);
758                         cur.update();
759                 }
760                 break;
761         }
762
763         case LFUN_INSET_APPLY: {
764                 string const name = cmd.getArg(0);
765                 InsetBase * inset = bv->owner()->getDialogs().getOpenInset(name);
766                 if (inset) {
767                         FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument);
768                         inset->dispatch(cur, fr);
769                 } else {
770                         FuncRequest fr(LFUN_INSET_INSERT, cmd.argument);
771                         dispatch(cur, fr);
772                 }
773                 break;
774         }
775
776         case LFUN_INSET_INSERT: {
777                 recordUndo(cur);
778                 InsetBase * inset = createInset(bv, cmd);
779                 if (inset)
780                         insertInset(cur, inset);
781                 break;
782         }
783
784         case LFUN_INSET_SETTINGS:
785                 if (cur.inset().asUpdatableInset())
786                         cur.inset().asUpdatableInset()->showInsetDialog(bv);
787                 break;
788
789         case LFUN_INSET_TOGGLE:
790                 cur.clearSelection();
791                 if (!toggleInset(cur))
792                         cur.undispatched();
793                 else
794                         bv->switchKeyMap();
795                 break;
796
797         case LFUN_SPACE_INSERT:
798                 if (cur.paragraph().layout()->free_spacing)
799                         insertChar(cur, ' ');
800                 else
801                         doInsertInset(cur, this, cmd, false, false);
802                 moveCursor(cur, false);
803                 break;
804
805         case LFUN_HYPHENATION:
806                 specialChar(cur, this, InsetSpecialChar::HYPHENATION);
807                 break;
808
809         case LFUN_LIGATURE_BREAK:
810                 specialChar(cur, this, InsetSpecialChar::LIGATURE_BREAK);
811                 break;
812
813         case LFUN_LDOTS:
814                 specialChar(cur, this, InsetSpecialChar::LDOTS);
815                 break;
816
817         case LFUN_END_OF_SENTENCE:
818                 specialChar(cur, this, InsetSpecialChar::END_OF_SENTENCE);
819                 break;
820
821         case LFUN_MENU_SEPARATOR:
822                 specialChar(cur, this, InsetSpecialChar::MENU_SEPARATOR);
823                 break;
824
825         case LFUN_UPCASE_WORD:
826                 changeCase(cur, LyXText::text_uppercase);
827                 cur.update();
828                 break;
829
830         case LFUN_LOWCASE_WORD:
831                 changeCase(cur, LyXText::text_lowercase);
832                 cur.update();
833                 break;
834
835         case LFUN_CAPITALIZE_WORD:
836                 changeCase(cur, LyXText::text_capitalization);
837                 cur.update();
838                 break;
839
840         case LFUN_TRANSPOSE_CHARS:
841                 recordUndo(cur);
842                 redoParagraph(cur);
843                 cur.update();
844                 break;
845
846         case LFUN_PASTE:
847                 cur.message(_("Paste"));
848                 replaceSelection(cur);
849 #warning FIXME Check if the arg is in the domain of available selections.
850                 if (isStrUnsignedInt(cmd.argument))
851                         pasteSelection(cur, strToUnsignedInt(cmd.argument));
852                 else
853                         pasteSelection(cur, 0);
854                 cur.clearSelection(); // bug 393
855                 cur.update();
856                 bv->switchKeyMap();
857                 finishUndo();
858                 break;
859
860         case LFUN_CUT:
861                 cutSelection(cur, true, true);
862                 cur.message(_("Cut"));
863                 cur.update();
864                 break;
865
866         case LFUN_COPY:
867                 copySelection(cur);
868                 cur.message(_("Copy"));
869                 break;
870
871         case LFUN_GETXY:
872                 cur.message(tostr(cursorX(cur.top())) + ' '
873                           + tostr(cursorY(cur.top())));
874                 break;
875
876         case LFUN_SETXY: {
877                 int x = 0;
878                 int y = 0;
879                 istringstream is(cmd.argument);
880                 is >> x >> y;
881                 if (!is)
882                         lyxerr << "SETXY: Could not parse coordinates in '"
883                                << cmd.argument << std::endl;
884                 else
885                         setCursorFromCoordinates(cur, x, y);
886                 break;
887         }
888
889         case LFUN_GETFONT:
890                 if (current_font.shape() == LyXFont::ITALIC_SHAPE)
891                         cur.message("E");
892                 else if (current_font.shape() == LyXFont::SMALLCAPS_SHAPE)
893                         cur.message("N");
894                 else
895                         cur.message("0");
896                 break;
897
898         case LFUN_GETLAYOUT:
899                 cur.message(cur.paragraph().layout()->name());
900                 break;
901
902         case LFUN_LAYOUT: {
903                 lyxerr[Debug::INFO] << "LFUN_LAYOUT: (arg) "
904                   << cmd.argument << endl;
905
906                 // This is not the good solution to the empty argument
907                 // problem, but it will hopefully suffice for 1.2.0.
908                 // The correct solution would be to augument the
909                 // function list/array with information about what
910                 // functions needs arguments and their type.
911                 if (cmd.argument.empty()) {
912                         cur.errorMessage(_("LyX function 'layout' needs an argument."));
913                         break;
914                 }
915
916                 // Derive layout number from given argument (string)
917                 // and current buffer's textclass (number)
918                 LyXTextClass const & tclass = bv->buffer()->params().getLyXTextClass();
919                 bool hasLayout = tclass.hasLayout(cmd.argument);
920                 string layout = cmd.argument;
921
922                 // If the entry is obsolete, use the new one instead.
923                 if (hasLayout) {
924                         string const & obs = tclass[layout]->obsoleted_by();
925                         if (!obs.empty())
926                                 layout = obs;
927                 }
928
929                 if (!hasLayout) {
930                         cur.errorMessage(string(N_("Layout ")) + cmd.argument +
931                                 N_(" not known"));
932                         break;
933                 }
934
935                 bool change_layout = (current_layout != layout);
936
937                 if (!change_layout && cur.selection() &&
938                         cur.selBegin().par() != cur.selEnd().par())
939                 {
940                         ParagraphList::iterator spit = getPar(cur.selBegin());
941                         ParagraphList::iterator epit = boost::next(getPar(cur.selEnd()));
942                         while (spit != epit) {
943                                 if (spit->layout()->name() != current_layout) {
944                                         change_layout = true;
945                                         break;
946                                 }
947                                 ++spit;
948                         }
949                 }
950
951                 if (change_layout) {
952                         current_layout = layout;
953                         setLayout(cur, layout);
954                         bv->owner()->setLayout(layout);
955                         cur.update();
956                         bv->switchKeyMap();
957                 }
958                 break;
959         }
960
961         case LFUN_PASTESELECTION: {
962                 cur.clearSelection();
963                 string const clip = bv->getClipboard();
964                 if (!clip.empty()) {
965                         if (cmd.argument == "paragraph")
966                                 insertStringAsParagraphs(cur, clip);
967                         else
968                                 insertStringAsLines(cur, clip);
969                         cur.update();
970                 }
971                 break;
972         }
973
974         case LFUN_GOTOERROR:
975                 gotoInset(cur, InsetBase::ERROR_CODE, false);
976                 break;
977
978         case LFUN_GOTONOTE:
979                 gotoInset(cur, InsetBase::NOTE_CODE, false);
980                 break;
981
982         case LFUN_REFERENCE_GOTO: {
983                 vector<InsetOld_code> tmp;
984                 tmp.push_back(InsetBase::LABEL_CODE);
985                 tmp.push_back(InsetBase::REF_CODE);
986                 gotoInset(cur, tmp, true);
987                 break;
988         }
989
990         case LFUN_QUOTE: {
991                 replaceSelection(cur);
992                 Paragraph & par = cur.paragraph();
993                 lyx::pos_type pos = cur.pos();
994                 char c;
995                 if (pos == 0)
996                         c = ' ';
997                 else if (cur.prevInset() && cur.prevInset()->isSpace())
998                         c = ' ';
999                 else
1000                         c = par.getChar(pos - 1);
1001
1002                 LyXLayout_ptr const & style = par.layout();
1003                 
1004                 BufferParams const & bufparams = bv->buffer()->params();
1005                 if (!style->pass_thru
1006                     && par.getFontSettings(bufparams, pos).language()->lang() != "hebrew") {
1007                         string arg = cmd.argument;
1008                         if (arg == "single")
1009                                 cur.insert(new InsetQuotes(c,
1010                                     bufparams.quotes_language, 
1011                                     InsetQuotes::SingleQ));
1012                         else if (arg == "double")
1013                                 cur.insert(new InsetQuotes(c,
1014                                     bufparams.quotes_language, 
1015                                     InsetQuotes::DoubleQ));
1016                         else
1017                                 cur.insert(new InsetQuotes(c, bufparams));
1018                 }
1019                 else
1020                         bv->owner()->dispatch(FuncRequest(LFUN_SELFINSERT, "\""));
1021                 break;
1022         }
1023
1024         case LFUN_DATE_INSERT: {
1025                 replaceSelection(cur);
1026                 time_t now_time_t = time(NULL);
1027                 struct tm * now_tm = localtime(&now_time_t);
1028                 setlocale(LC_TIME, "");
1029                 string arg;
1030                 if (!cmd.argument.empty())
1031                         arg = cmd.argument;
1032                 else
1033                         arg = lyxrc.date_insert_format;
1034                 char datetmp[32];
1035                 int const datetmp_len =
1036                         ::strftime(datetmp, 32, arg.c_str(), now_tm);
1037
1038                 for (int i = 0; i < datetmp_len; i++)
1039                         insertChar(cur, datetmp[i]);
1040
1041                 cur.resetAnchor();
1042                 moveCursor(cur, false);
1043                 break;
1044         }
1045
1046         case LFUN_MOUSE_TRIPLE:
1047                 if (cmd.button() == mouse_button::button1) {
1048                         selection_possible = true;
1049                         cursorHome(cur);
1050                         cur.resetAnchor();
1051                         cursorEnd(cur);
1052                         cur.setSelection();
1053                         bv->haveSelection(cur.selection());
1054                 }
1055                 break;
1056
1057         case LFUN_MOUSE_DOUBLE:
1058                 if (cmd.button() == mouse_button::button1) {
1059                         selection_possible = true;
1060                         selectWord(cur, lyx::WHOLE_WORD_STRICT);
1061                         bv->haveSelection(cur.selection());
1062                 }
1063                 break;
1064
1065         case LFUN_MOUSE_MOTION: {
1066                 // Only use motion with button 1
1067                 //if (cmd.button() != mouse_button::button1)
1068                 //      return false;
1069                 // The test for not selection possible is needed, that
1070                 // only motion events are used, where the bottom press
1071                 // event was on the drawing area too
1072                 if (!selection_possible) {
1073                         lyxerr[Debug::ACTION] << "BufferView::Pimpl::"
1074                                 "Dispatch: no selection possible\n";
1075                         break;
1076                 }
1077                 CursorSlice old = cur.top();
1078                 setCursorFromCoordinates(cur, cmd.x, cmd.y);
1079
1080                 // This is to allow jumping over large insets
1081                 // FIXME: shouldn't be top-text-specific
1082                 if (isMainText() && cur.top() == old) {
1083                         if (cmd.y - bv->top_y() >= bv->workHeight())
1084                                 cursorDown(cur);
1085                         else if (cmd.y - bv->top_y() < 0)
1086                                 cursorUp(cur);
1087                 }
1088
1089                 // don't set anchor_
1090                 bv->cursor().setCursor(cur, false);
1091                 break;
1092         }
1093
1094         // Single-click on work area
1095         case LFUN_MOUSE_PRESS: {
1096                 // ok ok, this is a hack (for xforms)
1097                 // We shouldn't go further down as we really should only do the
1098                 // scrolling and be done with this. Otherwise we may open some
1099                 // dialogs (Jug 20020424).
1100                 if (cmd.button() == mouse_button::button4) {
1101                         bv->scroll(-lyxrc.wheel_jump);
1102                         break;
1103                 }
1104
1105                 if (cmd.button() == mouse_button::button5) {
1106                         bv->scroll(lyxrc.wheel_jump);
1107                         break;
1108                 }
1109
1110                 // Right click on a footnote flag opens float menu
1111                 if (cmd.button() == mouse_button::button3) {
1112                         cur.clearSelection();
1113                         selection_possible = false;
1114                         break;
1115                 }
1116
1117                 // Middle button press pastes if we have a selection
1118                 // We do this here as if the selection was inside an inset
1119                 // it could get cleared on the unlocking of the inset so
1120                 // we have to check this first
1121                 bool paste_internally = false;
1122                 if (cmd.button() == mouse_button::button2 && cur.selection()) {
1123                         bv->owner()->dispatch(FuncRequest(LFUN_COPY));
1124                         paste_internally = true;
1125                 }
1126
1127                 selection_possible = true;
1128
1129                 // Clear the selection
1130                 cur.clearSelection();
1131
1132                 setCursorFromCoordinates(cur, cmd.x, cmd.y);
1133                 cur.resetAnchor();
1134                 finishUndo();
1135                 cur.x_target() = cursorX(cur.top());
1136
1137                 // set cursor and anchor to this position
1138                 bv->cursor() = cur;
1139
1140                 if (bv->fitCursor())
1141                         selection_possible = false;
1142
1143                 // Insert primary selection with middle mouse
1144                 // if there is a local selection in the current buffer,
1145                 // insert this
1146                 if (cmd.button() == mouse_button::button2) {
1147                         if (paste_internally)
1148                                 bv->owner()->dispatch(FuncRequest(LFUN_PASTE));
1149                         else
1150                                 bv->owner()->dispatch(FuncRequest(LFUN_PASTESELECTION, "paragraph"));
1151                         selection_possible = false;
1152                 }
1153                 break;
1154         }
1155
1156         case LFUN_MOUSE_RELEASE: {
1157                 // do nothing if we used the mouse wheel
1158                 if (cmd.button() == mouse_button::button4
1159                  || cmd.button() == mouse_button::button5) {
1160                         cur.undispatched();
1161                         break;
1162                 }
1163
1164                 selection_possible = false;
1165
1166                 if (cmd.button() == mouse_button::button2)
1167                         break;
1168
1169                 // finish selection
1170                 if (cmd.button() == mouse_button::button1)
1171                         bv->haveSelection(cur.selection());
1172
1173                 bv->switchKeyMap();
1174                 bv->owner()->updateMenubar();
1175                 bv->owner()->updateToolbar();
1176                 break;
1177         }
1178
1179         case LFUN_SELFINSERT: {
1180                 if (cmd.argument.empty())
1181                         break;
1182
1183                 // Automatically delete the currently selected
1184                 // text and replace it with what is being
1185                 // typed in now. Depends on lyxrc settings
1186                 // "auto_region_delete", which defaults to
1187                 // true (on).
1188
1189                 if (lyxrc.auto_region_delete) {
1190                         if (cur.selection())
1191                                 cutSelection(cur, false, false);
1192                         bv->haveSelection(false);
1193                 }
1194
1195                 cur.clearSelection();
1196                 LyXFont const old_font = real_current_font;
1197
1198                 string::const_iterator cit = cmd.argument.begin();
1199                 string::const_iterator end = cmd.argument.end();
1200                 for (; cit != end; ++cit)
1201                         bv->owner()->getIntl().getTransManager().
1202                                 TranslateAndInsert(*cit, this);
1203
1204                 cur.resetAnchor();
1205                 moveCursor(cur, false);
1206
1207                 // real_current_font.number can change so we need to
1208                 // update the minibuffer
1209                 if (old_font != real_current_font)
1210                 bv->updateScrollbar();
1211                 break;
1212         }
1213
1214         case LFUN_URL: {
1215                 InsetCommandParams p("url");
1216                 string const data = InsetCommandMailer::params2string("url", p);
1217                 bv->owner()->getDialogs().show("url", data, 0);
1218                 break;
1219         }
1220
1221         case LFUN_HTMLURL: {
1222                 InsetCommandParams p("htmlurl");
1223                 string const data = InsetCommandMailer::params2string("url", p);
1224                 bv->owner()->getDialogs().show("url", data, 0);
1225                 break;
1226         }
1227
1228         case LFUN_INSERT_LABEL: {
1229                 InsetCommandParams p("label");
1230                 string const data = InsetCommandMailer::params2string("label", p);
1231                 bv->owner()->getDialogs().show("label", data, 0);
1232                 break;
1233         }
1234
1235
1236 #if 0
1237         case LFUN_INSET_LIST:
1238         case LFUN_INSET_THEOREM:
1239         case LFUN_INSET_CAPTION:
1240 #endif
1241         case LFUN_INSERT_NOTE:
1242         case LFUN_INSERT_CHARSTYLE:
1243         case LFUN_INSERT_BOX:
1244         case LFUN_INSERT_BRANCH:
1245         case LFUN_INSERT_BIBITEM:
1246         case LFUN_INSET_ERT:
1247         case LFUN_INSET_FLOAT:
1248         case LFUN_INSET_FOOTNOTE:
1249         case LFUN_INSET_MARGINAL:
1250         case LFUN_INSET_OPTARG:
1251         case LFUN_INSET_WIDE_FLOAT:
1252         case LFUN_INSET_WRAP:
1253         case LFUN_TABULAR_INSERT:
1254         case LFUN_ENVIRONMENT_INSERT:
1255                 // Open the inset, and move the current selection
1256                 // inside it.
1257                 doInsertInset(cur, this, cmd, true, true);
1258                 break;
1259
1260         case LFUN_INDEX_INSERT:
1261                 // Just open the inset
1262                 doInsertInset(cur, this, cmd, true, false);
1263                 break;
1264
1265         case LFUN_INDEX_PRINT:
1266         case LFUN_TOC_INSERT:
1267         case LFUN_HFILL:
1268         case LFUN_INSERT_LINE:
1269         case LFUN_INSERT_PAGEBREAK:
1270                 // do nothing fancy
1271                 doInsertInset(cur, this, cmd, false, false);
1272                 break;
1273
1274         case LFUN_DEPTH_MIN:
1275                 changeDepth(cur, DEC_DEPTH);
1276                 cur.update();
1277                 break;
1278
1279         case LFUN_DEPTH_PLUS:
1280                 changeDepth(cur, INC_DEPTH);
1281                 cur.update();
1282                 break;
1283
1284         case LFUN_MATH_DISPLAY:
1285                 mathDispatch(cur, this, cmd, true);
1286                 break;
1287
1288         case LFUN_MATH_IMPORT_SELECTION:
1289         case LFUN_MATH_MODE:
1290                 mathDispatch(cur, this, cmd, false);
1291                 break;
1292
1293         case LFUN_MATH_MACRO:
1294                 if (cmd.argument.empty())
1295                         cur.errorMessage(N_("Missing argument"));
1296                 else {
1297                         string s = cmd.argument;
1298                         string const s1 = token(s, ' ', 1);
1299                         int const nargs = s1.empty() ? 0 : atoi(s1);
1300                         string const s2 = token(s, ' ', 2);
1301                         string const type = s2.empty() ? "newcommand" : s2;
1302                         cur.insert(new InsetFormulaMacro(token(s, ' ', 0), nargs, s2));
1303                         cur.nextInset()->edit(cur, true);
1304                 }
1305                 break;
1306
1307         case LFUN_INSERT_MATH:
1308         case LFUN_INSERT_MATRIX:
1309         case LFUN_MATH_DELIM: {
1310                 cur.insert(new MathHullInset);
1311                 cur.dispatch(FuncRequest(LFUN_RIGHT));
1312                 cur.dispatch(FuncRequest(LFUN_MATH_MUTATE, "simple"));
1313                 cur.dispatch(cmd);
1314                 break;
1315         }
1316
1317         case LFUN_EMPH: {
1318                 LyXFont font(LyXFont::ALL_IGNORE);
1319                 font.setEmph(LyXFont::TOGGLE);
1320                 toggleAndShow(cur, this, font);
1321                 break;
1322         }
1323
1324         case LFUN_BOLD: {
1325                 LyXFont font(LyXFont::ALL_IGNORE);
1326                 font.setSeries(LyXFont::BOLD_SERIES);
1327                 toggleAndShow(cur, this, font);
1328                 break;
1329         }
1330
1331         case LFUN_NOUN: {
1332                 LyXFont font(LyXFont::ALL_IGNORE);
1333                 font.setNoun(LyXFont::TOGGLE);
1334                 toggleAndShow(cur, this, font);
1335                 break;
1336         }
1337
1338         case LFUN_CODE: {
1339                 LyXFont font(LyXFont::ALL_IGNORE);
1340                 font.setFamily(LyXFont::TYPEWRITER_FAMILY); // no good
1341                 toggleAndShow(cur, this, font);
1342                 break;
1343         }
1344
1345         case LFUN_SANS: {
1346                 LyXFont font(LyXFont::ALL_IGNORE);
1347                 font.setFamily(LyXFont::SANS_FAMILY);
1348                 toggleAndShow(cur, this, font);
1349                 break;
1350         }
1351
1352         case LFUN_ROMAN: {
1353                 LyXFont font(LyXFont::ALL_IGNORE);
1354                 font.setFamily(LyXFont::ROMAN_FAMILY);
1355                 toggleAndShow(cur, this, font);
1356                 break;
1357         }
1358
1359         case LFUN_DEFAULT: {
1360                 LyXFont font(LyXFont::ALL_INHERIT, ignore_language);
1361                 toggleAndShow(cur, this, font);
1362                 break;
1363         }
1364
1365         case LFUN_UNDERLINE: {
1366                 LyXFont font(LyXFont::ALL_IGNORE);
1367                 font.setUnderbar(LyXFont::TOGGLE);
1368                 toggleAndShow(cur, this, font);
1369                 break;
1370         }
1371
1372         case LFUN_FONT_SIZE: {
1373                 LyXFont font(LyXFont::ALL_IGNORE);
1374                 font.setLyXSize(cmd.argument);
1375                 toggleAndShow(cur, this, font);
1376                 break;
1377         }
1378
1379         case LFUN_LANGUAGE: {
1380                 Language const * lang = languages.getLanguage(cmd.argument);
1381                 if (!lang)
1382                         break;
1383                 LyXFont font(LyXFont::ALL_IGNORE);
1384                 font.setLanguage(lang);
1385                 toggleAndShow(cur, this, font);
1386                 bv->switchKeyMap();
1387                 break;
1388         }
1389
1390         case LFUN_FREEFONT_APPLY:
1391                 toggleAndShow(cur, this, freefont, toggleall);
1392                 cur.message(_("Character set"));
1393                 break;
1394
1395         // Set the freefont using the contents of \param data dispatched from
1396         // the frontends and apply it at the current cursor location.
1397         case LFUN_FREEFONT_UPDATE: {
1398                 LyXFont font;
1399                 bool toggle;
1400                 if (bv_funcs::string2font(cmd.argument, font, toggle)) {
1401                         freefont = font;
1402                         toggleall = toggle;
1403                         toggleAndShow(cur, this, freefont, toggleall);
1404                         cur.message(_("Character set"));
1405                 }
1406                 break;
1407         }
1408
1409         case LFUN_FINISHED_LEFT:
1410                 lyxerr << "handle LFUN_FINISHED_LEFT" << endl;
1411                 if (isRTL(cur.paragraph()))
1412                         cursorLeft(cur);
1413                 cur.bv().cursor() = cur;
1414                 break;
1415
1416         case LFUN_FINISHED_RIGHT:
1417                 lyxerr << "handle LFUN_FINISHED_RIGHT" << endl;
1418                 if (!isRTL(cur.paragraph()))
1419                         cursorRight(cur);
1420                 cur.bv().cursor() = cur;
1421                 break;
1422
1423         case LFUN_FINISHED_UP:
1424                 lyxerr << "handle LFUN_FINISHED_UP" << endl;
1425                 cursorUp(cur);
1426                 cur.bv().cursor() = cur;
1427                 break;
1428
1429         case LFUN_FINISHED_DOWN:
1430                 lyxerr << "handle LFUN_FINISHED_DOWN" << endl;
1431                 cursorDown(cur);
1432                 cur.bv().cursor() = cur;
1433                 break;
1434
1435         case LFUN_LAYOUT_PARAGRAPH: {
1436                 string data;
1437                 params2string(cur.paragraph(), data);
1438                 data = "show\n" + data;
1439                 bv->owner()->getDialogs().show("paragraph", data);
1440                 break;
1441         }
1442
1443         case LFUN_PARAGRAPH_UPDATE: {
1444                 if (!bv->owner()->getDialogs().visible("paragraph"))
1445                         break;
1446                 string data;
1447                 params2string(cur.paragraph(), data);
1448
1449                 // Will the paragraph accept changes from the dialog?
1450                 InsetBase & inset = cur.inset();
1451                 bool const accept = !inset.forceDefaultParagraphs(&inset);
1452
1453                 data = "update " + tostr(accept) + '\n' + data;
1454                 bv->owner()->getDialogs().update("paragraph", data);
1455                 break;
1456         }
1457
1458         case LFUN_UMLAUT:
1459         case LFUN_CIRCUMFLEX:
1460         case LFUN_GRAVE:
1461         case LFUN_ACUTE:
1462         case LFUN_TILDE:
1463         case LFUN_CEDILLA:
1464         case LFUN_MACRON:
1465         case LFUN_DOT:
1466         case LFUN_UNDERDOT:
1467         case LFUN_UNDERBAR:
1468         case LFUN_CARON:
1469         case LFUN_SPECIAL_CARON:
1470         case LFUN_BREVE:
1471         case LFUN_TIE:
1472         case LFUN_HUNG_UMLAUT:
1473         case LFUN_CIRCLE:
1474         case LFUN_OGONEK:
1475                 bv->owner()->getLyXFunc().handleKeyFunc(cmd.action);
1476                 if (!cmd.argument.empty())
1477                         bv->owner()->getIntl().getTransManager()
1478                                 .TranslateAndInsert(cmd.argument[0], this);
1479                 break;
1480
1481         case LFUN_FLOAT_LIST: {
1482                 LyXTextClass const & tclass = bv->buffer()->params().getLyXTextClass();
1483                 if (tclass.floats().typeExist(cmd.argument)) {
1484                         // not quite sure if we want this...
1485                         recordUndo(cur);
1486                         cur.clearSelection();
1487                         breakParagraph(cur);
1488
1489                         if (cur.lastpos() != 0) {
1490                                 cursorLeft(cur);
1491                                 breakParagraph(cur);
1492                         }
1493
1494                         setLayout(cur, tclass.defaultLayoutName());
1495                         setParagraph(cur, Spacing(), LYX_ALIGN_LAYOUT, string(), 0);
1496                         insertInset(cur, new InsetFloatList(cmd.argument));
1497                 } else {
1498                         lyxerr << "Non-existent float type: "
1499                                << cmd.argument << endl;
1500                 }
1501                 break;
1502         }
1503
1504         case LFUN_ACCEPT_CHANGE: {
1505                 acceptChange(cur);
1506                 cur.update();
1507                 break;
1508         }
1509
1510         case LFUN_REJECT_CHANGE: {
1511                 rejectChange(cur);
1512                 cur.update();
1513                 break;
1514         }
1515
1516         case LFUN_THESAURUS_ENTRY: {
1517                 string arg = cmd.argument;
1518                 if (arg.empty()) {
1519                         arg = cur.selectionAsString(false);
1520                         // FIXME
1521                         if (arg.size() > 100 || arg.empty()) {
1522                                 // Get word or selection
1523                                 selectWordWhenUnderCursor(cur, lyx::WHOLE_WORD);
1524                                 arg = cur.selectionAsString(false);
1525                         }
1526                 }
1527                 bv->owner()->getDialogs().show("thesaurus", arg);
1528                 break;
1529         }
1530
1531         case LFUN_PARAGRAPH_APPLY: {
1532                 // Given data, an encoding of the ParagraphParameters
1533                 // generated in the Paragraph dialog, this function sets
1534                 // the current paragraph appropriately.
1535                 istringstream is(cmd.argument);
1536                 LyXLex lex(0, 0);
1537                 lex.setStream(is);
1538                 ParagraphParameters params;
1539                 params.read(lex);
1540                 setParagraph(cur,
1541                                          params.spacing(),
1542                                          params.align(),
1543                                          params.labelWidthString(),
1544                                          params.noindent());
1545                 cur.update();
1546                 cur.message(_("Paragraph layout set"));
1547                 break;
1548         }
1549
1550         case LFUN_INSET_DIALOG_SHOW: {
1551                 InsetBase * inset = cur.nextInset();
1552                 if (inset) {
1553                         FuncRequest fr(LFUN_INSET_DIALOG_SHOW);
1554                         inset->dispatch(cur, fr);
1555                 }
1556                 break;
1557         }
1558
1559         case LFUN_ESCAPE:
1560                 if (cur.selection())
1561                         cur.selection() = false;
1562                 else
1563                         cmd = FuncRequest(LFUN_FINISHED_LEFT);
1564                 break;
1565
1566         default:
1567                 cur.undispatched();
1568                 break;
1569         }
1570 }
1571
1572
1573 bool LyXText::getStatus(LCursor & cur, FuncRequest const & cmd,
1574         FuncStatus & flag) const
1575 {
1576         BOOST_ASSERT(cur.text() == this);
1577         LyXFont const & font = real_current_font;
1578         bool enable = true;
1579
1580         switch (cmd.action) {
1581
1582         case LFUN_DEPTH_MIN:
1583                 enable = changeDepthAllowed(cur, DEC_DEPTH);
1584                 break;
1585
1586         case LFUN_DEPTH_PLUS:
1587                 enable = changeDepthAllowed(cur, INC_DEPTH);
1588                 break;
1589
1590         case LFUN_INSET_OPTARG:
1591                 enable = cur.paragraph().layout()->optionalargs;
1592                 break;
1593
1594         case LFUN_APPENDIX:
1595                 flag.setOnOff(cur.paragraph().params().startOfAppendix());
1596                 break;
1597
1598 #if 0
1599         // the functions which insert insets
1600         InsetOld::Code code = InsetOld::NO_CODE;
1601         switch (cmd.action) {
1602         case LFUN_DIALOG_SHOW_NEW_INSET:
1603                 if (cmd.argument == "bibitem")
1604                         code = InsetOld::BIBITEM_CODE;
1605                 else if (cmd.argument == "bibtex")
1606                         code = InsetOld::BIBTEX_CODE;
1607                 else if (cmd.argument == "box")
1608                         code = InsetOld::BOX_CODE;
1609                 else if (cmd.argument == "branch")
1610                         code = InsetOld::BRANCH_CODE;
1611                 else if (cmd.argument == "citation")
1612                         code = InsetOld::CITE_CODE;
1613                 else if (cmd.argument == "ert")
1614                         code = InsetOld::ERT_CODE;
1615                 else if (cmd.argument == "external")
1616                         code = InsetOld::EXTERNAL_CODE;
1617                 else if (cmd.argument == "float")
1618                         code = InsetOld::FLOAT_CODE;
1619                 else if (cmd.argument == "graphics")
1620                         code = InsetOld::GRAPHICS_CODE;
1621                 else if (cmd.argument == "include")
1622                         code = InsetOld::INCLUDE_CODE;
1623                 else if (cmd.argument == "index")
1624                         code = InsetOld::INDEX_CODE;
1625                 else if (cmd.argument == "label")
1626                         code = InsetOld::LABEL_CODE;
1627                 else if (cmd.argument == "note")
1628                         code = InsetOld::NOTE_CODE;
1629                 else if (cmd.argument == "ref")
1630                         code = InsetOld::REF_CODE;
1631                 else if (cmd.argument == "toc")
1632                         code = InsetOld::TOC_CODE;
1633                 else if (cmd.argument == "url")
1634                         code = InsetOld::URL_CODE;
1635                 else if (cmd.argument == "vspace")
1636                         code = InsetOld::VSPACE_CODE;
1637                 else if (cmd.argument == "wrap")
1638                         code = InsetOld::WRAP_CODE;
1639                 break;
1640
1641         case LFUN_INSET_ERT:
1642                 code = InsetOld::ERT_CODE;
1643                 break;
1644         case LFUN_INSET_FOOTNOTE:
1645                 code = InsetOld::FOOT_CODE;
1646                 break;
1647         case LFUN_TABULAR_INSERT:
1648                 code = InsetOld::TABULAR_CODE;
1649                 break;
1650         case LFUN_INSET_MARGINAL:
1651                 code = InsetOld::MARGIN_CODE;
1652                 break;
1653         case LFUN_INSET_FLOAT:
1654         case LFUN_INSET_WIDE_FLOAT:
1655                 code = InsetOld::FLOAT_CODE;
1656                 break;
1657         case LFUN_INSET_WRAP:
1658                 code = InsetOld::WRAP_CODE;
1659                 break;
1660         case LFUN_FLOAT_LIST:
1661                 code = InsetOld::FLOAT_LIST_CODE;
1662                 break;
1663 #if 0
1664         case LFUN_INSET_LIST:
1665                 code = InsetOld::LIST_CODE;
1666                 break;
1667         case LFUN_INSET_THEOREM:
1668                 code = InsetOld::THEOREM_CODE;
1669                 break;
1670 #endif
1671         case LFUN_INSET_CAPTION:
1672                 code = InsetOld::CAPTION_CODE;
1673                 break;
1674         case LFUN_INSERT_NOTE:
1675                 code = InsetOld::NOTE_CODE;
1676                 break;
1677         case LFUN_INSERT_CHARSTYLE:
1678                 code = InsetOld::CHARSTYLE_CODE;
1679                 if (buf->params().getLyXTextClass().charstyles().empty())
1680                         enable = false;
1681                 break;
1682         case LFUN_INSERT_BOX:
1683                 code = InsetOld::BOX_CODE;
1684                 break;
1685         case LFUN_INSERT_BRANCH:
1686                 code = InsetOld::BRANCH_CODE;
1687                 if (buf->params().branchlist().empty())
1688                         enable = false;
1689                 break;
1690         case LFUN_INSERT_LABEL:
1691                 code = InsetOld::LABEL_CODE;
1692                 break;
1693         case LFUN_INSET_OPTARG:
1694                 code = InsetOld::OPTARG_CODE;
1695                 break;
1696         case LFUN_ENVIRONMENT_INSERT:
1697                 code = InsetOld::BOX_CODE;
1698                 break;
1699         case LFUN_INDEX_INSERT:
1700                 code = InsetOld::INDEX_CODE;
1701                 break;
1702         case LFUN_INDEX_PRINT:
1703                 code = InsetOld::INDEX_PRINT_CODE;
1704                 break;
1705         case LFUN_TOC_INSERT:
1706                 code = InsetOld::TOC_CODE;
1707                 break;
1708         case LFUN_HTMLURL:
1709         case LFUN_URL:
1710                 code = InsetOld::URL_CODE;
1711                 break;
1712         case LFUN_QUOTE:
1713                 // always allow this, since we will inset a raw quote
1714                 // if an inset is not allowed.
1715                 break;
1716         case LFUN_HYPHENATION:
1717         case LFUN_LIGATURE_BREAK:
1718         case LFUN_HFILL:
1719         case LFUN_MENU_SEPARATOR:
1720         case LFUN_LDOTS:
1721         case LFUN_END_OF_SENTENCE:
1722                 code = InsetOld::SPECIALCHAR_CODE;
1723                 break;
1724         case LFUN_SPACE_INSERT:
1725                 // slight hack: we know this is allowed in math mode
1726                 if (cur.inTexted())
1727                         code = InsetOld::SPACE_CODE;
1728                 break;
1729         case LFUN_INSET_DIALOG_SHOW: {
1730                 InsetBase * inset = cur.nextInset();
1731                 enable = inset;
1732                 if (inset) {
1733                         code = inset->lyxCode();
1734                         if (!(code == InsetOld::INCLUDE_CODE
1735                                 || code == InsetOld::BIBTEX_CODE
1736                                 || code == InsetOld::FLOAT_LIST_CODE
1737                                 || code == InsetOld::TOC_CODE))
1738                                 enable = false;
1739                 }
1740                 break;
1741         }
1742         default:
1743                 break;
1744         }
1745
1746         if (code != InsetOld::NO_CODE
1747                         && (cur.empty() || !cur.inset().insetAllowed(code)))
1748                 enable = false;
1749
1750 #endif
1751
1752         case LFUN_DIALOG_SHOW_NEW_INSET:
1753         case LFUN_INSET_ERT:
1754         case LFUN_INSERT_BOX:
1755         case LFUN_INSERT_BRANCH:
1756         case LFUN_ENVIRONMENT_INSERT:
1757         case LFUN_INDEX_INSERT:
1758         case LFUN_INDEX_PRINT:
1759         case LFUN_TOC_INSERT:
1760         case LFUN_HTMLURL:
1761         case LFUN_URL:
1762         case LFUN_QUOTE:
1763         case LFUN_HYPHENATION:
1764         case LFUN_LIGATURE_BREAK:
1765         case LFUN_HFILL:
1766         case LFUN_MENU_SEPARATOR:
1767         case LFUN_LDOTS:
1768         case LFUN_END_OF_SENTENCE:
1769         case LFUN_SPACE_INSERT:
1770         case LFUN_INSET_DIALOG_SHOW: 
1771                 break;
1772
1773         case LFUN_EMPH:
1774                 flag.setOnOff(font.emph() == LyXFont::ON);
1775                 break;
1776
1777         case LFUN_NOUN:
1778                 flag.setOnOff(font.noun() == LyXFont::ON);
1779                 break;
1780
1781         case LFUN_BOLD:
1782                 flag.setOnOff(font.series() == LyXFont::BOLD_SERIES);
1783                 break;
1784
1785         case LFUN_SANS:
1786                 flag.setOnOff(font.family() == LyXFont::SANS_FAMILY);
1787                 break;
1788
1789         case LFUN_ROMAN:
1790                 flag.setOnOff(font.family() == LyXFont::ROMAN_FAMILY);
1791                 break;
1792
1793         case LFUN_CODE:
1794                 flag.setOnOff(font.family() == LyXFont::TYPEWRITER_FAMILY);
1795                 break;
1796
1797         case LFUN_DELETE_WORD_FORWARD:
1798         case LFUN_DELETE_WORD_BACKWARD:
1799         case LFUN_DELETE_LINE_FORWARD:
1800         case LFUN_WORDRIGHT:
1801         case LFUN_WORDLEFT:
1802         case LFUN_ENDBUF:
1803         case LFUN_RIGHT:
1804         case LFUN_RIGHTSEL:
1805         case LFUN_LEFT:
1806         case LFUN_LEFTSEL:
1807         case LFUN_UP:
1808         case LFUN_UPSEL:
1809         case LFUN_DOWN:
1810         case LFUN_DOWNSEL:
1811         case LFUN_UP_PARAGRAPHSEL:
1812         case LFUN_DOWN_PARAGRAPHSEL:
1813         case LFUN_PRIORSEL:
1814         case LFUN_NEXTSEL:
1815         case LFUN_HOMESEL:
1816         case LFUN_ENDSEL:
1817         case LFUN_WORDRIGHTSEL:
1818         case LFUN_WORDLEFTSEL:
1819         case LFUN_WORDSEL:
1820         case LFUN_UP_PARAGRAPH:
1821         case LFUN_DOWN_PARAGRAPH:
1822         case LFUN_PRIOR:
1823         case LFUN_NEXT:
1824         case LFUN_HOME:
1825         case LFUN_END:
1826         case LFUN_BREAKLINE:
1827         case LFUN_DELETE:
1828         case LFUN_DELETE_SKIP:
1829         case LFUN_BACKSPACE:
1830         case LFUN_BACKSPACE_SKIP:
1831         case LFUN_BREAKPARAGRAPH:
1832         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
1833         case LFUN_BREAKPARAGRAPH_SKIP:
1834         case LFUN_PARAGRAPH_SPACING:
1835         case LFUN_INSET_APPLY:
1836         case LFUN_INSET_INSERT:
1837         case LFUN_INSET_TOGGLE:
1838         case LFUN_UPCASE_WORD:
1839         case LFUN_LOWCASE_WORD:
1840         case LFUN_CAPITALIZE_WORD:
1841         case LFUN_TRANSPOSE_CHARS:
1842         case LFUN_PASTE:
1843         case LFUN_CUT:
1844         case LFUN_COPY:
1845         case LFUN_GETXY:
1846         case LFUN_SETXY:
1847         case LFUN_GETFONT:
1848         case LFUN_GETLAYOUT:
1849         case LFUN_LAYOUT:
1850         case LFUN_PASTESELECTION:
1851         case LFUN_GOTOERROR:
1852         case LFUN_GOTONOTE:
1853         case LFUN_REFERENCE_GOTO:
1854         case LFUN_DATE_INSERT:
1855         case LFUN_SELFINSERT:
1856         case LFUN_INSERT_LABEL:
1857         case LFUN_INSERT_NOTE:
1858         case LFUN_INSERT_CHARSTYLE:
1859         case LFUN_INSERT_BIBITEM:
1860         case LFUN_INSET_FLOAT:
1861         case LFUN_INSET_FOOTNOTE:
1862         case LFUN_INSET_MARGINAL:
1863         case LFUN_INSET_WIDE_FLOAT:
1864         case LFUN_INSET_WRAP:
1865         case LFUN_TABULAR_INSERT:
1866         case LFUN_INSERT_LINE:
1867         case LFUN_INSERT_PAGEBREAK:
1868         case LFUN_MATH_DISPLAY:
1869         case LFUN_MATH_IMPORT_SELECTION:
1870         case LFUN_MATH_MODE:
1871         case LFUN_MATH_MACRO:
1872         case LFUN_INSERT_MATH:
1873         case LFUN_INSERT_MATRIX:
1874         case LFUN_MATH_DELIM:
1875         case LFUN_DEFAULT:
1876         case LFUN_UNDERLINE:
1877         case LFUN_FONT_SIZE:
1878         case LFUN_LANGUAGE:
1879         case LFUN_FREEFONT_APPLY:
1880         case LFUN_FREEFONT_UPDATE:
1881         case LFUN_LAYOUT_PARAGRAPH:
1882         case LFUN_PARAGRAPH_UPDATE:
1883         case LFUN_UMLAUT:
1884         case LFUN_CIRCUMFLEX:
1885         case LFUN_GRAVE:
1886         case LFUN_ACUTE:
1887         case LFUN_TILDE:
1888         case LFUN_CEDILLA:
1889         case LFUN_MACRON:
1890         case LFUN_DOT:
1891         case LFUN_UNDERDOT:
1892         case LFUN_UNDERBAR:
1893         case LFUN_CARON:
1894         case LFUN_SPECIAL_CARON:
1895         case LFUN_BREVE:
1896         case LFUN_TIE:
1897         case LFUN_HUNG_UMLAUT:
1898         case LFUN_CIRCLE:
1899         case LFUN_OGONEK:
1900         case LFUN_FLOAT_LIST:
1901         case LFUN_ACCEPT_CHANGE:
1902         case LFUN_REJECT_CHANGE:
1903         case LFUN_THESAURUS_ENTRY:
1904         case LFUN_PARAGRAPH_APPLY:
1905         case LFUN_ESCAPE:
1906                 // these are handled in our dispatch()
1907                 enable = true;
1908                 break;
1909
1910         default:
1911                 enable = false;
1912                 break;
1913         }
1914         flag.enabled(enable);
1915         return true;
1916 }