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