]> git.lyx.org Git - features.git/blob - src/lyxfunc.C
c73dd858e26058f8c2721273c0005b4406ff4989
[features.git] / src / lyxfunc.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *          Copyright 1995 Matthias Ettrich
7  *          Copyright 1995-2000 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #include "Lsstream.h"
14
15 #include <time.h>
16 #include <locale.h>
17
18 #include <cstdlib>
19 #include <cctype>
20 #include <cstring>
21
22 #ifdef __GNUG__
23 #pragma implementation
24 #endif
25
26 #include "version.h"
27 #include "kbmap.h"
28 #include "lyxfunc.h"
29 #include "bufferlist.h"
30 #include "ColorHandler.h"
31 #include "lyxserver.h"
32 #include "lyx.h"
33 #include "intl.h"
34 #include "lyx_main.h"
35 #include "lyx_cb.h"
36 #include "LyXAction.h"
37 #include "insets/inseturl.h"
38 #include "insets/insetlatexaccent.h"
39 #include "insets/insettoc.h"
40 #include "insets/insetref.h"
41 #include "insets/insetparent.h"
42 #include "insets/insetindex.h"
43 #include "insets/insetinclude.h"
44 #include "insets/insetbib.h"
45 #include "insets/insetcite.h"
46 #include "insets/insettext.h"
47 #include "insets/insetert.h"
48 #include "insets/insetexternal.h"
49 #include "insets/insetgraphics.h"
50 #include "insets/insetfoot.h"
51 #include "insets/insetmarginal.h"
52 #include "insets/insetminipage.h"
53 #include "insets/insetfloat.h"
54 #include "insets/insetlist.h"
55 #include "insets/insettabular.h"
56 #include "insets/insettheorem.h"
57 #include "insets/insetcaption.h"
58 #include "mathed/formulamacro.h"
59 #include "spellchecker.h" // RVDK_PATCH_5
60 #include "minibuffer.h"
61 #include "vspace.h"
62 #include "LyXView.h"
63 #include "filedlg.h"
64 #include "lyx_gui_misc.h"
65 #include "support/filetools.h"
66 #include "support/FileInfo.h"
67 #include "support/syscall.h"
68 #include "support/lstrings.h"
69 #include "support/path.h"
70 #include "support/lyxfunctional.h"
71 #include "debug.h"
72 #include "lyxrc.h"
73 #include "lyxtext.h"
74 #include "gettext.h"
75 #include "trans_mgr.h"
76 #include "layout.h"
77 #include "WorkArea.h"
78 #include "lyxfr1.h"
79 #include "bufferview_funcs.h"
80 #include "frontends/Dialogs.h"
81 #include "frontends/Toolbar.h"
82 #include "frontends/Menubar.h"
83 #include "FloatList.h"
84 #include "converter.h"
85 #include "exporter.h"
86 #include "importer.h"
87 #include "FontLoader.h"
88 #include "TextCache.h"
89
90 using std::pair;
91 using std::endl;
92 using std::find_if;
93
94 extern void math_insert_symbol(string const &);
95 extern bool math_insert_greek(char);
96 extern BufferList bufferlist;
97 extern LyXServer * lyxserver;
98 extern int greek_kb_flag;
99 extern bool selection_possible;
100
101 extern kb_keymap * toplevel_keymap;
102
103 #if 0
104 extern void MenuFax(Buffer *);
105 #endif
106 extern void show_symbols_form(LyXFunc *);
107
108 extern LyXAction lyxaction;
109 // (alkis)
110 extern tex_accent_struct get_accent(kb_action action);
111
112 extern LyXTextClass::size_type current_layout;
113
114 extern void ShowLatexLog();
115
116 /* === globals =========================================================== */
117
118 bool LyXFunc::show_sc = true;
119
120
121 LyXFunc::LyXFunc(LyXView * o)
122         : owner(o)
123 {
124         meta_fake_bit = 0;
125         lyx_dead_action = LFUN_NOACTION;
126         lyx_calling_dead_action = LFUN_NOACTION;
127         setupLocalKeymap();
128 }
129
130
131 // I changed this func slightly. I commented out the ...FinishUndo(),
132 // this means that all places that used to have a moveCursorUpdate, now
133 // have a ...FinishUndo() as the preceeding statement. I have also added
134 // a moveCursorUpdate to some of the functions that updated the cursor, but
135 // that did not show its new position.
136 inline
137 void LyXFunc::moveCursorUpdate(bool selecting)
138 {
139         if (selecting || owner->view()->text->mark_set) {
140                 owner->view()->text->SetSelection();
141                 owner->view()->toggleToggle();
142         }
143         owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
144         owner->view()->showCursor();
145         
146         /* ---> Everytime the cursor is moved, show the current font state. */
147         // should this too me moved out of this func?
148         //owner->showState();
149         owner->view()->setState();
150 }
151
152
153 int LyXFunc::processKeySym(KeySym keysym, unsigned int state) 
154 {
155         string argument;
156         
157         if (lyxerr.debugging(Debug::KEY)) {
158                 char * tmp = XKeysymToString(keysym);
159                 string stm = (tmp ? tmp : "");
160                 lyxerr << "KeySym is "
161                        << stm
162                        << "["
163                        << keysym << "]"
164                        << endl;
165         }
166         // Do nothing if we have nothing (JMarc)
167         if (keysym == NoSymbol) {
168                 lyxerr[Debug::KEY] << "Empty kbd action (probably composing)"
169                                    << endl;
170                 //return 0;
171                 return FL_PREEMPT;
172         }
173
174         if (owner->view()->available()) {
175                 // this function should be used always [asierra060396]
176                 UpdatableInset * tli = owner->view()->theLockingInset();
177                 if (tli && (keysym == XK_Escape)) {
178                         if (tli == tli->GetLockingInset()) {
179                                 owner->view()->unlockInset(tli);
180                                 owner->view()->text->CursorRight(owner->view());
181                                 moveCursorUpdate(false);
182                                 owner->showState();
183                         } else {
184                                 tli->UnlockInsetInInset(owner->view(),
185                                                         tli->GetLockingInset(),true);
186                         }
187                         //return 0;
188                         return FL_PREEMPT;
189                 }
190         }
191         
192         // Can we be sure that this will work for all X-Windows
193         // implementations? (Lgb)
194         // This code snippet makes lyx ignore some keys. Perhaps
195         // all of them should be explictly mentioned?
196         if ((keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
197            || keysym == XK_Mode_switch || keysym == 0x0)
198                 return 0;
199
200         // Do a one-deep top-level lookup for
201         // cancel and meta-fake keys. RVDK_PATCH_5
202         cancel_meta_seq.reset();
203
204         int action = cancel_meta_seq.addkey(keysym, state
205                                             &(ShiftMask|ControlMask
206                                               |Mod1Mask)); 
207
208         // When not cancel or meta-fake, do the normal lookup. 
209         // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
210         // Mostly, meta_fake_bit = 0. RVDK_PATCH_5.
211         if ((action != LFUN_CANCEL) && (action != LFUN_META_FAKE)) {
212
213                 // remove Caps Lock and Mod2 as a modifiers
214                 action = keyseq.addkey(keysym,
215                                        (state | meta_fake_bit)
216                                        &(ShiftMask|ControlMask
217                                          |Mod1Mask));      
218         }
219         // Dont remove this unless you know what you are doing.
220         meta_fake_bit = 0;
221                 
222         if (action == 0) action = LFUN_PREFIX;
223
224         if (lyxerr.debugging(Debug::KEY)) {
225                 string buf;
226                 keyseq.print(buf);
227                 lyxerr << "Key ["
228                        << action << "]["
229                        << buf << "]"
230                        << endl;
231         }
232
233         // already here we know if it any point in going further
234         // why not return already here if action == -1 and
235         // num_bytes == 0? (Lgb)
236
237         if (keyseq.length > 1 || keyseq.length < -1) {
238                 string buf;
239                 keyseq.print(buf);
240                 owner->getMiniBuffer()->Set(buf);
241         }
242
243         if (action == -1) {
244                 if (keyseq.length < -1) { // unknown key sequence...
245                         string buf;
246                         LyXBell();
247                         keyseq.print(buf);
248                         owner->getMiniBuffer()->Set(_("Unknown sequence:"), buf);
249                         return 0;
250                 }
251         
252                 char isochar = keyseq.getiso();
253                 if (!(state & ControlMask) &&
254                     !(state & Mod1Mask) &&
255                     (isochar && keysym < 0xF000)) {
256                         argument += isochar;
257                 }
258                 if (argument.empty()) {
259                         lyxerr.debug() << "Empty argument!" << endl;
260                         // This can`t possibly be of any use
261                         // so we`ll skip the dispatch.
262                         return 0;
263                 }
264         }
265
266         bool tmp_sc = show_sc;
267         show_sc = false;
268         Dispatch(action, argument);
269         show_sc = tmp_sc;
270         
271         return 0;
272
273
274
275 LyXFunc::func_status LyXFunc::getStatus(int ac) const
276 {
277         kb_action action;
278         func_status flag = LyXFunc::OK;
279         string argument;
280         Buffer * buf = owner->buffer();
281         
282         if (lyxaction.isPseudoAction(ac)) 
283                 action = lyxaction.retrieveActionArg(ac, argument);
284         else
285                 action = static_cast<kb_action>(ac);
286         
287         if (action == LFUN_UNKNOWN_ACTION) {
288                 setErrorMessage(N_("Unknown action"));
289                 return LyXFunc::Unknown;
290         }
291         
292         // Check whether we need a buffer
293         if (!lyxaction.funcHasFlag(action, LyXAction::NoBuffer)) {
294                 // Yes we need a buffer, do we have one?
295                 if (buf) {
296                         // yes
297                         // Can we use a readonly buffer?
298                         if (buf->isReadonly() && 
299                             !lyxaction.funcHasFlag(action,
300                                                    LyXAction::ReadOnly)) {
301                                 // no
302                                 setErrorMessage(N_("Document is read-only"));
303                                 flag |= LyXFunc::Disabled;
304                         }
305                 } else {
306                         // no
307                         setErrorMessage(N_("Command not allowed with"
308                                            "out any document open"));
309                         flag |= LyXFunc::Disabled;
310                         return flag;
311                 }
312         }
313
314         // I would really like to avoid having this switch and rather try to
315         // encode this in the function itself.
316         bool disable = false;
317         switch (action) {
318         case LFUN_MENUPRINT:
319                 disable = !Exporter::IsExportable(buf, "dvi")
320                         || lyxrc.print_command == "none";
321                 break;
322 #if 0
323         case LFUN_FAX:
324                 disable = !Exporter::IsExportable(buf, "ps")
325                         || lyxrc.fax_command == "none";
326                 break;
327 #else
328         case LFUN_EXPORT:
329                 disable = argument == "fax" &&
330                         !Exporter::IsExportable(buf, argument);
331                 break;
332 #endif
333         case LFUN_UNDO:
334                 disable = buf->undostack.empty();
335                 break;
336         case LFUN_REDO:
337                 disable = buf->redostack.empty();
338                 break;
339         case LFUN_SPELLCHECK:
340                 disable = lyxrc.isp_command == "none";
341                 break;
342         case LFUN_RUNCHKTEX:
343                 disable = lyxrc.chktex_command == "none";
344                 break;
345         case LFUN_BUILDPROG:
346                 disable = !Exporter::IsExportable(buf, "program");
347                 break;
348
349         case LFUN_LAYOUT_TABULAR:
350                 disable = true;
351                 if (owner->view()->theLockingInset()) {
352                         disable = (owner->view()->theLockingInset()->LyxCode() != Inset::TABULAR_CODE) &&
353                                 !owner->view()->theLockingInset()->GetFirstLockingInsetOfType(Inset::TABULAR_CODE);
354                 }
355                 break;
356
357         case LFUN_TABULAR_FEATURE:
358                 disable = true;
359                 if (owner->view()->theLockingInset()) {
360                         func_status ret = LyXFunc::Disabled;
361                         if (owner->view()->theLockingInset()->LyxCode() == Inset::TABULAR_CODE) {
362                                 ret = static_cast<InsetTabular *>
363                                         (owner->view()->theLockingInset())->
364                                         getStatus(argument);
365                         } else if (owner->view()->theLockingInset()->GetFirstLockingInsetOfType(Inset::TABULAR_CODE)) {
366                                 ret = static_cast<InsetTabular *>
367                                         (owner->view()->theLockingInset()->
368                                         GetFirstLockingInsetOfType(Inset::TABULAR_CODE))->
369                                         getStatus(argument);
370                         }
371                         flag |= ret;
372                         disable = false;
373                 } else {
374                     static InsetTabular inset(*owner->buffer(), 1, 1);
375                     func_status ret;
376
377                     disable = true;
378                     ret = inset.getStatus(argument);
379                     if ((ret & LyXFunc::ToggleOn) ||
380                         (ret & LyXFunc::ToggleOff))
381                         flag |= LyXFunc::ToggleOff;
382                 }
383                 break;
384
385         case LFUN_VC_REGISTER:
386                 disable = buf->lyxvc.inUse();
387                 break;
388         case LFUN_VC_CHECKIN:
389                 disable = !buf->lyxvc.inUse() || buf->isReadonly();
390                 break;
391         case LFUN_VC_CHECKOUT:
392                 disable = !buf->lyxvc.inUse() || !buf->isReadonly();
393                 break;
394         case LFUN_VC_REVERT:
395         case LFUN_VC_UNDO:
396         case LFUN_VC_HISTORY:
397                 disable = !buf->lyxvc.inUse();
398                 break;
399         case LFUN_REF_BACK:
400                 disable = owner->view()->NoSavedPositions();
401                 break;
402         default:
403                 break;
404         }
405         if (disable)
406                 flag |= LyXFunc::Disabled;
407
408         if (buf) {
409                 func_status box = LyXFunc::ToggleOff;
410                 LyXFont font;
411                 if (owner->view()->theLockingInset() &&
412                     owner->view()->theLockingInset()->getLyXText(owner->view()))
413                     font = owner->view()->theLockingInset()->
414                         getLyXText(owner->view())->real_current_font;
415                 else
416                     font = owner->view()->text->real_current_font;
417                 switch (action) {
418                 case LFUN_EMPH:
419                         if (font.emph() == LyXFont::ON)
420                                 box = LyXFunc::ToggleOn;
421                         break;
422                 case LFUN_NOUN:
423                         if (font.noun() == LyXFont::ON)
424                                 box = LyXFunc::ToggleOn;
425                         break;
426                 case LFUN_BOLD:
427                         if (font.series() == LyXFont::BOLD_SERIES)
428                                 box = LyXFunc::ToggleOn;
429                         break;
430                 case LFUN_TEX:
431                         if (font.latex() == LyXFont::ON)
432                                 box = LyXFunc::ToggleOn;
433                         break;
434                 default:
435                         box = LyXFunc::OK;
436                         break;
437                 }
438                 flag |= box;
439         }
440
441         return flag;
442 }
443
444
445 string const LyXFunc::Dispatch(string const & s) 
446 {
447         // Split command string into command and argument
448         string cmd;
449         string line = frontStrip(s);
450         string arg = strip(frontStrip(split(line, cmd, ' ')));
451
452         return Dispatch(lyxaction.LookupFunc(cmd), arg);
453 }
454
455
456 string const LyXFunc::Dispatch(int ac,
457                          string const & do_not_use_this_arg)
458 {
459         lyxerr[Debug::ACTION] << "LyXFunc::Dispatch: action[" << ac
460                               <<"] arg[" << do_not_use_this_arg << "]" << endl;
461         
462         string argument;
463         kb_action action;
464         LyXText * text = 0;
465         
466         // we have not done anything wrong yet.
467         errorstat = false;
468         dispatch_buffer.erase();
469         
470         // if action is a pseudo-action, we need the real action
471         if (lyxaction.isPseudoAction(ac)) {
472                 string tmparg;
473                 action = static_cast<kb_action>
474                         (lyxaction.retrieveActionArg(ac, tmparg));
475                 if (!tmparg.empty())
476                         argument = tmparg;
477         } else {
478                 action = static_cast<kb_action>(ac);
479                 if (!do_not_use_this_arg.empty())
480                         argument = do_not_use_this_arg; // except here
481         }
482     
483         selection_possible = false;
484         
485         if (owner->view()->available())
486                 owner->view()->hideCursor();
487
488         // We cannot use this function here
489         if (getStatus(ac) & Disabled)
490                 goto exit_with_message;
491
492         commandshortcut.erase();
493         
494         if (lyxrc.display_shortcuts && show_sc) {
495                 if (action != LFUN_SELFINSERT) {
496                         // Put name of command and list of shortcuts
497                         // for it in minibuffer
498                         string comname = lyxaction.getActionName(action);
499
500                         int pseudoaction = action;
501                         bool argsadded = false;
502
503                         if (!argument.empty()) {
504                                 // If we have the command with argument, 
505                                 // this is better
506                                 pseudoaction = 
507                                         lyxaction.searchActionArg(action,
508                                                                   argument);
509
510                                 if (pseudoaction == -1) {
511                                         pseudoaction = action;
512                                 } else {
513                                         comname += " " + argument;
514                                         argsadded = true;
515                                 }
516                         }
517
518                         string shortcuts = toplevel_keymap->findbinding(pseudoaction);
519
520                         if (!shortcuts.empty()) {
521                                 comname += ": " + shortcuts;
522                         } else if (!argsadded) {
523                                 comname += " " + argument;
524                         }
525
526                         if (!comname.empty()) {
527                                 comname = strip(comname);
528                                 commandshortcut = "(" + comname + ')';
529                                 owner->getMiniBuffer()->Set(commandshortcut);
530                                 // Here we could even add a small pause,
531                                 // to annoy the user and make him learn
532                                 // the shortcuts.
533                                 // No! That will just annoy, not teach
534                                 // anything. The user will read the messages
535                                 // if they are interested. (Asger)
536                         }
537                 }
538         }
539
540         if (owner->view()->available() && owner->view()->theLockingInset()) {
541                 UpdatableInset::RESULT result;
542                 if ((action > 1) || ((action == LFUN_UNKNOWN_ACTION) &&
543                                      (keyseq.length >= -1)))
544                 {
545                         if ((action==LFUN_UNKNOWN_ACTION) && argument.empty()){
546                                 argument = keyseq.getiso();
547                         }
548                         // Undo/Redo pre 0.13 is a bit tricky for insets.
549                         if (action == LFUN_UNDO) {
550                                 int slx;
551                                 int sly;
552                                 UpdatableInset * inset = 
553                                         owner->view()->theLockingInset();
554                                 inset->GetCursorPos(owner->view(), slx, sly);
555                                 owner->view()->unlockInset(inset);
556                                 owner->view()->menuUndo();
557                                 if (owner->view()->text->cursor.par()->
558                                     IsInset(owner->view()->text->cursor.pos())) {
559                                         inset = static_cast<UpdatableInset*>(
560                                                 owner->view()->text->cursor.par()->
561                                                 GetInset(owner->view()->text->
562                                                          cursor.pos()));
563                                 } else {
564                                         inset = 0;
565                                 }
566                                 if (inset)
567                                         inset->Edit(owner->view(),slx,sly,0);
568                                 return string();
569                         } else if (action == LFUN_REDO) {
570                                 int slx;
571                                 int sly;
572                                 UpdatableInset * inset = owner->view()->
573                                         theLockingInset();
574                                 inset->GetCursorPos(owner->view(), slx, sly);
575                                 owner->view()->unlockInset(inset);
576                                 owner->view()->menuRedo();
577                                 inset = static_cast<UpdatableInset*>(
578                                         owner->view()->text->cursor.par()->
579                                         GetInset(owner->view()->text->
580                                                  cursor.pos()));
581                                 if (inset)
582                                         inset->Edit(owner->view(),slx,sly,0); 
583                                 return string();
584                         } else if (((result=owner->view()->theLockingInset()->
585                                    LocalDispatch(owner->view(), action,
586                                                  argument)) ==
587                                    UpdatableInset::DISPATCHED) ||
588                                    (result == UpdatableInset::DISPATCHED_NOUPDATE))
589                                 return string();
590                         else {
591                                 setMessage(N_("Text mode"));
592                                 switch (action) {
593                                 case LFUN_UNKNOWN_ACTION:
594                                 case LFUN_BREAKPARAGRAPH:
595                                 case LFUN_BREAKLINE:
596                                         owner->view()->text->CursorRight(owner->view());
597                                         owner->view()->setState();
598                                         owner->showState();
599                                         break;
600                                 case LFUN_RIGHT:
601                                         if (!owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params)) {
602                                                 owner->view()->text->CursorRight(owner->view());
603                                                 moveCursorUpdate(false);
604                                                 owner->showState();
605                                         }
606                                         return string();
607                                 case LFUN_LEFT: 
608                                         if (owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params)) {
609                                                 owner->view()->text->CursorRight(owner->view());
610                                                 moveCursorUpdate(false);
611                                                 owner->showState();
612                                         }
613                                         return string();
614                                 case LFUN_DOWN:
615                                         owner->view()->text->CursorDown(owner->view());
616                                         moveCursorUpdate(false);
617                                         owner->showState();
618                                         return string();
619                                 default:
620                                         break;
621                                 }
622                         }
623                 }
624                 if (owner->view()->theLockingInset())
625                         text = owner->view()->theLockingInset()->
626                                 getLyXText(owner->view());
627         }
628
629         if (!text)
630             text = owner->view()->text;
631
632         switch (action) {
633                 // --- Misc -------------------------------------------
634         case LFUN_WORDFINDFORWARD  : 
635         case LFUN_WORDFINDBACKWARD : {
636                 static string last_search;
637                 string searched_string;
638             
639                 if (!argument.empty()) {
640                         last_search = argument;
641                         searched_string = argument;
642                 } else {
643                         searched_string = last_search;
644                 }
645
646                 LyXText * ltCur = owner->view()->text ;
647
648                 if (!searched_string.empty() &&
649                     ((action == LFUN_WORDFINDBACKWARD) ? 
650                      ltCur->SearchBackward(owner->view(), searched_string) :
651                      ltCur->SearchForward(owner->view(), searched_string))) {
652
653                         // ??? What is that ???
654                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
655
656                         // ??? Needed ???
657                         // clear the selection (if there is any) 
658                         owner->view()->toggleSelection();
659                         owner->view()->text->ClearSelection();
660
661                         // Move cursor so that successive C-s 's will not stand in place. 
662                         if (action == LFUN_WORDFINDFORWARD ) 
663                                 owner->view()->text->CursorRightOneWord(owner->view());
664                         owner->view()->text->FinishUndo();
665                         moveCursorUpdate(false);
666
667                         // ??? Needed ???
668                         // set the new selection 
669                         // SetSelectionOverLenChars(owner->view()->currentBuffer()->text, iLenSelected);
670                         owner->view()->toggleSelection(false);
671                 } else 
672                         LyXBell();      
673          
674                 // REMOVED : if (owner->view()->getWorkArea()->focus)
675                 owner->view()->showCursor();
676         }
677         break;
678
679         case LFUN_PREFIX:
680         {
681                 if (owner->view()->available()) {
682                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
683                 }
684                 string buf;
685                 keyseq.print(buf, true);
686                 owner->getMiniBuffer()->Set(buf, string(), string(), 1);
687         }
688         break;
689
690         // --- Misc -------------------------------------------
691         case LFUN_EXEC_COMMAND:
692                 owner->getMiniBuffer()->PrepareForCommand(); 
693                 break;
694                 
695         case LFUN_CANCEL:                   // RVDK_PATCH_5
696                 keyseq.reset();
697                 meta_fake_bit = 0;
698                 if (owner->view()->available())
699                         // cancel any selection
700                         Dispatch(LFUN_MARK_OFF);
701                 setMessage(N_("Cancel"));
702                 break;
703
704         case LFUN_META_FAKE:                                 // RVDK_PATCH_5
705         {
706                 meta_fake_bit = Mod1Mask;
707                 string buf;
708                 keyseq.print(buf, true);
709                 setMessage(buf); // RVDK_PATCH_5
710         }
711         break;  
712
713         case LFUN_READ_ONLY_TOGGLE:
714                 if (owner->buffer()->lyxvc.inUse()) {
715                         owner->buffer()->lyxvc.toggleReadOnly();
716                 } else {
717                         owner->buffer()->setReadonly(
718                                 !owner->buffer()->isReadonly());
719                 }
720                 break;
721                 
722         case LFUN_CENTER: // this is center and redraw.
723                 owner->view()->center();
724                 break;
725                 
726         case LFUN_APPENDIX:
727                 if (owner->view()->available()) {
728                         owner->view()->text->toggleAppendix(owner->view());
729                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
730                 }
731                 break;
732
733                 // --- Menus -----------------------------------------------
734         case LFUN_MENUNEW:
735                 MenuNew(false);
736                 break;
737                 
738         case LFUN_MENUNEWTMPLT:
739                 MenuNew(true);
740                 break;
741                 
742         case LFUN_MENUOPEN:
743                 MenuOpen();
744                 break;
745                 
746         case LFUN_CLOSEBUFFER:
747                 CloseBuffer();
748                 break;
749                 
750         case LFUN_MENUWRITE:
751                 if (!owner->buffer()->isUnnamed()) {
752                         owner->getMiniBuffer()->Set(_("Saving document"),
753                                                     MakeDisplayPath(owner->buffer()->fileName()),
754                                                     "...");
755                         MenuWrite(owner->view(), owner->buffer());
756                         //owner->getMiniBuffer()-> {
757                         //      Set(_("Document saved as"),
758                         //          MakeDisplayPath(owner->buffer()->fileName()));
759                         //} else {
760                         //owner->getMiniBuffer()->Set(_("Save failed!"));
761                         //}
762                 } else {
763                         MenuWriteAs(owner->view(), owner->buffer());
764                 }
765                 break;
766                 
767         case LFUN_MENUWRITEAS:
768                 MenuWriteAs(owner->view(), owner->buffer());
769                 break;
770                 
771         case LFUN_MENURELOAD:
772                 reloadBuffer();
773                 break;
774                 
775         case LFUN_UPDATE:
776                 Exporter::Export(owner->buffer(), argument, true);
777                 break;
778
779         case LFUN_PREVIEW:
780                 Exporter::Preview(owner->buffer(), argument);
781                 break;
782                 
783         case LFUN_BUILDPROG:
784                 Exporter::Export(owner->buffer(), "program", true);
785                 break;
786                 
787         case LFUN_RUNCHKTEX:
788                 MenuRunChktex(owner->buffer());
789                 break;
790                                 
791         case LFUN_MENUPRINT:
792                 owner->getDialogs()->showPrint();
793                 break;
794
795 #if 0
796         case LFUN_FAX:
797                 MenuFax(owner->buffer());
798                 break;
799 #endif
800                 
801         case LFUN_EXPORT:
802                 Exporter::Export(owner->buffer(), argument, false);
803                 break;
804
805         case LFUN_IMPORT:
806                 doImport(argument);
807                 break;
808                 
809         case LFUN_QUIT:
810                 QuitLyX();
811                 break;
812                 
813         case LFUN_TOCVIEW:
814         case LFUN_LOFVIEW:
815         case LFUN_LOTVIEW:
816         case LFUN_LOAVIEW:
817         {
818                 InsetCommandParams p;
819                 
820                 if (action == LFUN_TOCVIEW )
821                         p.setCmdName( "tableofcontents" );
822                 else if (action == LFUN_LOAVIEW )
823                         p.setCmdName( "listofalgorithms" );
824                 else if (action == LFUN_LOFVIEW )
825                         p.setCmdName( "listoffigures" );
826                 else
827                         p.setCmdName( "listoftables" );
828
829                 owner->getDialogs()->createTOC( p.getAsString() );
830                 break;
831         }       
832
833         case LFUN_TOC_INSERT:
834         case LFUN_LOA_INSERT:
835         case LFUN_LOF_INSERT:
836         case LFUN_LOT_INSERT:
837         {
838                 InsetCommandParams p;
839                 
840                 if (action == LFUN_TOC_INSERT )
841                         p.setCmdName( "tableofcontents" );
842                 else if (action == LFUN_LOA_INSERT )
843                         p.setCmdName( "listofalgorithms" );
844                 else if (action == LFUN_LOF_INSERT )
845                         p.setCmdName( "listoffigures" );
846                 else
847                         p.setCmdName( "listoftables" );
848
849                 Inset * inset = new InsetTOC( p );
850                 if (!owner->view()->insertInset( inset, "Standard", true ) )
851                         delete inset;
852                 break;
853         }
854                 
855         case LFUN_DIALOG_TABULAR_INSERT:
856                 owner->getDialogs()->showTabularCreate();
857                 break;
858                 
859         case LFUN_TABULAR_FEATURE:
860         case LFUN_SCROLL_INSET:
861                 // this is not handled here as this funktion is only aktive
862                 // if we have a locking_inset and that one is (or contains)
863                 // a tabular-inset
864                 break;
865
866         case LFUN_FIGURE:
867                 Figure();
868                 break;
869
870         case LFUN_INSET_GRAPHICS:
871         {
872                 Inset * new_inset = new InsetGraphics;
873                 if (!owner->view()->insertInset(new_inset)) {
874                         delete new_inset;
875                 } else {
876                         // this is need because you don't use a inset->Edit()
877                         owner->view()->updateInset(new_inset, true);
878                         new_inset->Edit(owner->view(), 0, 0, 0);
879                 }
880                 break;
881         }
882         
883         case LFUN_AUTOSAVE:
884                 AutoSave(owner->view());
885                 break;
886                 
887         case LFUN_UNDO:
888                 owner->view()->menuUndo();
889                 break;
890                 
891         case LFUN_REDO:
892                 owner->view()->menuRedo();
893                 break;
894                 
895         case LFUN_MENUSEARCH:
896         {
897                 // Ok this is one _very_ bad solution, but I think that some
898                 // of this will be rewritten as part of GUI indep anyway.
899                 // Lgb
900                 static LyXFindReplace FR_;
901                 FR_.StartSearch(owner->view());
902         }
903         break;
904                 
905         case LFUN_PASTE:
906                 owner->view()->paste();
907                 owner->view()->setState();
908                 break;
909                 
910         case LFUN_PASTESELECTION:
911         {
912                 bool asPara = false;
913                 if (argument == "paragraph") asPara = true;
914                 owner->view()->pasteClipboard(asPara);
915         }
916         break;
917         
918         case LFUN_CUT:
919                 owner->view()->cut();
920                 break;
921                 
922         case LFUN_COPY:
923                 owner->view()->copy();
924                 break;
925                 
926         case LFUN_LAYOUT_COPY:
927                 owner->view()->copyEnvironment();
928                 break;
929                 
930         case LFUN_LAYOUT_PASTE:
931                 owner->view()->pasteEnvironment();
932                 owner->view()->setState();
933                 break;
934                 
935         case LFUN_GOTOERROR:
936                 owner->view()->gotoError();
937                 break;
938                 
939         case LFUN_REMOVEERRORS:
940                 if (owner->view()->removeAutoInsets()) {
941                         owner->view()->redraw();
942                         owner->view()->fitCursor(owner->view()->text);
943                 }
944                 break;
945                 
946         case LFUN_GOTONOTE:
947                 owner->view()->gotoNote();
948                 break;
949
950 #ifndef NEW_INSETS
951         case LFUN_OPENSTUFF:
952                 owner->view()->openStuff();
953                 break;
954 #endif
955                 
956         case LFUN_HYPHENATION:
957                 owner->view()->hyphenationPoint();
958                 break;
959                 
960         case LFUN_LDOTS:
961                 owner->view()->ldots();
962                 break;
963                 
964         case LFUN_END_OF_SENTENCE:
965                 owner->view()->endOfSentenceDot();
966                 break;
967
968         case LFUN_MENU_SEPARATOR:
969                 owner->view()->menuSeparator();
970                 break;
971                 
972         case LFUN_HFILL:
973                 owner->view()->hfill();
974                 break;
975                 
976         case LFUN_DEPTH:
977                 changeDepth(owner->view(), 0);
978                 break;
979                 
980         case LFUN_DEPTH_MIN:
981                 changeDepth(owner->view(), -1);
982                 break;
983                 
984         case LFUN_DEPTH_PLUS:
985                 changeDepth(owner->view(), 1);
986                 break;
987                 
988         case LFUN_FREE:
989                 Free(owner->view());
990                 owner->view()->setState();
991                 owner->showState();
992                 break;
993                 
994         case LFUN_TEX:
995                 Tex(owner->view());
996                 owner->view()->setState();
997                 owner->showState();
998                 break;
999 #ifndef NEW_INSETS              
1000         case LFUN_MELT:
1001                 Melt(owner->view());
1002                 break;
1003 #endif
1004         case LFUN_RECONFIGURE:
1005                 Reconfigure(owner->view());
1006                 break;
1007 #ifndef NEW_INSETS
1008         case LFUN_FOOTMELT:
1009                 if (owner->view()->available()
1010                     && !owner->view()->text->selection
1011                     && owner->view()->text->cursor.par()->footnoteflag
1012                     != LyXParagraph::NO_FOOTNOTE)
1013                         { // only melt footnotes with FOOTMELT, not margins etc
1014                                 if (owner->view()->text->cursor.par()->footnotekind == LyXParagraph::FOOTNOTE)
1015                                         Melt(owner->view());
1016                         }
1017                 else
1018                         Foot(owner->view()); 
1019                 owner->view()->setState();
1020                 break;
1021
1022         case LFUN_MARGINMELT:
1023                 if (owner->view()->available()
1024                     && !owner->view()->text->selection
1025                     && owner->view()->text->cursor.par()->footnoteflag
1026                     != LyXParagraph::NO_FOOTNOTE) {
1027                         // only melt margins
1028                         if (owner->view()->text->cursor.par()->footnotekind == LyXParagraph::MARGIN)
1029                                 Melt(owner->view());
1030                 } else
1031                         Margin(owner->view()); 
1032                 owner->view()->setState();
1033                 break;
1034 #endif
1035 #ifndef NEW_INSETS
1036         case LFUN_FLOATSOPERATE:
1037                 if (argument == "openfoot")
1038                         owner->view()->allFloats(1,0);
1039                 else if (argument == "closefoot")
1040                         owner->view()->allFloats(0,0);
1041                 else if (argument == "openfig")
1042                         owner->view()->allFloats(1,1);
1043                 else if (argument == "closefig")
1044                         owner->view()->allFloats(0,1);
1045                 break;
1046 #else
1047 #warning Find another implementation here (or another lyxfunc)!
1048 #endif
1049         case LFUN_HELP_COPYRIGHT:
1050                 owner->getDialogs()->showCopyright();
1051                 break;
1052
1053         case LFUN_HELP_CREDITS:
1054                 owner->getDialogs()->showCredits();
1055                 break;
1056
1057         case LFUN_HELP_OPEN: {
1058                 string arg = argument;
1059                 if (arg.empty()) {
1060                         setErrorMessage(N_("Missing argument"));
1061                         break;
1062                 }
1063                 ProhibitInput(owner->view());
1064                 string fname = i18nLibFileSearch("doc", arg, "lyx");
1065                 if (fname.empty()) {
1066                         lyxerr << "LyX: unable to find documentation file `"
1067                                << arg << "'. Bad installation?" << endl;
1068                         AllowInput(owner->view());
1069                         break;
1070                 }
1071                 owner->getMiniBuffer()->Set(_("Opening help file"),
1072                                             MakeDisplayPath(fname),"...");
1073                 owner->view()->buffer(bufferlist.loadLyXFile(fname,false));
1074                 AllowInput(owner->view());
1075                 break;
1076         }
1077
1078         case LFUN_HELP_VERSION: {
1079                 ProhibitInput(owner->view());
1080                 string msg(_("LyX Version "));
1081                 msg += LYX_VERSION;
1082                 msg += " of ";
1083                 msg += LYX_RELEASE;
1084                 fl_show_message(msg.c_str(),
1085                                 (_("Library directory: ")
1086                                  + MakeDisplayPath(system_lyxdir)).c_str(),
1087                                 (_("User directory: ") 
1088                                  + MakeDisplayPath(user_lyxdir)).c_str());
1089                 AllowInput(owner->view());
1090                 break;
1091         }
1092         
1093                 // --- version control -------------------------------
1094         case LFUN_VC_REGISTER:
1095         {
1096                 if (!owner->buffer()->lyxvc.inUse())
1097                         owner->buffer()->lyxvc.registrer();
1098         }
1099         break;
1100                 
1101         case LFUN_VC_CHECKIN:
1102         {
1103                 if (owner->buffer()->lyxvc.inUse()
1104                     && !owner->buffer()->isReadonly())
1105                         owner->buffer()->lyxvc.checkIn();
1106         }
1107         break;
1108                 
1109         case LFUN_VC_CHECKOUT:
1110         {
1111                 if (owner->buffer()->lyxvc.inUse()
1112                     && owner->buffer()->isReadonly())
1113                         owner->buffer()->lyxvc.checkOut();
1114         }
1115         break;
1116         
1117         case LFUN_VC_REVERT:
1118         {
1119                 owner->buffer()->lyxvc.revert();
1120         }
1121         break;
1122                 
1123         case LFUN_VC_UNDO:
1124         {
1125                 owner->buffer()->lyxvc.undoLast();
1126         }
1127         break;
1128                 
1129         case LFUN_VC_HISTORY:
1130         {
1131                 owner->buffer()->lyxvc.showLog();
1132                 break;
1133         }
1134         
1135         // --- buffers ----------------------------------------
1136
1137         case LFUN_SWITCHBUFFER:
1138                 owner->view()->buffer(bufferlist.getBuffer(argument));
1139                 break;
1140
1141
1142         case LFUN_FILE_INSERT:
1143         {
1144                 MenuInsertLyXFile(argument);
1145         }
1146         break;
1147         
1148         case LFUN_FILE_INSERT_ASCII:
1149         {
1150                 bool asPara = (argument == "paragraph");
1151                 InsertAsciiFile(owner->view(), string(), asPara);
1152         }
1153         break;
1154         
1155         case LFUN_FILE_NEW:
1156         {
1157                 // servercmd: argument must be <file>:<template>
1158                 Buffer * tmpbuf = NewLyxFile(argument);
1159                 if (tmpbuf)
1160                         owner->view()->buffer(tmpbuf);
1161         }
1162         break;
1163                         
1164         case LFUN_FILE_OPEN:
1165                 owner->view()->buffer(bufferlist.loadLyXFile(argument));
1166                 break;
1167
1168         case LFUN_LATEX_LOG:
1169                 ShowLatexLog();
1170                 break;
1171                 
1172         case LFUN_LAYOUTNO:
1173         {
1174                 lyxerr.debug() << "LFUN_LAYOUTNO: (arg) " << argument << endl;
1175                 int sel = strToInt(argument);
1176                 lyxerr.debug() << "LFUN_LAYOUTNO: (sel) "<< sel << endl;
1177                 
1178                 // Should this give a setMessage instead?
1179                 if (sel == 0) 
1180                         return string(); // illegal argument
1181
1182                 --sel; // sel 1..., but layout 0...
1183
1184                 // Pretend we got the name instead.
1185                 Dispatch(int(LFUN_LAYOUT), 
1186                          textclasslist.NameOfLayout(owner->view()
1187                                                     ->buffer()->params.textclass,
1188                                                     sel));
1189                 return string();
1190         }
1191                 
1192         case LFUN_LAYOUT:
1193         {
1194                 lyxerr.debug() << "LFUN_LAYOUT: (arg) "
1195                                << argument << endl;
1196                 
1197                 // Derive layout number from given argument (string)
1198                 // and current buffer's textclass (number). */    
1199                 LyXTextClassList::ClassList::size_type tclass =
1200                         owner->view()->buffer()->params.textclass;
1201                 pair <bool, LyXTextClass::size_type> layout = 
1202                         textclasslist.NumberOfLayout(tclass, argument);
1203
1204                 // If the entry is obsolete, use the new one instead.
1205                 if (layout.first) {
1206                         string obs = textclasslist.Style(tclass,layout.second)
1207                               .obsoleted_by();
1208                         if (!obs.empty()) 
1209                                 layout = 
1210                                   textclasslist.NumberOfLayout(tclass, obs);
1211                 }
1212
1213                 // see if we found the layout number:
1214                 if (!layout.first) {
1215                         setErrorMessage(string(N_("Layout ")) + argument + 
1216                                         N_(" not known"));
1217                         break;
1218                 }
1219
1220                 if (current_layout != layout.second) {
1221                         owner->view()->hideCursor();
1222                         current_layout = layout.second;
1223                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1224                         owner->view()->text->
1225                                 SetLayout(owner->view(), layout.second);
1226                         owner->setLayout(layout.second);
1227                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1228                         owner->view()->setState();
1229                 }
1230         }
1231         break;
1232
1233         case LFUN_LAYOUT_DOCUMENT:
1234                 owner->getDialogs()->showLayoutDocument();
1235                 break;
1236                 
1237         case LFUN_LAYOUT_PARAGRAPH:
1238 #ifdef USE_OLD_PARAGRAPH_LAYOUT
1239                 MenuLayoutParagraph();
1240 #else
1241                 owner->getDialogs()->showLayoutParagraph();
1242 #endif
1243                 break;
1244                 
1245         case LFUN_LAYOUT_CHARACTER:
1246                 MenuLayoutCharacter();
1247                 break;
1248
1249         case LFUN_LAYOUT_TABULAR:
1250             if (owner->view()->theLockingInset()) {
1251                 if (owner->view()->theLockingInset()->LyxCode()==Inset::TABULAR_CODE) {
1252                     InsetTabular * inset = static_cast<InsetTabular *>
1253                         (owner->view()->theLockingInset());
1254                     inset->OpenLayoutDialog(owner->view());
1255                 } else if (owner->view()->theLockingInset()->
1256                            GetFirstLockingInsetOfType(Inset::TABULAR_CODE)!=0) {
1257                     InsetTabular * inset = static_cast<InsetTabular *>(
1258                         owner->view()->theLockingInset()->GetFirstLockingInsetOfType(Inset::TABULAR_CODE));
1259                     inset->OpenLayoutDialog(owner->view());
1260                 }
1261             }
1262             break;
1263
1264         case LFUN_LAYOUT_PREAMBLE:
1265                 MenuLayoutPreamble();
1266                 break;
1267                 
1268         case LFUN_LAYOUT_SAVE_DEFAULT:
1269                 MenuLayoutSave(owner->view());
1270                 break;
1271                 
1272         case LFUN_DROP_LAYOUTS_CHOICE:
1273                 owner->getToolbar()->openLayoutList();
1274                 break;
1275
1276         case LFUN_LANGUAGE:
1277                 Lang(owner->view(), argument);
1278                 owner->view()->setState();
1279                 owner->showState();
1280                 break;
1281
1282         case LFUN_EMPH:
1283                 Emph(owner->view());
1284                 owner->showState();
1285                 break;
1286
1287         case LFUN_BOLD:
1288                 Bold(owner->view());
1289                 owner->showState();
1290                 break;
1291                 
1292         case LFUN_NOUN:
1293                 Noun(owner->view());
1294                 owner->showState();
1295                 break;
1296                 
1297         case LFUN_CODE:
1298                 Code(owner->view());
1299                 owner->showState();
1300                 break;
1301                 
1302         case LFUN_SANS:
1303                 Sans(owner->view());
1304                 owner->showState();
1305                 break;
1306                 
1307         case LFUN_ROMAN:
1308                 Roman(owner->view());
1309                 owner->showState();
1310                 break;
1311                 
1312         case LFUN_DEFAULT:
1313                 StyleReset(owner->view());
1314                 owner->showState();
1315                 break;
1316                 
1317         case LFUN_UNDERLINE:
1318                 Underline(owner->view());
1319                 owner->showState();
1320                 break;
1321                 
1322         case LFUN_FONT_SIZE:
1323                 FontSize(owner->view(), argument);
1324                 owner->showState();
1325                 break;
1326                 
1327         case LFUN_FONT_STATE:
1328                 setMessage(CurrentState(owner->view()));
1329                 break;
1330                 
1331         case LFUN_UPCASE_WORD:
1332                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1333                 text->ChangeWordCase(owner->view(), LyXText::text_uppercase);
1334                 if (text->inset_owner)
1335                     owner->view()->updateInset(text->inset_owner, true);
1336                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1337                 break;
1338                 
1339         case LFUN_LOWCASE_WORD:
1340                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1341                 text->ChangeWordCase(owner->view(), LyXText::text_lowercase);
1342                 if (text->inset_owner)
1343                     owner->view()->updateInset(text->inset_owner, true);
1344                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1345                 break;
1346                 
1347         case LFUN_CAPITALIZE_WORD:
1348                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1349                 text->ChangeWordCase(owner->view(),
1350                                      LyXText::text_capitalization);
1351                 if (text->inset_owner)
1352                     owner->view()->updateInset(text->inset_owner, true);
1353                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1354                 break;
1355                 
1356         case LFUN_INSERT_LABEL:
1357                 MenuInsertLabel(owner->view(), argument);
1358                 break;
1359                 
1360         case LFUN_REF_INSERT:
1361                 if (argument.empty()) {
1362                         InsetCommandParams p("ref");
1363                 owner->getDialogs()->createRef(p.getAsString());
1364                 } else {
1365                         InsetCommandParams p;
1366                         p.setFromString(argument);
1367
1368                         InsetRef * inset = new InsetRef(p, *owner->buffer());
1369                         if (!owner->view()->insertInset(inset))
1370                                 delete inset;
1371                         else
1372                                 owner->view()->updateInset(inset, true);
1373                 }
1374                 break;
1375
1376         case LFUN_REF_BACK:
1377         {
1378                 owner->view()->restorePosition();
1379         }
1380         break;
1381
1382         case LFUN_REF_GOTO:
1383         {
1384                 string label(argument);
1385                 if (label.empty()) {
1386                         InsetRef * inset = 
1387                                 static_cast<InsetRef*>(getInsetByCode(Inset::REF_CODE));
1388                         if (inset)
1389                                 label = inset->getContents();
1390                 }
1391                 
1392                 if (!label.empty()) {
1393                         owner->view()->savePosition();
1394                         if (!owner->view()->gotoLabel(label))
1395                                 WriteAlert(_("Error"), 
1396                                            _("Couldn't find this label"), 
1397                                            _("in current document."));
1398                 }
1399         }
1400         break;
1401                 
1402         case LFUN_MENU_OPEN_BY_NAME:
1403                 owner->getMenubar()->openByName(argument);
1404                 break; // RVDK_PATCH_5
1405                 
1406         case LFUN_SPELLCHECK:
1407                 if (lyxrc.isp_command != "none")
1408                         ShowSpellChecker(owner->view());
1409                 break; // RVDK_PATCH_5
1410                 
1411                 // --- Cursor Movements -----------------------------
1412         case LFUN_RIGHT:
1413         {
1414                 LyXText * tmptext = owner->view()->text;
1415                 bool is_rtl = tmptext->cursor.par()->isRightToLeftPar(owner->buffer()->params);
1416                 if (!tmptext->mark_set)
1417                         owner->view()->beforeChange();
1418                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1419                 if (is_rtl)
1420                         tmptext->CursorLeft(owner->view(), false);
1421                 if (tmptext->cursor.pos() < tmptext->cursor.par()->Last()
1422                     && tmptext->cursor.par()->GetChar(tmptext->cursor.pos())
1423                     == LyXParagraph::META_INSET
1424                     && tmptext->cursor.par()->GetInset(tmptext->cursor.pos())
1425                     && tmptext->cursor.par()->GetInset(tmptext->cursor.pos())->Editable() == Inset::HIGHLY_EDITABLE){
1426                         Inset * tmpinset = tmptext->cursor.par()->GetInset(tmptext->cursor.pos());
1427                         setMessage(tmpinset->EditMessage());
1428                         tmpinset->Edit(owner->view(), 0, 0, 0);
1429                         break;
1430                 }
1431                 if (!is_rtl)
1432                         tmptext->CursorRight(owner->view(), false);
1433                 owner->view()->text->FinishUndo();
1434                 moveCursorUpdate(false);
1435                 owner->showState();
1436         }
1437         break;
1438                 
1439         case LFUN_LEFT:
1440         {
1441                 // This is soooo ugly. Isn`t it possible to make
1442                 // it simpler? (Lgb)
1443                 LyXText * txt = owner->view()->text;
1444                 bool is_rtl = txt->cursor.par()->isRightToLeftPar(owner->buffer()->params);
1445                 if (!txt->mark_set) owner->view()->beforeChange();
1446                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1447                 LyXCursor cur = txt->cursor;
1448                 if (!is_rtl)
1449                         txt->CursorLeft(owner->view(), false);
1450                 if ((cur != txt->cursor) && // only if really moved!
1451                     txt->cursor.pos() < txt->cursor.par()->Last() &&
1452                     (txt->cursor.par()->GetChar(txt->cursor.pos()) ==
1453                      LyXParagraph::META_INSET) &&
1454                     txt->cursor.par()->GetInset(txt->cursor.pos()) &&
1455                     (txt->cursor.par()->GetInset(txt->cursor.pos())->Editable()
1456                      == Inset::HIGHLY_EDITABLE))
1457                 {
1458                         Inset * tmpinset = txt->cursor.par()->GetInset(txt->cursor.pos());
1459                         setMessage(tmpinset->EditMessage());
1460                         LyXFont font = txt->GetFont(owner->view()->buffer(),
1461                                                     txt->cursor.par(),
1462                                                     txt->cursor.pos());
1463                         tmpinset->Edit(owner->view(),
1464                                        tmpinset->x() +
1465                                        tmpinset->width(owner->view(),font),
1466                                        tmpinset->descent(owner->view(),font),
1467                                        0);
1468                         break;
1469                 }
1470                 if  (is_rtl)
1471                         txt->CursorRight(owner->view(), false);
1472
1473                 owner->view()->text->FinishUndo();
1474                 moveCursorUpdate(false);
1475                 owner->showState();
1476         }
1477         break;
1478                 
1479         case LFUN_UP:
1480                 if (!owner->view()->text->mark_set) owner->view()->beforeChange();
1481                 owner->view()->update(BufferView::UPDATE);
1482                 owner->view()->text->CursorUp(owner->view());
1483                 owner->view()->text->FinishUndo();
1484                 moveCursorUpdate(false);
1485                 owner->showState();
1486                 break;
1487                 
1488         case LFUN_DOWN:
1489                 if (!owner->view()->text->mark_set)
1490                         owner->view()->beforeChange();
1491                 owner->view()->update(BufferView::UPDATE);
1492                 owner->view()->text->CursorDown(owner->view());
1493                 owner->view()->text->FinishUndo();
1494                 moveCursorUpdate(false);
1495                 owner->showState();
1496                 break;
1497
1498         case LFUN_UP_PARAGRAPH:
1499                 if (!owner->view()->text->mark_set)
1500                         owner->view()->beforeChange();
1501                 owner->view()->update(BufferView::UPDATE);
1502                 owner->view()->text->CursorUpParagraph(owner->view());
1503                 owner->view()->text->FinishUndo();
1504                 moveCursorUpdate(false);
1505                 owner->showState();
1506                 break;
1507                 
1508         case LFUN_DOWN_PARAGRAPH:
1509                 if (!owner->view()->text->mark_set)
1510                         owner->view()->beforeChange();
1511                 owner->view()->update(BufferView::UPDATE);
1512                 owner->view()->text->CursorDownParagraph(owner->view());
1513                 owner->view()->text->FinishUndo();
1514                 moveCursorUpdate(false);
1515                 owner->showState();
1516                 break;
1517                 
1518         case LFUN_PRIOR:
1519                 if (!text->mark_set)
1520                     owner->view()->beforeChange();
1521                 owner->view()->update(BufferView::UPDATE);
1522                 owner->view()->cursorPrevious(text);
1523                 owner->view()->text->FinishUndo();
1524                 if (text->inset_owner)
1525                     owner->view()->updateInset(text->inset_owner, false);
1526                 else
1527                     moveCursorUpdate(false);
1528                 owner->showState();
1529                 break;
1530                 
1531         case LFUN_NEXT:
1532                 if (!text->mark_set)
1533                         owner->view()->beforeChange();
1534                 owner->view()->update(BufferView::UPDATE);
1535                 owner->view()->cursorNext(text);
1536                 owner->view()->text->FinishUndo();
1537                 if (text->inset_owner)
1538                     owner->view()->updateInset(text->inset_owner, false);
1539                 else
1540                     moveCursorUpdate(false);
1541                 owner->showState();
1542                 break;
1543                 
1544         case LFUN_HOME:
1545                 if (!owner->view()->text->mark_set)
1546                         owner->view()->beforeChange();
1547                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1548                 owner->view()->text->CursorHome(owner->view());
1549                 owner->view()->text->FinishUndo();
1550                 moveCursorUpdate(false);
1551                 owner->showState();
1552                 break;
1553                 
1554         case LFUN_END:
1555                 if (!owner->view()->text->mark_set)
1556                         owner->view()->beforeChange();
1557                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1558                 owner->view()->text->CursorEnd(owner->view());
1559                 owner->view()->text->FinishUndo();
1560                 moveCursorUpdate(false);
1561                 owner->showState();
1562                 break;
1563                 
1564         case LFUN_SHIFT_TAB:
1565         case LFUN_TAB:
1566                 if (!owner->view()->text->mark_set)
1567                         owner->view()->beforeChange();
1568                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1569                 owner->view()->text->CursorTab(owner->view());
1570                 owner->view()->text->FinishUndo();
1571                 moveCursorUpdate(false);
1572                 owner->showState();
1573                 break;
1574                 
1575         case LFUN_WORDRIGHT:
1576                 if (!text->mark_set)
1577                         owner->view()->beforeChange();
1578                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1579                 if (text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1580                         text->CursorLeftOneWord(owner->view());
1581                 else
1582                         text->CursorRightOneWord(owner->view());
1583                 owner->view()->text->FinishUndo();
1584                 if (text->inset_owner)
1585                     owner->view()->updateInset(text->inset_owner, true);
1586                 moveCursorUpdate(false);
1587                 owner->showState();
1588                 break;
1589                 
1590         case LFUN_WORDLEFT:
1591                 if (!text->mark_set)
1592                         owner->view()->beforeChange();
1593                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1594                 if (text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1595                         text->CursorRightOneWord(owner->view());
1596                 else
1597                         text->CursorLeftOneWord(owner->view());
1598                 owner->view()->text->FinishUndo();
1599                 if (text->inset_owner)
1600                     owner->view()->updateInset(text->inset_owner, true);
1601                 moveCursorUpdate(false);
1602                 owner->showState();
1603                 break;
1604                 
1605         case LFUN_BEGINNINGBUF:
1606                 if (!owner->view()->text->mark_set)
1607                         owner->view()->beforeChange();
1608                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1609                 owner->view()->text->CursorTop(owner->view());
1610                 owner->view()->text->FinishUndo();
1611                 moveCursorUpdate(false);
1612                 owner->showState();
1613                 break;
1614                 
1615         case LFUN_ENDBUF:
1616                 if (!owner->view()->text->mark_set)
1617                         owner->view()->beforeChange();
1618                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1619                 owner->view()->text->CursorBottom(owner->view());
1620                 owner->view()->text->FinishUndo();
1621                 moveCursorUpdate(false);
1622                 owner->showState();
1623                 break;
1624
1625       
1626                 /* cursor selection ---------------------------- */
1627         case LFUN_RIGHTSEL:
1628                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1629                 if (owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1630                         owner->view()->text->CursorLeft(owner->view());
1631                 else
1632                         owner->view()->text->CursorRight(owner->view());
1633                 owner->view()->text->FinishUndo();
1634                 moveCursorUpdate(true);
1635                 owner->showState();
1636                 break;
1637                 
1638         case LFUN_LEFTSEL:
1639                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1640                 if (owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1641                         owner->view()->text->CursorRight(owner->view());
1642                 else
1643                         owner->view()->text->CursorLeft(owner->view());
1644                 owner->view()->text->FinishUndo();
1645                 moveCursorUpdate(true);
1646                 owner->showState();
1647                 break;
1648                 
1649         case LFUN_UPSEL:
1650                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1651                 owner->view()->text->CursorUp(owner->view());
1652                 owner->view()->text->FinishUndo();
1653                 moveCursorUpdate(true);
1654                 owner->showState();
1655                 break;
1656                 
1657         case LFUN_DOWNSEL:
1658                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1659                 owner->view()->text->CursorDown(owner->view());
1660                 owner->view()->text->FinishUndo();
1661                 moveCursorUpdate(true);
1662                 owner->showState();
1663                 break;
1664
1665         case LFUN_UP_PARAGRAPHSEL:
1666                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1667                 owner->view()->text->CursorUpParagraph(owner->view());
1668                 owner->view()->text->FinishUndo();
1669                 moveCursorUpdate(true);
1670                 owner->showState();
1671                 break;
1672                 
1673         case LFUN_DOWN_PARAGRAPHSEL:
1674                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1675                 owner->view()->text->CursorDownParagraph(owner->view());
1676                 owner->view()->text->FinishUndo();
1677                 moveCursorUpdate(true);
1678                 owner->showState();
1679                 break;
1680                 
1681         case LFUN_PRIORSEL:
1682                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1683                 owner->view()->cursorPrevious(text);
1684                 owner->view()->text->FinishUndo();
1685                 if (text->inset_owner)
1686                     owner->view()->updateInset(text->inset_owner, false);
1687                 else
1688                     moveCursorUpdate(true);
1689                 owner->showState();
1690                 break;
1691                 
1692         case LFUN_NEXTSEL:
1693                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1694                 owner->view()->cursorNext(text);
1695                 owner->view()->text->FinishUndo();
1696                 if (text->inset_owner)
1697                     owner->view()->updateInset(text->inset_owner, false);
1698                 else
1699                     moveCursorUpdate(true);
1700                 owner->showState();
1701                 break;
1702                 
1703         case LFUN_HOMESEL:
1704                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1705                 owner->view()->text->CursorHome(owner->view());
1706                 owner->view()->text->FinishUndo();
1707                 moveCursorUpdate(true);
1708                 owner->showState();
1709                 break;
1710                 
1711         case LFUN_ENDSEL:
1712                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1713                 owner->view()->text->CursorEnd(owner->view());
1714                 owner->view()->text->FinishUndo();
1715                 moveCursorUpdate(true);
1716                 owner->showState();
1717                 break;
1718                 
1719         case LFUN_WORDRIGHTSEL:
1720                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1721                 if (owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1722                         owner->view()->text->CursorLeftOneWord(owner->view());
1723                 else
1724                         owner->view()->text->CursorRightOneWord(owner->view());
1725                 owner->view()->text->FinishUndo();
1726                 moveCursorUpdate(true);
1727                 owner->showState();
1728                 break;
1729                 
1730         case LFUN_WORDLEFTSEL:
1731                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1732                 if (owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1733                         owner->view()->text->CursorRightOneWord(owner->view());
1734                 else
1735                         owner->view()->text->CursorLeftOneWord(owner->view());
1736                 owner->view()->text->FinishUndo();
1737                 moveCursorUpdate(true);
1738                 owner->showState();
1739                 break;
1740                 
1741         case LFUN_BEGINNINGBUFSEL:
1742                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1743                 owner->view()->text->CursorTop(owner->view());
1744                 owner->view()->text->FinishUndo();
1745                 moveCursorUpdate(true);
1746                 owner->showState();
1747                 break;
1748                 
1749         case LFUN_ENDBUFSEL:
1750                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1751                 owner->view()->text->CursorBottom(owner->view());
1752                 owner->view()->text->FinishUndo();
1753                 moveCursorUpdate(true);
1754                 owner->showState();
1755                 break;
1756
1757                 // --- text changing commands ------------------------
1758         case LFUN_BREAKLINE:
1759                 owner->view()->beforeChange();
1760                 owner->view()->text->InsertChar(owner->view(), LyXParagraph::META_NEWLINE);
1761                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1762                 moveCursorUpdate(false);
1763                 break;
1764                 
1765         case LFUN_PROTECTEDSPACE:
1766         {
1767                 LyXLayout const & style =
1768                         textclasslist.Style(owner->view()->buffer()->params.textclass,
1769                                             owner->view()->text->cursor.par()->GetLayout());
1770
1771                 if (style.free_spacing) {
1772                         owner->view()->text->InsertChar(owner->view(), ' ');
1773                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1774                 } else {
1775                         owner->view()->protectedBlank();
1776                 }
1777                 moveCursorUpdate(false);
1778         }
1779         break;
1780                 
1781         case LFUN_SETMARK:
1782                 if (text->mark_set) {
1783                         owner->view()->beforeChange();
1784                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1785                         setMessage(N_("Mark removed"));
1786                 } else {
1787                         owner->view()->beforeChange();
1788                         text->mark_set = 1;
1789                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1790                         setMessage(N_("Mark set"));
1791                 }
1792                 text->sel_cursor = text->cursor;
1793                 if (text->inset_owner)
1794                     owner->view()->updateInset(text->inset_owner, true);
1795                 break;
1796                 
1797         case LFUN_DELETE:
1798                 if (!owner->view()->text->selection) {
1799                         owner->view()->text->Delete(owner->view());
1800                         owner->view()->text->sel_cursor = 
1801                                 owner->view()->text->cursor;
1802                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1803                         // It is possible to make it a lot faster still
1804                         // just comment out the lone below...
1805                         owner->view()->showCursor();
1806                 } else {
1807                         owner->view()->cut();
1808                 }
1809                 moveCursorUpdate(false);
1810                 owner->showState();
1811                 owner->view()->setState();
1812                 break;
1813
1814         case LFUN_DELETE_SKIP:
1815         {
1816                 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
1817                 
1818                 LyXCursor cursor = owner->view()->text->cursor;
1819
1820                 if (!owner->view()->text->selection) {
1821                         if (cursor.pos() == cursor.par()->Last()) {
1822                                 owner->view()->text->CursorRight(owner->view());
1823                                 cursor = owner->view()->text->cursor;
1824                                 if (cursor.pos() == 0
1825                                     && !(cursor.par()->added_space_top 
1826                                          == VSpace (VSpace::NONE))) {
1827                                         owner->view()->text->SetParagraph
1828                                                 (owner->view(),
1829                                                  cursor.par()->line_top,
1830                                                  cursor.par()->line_bottom,
1831                                                  cursor.par()->pagebreak_top, 
1832                                                  cursor.par()->pagebreak_bottom,
1833                                                  VSpace(VSpace::NONE), 
1834                                                  cursor.par()->added_space_bottom,
1835                                                  cursor.par()->align, 
1836                                                  cursor.par()->labelwidthstring, 0);
1837                                         owner->view()->text->CursorLeft(owner->view());
1838                                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1839                                 } else {
1840                                         owner->view()->text->CursorLeft(owner->view());
1841                                         owner->view()->text->Delete(owner->view());
1842                                         owner->view()->text->sel_cursor = 
1843                                                 owner->view()->text->cursor;
1844                                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1845                                 }
1846                         } else {
1847                                 owner->view()->text->Delete(owner->view());
1848                                 owner->view()->text->sel_cursor = 
1849                                         owner->view()->text->cursor;
1850                                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1851                         }
1852                 } else {
1853                         owner->view()->cut();
1854                 }
1855         }
1856         break;
1857
1858         /* -------> Delete word forward. */
1859         case LFUN_DELETE_WORD_FORWARD:
1860                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1861                 text->DeleteWordForward(owner->view());
1862                 if (text->inset_owner)
1863                     owner->view()->updateInset(text->inset_owner, true);
1864                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1865                 moveCursorUpdate(false);
1866                 owner->showState();
1867                 break;
1868
1869                 /* -------> Delete word backward. */
1870         case LFUN_DELETE_WORD_BACKWARD:
1871                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1872                 text->DeleteWordBackward(owner->view());
1873                 if (text->inset_owner)
1874                     owner->view()->updateInset(text->inset_owner, true);
1875                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1876                 moveCursorUpdate(false);
1877                 owner->showState();
1878                 break;
1879                 
1880                 /* -------> Kill to end of line. */
1881         case LFUN_DELETE_LINE_FORWARD:
1882                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1883                 text->DeleteLineForward(owner->view());
1884                 if (text->inset_owner)
1885                     owner->view()->updateInset(text->inset_owner, true);
1886                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1887                 moveCursorUpdate(false);
1888                 break;
1889                 
1890                 /* -------> Set mark off. */
1891         case LFUN_MARK_OFF:
1892                 owner->view()->beforeChange();
1893                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1894                 text->sel_cursor = text->cursor;
1895                 setMessage(N_("Mark off"));
1896                 if (text->inset_owner)
1897                     owner->view()->updateInset(text->inset_owner, true);
1898                 break;
1899
1900                 /* -------> Set mark on. */
1901         case LFUN_MARK_ON:
1902                 owner->view()->beforeChange();
1903                 owner->view()->text->mark_set = 1;
1904                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1905                 text->sel_cursor = text->cursor;
1906                 if (text->inset_owner)
1907                     owner->view()->updateInset(text->inset_owner, true);
1908                 setMessage(N_("Mark on"));
1909                 break;
1910                 
1911         case LFUN_BACKSPACE:
1912         {
1913                 if (!owner->view()->text->selection) {
1914                         if (owner->getIntl()->getTrans()->backspace()) {
1915                                 owner->view()->text->Backspace(owner->view());
1916                                 owner->view()->text->sel_cursor = 
1917                                         owner->view()->text->cursor;
1918                                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1919                                 // It is possible to make it a lot faster still
1920                                 // just comment out the lone below...
1921                                 owner->view()->showCursor();
1922                         }
1923                 } else {
1924                         owner->view()->cut();
1925                 }
1926                 owner->showState();
1927                 owner->view()->setState();
1928         }
1929         break;
1930
1931         case LFUN_BACKSPACE_SKIP:
1932         {
1933                 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
1934                 
1935                 LyXCursor cursor = owner->view()->text->cursor;
1936                 
1937                 if (!owner->view()->text->selection) {
1938                         if (cursor.pos() == 0 
1939                             && !(cursor.par()->added_space_top 
1940                                  == VSpace (VSpace::NONE))) {
1941                                 owner->view()->text->SetParagraph 
1942                                         (owner->view(),
1943                                          cursor.par()->line_top,      
1944                                          cursor.par()->line_bottom,
1945                                          cursor.par()->pagebreak_top, 
1946                                          cursor.par()->pagebreak_bottom,
1947                                          VSpace(VSpace::NONE), cursor.par()->added_space_bottom,
1948                                          cursor.par()->align, 
1949                                          cursor.par()->labelwidthstring, 0);
1950                                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1951                         } else {
1952                                 owner->view()->text->Backspace(owner->view());
1953                                 owner->view()->text->sel_cursor 
1954                                         = cursor;
1955                                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1956                         }
1957                 } else
1958                         owner->view()->cut();
1959         }
1960         break;
1961
1962         case LFUN_BREAKPARAGRAPH:
1963         {
1964                 owner->view()->beforeChange();
1965                 owner->view()->text->BreakParagraph(owner->view(), 0);
1966                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1967                 owner->view()->text->sel_cursor = 
1968                         owner->view()->text->cursor;
1969                 owner->view()->setState();
1970                 owner->showState();
1971                 break;
1972         }
1973
1974         case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
1975         {
1976                 owner->view()->beforeChange();
1977                 owner->view()->text->BreakParagraph(owner->view(), 1);
1978                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1979                 owner->view()->text->sel_cursor = 
1980                         owner->view()->text->cursor;
1981                 owner->view()->setState();
1982                 owner->showState();
1983                 break;
1984         }
1985         
1986         case LFUN_BREAKPARAGRAPH_SKIP:
1987         {
1988                 // When at the beginning of a paragraph, remove
1989                 // indentation and add a "defskip" at the top.
1990                 // Otherwise, do the same as LFUN_BREAKPARAGRAPH.
1991                 
1992                 LyXCursor cursor = owner->view()->text->cursor;
1993                 
1994                 owner->view()->beforeChange();
1995                 if (cursor.pos() == 0) {
1996                         if (cursor.par()->added_space_top == VSpace(VSpace::NONE)) {
1997                                 owner->view()->text->SetParagraph
1998                                         (owner->view(),
1999                                          cursor.par()->line_top,      
2000                                          cursor.par()->line_bottom,
2001                                          cursor.par()->pagebreak_top, 
2002                                          cursor.par()->pagebreak_bottom,
2003                                          VSpace(VSpace::DEFSKIP), cursor.par()->added_space_bottom,
2004                                          cursor.par()->align, 
2005                                          cursor.par()->labelwidthstring, 1);
2006                                 //owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2007                         } 
2008                 }
2009                 else {
2010                         owner->view()->text->BreakParagraph(owner->view(), 0);
2011                         //owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2012                 }
2013
2014                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2015                 owner->view()->text->sel_cursor = cursor;
2016                 owner->view()->setState();
2017                 owner->showState();
2018         }
2019         break;
2020
2021         case LFUN_PARAGRAPH_SPACING:
2022         {
2023                 LyXParagraph * par = owner->view()->text->cursor.par();
2024                 Spacing::Space cur_spacing = par->spacing.getSpace();
2025                 float cur_value = 1.0;
2026                 if (cur_spacing == Spacing::Other) {
2027                         cur_value = par->spacing.getValue();
2028                 }
2029                 
2030                 istringstream istr(argument.c_str());
2031
2032                 string tmp;
2033                 istr >> tmp;
2034                 Spacing::Space new_spacing = cur_spacing;
2035                 float new_value = cur_value;
2036                 if (tmp.empty()) {
2037                         lyxerr << "Missing argument to `paragraph-spacing'"
2038                                << endl;
2039                 } else if (tmp == "single") {
2040                         new_spacing = Spacing::Single;
2041                 } else if (tmp == "onehalf") {
2042                         new_spacing = Spacing::Onehalf;
2043                 } else if (tmp == "double") {
2044                         new_spacing = Spacing::Double;
2045                 } else if (tmp == "other") {
2046                         new_spacing = Spacing::Other;
2047                         float tmpval = 0.0;
2048                         istr >> tmpval;
2049                         lyxerr << "new_value = " << tmpval << endl;
2050                         if (tmpval != 0.0)
2051                                 new_value = tmpval;
2052                 } else if (tmp == "default") {
2053                         new_spacing = Spacing::Default;
2054                 } else {
2055                         lyxerr << _("Unknown spacing argument: ")
2056                                << argument << endl;
2057                 }
2058                 if (cur_spacing != new_spacing || cur_value != new_value) {
2059                         par->spacing.set(new_spacing, new_value);
2060                         owner->view()->text->RedoParagraph(owner->view());
2061                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2062                 }
2063         }
2064         break;
2065         
2066         case LFUN_QUOTE:
2067                 owner->view()->beforeChange();
2068                 owner->view()->text->InsertChar(owner->view(), '\"');  // This " matches the single quote in the code
2069                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2070                 moveCursorUpdate(false);
2071                 break;
2072
2073         case LFUN_HTMLURL:
2074         case LFUN_URL:
2075         {
2076                 InsetCommandParams p;
2077                 if (action == LFUN_HTMLURL)
2078                         p.setCmdName("htmlurl");
2079                 else
2080                         p.setCmdName("url");
2081                 owner->getDialogs()->createUrl( p.getAsString() );
2082         }
2083         break;
2084                     
2085         case LFUN_INSERT_URL:
2086         {
2087                 InsetCommandParams p;
2088                 p.setFromString( argument );
2089
2090                 InsetUrl * inset = new InsetUrl( p );
2091                 if (!owner->view()->insertInset(inset))
2092                         delete inset;
2093                 else
2094                         owner->view()->updateInset( inset, true );
2095         }
2096         break;
2097                     
2098         case LFUN_INSET_TEXT:
2099         {
2100                 InsetText * new_inset = new InsetText;
2101                 if (owner->view()->insertInset(new_inset))
2102                         new_inset->Edit(owner->view(), 0, 0, 0);
2103                 else
2104                         delete new_inset;
2105         }
2106         break;
2107         
2108         case LFUN_INSET_ERT:
2109         {
2110                 InsetERT * new_inset = new InsetERT;
2111                 if (owner->view()->insertInset(new_inset))
2112                         new_inset->Edit(owner->view(), 0, 0, 0);
2113                 else
2114                         delete new_inset;
2115         }
2116         break;
2117         
2118         case LFUN_INSET_EXTERNAL:
2119         {
2120                 InsetExternal * new_inset = new InsetExternal;
2121                 if (owner->view()->insertInset(new_inset))
2122                         new_inset->Edit(owner->view(), 0, 0, 0);
2123                 else
2124                         delete new_inset;
2125         }
2126         break;
2127         
2128         case LFUN_INSET_FOOTNOTE:
2129         {
2130                 InsetFoot * new_inset = new InsetFoot;
2131                 if (owner->view()->insertInset(new_inset))
2132                         new_inset->Edit(owner->view(), 0, 0, 0);
2133                 else
2134                         delete new_inset;
2135         }
2136         break;
2137
2138         case LFUN_INSET_MARGINAL:
2139         {
2140                 InsetMarginal * new_inset = new InsetMarginal;
2141                 if (owner->view()->insertInset(new_inset))
2142                         new_inset->Edit(owner->view(), 0, 0, 0);
2143                 else
2144                         delete new_inset;
2145         }
2146         break;
2147
2148         case LFUN_INSET_MINIPAGE:
2149         {
2150                 InsetMinipage * new_inset = new InsetMinipage;
2151                 if (owner->view()->insertInset(new_inset))
2152                         new_inset->Edit(owner->view(), 0, 0, 0);
2153                 else
2154                         delete new_inset;
2155         }
2156         break;
2157
2158         case LFUN_INSET_FLOAT:
2159         {
2160                 // check if the float type exist
2161                 if (floatList.typeExist(argument)) {
2162                         InsetFloat * new_inset = new InsetFloat(argument);
2163                         if (owner->view()->insertInset(new_inset))
2164                                 new_inset->Edit(owner->view(), 0, 0, 0);
2165                         else
2166                                 delete new_inset;
2167                 } else {
2168                         lyxerr << "Non-existant float type: "
2169                                << argument << endl;
2170                 }
2171                 
2172         }
2173         break;
2174
2175         case LFUN_INSET_LIST:
2176         {
2177                 InsetList * new_inset = new InsetList;
2178                 if (owner->view()->insertInset(new_inset))
2179                         new_inset->Edit(owner->view(), 0, 0, 0);
2180                 else
2181                         delete new_inset;
2182         }
2183         break;
2184
2185         case LFUN_INSET_THEOREM:
2186         {
2187                 InsetTheorem * new_inset = new InsetTheorem;
2188                 if (owner->view()->insertInset(new_inset))
2189                         new_inset->Edit(owner->view(), 0, 0, 0);
2190                 else
2191                         delete new_inset;
2192         }
2193         break;
2194
2195         case LFUN_INSET_CAPTION:
2196         {
2197                 // Do we have a locking inset...
2198                 if (owner->view()->theLockingInset()) {
2199                         lyxerr << "Locking inset code: "
2200                                << static_cast<int>(owner->view()->theLockingInset()->LyxCode());
2201                         InsetCaption * new_inset = new InsetCaption;
2202                         new_inset->setOwner(owner->view()->theLockingInset());
2203                         new_inset->SetAutoBreakRows(true);
2204                         new_inset->SetDrawFrame(0, InsetText::LOCKED);
2205                         new_inset->SetFrameColor(0, LColor::footnoteframe);
2206                         if (owner->view()->insertInset(new_inset))
2207                                 new_inset->Edit(owner->view(), 0, 0, 0);
2208                         else
2209                                 delete new_inset;
2210                 }
2211         }
2212         break;
2213         
2214         case LFUN_INSET_TABULAR:
2215         {
2216                 int r = 2, c = 2;
2217                 if (!argument.empty())
2218                         ::sscanf(argument.c_str(),"%d%d", &r, &c);
2219                 InsetTabular * new_inset =
2220                         new InsetTabular(*owner->buffer(), r, c);
2221                 if (owner->view()->insertInset(new_inset))
2222                         new_inset->Edit(owner->view(), 0, 0, 0);
2223                 else
2224                         delete new_inset;
2225         }
2226         break;
2227
2228         // --- lyxserver commands ----------------------------
2229
2230         case LFUN_CHARATCURSOR:
2231         {
2232                 LyXParagraph::size_type pos = 
2233                         owner->view()->text->cursor.pos();
2234                 if (pos < owner->view()->text->cursor.par()->size())
2235                         //dispatch_buffer = owner->view()->text->
2236                         //      cursor.par()->text[pos];
2237                         dispatch_buffer =
2238                                 owner->view()->text->
2239                                 cursor.par()->GetChar(pos);
2240                 else
2241                         dispatch_buffer = "EOF";
2242         }
2243         break;
2244         
2245         case LFUN_GETXY:
2246                 dispatch_buffer = 
2247                         tostr(owner->view()->text->cursor.x()) + ' '
2248                         + tostr(owner->view()->text->cursor.y());
2249                 break;
2250                 
2251         case LFUN_SETXY:
2252         {
2253                 int x;
2254                 int y;
2255                 ::sscanf(argument.c_str(), " %d %d", &x, &y);
2256                 owner->view()->text->SetCursorFromCoordinates(owner->view(), x, y);
2257         }
2258         break;
2259         
2260         case LFUN_GETLAYOUT:
2261                 dispatch_buffer =  
2262                         tostr(owner->view()->text->cursor.par()->layout);
2263                 break;
2264                         
2265         case LFUN_GETFONT:
2266         {
2267                 LyXFont & font = owner->view()->text->current_font;
2268                 if (font.shape() == LyXFont::ITALIC_SHAPE)
2269                         dispatch_buffer = 'E';
2270                 else if (font.shape() == LyXFont::SMALLCAPS_SHAPE)
2271                         dispatch_buffer = 'N';
2272                 else
2273                         dispatch_buffer = '0';
2274
2275         }
2276         break;
2277
2278         case LFUN_GETLATEX:
2279         {
2280                 LyXFont & font = owner->view()->text->current_font;
2281                 if (font.latex() == LyXFont::ON)
2282                         dispatch_buffer = 'L';
2283                 else
2284                         dispatch_buffer = '0';
2285         }
2286         break;
2287
2288         case LFUN_GETNAME:
2289                 setMessage(owner->buffer()->fileName());
2290                 lyxerr.debug() << "FNAME["
2291                                << owner->buffer()->fileName()
2292                                << "] " << endl;
2293                 break;
2294                 
2295         case LFUN_NOTIFY:
2296         {
2297                 string buf;
2298                 keyseq.print(buf);
2299                 dispatch_buffer = buf;
2300                 lyxserver->notifyClient(dispatch_buffer);
2301         }
2302         break;
2303
2304         case LFUN_GOTOFILEROW:
2305         {
2306                 char file_name[100];
2307                 int row;
2308                 ::sscanf(argument.c_str(), " %s %d", file_name, &row);
2309
2310                 // Must replace extension of the file to be .lyx and get full path
2311                 string s = ChangeExtension(string(file_name), ".lyx");
2312
2313                 // Either change buffer or load the file
2314                 if (bufferlist.exists(s))
2315                         owner->view()->buffer(bufferlist.getBuffer(s));
2316                 else
2317                         owner->view()->buffer(bufferlist.loadLyXFile(s));
2318
2319                 // Set the cursor  
2320                 owner->view()->setCursorFromRow(row);
2321
2322                 // Recenter screen
2323                 owner->view()->center();
2324         }
2325         break;
2326
2327         case LFUN_GOTO_PARAGRAPH:
2328         {
2329                 istringstream istr(argument.c_str());
2330
2331                 int id;
2332                 istr >> id;
2333                 LyXParagraph * par = owner->view()->text->GetParFromID(id);
2334
2335                 // Set the cursor
2336                 owner->view()->text->SetCursor(owner->view(), par, 0);
2337                 owner->view()->setState();
2338                 owner->showState();
2339
2340                 // Recenter screen
2341                 owner->view()->center();
2342         }
2343         break;
2344
2345         case LFUN_APROPOS:
2346         case LFUN_GETTIP:
2347         {
2348                 int const qa = lyxaction.LookupFunc(argument);
2349                 setMessage(lyxaction.helpText(static_cast<kb_action>(qa)));
2350         }
2351         break;
2352
2353         // --- accented characters ---------------------------
2354                 
2355         case LFUN_UMLAUT:
2356         case LFUN_CIRCUMFLEX:
2357         case LFUN_GRAVE:
2358         case LFUN_ACUTE:
2359         case LFUN_TILDE:
2360         case LFUN_CEDILLA:
2361         case LFUN_MACRON:
2362         case LFUN_DOT:
2363         case LFUN_UNDERDOT:
2364         case LFUN_UNDERBAR:
2365         case LFUN_CARON:
2366         case LFUN_SPECIAL_CARON:
2367         case LFUN_BREVE:
2368         case LFUN_TIE:
2369         case LFUN_HUNG_UMLAUT:
2370         case LFUN_CIRCLE:
2371         case LFUN_OGONEK:
2372         {
2373                 char c = 0;
2374                 
2375                 if (keyseq.length == -1 && keyseq.getiso() != 0) 
2376                         c = keyseq.getiso();
2377                 
2378                 owner->getIntl()->getTrans()->
2379                         deadkey(c, get_accent(action).accent, 
2380                                 owner->view()->text);
2381                 
2382                 // Need to reset, in case the minibuffer calls these
2383                 // actions
2384                 keyseq.reset();
2385                 keyseq.length = 0;
2386                 
2387                 // copied verbatim from do_accent_char
2388                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2389
2390                 owner->view()->text->sel_cursor = 
2391                         owner->view()->text->cursor;
2392         }   
2393         break;
2394         
2395         // --- toolbar ----------------------------------
2396         case LFUN_PUSH_TOOLBAR:
2397         {
2398                 int nth = strToInt(argument);
2399                 if (nth <= 0) {
2400                         setErrorMessage(N_("Push-toolbar needs argument > 0"));
2401                 } else {
2402                         owner->getToolbar()->push(nth);
2403                 }
2404         }
2405         break;
2406         
2407         case LFUN_ADD_TO_TOOLBAR:
2408         {
2409                 if (lyxerr.debugging(Debug::GUI)) {
2410                         lyxerr << "LFUN_ADD_TO_TOOLBAR:"
2411                                 "argument = `" << argument << '\'' << endl;
2412                 }
2413                 string tmp(argument);
2414                 //lyxerr <<string("Argument: ") + argument);
2415                 //lyxerr <<string("Tmp     : ") + tmp);
2416                 if (tmp.empty()) {
2417                         setErrorMessage(N_("Usage: toolbar-add-to <LyX command>"));
2418                 } else {
2419                         owner->getToolbar()->add(argument, false);
2420                         owner->getToolbar()->set();
2421                 }
2422         }
2423         break;
2424         
2425         // --- insert characters ----------------------------------------
2426
2427         // ---  Mathed stuff. If we are here, there is no locked inset yet.
2428         
2429         // Greek mode     
2430         case LFUN_GREEK:
2431         {
2432                 if (!greek_kb_flag) {
2433                         greek_kb_flag = 1;
2434                         setMessage(N_("Math greek mode on"));
2435                 } else
2436                         greek_kb_flag = 0;
2437         }  
2438         break;
2439       
2440         // Greek keyboard      
2441         case LFUN_GREEK_TOGGLE:
2442         {
2443                 greek_kb_flag = greek_kb_flag ? 0 : 2;
2444                 if (greek_kb_flag) {
2445                         setMessage(N_("Math greek keyboard on"));
2446                 } else {
2447                         setMessage(N_("Math greek keyboard off"));
2448                 }
2449         }
2450         break;
2451         
2452         case LFUN_MATH_DELIM:     
2453         case LFUN_INSERT_MATRIX:
2454         {          
2455                 if (owner->view()->available()) { 
2456                         if (owner->view()->
2457                             open_new_inset(new InsetFormula(false)))
2458                         {
2459                                 owner->view()->theLockingInset()
2460                                         ->LocalDispatch(owner->view(),
2461                                                         action,
2462                                                         argument);
2463                         }
2464                 }
2465         }          
2466         break;
2467                
2468         case LFUN_INSERT_MATH:
2469         {
2470                 math_insert_symbol(argument);
2471         }
2472         break;
2473         
2474         case LFUN_MATH_DISPLAY:
2475         {
2476                 if (owner->view()->available())
2477                         owner->view()->open_new_inset(new InsetFormula(true));
2478                 break;
2479         }
2480                     
2481         case LFUN_MATH_MACRO:
2482         {
2483                 if (owner->view()->available()) {
2484                         string s(argument);
2485                         if (s.empty())
2486                                 setErrorMessage(N_("Missing argument"));
2487                         else {
2488                                 string const s1 = token(s, ' ', 1);
2489                                 int const na = s1.empty() ? 0 : lyx::atoi(s1);
2490                                 owner->view()->
2491                                         open_new_inset(new InsetFormulaMacro(token(s, ' ', 0), na));
2492                         }
2493                 }
2494         }
2495         break;
2496
2497         case LFUN_MATH_MODE:   // Open or create a math inset
2498         {               
2499                 if (owner->view()->available())
2500                         owner->view()->open_new_inset(new InsetFormula);
2501                 setMessage(N_("Math editor mode"));
2502         }
2503         break;
2504           
2505         case LFUN_MATH_NUMBER:
2506         case LFUN_MATH_LIMITS:
2507         {
2508                 setErrorMessage(N_("This is only allowed in math mode!"));
2509         
2510         }
2511         break;
2512
2513         case LFUN_MATH_PANEL:
2514         {
2515                 show_symbols_form(this);
2516         }
2517         break;
2518         
2519         case LFUN_CITATION_CREATE:
2520         {
2521                 // Should do this "at source"
2522                 InsetCommandParams p( "cite" );
2523                 
2524                 if (contains(argument, "|")) {
2525                         p.setContents( token(argument, '|', 0) );
2526                         p.setOptions(  token(argument, '|', 1) );
2527                 } else {
2528                         p.setContents( argument );
2529                 }
2530
2531                 owner->getDialogs()->createCitation( p.getAsString() );
2532         }
2533         break;
2534                     
2535         case LFUN_CITATION_INSERT:
2536         {
2537                 InsetCommandParams p;
2538                 p.setFromString( argument );
2539
2540                 InsetCitation * inset = new InsetCitation( p );
2541                 if (!owner->view()->insertInset(inset))
2542                         delete inset;
2543                 else
2544                         owner->view()->updateInset( inset, true );
2545         }
2546         break;
2547                     
2548         case LFUN_INSERT_BIBTEX:
2549         {   
2550                 // ale970405+lasgoutt970425
2551                 // The argument can be up to two tokens separated 
2552                 // by a space. The first one is the bibstyle.
2553                 string const db       = token(argument, ' ', 0);
2554                 string bibstyle = token(argument, ' ', 1);
2555                 if (bibstyle.empty())
2556                         bibstyle = "plain";
2557
2558                 InsetCommandParams p( "BibTeX", db, bibstyle );
2559                 InsetBibtex * inset = new InsetBibtex(p);
2560                 
2561                 if (owner->view()->insertInset(inset)) {
2562                         if (argument.empty())
2563                                 inset->Edit(owner->view(), 0, 0, 0);
2564                 } else
2565                         delete inset;
2566         }
2567         break;
2568                 
2569         // BibTeX data bases
2570         case LFUN_BIBDB_ADD:
2571         {
2572                 InsetBibtex * inset = 
2573                         static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
2574                 if (inset) {
2575                         inset->addDatabase(argument);
2576                 }
2577         }
2578         break;
2579                     
2580         case LFUN_BIBDB_DEL:
2581         {
2582                 InsetBibtex * inset = 
2583                         static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
2584                 if (inset) {
2585                         inset->delDatabase(argument);
2586                 }
2587         }
2588         break;
2589         
2590         case LFUN_BIBTEX_STYLE:
2591         {
2592                 InsetBibtex * inset = 
2593                         static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
2594                 if (inset) {
2595                         inset->setOptions(argument);
2596                 }
2597         }
2598         break;
2599                 
2600         case LFUN_INDEX_CREATE:
2601         {
2602                 InsetCommandParams p( "index" );
2603                 
2604                 if (argument.empty()) {
2605                         // Get the word immediately preceding the cursor
2606                         LyXParagraph::size_type curpos = 
2607                                 owner->view()->text->cursor.pos() - 1;
2608
2609                         string curstring;
2610                         if (curpos >= 0 )
2611                                 curstring = owner->view()->text
2612                                             ->cursor.par()->GetWord(curpos);
2613
2614                         p.setContents( curstring );
2615                 } else {
2616                         p.setContents( argument );
2617                 }
2618
2619                 owner->getDialogs()->createIndex( p.getAsString() );
2620         }
2621         break;
2622                     
2623         case LFUN_INDEX_INSERT:
2624         {
2625                 InsetCommandParams p;
2626                 p.setFromString(argument);
2627                 InsetIndex * inset = new InsetIndex(p);
2628
2629                 if (!owner->view()->insertInset(inset))
2630                         delete inset;
2631                 else
2632                         owner->view()->updateInset(inset, true);
2633         }
2634         break;
2635                     
2636         case LFUN_INDEX_INSERT_LAST:
2637         {
2638                 // Get word immediately preceding the cursor
2639                 LyXParagraph::size_type curpos = 
2640                         owner->view()->text->cursor.pos() - 1;
2641                 // Can't do that at the beginning of a paragraph
2642                 if (curpos < 0) break;
2643
2644                 string const curstring(owner->view()->text
2645                                   ->cursor.par()->GetWord(curpos));
2646
2647                 InsetCommandParams p("index", curstring);
2648                 InsetIndex * inset = new InsetIndex(p);
2649
2650                 if (!owner->view()->insertInset(inset))
2651                         delete inset;
2652                 else
2653                         owner->view()->updateInset(inset, true);
2654         }
2655         break;
2656                     
2657         case LFUN_INDEX_PRINT:
2658         {
2659                 InsetCommandParams p("printindex");
2660                 Inset * inset = new InsetPrintIndex(p);
2661                 if (!owner->view()->insertInset(inset, "Standard", true))
2662                         delete inset;
2663         }
2664         break;
2665
2666         case LFUN_PARENTINSERT:
2667         {
2668                 lyxerr << "arg " << argument << endl;
2669                 InsetCommandParams p( "lyxparent", argument );
2670                 Inset * inset = new InsetParent(p, *owner->buffer());
2671                 if (!owner->view()->insertInset(inset, "Standard", true))
2672                         delete inset;
2673         }
2674         break;
2675
2676         case LFUN_CHILDINSERT:
2677         {
2678                 InsetCommandParams p( "Include", argument );
2679                 Inset * inset = new InsetInclude(p, *owner->buffer());
2680                 if (owner->view()->insertInset(inset, "Standard", true))
2681                         inset->Edit(owner->view(), 0, 0, 0);
2682                 else
2683                         delete inset;
2684         }
2685         break;
2686
2687         case LFUN_CHILDOPEN:
2688         {
2689                 string const filename =
2690                         MakeAbsPath(argument, 
2691                                     OnlyPath(owner->buffer()->fileName()));
2692                 setMessage(N_("Opening child document ") +
2693                            MakeDisplayPath(filename) + "...");
2694                 owner->view()->savePosition();
2695                 if (bufferlist.exists(filename))
2696                         owner->view()->buffer(bufferlist.getBuffer(filename));
2697                 else
2698                         owner->view()->buffer(bufferlist.loadLyXFile(filename));
2699         }
2700         break;
2701
2702         case LFUN_INSERT_NOTE:
2703                 owner->view()->insertNote();
2704                 break;
2705 #ifndef NEW_INSETS
2706         case LFUN_INSERTFOOTNOTE: 
2707         {
2708                 LyXParagraph::footnote_kind kind;
2709                 if (argument == "footnote") {
2710                         kind = LyXParagraph::FOOTNOTE;
2711                 } else if (argument == "margin") {
2712                         kind = LyXParagraph::MARGIN;
2713                 } else if (argument == "figure") {
2714                         kind = LyXParagraph::FIG;
2715                 } else if (argument == "table") {
2716                         kind = LyXParagraph::TAB;
2717                 } else if (argument == "wide-fig") {
2718                         kind = LyXParagraph::WIDE_FIG;
2719                 } else if (argument == "wide-tab") {
2720                         kind = LyXParagraph::WIDE_TAB;
2721                 } else if (argument == "algorithm") {
2722                         kind = LyXParagraph::ALGORITHM;
2723                 } else {
2724                         setErrorMessage(N_("Unknown kind of footnote"));
2725                         break;
2726                 }
2727                 owner->view()->text->InsertFootnoteEnvironment(owner->view(), kind);
2728                 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2729                 owner->view()->setState();
2730         }
2731         break;
2732 #endif
2733         case LFUN_TOGGLECURSORFOLLOW:
2734                 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
2735                 break;
2736                 
2737         case LFUN_KMAP_OFF:             // keymap off
2738                 owner->getIntl()->KeyMapOn(false);
2739                 break;
2740                 
2741         case LFUN_KMAP_PRIM:    // primary keymap
2742                 owner->getIntl()->KeyMapPrim();
2743                 break;
2744                 
2745         case LFUN_KMAP_SEC:             // secondary keymap
2746                 owner->getIntl()->KeyMapSec();
2747                 break;
2748                 
2749         case LFUN_KMAP_TOGGLE:  // toggle keymap
2750                 owner->getIntl()->ToggleKeyMap();
2751                 break;
2752
2753         case LFUN_SELFINSERT:
2754         {
2755                 LyXFont const old_font(owner->view()->text->real_current_font);
2756                 for (string::size_type i = 0; i < argument.length(); ++i) {
2757                         owner->view()->text->InsertChar(owner->view(), argument[i]);
2758                         // This needs to be in the loop, or else we
2759                         // won't break lines correctly. (Asger)
2760                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2761                 }
2762                 owner->view()->text->sel_cursor = 
2763                         owner->view()->text->cursor;
2764                 moveCursorUpdate(false);
2765
2766                 // real_current_font.number can change so we need to 
2767                 // update the minibuffer
2768                 if (old_font != owner->view()->text->real_current_font)
2769                         owner->showState();
2770         }
2771         break;
2772
2773         case LFUN_SEQUENCE: 
2774         {
2775                 // argument contains ';'-terminated commands
2776                 while (argument.find(';') != string::npos) {
2777                         string first;
2778                         argument = split(argument, first, ';');
2779                         Dispatch(first);
2780                 }
2781         }
2782         break;
2783
2784         case LFUN_DATE_INSERT:  // jdblair: date-insert cmd
2785         {
2786                 struct tm * now_tm;
2787                 
2788                 time_t now_time_t = time(NULL);
2789                 now_tm = localtime(&now_time_t);
2790                 setlocale(LC_TIME, "");
2791                 string arg;
2792                 if (!argument.empty())
2793                         arg = argument;
2794                 else 
2795                         arg = lyxrc.date_insert_format;
2796                 char datetmp[32];
2797                 int const datetmp_len =
2798                         ::strftime(datetmp, 32, arg.c_str(), now_tm);
2799                 for (int i = 0; i < datetmp_len; i++) {
2800                         owner->view()->text->InsertChar(owner->view(), datetmp[i]);
2801                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2802                 }
2803
2804                 owner->view()->text->sel_cursor = owner->view()->text->cursor;
2805                 moveCursorUpdate(false);
2806         }
2807         break;
2808
2809         case LFUN_DIALOG_PREFERENCES:
2810                 owner->getDialogs()->showPreferences();
2811                 break;
2812                 
2813         case LFUN_SAVEPREFERENCES:
2814         {
2815                 Path p(user_lyxdir);
2816                 lyxrc.write("preferences");
2817         }
2818         break;
2819
2820         case LFUN_SCREEN_FONT_UPDATE:
2821         {
2822                 // handle the screen font changes.
2823                 // 
2824                 lyxrc.set_font_norm_type();
2825                 fontloader.update();
2826                 // Of course we should only do the resize and the textcache.clear
2827                 // if values really changed...but not very important right now. (Lgb)
2828                 // All buffers will need resize
2829                 bufferlist.resize();
2830                 // We also need to empty the textcache so that
2831                 // the buffer will be formatted correctly after
2832                 // a zoom change.
2833                 textcache.clear();
2834         }
2835         break;
2836
2837         case LFUN_SET_COLOR:
2838         {
2839                 string lyx_name;
2840                 string const x11_name = split(argument, lyx_name, ' ');
2841                 if (lyx_name.empty() || x11_name.empty()) {
2842                         LyXBell();
2843                         setErrorMessage(N_("Syntax: set-color <lyx_name>"
2844                                                 " <x11_name>"));
2845                         break;
2846                         }
2847
2848                 if (!lcolor.setColor(lyx_name, x11_name)) {
2849                         static string const err1 (N_("Set-color \""));
2850                         static string const err2 (
2851                                 N_("\" failed - color is undefined "
2852                                    "or may not be redefined"));
2853                         LyXBell();
2854                         setErrorMessage(_(err1) + lyx_name + _(err2));
2855                         break;
2856                 }
2857                 lyxColorHandler->updateColor(lcolor.getFromLyXName(lyx_name));
2858                 owner->view()->redraw();
2859                 break;
2860         }
2861
2862         case LFUN_UNKNOWN_ACTION:
2863         {
2864                 if (!owner->buffer()) {
2865                         LyXBell();
2866                         setErrorMessage(N_("No document open"));
2867                         break;
2868                 }
2869
2870                 if (owner->buffer()->isReadonly()) {
2871                         LyXBell();
2872                         setErrorMessage(N_("Document is read only"));
2873                         break;
2874                 }
2875                          
2876                 if (!argument.empty()) {
2877                         
2878                         /* Automatically delete the currently selected
2879                          * text and replace it with what is being
2880                          * typed in now. Depends on lyxrc settings
2881                          * "auto_region_delete", which defaults to
2882                          * true (on). */
2883                 
2884                         if (lyxrc.auto_region_delete) {
2885                                 if (owner->view()->text->selection){
2886                                         owner->view()->text->CutSelection(owner->view(), false);
2887                                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2888                                 }
2889                         }
2890                         
2891                         owner->view()->beforeChange();
2892                         LyXFont const old_font(owner->view()->text->real_current_font);
2893                         for (string::size_type i = 0;
2894                              i < argument.length(); ++i) {
2895                                 if (greek_kb_flag) {
2896                                         if (!math_insert_greek(argument[i]))
2897                                                 owner->getIntl()->getTrans()->TranslateAndInsert(argument[i], owner->view()->text);
2898                                 } else
2899                                         owner->getIntl()->getTrans()->TranslateAndInsert(argument[i], owner->view()->text);
2900                         }
2901
2902                         owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2903
2904                         owner->view()->text->sel_cursor = 
2905                                 owner->view()->text->cursor;
2906                         moveCursorUpdate(false);
2907
2908                         // real_current_font.number can change so we need to
2909                         // update the minibuffer
2910                         if (old_font != owner->view()->text->real_current_font)
2911                                 owner->showState();
2912                         return string();
2913                 } else {
2914                         // why is an "Unknown action" with empty
2915                         // argument even dispatched in the first
2916                         // place? I`ll probably change that. (Lgb)
2917                         LyXBell();
2918                         setErrorMessage(N_("Unknown action"));
2919                 }
2920                 break;
2921         }
2922
2923         default:
2924                 lyxerr << "A truly unknown func!" << endl;
2925                 break;
2926         } // end of switch
2927   exit_with_message:
2928
2929         string const res = getMessage();
2930
2931         if (res.empty()) {
2932                 if (!commandshortcut.empty()) {
2933                         string const newbuf =
2934                                 owner->getMiniBuffer()->GetText();
2935                         if (newbuf != commandshortcut) {
2936                                 owner->getMiniBuffer()->Set(newbuf
2937                                                             + " " +
2938                                                             commandshortcut);
2939                         }
2940                 }
2941         } else {
2942                 string msg(_(res));
2943                 msg += " ";
2944                 msg += commandshortcut;
2945                 owner->getMiniBuffer()->Set(msg);
2946         }
2947
2948         return res;
2949 }
2950
2951
2952 void LyXFunc::setupLocalKeymap()
2953 {
2954         keyseq.stdmap = keyseq.curmap = toplevel_keymap;
2955         cancel_meta_seq.stdmap = cancel_meta_seq.curmap = toplevel_keymap;
2956 }
2957
2958
2959 void LyXFunc::MenuNew(bool fromTemplate)
2960 {
2961         string initpath = lyxrc.document_path;
2962         LyXFileDlg fileDlg;
2963
2964         if (owner->view()->available()) {
2965                 string const trypath = owner->buffer()->filepath;
2966                 // If directory is writeable, use this as default.
2967                 if (IsDirWriteable(trypath) == 1)
2968                         initpath = trypath;
2969         }
2970
2971         static int newfile_number = 0;
2972         string s;
2973         
2974         if (lyxrc.new_ask_filename) {
2975                 ProhibitInput(owner->view());
2976                 fileDlg.SetButton(0, _("Documents"), lyxrc.document_path);
2977                 fileDlg.SetButton(1, _("Templates"), lyxrc.template_path);
2978                 string fname = fileDlg.Select(_("Enter Filename for new document"), 
2979                                        initpath, "*.lyx", _("newfile"));
2980                 AllowInput(owner->view());
2981         
2982                 if (fname.empty()) {
2983                         owner->getMiniBuffer()->Set(_("Canceled."));
2984                         lyxerr.debug() << "New Document Cancelled." << endl;
2985                         return;
2986                 }
2987         
2988                 // get absolute path of file and make sure the filename ends
2989                 // with .lyx
2990                 s = MakeAbsPath(fname);
2991                 if (!IsLyXFilename(s))
2992                         s += ".lyx";
2993
2994                 // Check if the document already is open
2995                 if (bufferlist.exists(s)) {
2996                         switch (AskConfirmation(_("Document is already open:"), 
2997                                                MakeDisplayPath(s, 50),
2998                                                _("Do you want to close that document now?\n"
2999                                                  "('No' will just switch to the open version)")))
3000                         {
3001                         case 1: // Yes: close the document
3002                                 if (!bufferlist.close(bufferlist.getBuffer(s)))
3003                                 // If close is canceled, we cancel here too.
3004                                         return;
3005                                 break;
3006                         case 2: // No: switch to the open document
3007                                 owner->view()->buffer(bufferlist.getBuffer(s));
3008                                 return;
3009                         case 3: // Cancel: Do nothing
3010                                 owner->getMiniBuffer()->Set(_("Canceled."));
3011                                 return;
3012                         }
3013                 }
3014                 // Check whether the file already exists
3015                 if (IsLyXFilename(s)) {
3016                         FileInfo fi(s);
3017                         if (fi.readable() &&
3018                             AskQuestion(_("File already exists:"), 
3019                                         MakeDisplayPath(s, 50),
3020                                         _("Do you want to open the document?"))) {
3021                                 // loads document
3022                                 owner->getMiniBuffer()->Set(_("Opening document"), 
3023                                                             MakeDisplayPath(s), "...");
3024                                 XFlush(fl_get_display());
3025                                 owner->view()->buffer(
3026                                         bufferlist.loadLyXFile(s));
3027                                 owner->getMiniBuffer()->Set(_("Document"),
3028                                                             MakeDisplayPath(s),
3029                                                             _("opened."));
3030                                 return;
3031                         }
3032                 }
3033         } else {
3034                 s = AddName(lyxrc.document_path,
3035                             "newfile" + tostr(++newfile_number) + ".lyx");
3036                 FileInfo fi(s);
3037                 while (bufferlist.exists(s) || fi.readable()) {
3038                         ++newfile_number;
3039                         s = AddName(lyxrc.document_path,
3040                                     "newfile" + tostr(newfile_number) +
3041                                     ".lyx");
3042                         fi.newFile(s);
3043                 }
3044         }
3045
3046         // The template stuff
3047         string templname;
3048         if (fromTemplate) {
3049                 ProhibitInput(owner->view());
3050                 string const fname = fileDlg.Select(_("Choose template"),
3051                                                     lyxrc.template_path,
3052                                                     "*.lyx");
3053                 AllowInput(owner->view());
3054                 if (fname.empty()) return;
3055                 templname = fname;
3056         }
3057   
3058         // find a free buffer
3059         lyxerr.debug() << "Find a free buffer." << endl;
3060         owner->view()->buffer(bufferlist.newFile(s, templname));
3061 }
3062
3063
3064 void LyXFunc::MenuOpen()
3065 {
3066         string initpath = lyxrc.document_path;
3067         LyXFileDlg fileDlg;
3068   
3069         if (owner->view()->available()) {
3070                 string const trypath = owner->buffer()->filepath;
3071                 // If directory is writeable, use this as default.
3072                 if (IsDirWriteable(trypath) == 1)
3073                         initpath = trypath;
3074         }
3075
3076         // launches dialog
3077         ProhibitInput(owner->view());
3078         fileDlg.SetButton(0, _("Documents"), lyxrc.document_path);
3079         fileDlg.SetButton(1, _("Examples"), 
3080                           AddPath(system_lyxdir, "examples"));
3081         string filename = fileDlg.Select(_("Select Document to Open"),
3082                                          initpath, "*.lyx");
3083         AllowInput(owner->view());
3084  
3085         // check selected filename
3086         if (filename.empty()) {
3087                 owner->getMiniBuffer()->Set(_("Canceled."));
3088                 return;
3089         }
3090
3091         // get absolute path of file and make sure the filename ends
3092         // with .lyx
3093         filename = MakeAbsPath(filename);
3094         if (!IsLyXFilename(filename))
3095                 filename += ".lyx";
3096
3097         // loads document
3098         owner->getMiniBuffer()->Set(_("Opening document"),
3099                                     MakeDisplayPath(filename), "...");
3100         Buffer * openbuf = bufferlist.loadLyXFile(filename);
3101         if (openbuf) {
3102                 owner->view()->buffer(openbuf);
3103                 owner->getMiniBuffer()->Set(_("Document"),
3104                                             MakeDisplayPath(filename),
3105                                             _("opened."));
3106         } else {
3107                 owner->getMiniBuffer()->Set(_("Could not open document"),
3108                                             MakeDisplayPath(filename));
3109         }
3110 }
3111
3112
3113 // checks for running without gui are missing.
3114 void LyXFunc::doImport(string const & argument)
3115 {
3116         string format;
3117         string filename = split(argument, format, ' ');
3118         lyxerr.debug() << "LyXFunc::doImport: " << format 
3119                        << " file: " << filename << endl;
3120
3121         if (filename.empty()) { // need user interaction
3122                 string initpath = lyxrc.document_path;
3123                 LyXFileDlg fileDlg;
3124                 
3125                 if (owner->view()->available()) {
3126                         string const trypath = owner->buffer()->filepath;
3127                         // If directory is writeable, use this as default.
3128                         if (IsDirWriteable(trypath) == 1)
3129                                 initpath = trypath;
3130                 }
3131
3132                 // launches dialog
3133                 ProhibitInput(owner->view());
3134                 fileDlg.SetButton(0, _("Documents"), lyxrc.document_path);
3135                 fileDlg.SetButton(1, _("Examples"), 
3136                                         AddPath(system_lyxdir, "examples"));
3137                 string const text = _("Select ") + formats.PrettyName(format)
3138                         + _(" file to import");
3139                 string const extension = "*." + formats.Extension(format);
3140                 filename = fileDlg.Select(text, initpath, extension);
3141                 AllowInput(owner->view());
3142  
3143                 // check selected filename
3144                 if (filename.empty()) 
3145                         owner->getMiniBuffer()->Set(_("Canceled."));
3146         }
3147
3148         // still no filename? abort
3149         if (filename.empty()) 
3150                 return;
3151
3152         // get absolute path of file
3153         filename = MakeAbsPath(filename);
3154
3155         string const lyxfile = ChangeExtension(filename, ".lyx");
3156
3157         // Check if the document already is open
3158         if (bufferlist.exists(lyxfile)) {
3159                 switch (AskConfirmation(_("Document is already open:"), 
3160                                        MakeDisplayPath(lyxfile, 50),
3161                                        _("Do you want to close that document now?\n"
3162                                          "('No' will just switch to the open version)")))
3163                         {
3164                         case 1: // Yes: close the document
3165                                 if (!bufferlist.close(bufferlist.getBuffer(lyxfile)))
3166                                 // If close is canceled, we cancel here too.
3167                                         return;
3168                                 break;
3169                         case 2: // No: switch to the open document
3170                                 owner->view()->buffer(bufferlist.getBuffer(lyxfile));
3171                                 return;
3172                         case 3: // Cancel: Do nothing
3173                                 owner->getMiniBuffer()->Set(_("Canceled."));
3174                                 return;
3175                         }
3176         }
3177
3178         // Check if a LyX document by the same root exists in filesystem
3179         FileInfo const f(lyxfile, true);
3180         if (f.exist() && !AskQuestion(_("A document by the name"), 
3181                                       MakeDisplayPath(lyxfile),
3182                                       _("already exists. Overwrite?"))) {
3183                 owner->getMiniBuffer()->Set(_("Canceled."));
3184                 return;
3185         }
3186         // filename should be valid now
3187
3188         Importer::Import(owner, filename, format);
3189 }
3190
3191
3192 void LyXFunc::MenuInsertLyXFile(string const & filen)
3193 {
3194         string filename = filen;
3195
3196         if (filename.empty()) {
3197                 // Launch a file browser
3198                 string initpath = lyxrc.document_path;
3199                 LyXFileDlg fileDlg;
3200
3201                 if (owner->view()->available()) {
3202                         string const trypath = owner->buffer()->filepath;
3203                         // If directory is writeable, use this as default.
3204                         if (IsDirWriteable(trypath) == 1)
3205                                 initpath = trypath;
3206                 }
3207
3208                 // launches dialog
3209                 ProhibitInput(owner->view());
3210                 fileDlg.SetButton(0, _("Documents"), lyxrc.document_path);
3211                 fileDlg.SetButton(1, _("Examples"), 
3212                                   AddPath(system_lyxdir, "examples"));
3213                 filename = fileDlg.Select(_("Select Document to Insert"),
3214                                           initpath, "*.lyx");
3215                 AllowInput(owner->view());
3216
3217                 // check selected filename
3218                 if (filename.empty()) {
3219                         owner->getMiniBuffer()->Set(_("Canceled."));
3220                         return;
3221                 }
3222         } 
3223
3224         // get absolute path of file and make sure the filename ends
3225         // with .lyx
3226         filename = MakeAbsPath(filename);
3227         if (!IsLyXFilename(filename))
3228                 filename += ".lyx";
3229
3230         // Inserts document
3231         owner->getMiniBuffer()->Set(_("Inserting document"),
3232                                     MakeDisplayPath(filename), "...");
3233         bool const res = owner->view()->insertLyXFile(filename);
3234         if (res) {
3235                 owner->getMiniBuffer()->Set(_("Document"),
3236                                             MakeDisplayPath(filename),
3237                                             _("inserted."));
3238         } else {
3239                 owner->getMiniBuffer()->Set(_("Could not insert document"),
3240                                             MakeDisplayPath(filename));
3241         }
3242 }
3243
3244
3245 void LyXFunc::reloadBuffer()
3246 {
3247         string const fn = owner->buffer()->fileName();
3248         if (bufferlist.close(owner->buffer()))
3249                 owner->view()->buffer(bufferlist.loadLyXFile(fn));
3250 }
3251
3252
3253 void LyXFunc::CloseBuffer()
3254 {
3255         if (bufferlist.close(owner->buffer()) && !quitting) {
3256                 if (bufferlist.empty()) {
3257                         // need this otherwise SEGV may occur while trying to
3258                         // set variables that don't exist
3259                         // since there's no current buffer
3260                         owner->getDialogs()->hideBufferDependent();
3261                 } else {
3262                         owner->view()->buffer(bufferlist.first());
3263                 }
3264         }
3265 }
3266
3267
3268 Inset * LyXFunc::getInsetByCode(Inset::Code code)
3269 {
3270         LyXCursor cursor = owner->view()->text->cursor;
3271         Buffer * buffer = owner->view()->buffer();
3272         Buffer::inset_iterator it =
3273                 find_if(Buffer::inset_iterator(cursor.par(),
3274                                                cursor.pos()),
3275                         buffer->inset_iterator_end(),
3276                         compare_memfun(&Inset::LyxCode, code));
3277         return it != buffer->inset_iterator_end() ? (*it) : 0;
3278 }
3279
3280
3281 // Each "owner" should have it's own message method. lyxview and
3282 // the minibuffer would use the minibuffer, but lyxserver would
3283 // send an ERROR signal to its client.  Alejandro 970603
3284 // This func is bit problematic when it comes to NLS, to make the
3285 // lyx servers client be language indepenent we must not translate
3286 // strings sent to this func.
3287 void LyXFunc::setErrorMessage(string const & m) const
3288 {
3289         dispatch_buffer = m;
3290         errorstat = true;
3291 }
3292
3293
3294 void LyXFunc::setMessage(string const & m)
3295 {
3296         dispatch_buffer = m;
3297 }