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