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