1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2000 The LyX Team.
9 * ====================================================== */
23 #pragma implementation
29 #include "bufferlist.h"
30 #include "ColorHandler.h"
31 #include "lyxserver.h"
36 #include "LyXAction.h"
37 #include "insets/inseturl.h"
38 #include "insets/insetlatexaccent.h"
39 #include "insets/insettoc.h"
40 #include "insets/insetref.h"
41 #include "insets/insetparent.h"
42 #include "insets/insetindex.h"
43 #include "insets/insetinclude.h"
44 #include "insets/insetbib.h"
45 #include "insets/insetcite.h"
46 #include "insets/insettext.h"
47 #include "insets/insetert.h"
48 #include "insets/insetexternal.h"
49 #include "insets/insetgraphics.h"
50 #include "insets/insetfoot.h"
51 #include "insets/insetmarginal.h"
52 #include "insets/insetminipage.h"
53 #include "insets/insetfloat.h"
54 #include "insets/insetlist.h"
55 #include "insets/insettabular.h"
56 #include "insets/insettheorem.h"
57 #include "insets/insetcaption.h"
58 #include "mathed/formulamacro.h"
59 #include "spellchecker.h" // RVDK_PATCH_5
60 #include "minibuffer.h"
64 #include "lyx_gui_misc.h"
65 #include "support/filetools.h"
66 #include "support/FileInfo.h"
67 #include "support/syscall.h"
68 #include "support/lstrings.h"
69 #include "support/path.h"
70 #include "support/lyxfunctional.h"
75 #include "trans_mgr.h"
79 #include "bufferview_funcs.h"
80 #include "frontends/Dialogs.h"
81 #include "frontends/Toolbar.h"
82 #include "frontends/Menubar.h"
83 #include "FloatList.h"
84 #include "converter.h"
87 #include "FontLoader.h"
88 #include "TextCache.h"
94 extern void math_insert_symbol(string const &);
95 extern bool math_insert_greek(char);
96 extern BufferList bufferlist;
97 extern LyXServer * lyxserver;
98 extern int greek_kb_flag;
99 extern bool selection_possible;
101 extern kb_keymap * toplevel_keymap;
104 extern void MenuFax(Buffer *);
106 extern void show_symbols_form(LyXFunc *);
108 extern LyXAction lyxaction;
110 extern tex_accent_struct get_accent(kb_action action);
112 extern LyXTextClass::size_type current_layout;
114 extern void ShowLatexLog();
116 /* === globals =========================================================== */
118 bool LyXFunc::show_sc = true;
121 LyXFunc::LyXFunc(LyXView * o)
125 lyx_dead_action = LFUN_NOACTION;
126 lyx_calling_dead_action = LFUN_NOACTION;
131 // I changed this func slightly. I commented out the ...FinishUndo(),
132 // this means that all places that used to have a moveCursorUpdate, now
133 // have a ...FinishUndo() as the preceeding statement. I have also added
134 // a moveCursorUpdate to some of the functions that updated the cursor, but
135 // that did not show its new position.
137 void LyXFunc::moveCursorUpdate(bool selecting)
139 if (selecting || owner->view()->text->mark_set) {
140 owner->view()->text->SetSelection();
141 owner->view()->toggleToggle();
143 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
144 owner->view()->showCursor();
146 /* ---> Everytime the cursor is moved, show the current font state. */
147 // should this too me moved out of this func?
148 //owner->showState();
149 owner->view()->setState();
153 int LyXFunc::processKeySym(KeySym keysym, unsigned int state)
157 if (lyxerr.debugging(Debug::KEY)) {
158 char * tmp = XKeysymToString(keysym);
159 string const stm = (tmp ? tmp : "");
160 lyxerr << "KeySym is "
163 << keysym << "] State is ["
167 // Do nothing if we have nothing (JMarc)
168 if (keysym == NoSymbol) {
169 lyxerr[Debug::KEY] << "Empty kbd action (probably composing)"
175 if (owner->view()->available()) {
176 // this function should be used always [asierra060396]
177 UpdatableInset * tli = owner->view()->theLockingInset();
178 if (tli && (keysym == XK_Escape)) {
179 if (tli == tli->GetLockingInset()) {
180 owner->view()->unlockInset(tli);
181 owner->view()->text->CursorRight(owner->view());
182 moveCursorUpdate(false);
185 tli->UnlockInsetInInset(owner->view(),
186 tli->GetLockingInset(),true);
193 // Can we be sure that this will work for all X-Windows
194 // implementations? (Lgb)
195 // This code snippet makes lyx ignore some keys. Perhaps
196 // all of them should be explictly mentioned?
197 if ((keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
198 || keysym == XK_Mode_switch || keysym == 0x0)
201 // Do a one-deep top-level lookup for
202 // cancel and meta-fake keys. RVDK_PATCH_5
203 cancel_meta_seq.reset();
205 int action = cancel_meta_seq.addkey(keysym, state
206 &(ShiftMask|ControlMask
208 if (lyxerr.debugging(Debug::KEY)) {
209 lyxerr << "action first set to [" << action << "]" << endl;
212 // When not cancel or meta-fake, do the normal lookup.
213 // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
214 // Mostly, meta_fake_bit = 0. RVDK_PATCH_5.
215 if ((action != LFUN_CANCEL) && (action != LFUN_META_FAKE)) {
216 if (lyxerr.debugging(Debug::KEY)) {
217 lyxerr << "meta_fake_bit is [" << meta_fake_bit << "]" << endl;
219 // remove Caps Lock and Mod2 as a modifiers
220 action = keyseq.addkey(keysym,
221 (state | meta_fake_bit)
222 &(ShiftMask|ControlMask
224 if (lyxerr.debugging(Debug::KEY)) {
225 lyxerr << "action now set to [" << action << "]" << endl;
228 // Dont remove this unless you know what you are doing.
231 if (action == 0) action = LFUN_PREFIX;
233 if (lyxerr.debugging(Debug::KEY)) {
242 // already here we know if it any point in going further
243 // why not return already here if action == -1 and
244 // num_bytes == 0? (Lgb)
246 if (keyseq.length > 1 || keyseq.length < -1) {
249 owner->getMiniBuffer()->Set(buf);
253 if (keyseq.length < -1) { // unknown key sequence...
257 owner->getMiniBuffer()->Set(_("Unknown sequence:"), buf);
261 char const isochar = keyseq.getiso();
262 if (!(state & ControlMask) &&
263 !(state & Mod1Mask) &&
264 (isochar && keysym < 0xF000)) {
267 if (argument.empty()) {
268 lyxerr.debug() << "Empty argument!" << endl;
269 // This can`t possibly be of any use
270 // so we`ll skip the dispatch.
275 bool tmp_sc = show_sc;
277 Dispatch(action, argument);
284 LyXFunc::func_status LyXFunc::getStatus(int ac) const
287 func_status flag = LyXFunc::OK;
289 Buffer * buf = owner->buffer();
291 if (lyxaction.isPseudoAction(ac))
292 action = lyxaction.retrieveActionArg(ac, argument);
294 action = static_cast<kb_action>(ac);
296 if (action == LFUN_UNKNOWN_ACTION) {
297 setErrorMessage(N_("Unknown action"));
298 return LyXFunc::Unknown;
301 // Check whether we need a buffer
302 if (!lyxaction.funcHasFlag(action, LyXAction::NoBuffer)) {
303 // Yes we need a buffer, do we have one?
306 // Can we use a readonly buffer?
307 if (buf->isReadonly() &&
308 !lyxaction.funcHasFlag(action,
309 LyXAction::ReadOnly)) {
311 setErrorMessage(N_("Document is read-only"));
312 flag |= LyXFunc::Disabled;
316 setErrorMessage(N_("Command not allowed with"
317 "out any document open"));
318 flag |= LyXFunc::Disabled;
323 // I would really like to avoid having this switch and rather try to
324 // encode this in the function itself.
325 bool disable = false;
328 disable = !Exporter::IsExportable(buf, "dvi")
329 || lyxrc.print_command == "none";
333 disable = !Exporter::IsExportable(buf, "ps")
334 || lyxrc.fax_command == "none";
338 disable = argument == "fax" &&
339 !Exporter::IsExportable(buf, argument);
343 disable = buf->undostack.empty();
346 disable = buf->redostack.empty();
348 case LFUN_SPELLCHECK:
349 disable = lyxrc.isp_command == "none";
352 disable = lyxrc.chktex_command == "none";
355 disable = !Exporter::IsExportable(buf, "program");
358 case LFUN_INSERTFOOTNOTE:
360 case LFUN_MARGINMELT:
361 // Disable insertion of floats in a tabular.
363 if (owner->view()->theLockingInset()) {
364 disable = (owner->view()->theLockingInset()->LyxCode() == Inset::TABULAR_CODE) ||
365 owner->view()->theLockingInset()->GetFirstLockingInsetOfType(Inset::TABULAR_CODE);
369 case LFUN_LAYOUT_TABULAR:
371 if (owner->view()->theLockingInset()) {
372 disable = (owner->view()->theLockingInset()->LyxCode() != Inset::TABULAR_CODE) &&
373 !owner->view()->theLockingInset()->GetFirstLockingInsetOfType(Inset::TABULAR_CODE);
377 case LFUN_TABULAR_FEATURE:
379 if (owner->view()->theLockingInset()) {
380 func_status ret = LyXFunc::Disabled;
381 if (owner->view()->theLockingInset()->LyxCode() == Inset::TABULAR_CODE) {
382 ret = static_cast<InsetTabular *>
383 (owner->view()->theLockingInset())->
385 } else if (owner->view()->theLockingInset()->GetFirstLockingInsetOfType(Inset::TABULAR_CODE)) {
386 ret = static_cast<InsetTabular *>
387 (owner->view()->theLockingInset()->
388 GetFirstLockingInsetOfType(Inset::TABULAR_CODE))->
394 static InsetTabular inset(*owner->buffer(), 1, 1);
398 ret = inset.getStatus(argument);
399 if ((ret & LyXFunc::ToggleOn) ||
400 (ret & LyXFunc::ToggleOff))
401 flag |= LyXFunc::ToggleOff;
405 case LFUN_VC_REGISTER:
406 disable = buf->lyxvc.inUse();
408 case LFUN_VC_CHECKIN:
409 disable = !buf->lyxvc.inUse() || buf->isReadonly();
411 case LFUN_VC_CHECKOUT:
412 disable = !buf->lyxvc.inUse() || !buf->isReadonly();
416 case LFUN_VC_HISTORY:
417 disable = !buf->lyxvc.inUse();
420 disable = owner->view()->NoSavedPositions();
426 flag |= LyXFunc::Disabled;
429 func_status box = LyXFunc::ToggleOff;
430 LyXFont const & font =
431 owner->view()->getLyXText()->real_current_font;
434 if (font.emph() == LyXFont::ON)
435 box = LyXFunc::ToggleOn;
438 if (font.noun() == LyXFont::ON)
439 box = LyXFunc::ToggleOn;
442 if (font.series() == LyXFont::BOLD_SERIES)
443 box = LyXFunc::ToggleOn;
446 if (font.latex() == LyXFont::ON)
447 box = LyXFunc::ToggleOn;
460 string const LyXFunc::Dispatch(string const & s)
462 // Split command string into command and argument
464 string line = frontStrip(s);
465 string arg = strip(frontStrip(split(line, cmd, ' ')));
467 return Dispatch(lyxaction.LookupFunc(cmd), arg);
471 string const LyXFunc::Dispatch(int ac,
472 string const & do_not_use_this_arg)
474 lyxerr[Debug::ACTION] << "LyXFunc::Dispatch: action[" << ac
475 <<"] arg[" << do_not_use_this_arg << "]" << endl;
480 // we have not done anything wrong yet.
482 dispatch_buffer.erase();
484 // if action is a pseudo-action, we need the real action
485 if (lyxaction.isPseudoAction(ac)) {
487 action = static_cast<kb_action>
488 (lyxaction.retrieveActionArg(ac, tmparg));
492 action = static_cast<kb_action>(ac);
493 if (!do_not_use_this_arg.empty())
494 argument = do_not_use_this_arg; // except here
497 selection_possible = false;
499 if (owner->view()->available())
500 owner->view()->hideCursor();
502 // We have to do this heare because of te goto below. (Lgb)
503 LyXText * text = owner->view()->getLyXText();
505 // We cannot use this function here
506 if (getStatus(ac) & Disabled)
507 goto exit_with_message;
509 commandshortcut.erase();
511 if (lyxrc.display_shortcuts && show_sc) {
512 if (action != LFUN_SELFINSERT) {
513 // Put name of command and list of shortcuts
514 // for it in minibuffer
515 string comname = lyxaction.getActionName(action);
517 int pseudoaction = action;
518 bool argsadded = false;
520 if (!argument.empty()) {
521 // If we have the command with argument,
524 lyxaction.searchActionArg(action,
527 if (pseudoaction == -1) {
528 pseudoaction = action;
530 comname += " " + argument;
535 string const shortcuts =
536 toplevel_keymap->findbinding(pseudoaction);
538 if (!shortcuts.empty()) {
539 comname += ": " + shortcuts;
540 } else if (!argsadded) {
541 comname += " " + argument;
544 if (!comname.empty()) {
545 comname = strip(comname);
546 commandshortcut = "(" + comname + ')';
547 owner->getMiniBuffer()->Set(commandshortcut);
548 // Here we could even add a small pause,
549 // to annoy the user and make him learn
551 // No! That will just annoy, not teach
552 // anything. The user will read the messages
553 // if they are interested. (Asger)
558 if (owner->view()->available() && owner->view()->theLockingInset()) {
559 UpdatableInset::RESULT result;
560 if ((action > 1) || ((action == LFUN_UNKNOWN_ACTION) &&
561 (keyseq.length >= -1)))
563 if ((action==LFUN_UNKNOWN_ACTION) && argument.empty()){
564 argument = keyseq.getiso();
566 // Undo/Redo pre 0.13 is a bit tricky for insets.
567 if (action == LFUN_UNDO) {
570 UpdatableInset * inset =
571 owner->view()->theLockingInset();
572 inset->GetCursorPos(owner->view(), slx, sly);
573 owner->view()->unlockInset(inset);
574 owner->view()->menuUndo();
575 if (owner->view()->text->cursor.par()->
576 IsInset(owner->view()->text->cursor.pos())) {
577 inset = static_cast<UpdatableInset*>(
578 owner->view()->text->cursor.par()->
579 GetInset(owner->view()->text->
585 inset->Edit(owner->view(),slx,sly,0);
587 } else if (action == LFUN_REDO) {
590 UpdatableInset * inset = owner->view()->
592 inset->GetCursorPos(owner->view(), slx, sly);
593 owner->view()->unlockInset(inset);
594 owner->view()->menuRedo();
595 inset = static_cast<UpdatableInset*>(
596 owner->view()->text->cursor.par()->
597 GetInset(owner->view()->text->
600 inset->Edit(owner->view(),slx,sly,0);
602 } else if (((result=owner->view()->theLockingInset()->
603 LocalDispatch(owner->view(), action,
605 UpdatableInset::DISPATCHED) ||
606 (result == UpdatableInset::DISPATCHED_NOUPDATE))
609 setMessage(N_("Text mode"));
611 case LFUN_UNKNOWN_ACTION:
612 case LFUN_BREAKPARAGRAPH:
614 owner->view()->text->CursorRight(owner->view());
615 owner->view()->setState();
619 if (!owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params)) {
620 owner->view()->text->CursorRight(owner->view());
621 moveCursorUpdate(false);
626 if (owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params)) {
627 owner->view()->text->CursorRight(owner->view());
628 moveCursorUpdate(false);
633 owner->view()->text->CursorDown(owner->view());
634 moveCursorUpdate(false);
645 // --- Misc -------------------------------------------
646 case LFUN_WORDFINDFORWARD :
647 case LFUN_WORDFINDBACKWARD : {
648 static string last_search;
649 string searched_string;
651 if (!argument.empty()) {
652 last_search = argument;
653 searched_string = argument;
655 searched_string = last_search;
658 LyXText * ltCur = owner->view()->text ;
660 if (!searched_string.empty() &&
661 ((action == LFUN_WORDFINDBACKWARD) ?
662 ltCur->SearchBackward(owner->view(), searched_string) :
663 ltCur->SearchForward(owner->view(), searched_string))) {
665 // ??? What is that ???
666 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
669 // clear the selection (if there is any)
670 owner->view()->toggleSelection();
671 owner->view()->text->ClearSelection();
673 // Move cursor so that successive C-s 's will not stand in place.
674 if (action == LFUN_WORDFINDFORWARD )
675 owner->view()->text->CursorRightOneWord(owner->view());
676 owner->view()->text->FinishUndo();
677 moveCursorUpdate(false);
680 // set the new selection
681 // SetSelectionOverLenChars(owner->view()->currentBuffer()->text, iLenSelected);
682 owner->view()->toggleSelection(false);
686 // REMOVED : if (owner->view()->getWorkArea()->focus)
687 owner->view()->showCursor();
693 if (owner->view()->available()) {
694 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
697 keyseq.print(buf, true);
698 owner->getMiniBuffer()->Set(buf, string(), string(), 1);
702 // --- Misc -------------------------------------------
703 case LFUN_EXEC_COMMAND:
704 owner->getMiniBuffer()->PrepareForCommand();
707 case LFUN_CANCEL: // RVDK_PATCH_5
710 if (owner->view()->available())
711 // cancel any selection
712 Dispatch(LFUN_MARK_OFF);
713 setMessage(N_("Cancel"));
716 case LFUN_META_FAKE: // RVDK_PATCH_5
718 meta_fake_bit = Mod1Mask;
720 keyseq.print(buf, true);
721 setMessage(buf); // RVDK_PATCH_5
725 case LFUN_READ_ONLY_TOGGLE:
726 if (owner->buffer()->lyxvc.inUse()) {
727 owner->buffer()->lyxvc.toggleReadOnly();
729 owner->buffer()->setReadonly(
730 !owner->buffer()->isReadonly());
734 case LFUN_CENTER: // this is center and redraw.
735 owner->view()->center();
739 if (owner->view()->available()) {
740 owner->view()->text->toggleAppendix(owner->view());
741 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
745 // --- Menus -----------------------------------------------
750 case LFUN_MENUNEWTMPLT:
758 case LFUN_CLOSEBUFFER:
763 if (!owner->buffer()->isUnnamed()) {
764 owner->getMiniBuffer()->Set(_("Saving document"),
765 MakeDisplayPath(owner->buffer()->fileName()),
767 MenuWrite(owner->view(), owner->buffer());
768 //owner->getMiniBuffer()-> {
769 // Set(_("Document saved as"),
770 // MakeDisplayPath(owner->buffer()->fileName()));
772 //owner->getMiniBuffer()->Set(_("Save failed!"));
775 MenuWriteAs(owner->view(), owner->buffer());
779 case LFUN_MENUWRITEAS:
780 MenuWriteAs(owner->view(), owner->buffer());
783 case LFUN_MENURELOAD:
788 Exporter::Export(owner->buffer(), argument, true);
792 Exporter::Preview(owner->buffer(), argument);
796 Exporter::Export(owner->buffer(), "program", true);
800 MenuRunChktex(owner->buffer());
804 owner->getDialogs()->showPrint();
809 MenuFax(owner->buffer());
814 Exporter::Export(owner->buffer(), argument, false);
830 InsetCommandParams p;
832 if (action == LFUN_TOCVIEW )
833 p.setCmdName( "tableofcontents" );
834 else if (action == LFUN_LOAVIEW )
835 p.setCmdName( "listofalgorithms" );
836 else if (action == LFUN_LOFVIEW )
837 p.setCmdName( "listoffigures" );
839 p.setCmdName( "listoftables" );
841 owner->getDialogs()->createTOC( p.getAsString() );
845 case LFUN_TOC_INSERT:
846 case LFUN_LOA_INSERT:
847 case LFUN_LOF_INSERT:
848 case LFUN_LOT_INSERT:
850 InsetCommandParams p;
852 if (action == LFUN_TOC_INSERT )
853 p.setCmdName( "tableofcontents" );
854 else if (action == LFUN_LOA_INSERT )
855 p.setCmdName( "listofalgorithms" );
856 else if (action == LFUN_LOF_INSERT )
857 p.setCmdName( "listoffigures" );
859 p.setCmdName( "listoftables" );
861 Inset * inset = new InsetTOC( p );
862 if (!owner->view()->insertInset( inset, "Standard", true ) )
867 case LFUN_DIALOG_TABULAR_INSERT:
868 owner->getDialogs()->showTabularCreate();
871 case LFUN_TABULAR_FEATURE:
872 case LFUN_SCROLL_INSET:
873 // this is not handled here as this funktion is only aktive
874 // if we have a locking_inset and that one is (or contains)
882 case LFUN_INSET_GRAPHICS:
884 Inset * new_inset = new InsetGraphics;
885 if (!owner->view()->insertInset(new_inset)) {
888 // this is need because you don't use a inset->Edit()
889 owner->view()->updateInset(new_inset, true);
890 new_inset->Edit(owner->view(), 0, 0, 0);
896 AutoSave(owner->view());
900 owner->view()->menuUndo();
904 owner->view()->menuRedo();
907 case LFUN_MENUSEARCH:
909 // Ok this is one _very_ bad solution, but I think that some
910 // of this will be rewritten as part of GUI indep anyway.
912 static LyXFindReplace FR_;
913 FR_.StartSearch(owner->view());
918 owner->view()->paste();
919 owner->view()->setState();
922 case LFUN_PASTESELECTION:
925 if (argument == "paragraph") asPara = true;
926 owner->view()->pasteClipboard(asPara);
931 owner->view()->cut();
935 owner->view()->copy();
938 case LFUN_LAYOUT_COPY:
939 owner->view()->copyEnvironment();
942 case LFUN_LAYOUT_PASTE:
943 owner->view()->pasteEnvironment();
944 owner->view()->setState();
948 owner->view()->gotoError();
951 case LFUN_REMOVEERRORS:
952 if (owner->view()->removeAutoInsets()) {
953 owner->view()->redraw();
954 owner->view()->fitCursor(owner->view()->text);
959 owner->view()->gotoNote();
964 owner->view()->openStuff();
968 case LFUN_HYPHENATION:
969 owner->view()->hyphenationPoint();
973 owner->view()->ldots();
976 case LFUN_END_OF_SENTENCE:
977 owner->view()->endOfSentenceDot();
980 case LFUN_MENU_SEPARATOR:
981 owner->view()->menuSeparator();
985 owner->view()->hfill();
989 changeDepth(owner->view(), 0);
993 changeDepth(owner->view(), -1);
996 case LFUN_DEPTH_PLUS:
997 changeDepth(owner->view(), 1);
1001 Free(owner->view());
1002 owner->view()->setState();
1008 owner->view()->setState();
1013 Melt(owner->view());
1016 case LFUN_RECONFIGURE:
1017 Reconfigure(owner->view());
1021 if (owner->view()->available()
1022 && !owner->view()->text->selection
1023 && owner->view()->text->cursor.par()->footnoteflag
1024 != LyXParagraph::NO_FOOTNOTE)
1025 { // only melt footnotes with FOOTMELT, not margins etc
1026 if (owner->view()->text->cursor.par()->footnotekind == LyXParagraph::FOOTNOTE)
1027 Melt(owner->view());
1030 Foot(owner->view());
1031 owner->view()->setState();
1034 case LFUN_MARGINMELT:
1035 if (owner->view()->available()
1036 && !owner->view()->text->selection
1037 && owner->view()->text->cursor.par()->footnoteflag
1038 != LyXParagraph::NO_FOOTNOTE) {
1039 // only melt margins
1040 if (owner->view()->text->cursor.par()->footnotekind == LyXParagraph::MARGIN)
1041 Melt(owner->view());
1043 Margin(owner->view());
1044 owner->view()->setState();
1048 case LFUN_FLOATSOPERATE:
1049 if (argument == "openfoot")
1050 owner->view()->allFloats(1,0);
1051 else if (argument == "closefoot")
1052 owner->view()->allFloats(0,0);
1053 else if (argument == "openfig")
1054 owner->view()->allFloats(1,1);
1055 else if (argument == "closefig")
1056 owner->view()->allFloats(0,1);
1059 #warning Find another implementation here (or another lyxfunc)!
1061 case LFUN_HELP_COPYRIGHT:
1062 owner->getDialogs()->showCopyright();
1065 case LFUN_HELP_CREDITS:
1066 owner->getDialogs()->showCredits();
1069 case LFUN_HELP_OPEN: {
1070 string arg = argument;
1072 setErrorMessage(N_("Missing argument"));
1075 ProhibitInput(owner->view());
1076 string fname = i18nLibFileSearch("doc", arg, "lyx");
1077 if (fname.empty()) {
1078 lyxerr << "LyX: unable to find documentation file `"
1079 << arg << "'. Bad installation?" << endl;
1080 AllowInput(owner->view());
1083 owner->getMiniBuffer()->Set(_("Opening help file"),
1084 MakeDisplayPath(fname),"...");
1085 owner->view()->buffer(bufferlist.loadLyXFile(fname,false));
1086 AllowInput(owner->view());
1090 case LFUN_HELP_VERSION: {
1091 ProhibitInput(owner->view());
1092 string msg(_("LyX Version "));
1096 fl_show_message(msg.c_str(),
1097 (_("Library directory: ")
1098 + MakeDisplayPath(system_lyxdir)).c_str(),
1099 (_("User directory: ")
1100 + MakeDisplayPath(user_lyxdir)).c_str());
1101 AllowInput(owner->view());
1105 // --- version control -------------------------------
1106 case LFUN_VC_REGISTER:
1108 if (!owner->buffer()->lyxvc.inUse())
1109 owner->buffer()->lyxvc.registrer();
1113 case LFUN_VC_CHECKIN:
1115 if (owner->buffer()->lyxvc.inUse()
1116 && !owner->buffer()->isReadonly())
1117 owner->buffer()->lyxvc.checkIn();
1121 case LFUN_VC_CHECKOUT:
1123 if (owner->buffer()->lyxvc.inUse()
1124 && owner->buffer()->isReadonly())
1125 owner->buffer()->lyxvc.checkOut();
1129 case LFUN_VC_REVERT:
1131 owner->buffer()->lyxvc.revert();
1137 owner->buffer()->lyxvc.undoLast();
1141 case LFUN_VC_HISTORY:
1143 owner->buffer()->lyxvc.showLog();
1147 // --- buffers ----------------------------------------
1149 case LFUN_SWITCHBUFFER:
1150 owner->view()->buffer(bufferlist.getBuffer(argument));
1154 case LFUN_FILE_INSERT:
1156 MenuInsertLyXFile(argument);
1160 case LFUN_FILE_INSERT_ASCII:
1162 bool asPara = (argument == "paragraph");
1163 InsertAsciiFile(owner->view(), string(), asPara);
1169 // servercmd: argument must be <file>:<template>
1170 Buffer * tmpbuf = NewLyxFile(argument);
1172 owner->view()->buffer(tmpbuf);
1176 case LFUN_FILE_OPEN:
1177 owner->view()->buffer(bufferlist.loadLyXFile(argument));
1180 case LFUN_LATEX_LOG:
1186 lyxerr.debug() << "LFUN_LAYOUTNO: (arg) " << argument << endl;
1187 int sel = strToInt(argument);
1188 lyxerr.debug() << "LFUN_LAYOUTNO: (sel) "<< sel << endl;
1190 // Should this give a setMessage instead?
1192 return string(); // illegal argument
1194 --sel; // sel 1..., but layout 0...
1196 // Pretend we got the name instead.
1197 Dispatch(int(LFUN_LAYOUT),
1198 textclasslist.NameOfLayout(owner->view()
1199 ->buffer()->params.textclass,
1206 lyxerr.debug() << "LFUN_LAYOUT: (arg) "
1207 << argument << endl;
1209 // Derive layout number from given argument (string)
1210 // and current buffer's textclass (number). */
1211 LyXTextClassList::ClassList::size_type tclass =
1212 owner->view()->buffer()->params.textclass;
1213 pair <bool, LyXTextClass::size_type> layout =
1214 textclasslist.NumberOfLayout(tclass, argument);
1216 // If the entry is obsolete, use the new one instead.
1218 string obs = textclasslist.Style(tclass,layout.second)
1222 textclasslist.NumberOfLayout(tclass, obs);
1225 // see if we found the layout number:
1226 if (!layout.first) {
1227 setErrorMessage(string(N_("Layout ")) + argument +
1232 if (current_layout != layout.second) {
1233 owner->view()->hideCursor();
1234 current_layout = layout.second;
1235 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1236 owner->view()->text->
1237 SetLayout(owner->view(), layout.second);
1238 owner->setLayout(layout.second);
1239 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1240 owner->view()->setState();
1245 case LFUN_LAYOUT_DOCUMENT:
1246 owner->getDialogs()->showLayoutDocument();
1249 case LFUN_LAYOUT_PARAGRAPH:
1250 #ifdef USE_OLD_PARAGRAPH_LAYOUT
1251 MenuLayoutParagraph();
1253 owner->getDialogs()->showLayoutParagraph();
1257 case LFUN_LAYOUT_CHARACTER:
1258 MenuLayoutCharacter();
1261 case LFUN_LAYOUT_TABULAR:
1262 if (owner->view()->theLockingInset()) {
1263 if (owner->view()->theLockingInset()->LyxCode()==Inset::TABULAR_CODE) {
1264 InsetTabular * inset = static_cast<InsetTabular *>
1265 (owner->view()->theLockingInset());
1266 inset->OpenLayoutDialog(owner->view());
1267 } else if (owner->view()->theLockingInset()->
1268 GetFirstLockingInsetOfType(Inset::TABULAR_CODE)!=0) {
1269 InsetTabular * inset = static_cast<InsetTabular *>(
1270 owner->view()->theLockingInset()->GetFirstLockingInsetOfType(Inset::TABULAR_CODE));
1271 inset->OpenLayoutDialog(owner->view());
1276 case LFUN_LAYOUT_PREAMBLE:
1277 MenuLayoutPreamble();
1280 case LFUN_LAYOUT_SAVE_DEFAULT:
1281 MenuLayoutSave(owner->view());
1284 case LFUN_DROP_LAYOUTS_CHOICE:
1285 owner->getToolbar()->openLayoutList();
1289 Lang(owner->view(), argument);
1290 owner->view()->setState();
1295 Emph(owner->view());
1300 Bold(owner->view());
1305 Noun(owner->view());
1310 Code(owner->view());
1315 Sans(owner->view());
1320 Roman(owner->view());
1325 StyleReset(owner->view());
1329 case LFUN_UNDERLINE:
1330 Underline(owner->view());
1334 case LFUN_FONT_SIZE:
1335 FontSize(owner->view(), argument);
1339 case LFUN_FONT_STATE:
1340 setMessage(CurrentState(owner->view()));
1343 case LFUN_UPCASE_WORD:
1344 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1345 text->ChangeWordCase(owner->view(), LyXText::text_uppercase);
1346 if (text->inset_owner)
1347 owner->view()->updateInset(text->inset_owner, true);
1348 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1351 case LFUN_LOWCASE_WORD:
1352 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1353 text->ChangeWordCase(owner->view(), LyXText::text_lowercase);
1354 if (text->inset_owner)
1355 owner->view()->updateInset(text->inset_owner, true);
1356 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1359 case LFUN_CAPITALIZE_WORD:
1360 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1361 text->ChangeWordCase(owner->view(),
1362 LyXText::text_capitalization);
1363 if (text->inset_owner)
1364 owner->view()->updateInset(text->inset_owner, true);
1365 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1368 case LFUN_INSERT_LABEL:
1369 MenuInsertLabel(owner->view(), argument);
1372 case LFUN_REF_INSERT:
1373 if (argument.empty()) {
1374 InsetCommandParams p("ref");
1375 owner->getDialogs()->createRef(p.getAsString());
1377 InsetCommandParams p;
1378 p.setFromString(argument);
1380 InsetRef * inset = new InsetRef(p, *owner->buffer());
1381 if (!owner->view()->insertInset(inset))
1384 owner->view()->updateInset(inset, true);
1390 owner->view()->restorePosition();
1396 string label(argument);
1397 if (label.empty()) {
1399 static_cast<InsetRef*>(getInsetByCode(Inset::REF_CODE));
1401 label = inset->getContents();
1404 if (!label.empty()) {
1405 owner->view()->savePosition();
1406 if (!owner->view()->gotoLabel(label))
1407 WriteAlert(_("Error"),
1408 _("Couldn't find this label"),
1409 _("in current document."));
1414 case LFUN_MENU_OPEN_BY_NAME:
1415 owner->getMenubar()->openByName(argument);
1416 break; // RVDK_PATCH_5
1418 case LFUN_SPELLCHECK:
1419 if (lyxrc.isp_command != "none")
1420 ShowSpellChecker(owner->view());
1421 break; // RVDK_PATCH_5
1423 // --- Cursor Movements -----------------------------
1426 LyXText * tmptext = owner->view()->text;
1427 bool is_rtl = tmptext->cursor.par()->isRightToLeftPar(owner->buffer()->params);
1428 if (!tmptext->mark_set)
1429 owner->view()->beforeChange();
1430 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1432 tmptext->CursorLeft(owner->view(), false);
1433 if (tmptext->cursor.pos() < tmptext->cursor.par()->Last()
1434 && tmptext->cursor.par()->GetChar(tmptext->cursor.pos())
1435 == LyXParagraph::META_INSET
1436 && tmptext->cursor.par()->GetInset(tmptext->cursor.pos())
1437 && tmptext->cursor.par()->GetInset(tmptext->cursor.pos())->Editable() == Inset::HIGHLY_EDITABLE){
1438 Inset * tmpinset = tmptext->cursor.par()->GetInset(tmptext->cursor.pos());
1439 setMessage(tmpinset->EditMessage());
1440 tmpinset->Edit(owner->view(), 0, 0, 0);
1444 tmptext->CursorRight(owner->view(), false);
1445 owner->view()->text->FinishUndo();
1446 moveCursorUpdate(false);
1453 // This is soooo ugly. Isn`t it possible to make
1454 // it simpler? (Lgb)
1455 LyXText * txt = owner->view()->text;
1456 bool is_rtl = txt->cursor.par()->isRightToLeftPar(owner->buffer()->params);
1457 if (!txt->mark_set) owner->view()->beforeChange();
1458 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1459 LyXCursor cur = txt->cursor;
1461 txt->CursorLeft(owner->view(), false);
1462 if ((cur != txt->cursor) && // only if really moved!
1463 txt->cursor.pos() < txt->cursor.par()->Last() &&
1464 (txt->cursor.par()->GetChar(txt->cursor.pos()) ==
1465 LyXParagraph::META_INSET) &&
1466 txt->cursor.par()->GetInset(txt->cursor.pos()) &&
1467 (txt->cursor.par()->GetInset(txt->cursor.pos())->Editable()
1468 == Inset::HIGHLY_EDITABLE))
1470 Inset * tmpinset = txt->cursor.par()->GetInset(txt->cursor.pos());
1471 setMessage(tmpinset->EditMessage());
1472 LyXFont font = txt->GetFont(owner->view()->buffer(),
1475 tmpinset->Edit(owner->view(),
1477 tmpinset->width(owner->view(),font),
1478 tmpinset->descent(owner->view(),font),
1483 txt->CursorRight(owner->view(), false);
1485 owner->view()->text->FinishUndo();
1486 moveCursorUpdate(false);
1492 if (!owner->view()->text->mark_set) owner->view()->beforeChange();
1493 owner->view()->update(BufferView::UPDATE);
1494 owner->view()->text->CursorUp(owner->view());
1495 owner->view()->text->FinishUndo();
1496 moveCursorUpdate(false);
1501 if (!owner->view()->text->mark_set)
1502 owner->view()->beforeChange();
1503 owner->view()->update(BufferView::UPDATE);
1504 owner->view()->text->CursorDown(owner->view());
1505 owner->view()->text->FinishUndo();
1506 moveCursorUpdate(false);
1510 case LFUN_UP_PARAGRAPH:
1511 if (!owner->view()->text->mark_set)
1512 owner->view()->beforeChange();
1513 owner->view()->update(BufferView::UPDATE);
1514 owner->view()->text->CursorUpParagraph(owner->view());
1515 owner->view()->text->FinishUndo();
1516 moveCursorUpdate(false);
1520 case LFUN_DOWN_PARAGRAPH:
1521 if (!owner->view()->text->mark_set)
1522 owner->view()->beforeChange();
1523 owner->view()->update(BufferView::UPDATE);
1524 owner->view()->text->CursorDownParagraph(owner->view());
1525 owner->view()->text->FinishUndo();
1526 moveCursorUpdate(false);
1531 if (!text->mark_set)
1532 owner->view()->beforeChange();
1533 owner->view()->update(BufferView::UPDATE);
1534 owner->view()->cursorPrevious(text);
1535 owner->view()->text->FinishUndo();
1536 if (text->inset_owner)
1537 owner->view()->updateInset(text->inset_owner, false);
1539 moveCursorUpdate(false);
1544 if (!text->mark_set)
1545 owner->view()->beforeChange();
1546 owner->view()->update(BufferView::UPDATE);
1547 owner->view()->cursorNext(text);
1548 owner->view()->text->FinishUndo();
1549 if (text->inset_owner)
1550 owner->view()->updateInset(text->inset_owner, false);
1552 moveCursorUpdate(false);
1557 if (!owner->view()->text->mark_set)
1558 owner->view()->beforeChange();
1559 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1560 owner->view()->text->CursorHome(owner->view());
1561 owner->view()->text->FinishUndo();
1562 moveCursorUpdate(false);
1567 if (!owner->view()->text->mark_set)
1568 owner->view()->beforeChange();
1569 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1570 owner->view()->text->CursorEnd(owner->view());
1571 owner->view()->text->FinishUndo();
1572 moveCursorUpdate(false);
1576 case LFUN_SHIFT_TAB:
1578 if (!owner->view()->text->mark_set)
1579 owner->view()->beforeChange();
1580 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1581 owner->view()->text->CursorTab(owner->view());
1582 owner->view()->text->FinishUndo();
1583 moveCursorUpdate(false);
1587 case LFUN_WORDRIGHT:
1588 if (!text->mark_set)
1589 owner->view()->beforeChange();
1590 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1591 if (text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1592 text->CursorLeftOneWord(owner->view());
1594 text->CursorRightOneWord(owner->view());
1595 owner->view()->text->FinishUndo();
1596 if (text->inset_owner)
1597 owner->view()->updateInset(text->inset_owner, true);
1598 moveCursorUpdate(false);
1603 if (!text->mark_set)
1604 owner->view()->beforeChange();
1605 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1606 if (text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1607 text->CursorRightOneWord(owner->view());
1609 text->CursorLeftOneWord(owner->view());
1610 owner->view()->text->FinishUndo();
1611 if (text->inset_owner)
1612 owner->view()->updateInset(text->inset_owner, true);
1613 moveCursorUpdate(false);
1617 case LFUN_BEGINNINGBUF:
1618 if (!owner->view()->text->mark_set)
1619 owner->view()->beforeChange();
1620 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1621 owner->view()->text->CursorTop(owner->view());
1622 owner->view()->text->FinishUndo();
1623 moveCursorUpdate(false);
1628 if (!owner->view()->text->mark_set)
1629 owner->view()->beforeChange();
1630 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1631 owner->view()->text->CursorBottom(owner->view());
1632 owner->view()->text->FinishUndo();
1633 moveCursorUpdate(false);
1638 /* cursor selection ---------------------------- */
1640 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1641 if (owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1642 owner->view()->text->CursorLeft(owner->view());
1644 owner->view()->text->CursorRight(owner->view());
1645 owner->view()->text->FinishUndo();
1646 moveCursorUpdate(true);
1651 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1652 if (owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1653 owner->view()->text->CursorRight(owner->view());
1655 owner->view()->text->CursorLeft(owner->view());
1656 owner->view()->text->FinishUndo();
1657 moveCursorUpdate(true);
1662 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1663 owner->view()->text->CursorUp(owner->view());
1664 owner->view()->text->FinishUndo();
1665 moveCursorUpdate(true);
1670 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1671 owner->view()->text->CursorDown(owner->view());
1672 owner->view()->text->FinishUndo();
1673 moveCursorUpdate(true);
1677 case LFUN_UP_PARAGRAPHSEL:
1678 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1679 owner->view()->text->CursorUpParagraph(owner->view());
1680 owner->view()->text->FinishUndo();
1681 moveCursorUpdate(true);
1685 case LFUN_DOWN_PARAGRAPHSEL:
1686 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1687 owner->view()->text->CursorDownParagraph(owner->view());
1688 owner->view()->text->FinishUndo();
1689 moveCursorUpdate(true);
1694 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1695 owner->view()->cursorPrevious(text);
1696 owner->view()->text->FinishUndo();
1697 if (text->inset_owner)
1698 owner->view()->updateInset(text->inset_owner, false);
1700 moveCursorUpdate(true);
1705 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1706 owner->view()->cursorNext(text);
1707 owner->view()->text->FinishUndo();
1708 if (text->inset_owner)
1709 owner->view()->updateInset(text->inset_owner, false);
1711 moveCursorUpdate(true);
1716 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1717 owner->view()->text->CursorHome(owner->view());
1718 owner->view()->text->FinishUndo();
1719 moveCursorUpdate(true);
1724 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1725 owner->view()->text->CursorEnd(owner->view());
1726 owner->view()->text->FinishUndo();
1727 moveCursorUpdate(true);
1731 case LFUN_WORDRIGHTSEL:
1732 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1733 if (owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1734 owner->view()->text->CursorLeftOneWord(owner->view());
1736 owner->view()->text->CursorRightOneWord(owner->view());
1737 owner->view()->text->FinishUndo();
1738 moveCursorUpdate(true);
1742 case LFUN_WORDLEFTSEL:
1743 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1744 if (owner->view()->text->cursor.par()->isRightToLeftPar(owner->buffer()->params))
1745 owner->view()->text->CursorRightOneWord(owner->view());
1747 owner->view()->text->CursorLeftOneWord(owner->view());
1748 owner->view()->text->FinishUndo();
1749 moveCursorUpdate(true);
1753 case LFUN_BEGINNINGBUFSEL:
1754 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1755 owner->view()->text->CursorTop(owner->view());
1756 owner->view()->text->FinishUndo();
1757 moveCursorUpdate(true);
1761 case LFUN_ENDBUFSEL:
1762 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1763 owner->view()->text->CursorBottom(owner->view());
1764 owner->view()->text->FinishUndo();
1765 moveCursorUpdate(true);
1769 // --- text changing commands ------------------------
1770 case LFUN_BREAKLINE:
1771 owner->view()->beforeChange();
1772 owner->view()->text->InsertChar(owner->view(), LyXParagraph::META_NEWLINE);
1773 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1774 moveCursorUpdate(false);
1777 case LFUN_PROTECTEDSPACE:
1779 LyXLayout const & style =
1780 textclasslist.Style(owner->view()->buffer()->params.textclass,
1781 owner->view()->text->cursor.par()->GetLayout());
1783 if (style.free_spacing) {
1784 owner->view()->text->InsertChar(owner->view(), ' ');
1785 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1787 owner->view()->protectedBlank();
1789 moveCursorUpdate(false);
1794 if (text->mark_set) {
1795 owner->view()->beforeChange();
1796 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1797 setMessage(N_("Mark removed"));
1799 owner->view()->beforeChange();
1801 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1802 setMessage(N_("Mark set"));
1804 text->sel_cursor = text->cursor;
1805 if (text->inset_owner)
1806 owner->view()->updateInset(text->inset_owner, true);
1810 if (!owner->view()->text->selection) {
1811 owner->view()->text->Delete(owner->view());
1812 owner->view()->text->sel_cursor =
1813 owner->view()->text->cursor;
1814 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1815 // It is possible to make it a lot faster still
1816 // just comment out the lone below...
1817 owner->view()->showCursor();
1819 owner->view()->cut();
1821 moveCursorUpdate(false);
1823 owner->view()->setState();
1826 case LFUN_DELETE_SKIP:
1828 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
1830 LyXCursor cursor = owner->view()->text->cursor;
1832 if (!owner->view()->text->selection) {
1833 if (cursor.pos() == cursor.par()->Last()) {
1834 owner->view()->text->CursorRight(owner->view());
1835 cursor = owner->view()->text->cursor;
1836 if (cursor.pos() == 0
1837 && !(cursor.par()->added_space_top
1838 == VSpace (VSpace::NONE))) {
1839 owner->view()->text->SetParagraph
1841 cursor.par()->line_top,
1842 cursor.par()->line_bottom,
1843 cursor.par()->pagebreak_top,
1844 cursor.par()->pagebreak_bottom,
1845 VSpace(VSpace::NONE),
1846 cursor.par()->added_space_bottom,
1847 cursor.par()->align,
1848 cursor.par()->labelwidthstring, 0);
1849 owner->view()->text->CursorLeft(owner->view());
1850 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1852 owner->view()->text->CursorLeft(owner->view());
1853 owner->view()->text->Delete(owner->view());
1854 owner->view()->text->sel_cursor =
1855 owner->view()->text->cursor;
1856 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1859 owner->view()->text->Delete(owner->view());
1860 owner->view()->text->sel_cursor =
1861 owner->view()->text->cursor;
1862 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1865 owner->view()->cut();
1870 /* -------> Delete word forward. */
1871 case LFUN_DELETE_WORD_FORWARD:
1872 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1873 text->DeleteWordForward(owner->view());
1874 if (text->inset_owner)
1875 owner->view()->updateInset(text->inset_owner, true);
1876 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1877 moveCursorUpdate(false);
1881 /* -------> Delete word backward. */
1882 case LFUN_DELETE_WORD_BACKWARD:
1883 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1884 text->DeleteWordBackward(owner->view());
1885 if (text->inset_owner)
1886 owner->view()->updateInset(text->inset_owner, true);
1887 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1888 moveCursorUpdate(false);
1892 /* -------> Kill to end of line. */
1893 case LFUN_DELETE_LINE_FORWARD:
1894 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1895 text->DeleteLineForward(owner->view());
1896 if (text->inset_owner)
1897 owner->view()->updateInset(text->inset_owner, true);
1898 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1899 moveCursorUpdate(false);
1902 /* -------> Set mark off. */
1904 owner->view()->beforeChange();
1905 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1906 text->sel_cursor = text->cursor;
1907 setMessage(N_("Mark off"));
1908 if (text->inset_owner)
1909 owner->view()->updateInset(text->inset_owner, true);
1912 /* -------> Set mark on. */
1914 owner->view()->beforeChange();
1915 owner->view()->text->mark_set = 1;
1916 owner->view()->update(BufferView::SELECT|BufferView::FITCUR);
1917 text->sel_cursor = text->cursor;
1918 if (text->inset_owner)
1919 owner->view()->updateInset(text->inset_owner, true);
1920 setMessage(N_("Mark on"));
1923 case LFUN_BACKSPACE:
1925 if (!owner->view()->text->selection) {
1926 if (owner->getIntl()->getTrans()->backspace()) {
1927 owner->view()->text->Backspace(owner->view());
1928 owner->view()->text->sel_cursor =
1929 owner->view()->text->cursor;
1930 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1931 // It is possible to make it a lot faster still
1932 // just comment out the lone below...
1933 owner->view()->showCursor();
1936 owner->view()->cut();
1939 owner->view()->setState();
1943 case LFUN_BACKSPACE_SKIP:
1945 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
1947 LyXCursor cursor = owner->view()->text->cursor;
1949 if (!owner->view()->text->selection) {
1950 if (cursor.pos() == 0
1951 && !(cursor.par()->added_space_top
1952 == VSpace (VSpace::NONE))) {
1953 owner->view()->text->SetParagraph
1955 cursor.par()->line_top,
1956 cursor.par()->line_bottom,
1957 cursor.par()->pagebreak_top,
1958 cursor.par()->pagebreak_bottom,
1959 VSpace(VSpace::NONE), cursor.par()->added_space_bottom,
1960 cursor.par()->align,
1961 cursor.par()->labelwidthstring, 0);
1962 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1964 owner->view()->text->Backspace(owner->view());
1965 owner->view()->text->sel_cursor
1967 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1970 owner->view()->cut();
1974 case LFUN_BREAKPARAGRAPH:
1976 owner->view()->beforeChange();
1977 owner->view()->text->BreakParagraph(owner->view(), 0);
1978 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1979 owner->view()->text->sel_cursor =
1980 owner->view()->text->cursor;
1981 owner->view()->setState();
1986 case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
1988 owner->view()->beforeChange();
1989 owner->view()->text->BreakParagraph(owner->view(), 1);
1990 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
1991 owner->view()->text->sel_cursor =
1992 owner->view()->text->cursor;
1993 owner->view()->setState();
1998 case LFUN_BREAKPARAGRAPH_SKIP:
2000 // When at the beginning of a paragraph, remove
2001 // indentation and add a "defskip" at the top.
2002 // Otherwise, do the same as LFUN_BREAKPARAGRAPH.
2004 LyXCursor cursor = owner->view()->text->cursor;
2006 owner->view()->beforeChange();
2007 if (cursor.pos() == 0) {
2008 if (cursor.par()->added_space_top == VSpace(VSpace::NONE)) {
2009 owner->view()->text->SetParagraph
2011 cursor.par()->line_top,
2012 cursor.par()->line_bottom,
2013 cursor.par()->pagebreak_top,
2014 cursor.par()->pagebreak_bottom,
2015 VSpace(VSpace::DEFSKIP), cursor.par()->added_space_bottom,
2016 cursor.par()->align,
2017 cursor.par()->labelwidthstring, 1);
2018 //owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2022 owner->view()->text->BreakParagraph(owner->view(), 0);
2023 //owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2026 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2027 owner->view()->text->sel_cursor = cursor;
2028 owner->view()->setState();
2033 case LFUN_PARAGRAPH_SPACING:
2035 LyXParagraph * par = owner->view()->text->cursor.par();
2036 Spacing::Space cur_spacing = par->spacing.getSpace();
2037 float cur_value = 1.0;
2038 if (cur_spacing == Spacing::Other) {
2039 cur_value = par->spacing.getValue();
2042 istringstream istr(argument.c_str());
2046 Spacing::Space new_spacing = cur_spacing;
2047 float new_value = cur_value;
2049 lyxerr << "Missing argument to `paragraph-spacing'"
2051 } else if (tmp == "single") {
2052 new_spacing = Spacing::Single;
2053 } else if (tmp == "onehalf") {
2054 new_spacing = Spacing::Onehalf;
2055 } else if (tmp == "double") {
2056 new_spacing = Spacing::Double;
2057 } else if (tmp == "other") {
2058 new_spacing = Spacing::Other;
2061 lyxerr << "new_value = " << tmpval << endl;
2064 } else if (tmp == "default") {
2065 new_spacing = Spacing::Default;
2067 lyxerr << _("Unknown spacing argument: ")
2068 << argument << endl;
2070 if (cur_spacing != new_spacing || cur_value != new_value) {
2071 par->spacing.set(new_spacing, new_value);
2072 owner->view()->text->RedoParagraph(owner->view());
2073 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2079 owner->view()->beforeChange();
2080 owner->view()->text->InsertChar(owner->view(), '\"'); // This " matches the single quote in the code
2081 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2082 moveCursorUpdate(false);
2088 InsetCommandParams p;
2089 if (action == LFUN_HTMLURL)
2090 p.setCmdName("htmlurl");
2092 p.setCmdName("url");
2093 owner->getDialogs()->createUrl( p.getAsString() );
2097 case LFUN_INSERT_URL:
2099 InsetCommandParams p;
2100 p.setFromString( argument );
2102 InsetUrl * inset = new InsetUrl( p );
2103 if (!owner->view()->insertInset(inset))
2106 owner->view()->updateInset( inset, true );
2110 case LFUN_INSET_TEXT:
2112 InsetText * new_inset = new InsetText;
2113 if (owner->view()->insertInset(new_inset))
2114 new_inset->Edit(owner->view(), 0, 0, 0);
2120 case LFUN_INSET_ERT:
2122 InsetERT * new_inset = new InsetERT;
2123 if (owner->view()->insertInset(new_inset))
2124 new_inset->Edit(owner->view(), 0, 0, 0);
2130 case LFUN_INSET_EXTERNAL:
2132 InsetExternal * new_inset = new InsetExternal;
2133 if (owner->view()->insertInset(new_inset))
2134 new_inset->Edit(owner->view(), 0, 0, 0);
2140 case LFUN_INSET_FOOTNOTE:
2142 InsetFoot * new_inset = new InsetFoot;
2143 if (owner->view()->insertInset(new_inset))
2144 new_inset->Edit(owner->view(), 0, 0, 0);
2150 case LFUN_INSET_MARGINAL:
2152 InsetMarginal * new_inset = new InsetMarginal;
2153 if (owner->view()->insertInset(new_inset))
2154 new_inset->Edit(owner->view(), 0, 0, 0);
2160 case LFUN_INSET_MINIPAGE:
2162 InsetMinipage * new_inset = new InsetMinipage;
2163 if (owner->view()->insertInset(new_inset))
2164 new_inset->Edit(owner->view(), 0, 0, 0);
2170 case LFUN_INSET_FLOAT:
2172 // check if the float type exist
2173 if (floatList.typeExist(argument)) {
2174 InsetFloat * new_inset = new InsetFloat(argument);
2175 if (owner->view()->insertInset(new_inset))
2176 new_inset->Edit(owner->view(), 0, 0, 0);
2180 lyxerr << "Non-existant float type: "
2181 << argument << endl;
2187 case LFUN_INSET_LIST:
2189 InsetList * new_inset = new InsetList;
2190 if (owner->view()->insertInset(new_inset))
2191 new_inset->Edit(owner->view(), 0, 0, 0);
2197 case LFUN_INSET_THEOREM:
2199 InsetTheorem * new_inset = new InsetTheorem;
2200 if (owner->view()->insertInset(new_inset))
2201 new_inset->Edit(owner->view(), 0, 0, 0);
2207 case LFUN_INSET_CAPTION:
2209 // Do we have a locking inset...
2210 if (owner->view()->theLockingInset()) {
2211 lyxerr << "Locking inset code: "
2212 << static_cast<int>(owner->view()->theLockingInset()->LyxCode());
2213 InsetCaption * new_inset = new InsetCaption;
2214 new_inset->setOwner(owner->view()->theLockingInset());
2215 new_inset->SetAutoBreakRows(true);
2216 new_inset->SetDrawFrame(0, InsetText::LOCKED);
2217 new_inset->SetFrameColor(0, LColor::footnoteframe);
2218 if (owner->view()->insertInset(new_inset))
2219 new_inset->Edit(owner->view(), 0, 0, 0);
2226 case LFUN_INSET_TABULAR:
2229 if (!argument.empty())
2230 ::sscanf(argument.c_str(),"%d%d", &r, &c);
2231 InsetTabular * new_inset =
2232 new InsetTabular(*owner->buffer(), r, c);
2233 if (owner->view()->insertInset(new_inset))
2234 new_inset->Edit(owner->view(), 0, 0, 0);
2240 // --- lyxserver commands ----------------------------
2242 case LFUN_CHARATCURSOR:
2244 LyXParagraph::size_type pos =
2245 owner->view()->text->cursor.pos();
2246 if (pos < owner->view()->text->cursor.par()->size())
2247 //dispatch_buffer = owner->view()->text->
2248 // cursor.par()->text[pos];
2250 owner->view()->text->
2251 cursor.par()->GetChar(pos);
2253 dispatch_buffer = "EOF";
2259 tostr(owner->view()->text->cursor.x()) + ' '
2260 + tostr(owner->view()->text->cursor.y());
2267 ::sscanf(argument.c_str(), " %d %d", &x, &y);
2268 owner->view()->text->SetCursorFromCoordinates(owner->view(), x, y);
2272 case LFUN_GETLAYOUT:
2274 tostr(owner->view()->text->cursor.par()->layout);
2279 LyXFont & font = owner->view()->text->current_font;
2280 if (font.shape() == LyXFont::ITALIC_SHAPE)
2281 dispatch_buffer = 'E';
2282 else if (font.shape() == LyXFont::SMALLCAPS_SHAPE)
2283 dispatch_buffer = 'N';
2285 dispatch_buffer = '0';
2292 LyXFont & font = owner->view()->text->current_font;
2293 if (font.latex() == LyXFont::ON)
2294 dispatch_buffer = 'L';
2296 dispatch_buffer = '0';
2301 setMessage(owner->buffer()->fileName());
2302 lyxerr.debug() << "FNAME["
2303 << owner->buffer()->fileName()
2311 dispatch_buffer = buf;
2312 lyxserver->notifyClient(dispatch_buffer);
2316 case LFUN_GOTOFILEROW:
2318 char file_name[100];
2320 ::sscanf(argument.c_str(), " %s %d", file_name, &row);
2322 // Must replace extension of the file to be .lyx and get full path
2323 string s = ChangeExtension(string(file_name), ".lyx");
2325 // Either change buffer or load the file
2326 if (bufferlist.exists(s))
2327 owner->view()->buffer(bufferlist.getBuffer(s));
2329 owner->view()->buffer(bufferlist.loadLyXFile(s));
2332 owner->view()->setCursorFromRow(row);
2335 owner->view()->center();
2339 case LFUN_GOTO_PARAGRAPH:
2341 istringstream istr(argument.c_str());
2345 LyXParagraph * par = owner->view()->text->GetParFromID(id);
2348 owner->view()->text->SetCursor(owner->view(), par, 0);
2349 owner->view()->setState();
2353 owner->view()->center();
2360 int const qa = lyxaction.LookupFunc(argument);
2361 setMessage(lyxaction.helpText(static_cast<kb_action>(qa)));
2365 // --- accented characters ---------------------------
2368 case LFUN_CIRCUMFLEX:
2378 case LFUN_SPECIAL_CARON:
2381 case LFUN_HUNG_UMLAUT:
2387 if (keyseq.length == -1 && keyseq.getiso() != 0)
2388 c = keyseq.getiso();
2390 owner->getIntl()->getTrans()->
2391 deadkey(c, get_accent(action).accent,
2392 owner->view()->text);
2394 // Need to reset, in case the minibuffer calls these
2399 // copied verbatim from do_accent_char
2400 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2402 owner->view()->text->sel_cursor =
2403 owner->view()->text->cursor;
2407 // --- toolbar ----------------------------------
2408 case LFUN_PUSH_TOOLBAR:
2410 int nth = strToInt(argument);
2412 setErrorMessage(N_("Push-toolbar needs argument > 0"));
2414 owner->getToolbar()->push(nth);
2419 case LFUN_ADD_TO_TOOLBAR:
2421 if (lyxerr.debugging(Debug::GUI)) {
2422 lyxerr << "LFUN_ADD_TO_TOOLBAR:"
2423 "argument = `" << argument << '\'' << endl;
2425 string tmp(argument);
2426 //lyxerr <<string("Argument: ") + argument);
2427 //lyxerr <<string("Tmp : ") + tmp);
2429 setErrorMessage(N_("Usage: toolbar-add-to <LyX command>"));
2431 owner->getToolbar()->add(argument, false);
2432 owner->getToolbar()->set();
2437 // --- insert characters ----------------------------------------
2439 // --- Mathed stuff. If we are here, there is no locked inset yet.
2444 if (!greek_kb_flag) {
2446 setMessage(N_("Math greek mode on"));
2453 case LFUN_GREEK_TOGGLE:
2455 greek_kb_flag = greek_kb_flag ? 0 : 2;
2456 if (greek_kb_flag) {
2457 setMessage(N_("Math greek keyboard on"));
2459 setMessage(N_("Math greek keyboard off"));
2464 case LFUN_MATH_DELIM:
2465 case LFUN_INSERT_MATRIX:
2467 if (owner->view()->available()) {
2469 open_new_inset(new InsetFormula(false)))
2471 owner->view()->theLockingInset()
2472 ->LocalDispatch(owner->view(),
2480 case LFUN_INSERT_MATH:
2482 math_insert_symbol(argument);
2486 case LFUN_MATH_DISPLAY:
2488 if (owner->view()->available())
2489 owner->view()->open_new_inset(new InsetFormula(true));
2493 case LFUN_MATH_MACRO:
2495 if (owner->view()->available()) {
2498 setErrorMessage(N_("Missing argument"));
2500 string const s1 = token(s, ' ', 1);
2501 int const na = s1.empty() ? 0 : lyx::atoi(s1);
2503 open_new_inset(new InsetFormulaMacro(token(s, ' ', 0), na));
2509 case LFUN_MATH_MODE: // Open or create a math inset
2511 if (owner->view()->available())
2512 owner->view()->open_new_inset(new InsetFormula);
2513 setMessage(N_("Math editor mode"));
2517 case LFUN_MATH_NUMBER:
2518 case LFUN_MATH_LIMITS:
2520 setErrorMessage(N_("This is only allowed in math mode!"));
2525 case LFUN_MATH_PANEL:
2527 show_symbols_form(this);
2531 case LFUN_CITATION_CREATE:
2533 InsetCommandParams p( "cite" );
2535 if (!argument.empty()) {
2536 // This should be set at source, ie when typing
2537 // "citation-insert foo" in the minibuffer.
2538 // Question: would pybibliographer also need to be
2539 // changed. Suspect so. Leave as-is therefore.
2540 if (contains(argument, "|")) {
2541 p.setContents( token(argument, '|', 0) );
2542 p.setOptions( token(argument, '|', 1) );
2544 p.setContents( argument );
2546 Dispatch(LFUN_CITATION_INSERT, p.getAsString());
2548 owner->getDialogs()->createCitation( p.getAsString() );
2552 case LFUN_CITATION_INSERT:
2554 InsetCommandParams p;
2555 p.setFromString( argument );
2557 InsetCitation * inset = new InsetCitation( p );
2558 if (!owner->view()->insertInset(inset))
2561 owner->view()->updateInset( inset, true );
2565 case LFUN_INSERT_BIBTEX:
2567 // ale970405+lasgoutt970425
2568 // The argument can be up to two tokens separated
2569 // by a space. The first one is the bibstyle.
2570 string const db = token(argument, ' ', 0);
2571 string bibstyle = token(argument, ' ', 1);
2572 if (bibstyle.empty())
2575 InsetCommandParams p( "BibTeX", db, bibstyle );
2576 InsetBibtex * inset = new InsetBibtex(p);
2578 if (owner->view()->insertInset(inset)) {
2579 if (argument.empty())
2580 inset->Edit(owner->view(), 0, 0, 0);
2586 // BibTeX data bases
2587 case LFUN_BIBDB_ADD:
2589 InsetBibtex * inset =
2590 static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
2592 inset->addDatabase(argument);
2597 case LFUN_BIBDB_DEL:
2599 InsetBibtex * inset =
2600 static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
2602 inset->delDatabase(argument);
2607 case LFUN_BIBTEX_STYLE:
2609 InsetBibtex * inset =
2610 static_cast<InsetBibtex*>(getInsetByCode(Inset::BIBTEX_CODE));
2612 inset->setOptions(argument);
2617 case LFUN_INDEX_CREATE:
2619 InsetCommandParams p( "index" );
2621 if (argument.empty()) {
2622 // Get the word immediately preceding the cursor
2623 LyXParagraph::size_type curpos =
2624 owner->view()->text->cursor.pos() - 1;
2628 curstring = owner->view()->text
2629 ->cursor.par()->GetWord(curpos);
2631 p.setContents( curstring );
2633 p.setContents( argument );
2636 owner->getDialogs()->createIndex( p.getAsString() );
2640 case LFUN_INDEX_INSERT:
2642 InsetCommandParams p;
2643 p.setFromString(argument);
2644 InsetIndex * inset = new InsetIndex(p);
2646 if (!owner->view()->insertInset(inset))
2649 owner->view()->updateInset(inset, true);
2653 case LFUN_INDEX_INSERT_LAST:
2655 // Get word immediately preceding the cursor
2656 LyXParagraph::size_type curpos =
2657 owner->view()->text->cursor.pos() - 1;
2658 // Can't do that at the beginning of a paragraph
2659 if (curpos < 0) break;
2661 string const curstring(owner->view()->text
2662 ->cursor.par()->GetWord(curpos));
2664 InsetCommandParams p("index", curstring);
2665 InsetIndex * inset = new InsetIndex(p);
2667 if (!owner->view()->insertInset(inset))
2670 owner->view()->updateInset(inset, true);
2674 case LFUN_INDEX_PRINT:
2676 InsetCommandParams p("printindex");
2677 Inset * inset = new InsetPrintIndex(p);
2678 if (!owner->view()->insertInset(inset, "Standard", true))
2683 case LFUN_PARENTINSERT:
2685 lyxerr << "arg " << argument << endl;
2686 InsetCommandParams p( "lyxparent", argument );
2687 Inset * inset = new InsetParent(p, *owner->buffer());
2688 if (!owner->view()->insertInset(inset, "Standard", true))
2693 case LFUN_CHILDINSERT:
2695 InsetCommandParams p( "Include", argument );
2696 Inset * inset = new InsetInclude(p, *owner->buffer());
2697 if (owner->view()->insertInset(inset, "Standard", true))
2698 inset->Edit(owner->view(), 0, 0, 0);
2704 case LFUN_CHILDOPEN:
2706 string const filename =
2707 MakeAbsPath(argument,
2708 OnlyPath(owner->buffer()->fileName()));
2709 setMessage(N_("Opening child document ") +
2710 MakeDisplayPath(filename) + "...");
2711 owner->view()->savePosition();
2712 if (bufferlist.exists(filename))
2713 owner->view()->buffer(bufferlist.getBuffer(filename));
2715 owner->view()->buffer(bufferlist.loadLyXFile(filename));
2719 case LFUN_INSERT_NOTE:
2720 owner->view()->insertNote();
2723 case LFUN_INSERTFOOTNOTE:
2725 LyXParagraph::footnote_kind kind;
2726 if (argument == "footnote") {
2727 kind = LyXParagraph::FOOTNOTE;
2728 } else if (argument == "margin") {
2729 kind = LyXParagraph::MARGIN;
2730 } else if (argument == "figure") {
2731 kind = LyXParagraph::FIG;
2732 } else if (argument == "table") {
2733 kind = LyXParagraph::TAB;
2734 } else if (argument == "wide-fig") {
2735 kind = LyXParagraph::WIDE_FIG;
2736 } else if (argument == "wide-tab") {
2737 kind = LyXParagraph::WIDE_TAB;
2738 } else if (argument == "algorithm") {
2739 kind = LyXParagraph::ALGORITHM;
2741 setErrorMessage(N_("Unknown kind of footnote"));
2744 owner->view()->text->InsertFootnoteEnvironment(owner->view(), kind);
2745 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2746 owner->view()->setState();
2750 case LFUN_TOGGLECURSORFOLLOW:
2751 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
2754 case LFUN_KMAP_OFF: // keymap off
2755 owner->getIntl()->KeyMapOn(false);
2758 case LFUN_KMAP_PRIM: // primary keymap
2759 owner->getIntl()->KeyMapPrim();
2762 case LFUN_KMAP_SEC: // secondary keymap
2763 owner->getIntl()->KeyMapSec();
2766 case LFUN_KMAP_TOGGLE: // toggle keymap
2767 owner->getIntl()->ToggleKeyMap();
2770 case LFUN_SELFINSERT:
2772 LyXFont const old_font(owner->view()->text->real_current_font);
2773 for (string::size_type i = 0; i < argument.length(); ++i) {
2774 owner->view()->text->InsertChar(owner->view(), argument[i]);
2775 // This needs to be in the loop, or else we
2776 // won't break lines correctly. (Asger)
2777 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2779 owner->view()->text->sel_cursor =
2780 owner->view()->text->cursor;
2781 moveCursorUpdate(false);
2783 // real_current_font.number can change so we need to
2784 // update the minibuffer
2785 if (old_font != owner->view()->text->real_current_font)
2792 // argument contains ';'-terminated commands
2793 while (argument.find(';') != string::npos) {
2795 argument = split(argument, first, ';');
2801 case LFUN_DATE_INSERT: // jdblair: date-insert cmd
2805 time_t now_time_t = time(NULL);
2806 now_tm = localtime(&now_time_t);
2807 setlocale(LC_TIME, "");
2809 if (!argument.empty())
2812 arg = lyxrc.date_insert_format;
2814 int const datetmp_len =
2815 ::strftime(datetmp, 32, arg.c_str(), now_tm);
2816 for (int i = 0; i < datetmp_len; i++) {
2817 owner->view()->text->InsertChar(owner->view(), datetmp[i]);
2818 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2821 owner->view()->text->sel_cursor = owner->view()->text->cursor;
2822 moveCursorUpdate(false);
2826 case LFUN_DIALOG_PREFERENCES:
2827 owner->getDialogs()->showPreferences();
2830 case LFUN_SAVEPREFERENCES:
2832 Path p(user_lyxdir);
2833 lyxrc.write("preferences");
2837 case LFUN_SCREEN_FONT_UPDATE:
2839 // handle the screen font changes.
2841 lyxrc.set_font_norm_type();
2842 fontloader.update();
2843 // Of course we should only do the resize and the textcache.clear
2844 // if values really changed...but not very important right now. (Lgb)
2845 // All buffers will need resize
2846 bufferlist.resize();
2847 // We also need to empty the textcache so that
2848 // the buffer will be formatted correctly after
2854 case LFUN_SET_COLOR:
2857 string const x11_name = split(argument, lyx_name, ' ');
2858 if (lyx_name.empty() || x11_name.empty()) {
2860 setErrorMessage(N_("Syntax: set-color <lyx_name>"
2865 if (!lcolor.setColor(lyx_name, x11_name)) {
2866 static string const err1 (N_("Set-color \""));
2867 static string const err2 (
2868 N_("\" failed - color is undefined "
2869 "or may not be redefined"));
2871 setErrorMessage(_(err1) + lyx_name + _(err2));
2874 lyxColorHandler->updateColor(lcolor.getFromLyXName(lyx_name));
2875 owner->view()->redraw();
2879 case LFUN_UNKNOWN_ACTION:
2881 if (!owner->buffer()) {
2883 setErrorMessage(N_("No document open"));
2887 if (owner->buffer()->isReadonly()) {
2889 setErrorMessage(N_("Document is read only"));
2893 if (!argument.empty()) {
2895 /* Automatically delete the currently selected
2896 * text and replace it with what is being
2897 * typed in now. Depends on lyxrc settings
2898 * "auto_region_delete", which defaults to
2901 if (lyxrc.auto_region_delete) {
2902 if (owner->view()->text->selection){
2903 owner->view()->text->CutSelection(owner->view(), false);
2904 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2908 owner->view()->beforeChange();
2909 LyXFont const old_font(owner->view()->text->real_current_font);
2910 for (string::size_type i = 0;
2911 i < argument.length(); ++i) {
2912 if (greek_kb_flag) {
2913 if (!math_insert_greek(argument[i]))
2914 owner->getIntl()->getTrans()->TranslateAndInsert(argument[i], owner->view()->text);
2916 owner->getIntl()->getTrans()->TranslateAndInsert(argument[i], owner->view()->text);
2919 owner->view()->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
2921 owner->view()->text->sel_cursor =
2922 owner->view()->text->cursor;
2923 moveCursorUpdate(false);
2925 // real_current_font.number can change so we need to
2926 // update the minibuffer
2927 if (old_font != owner->view()->text->real_current_font)
2931 // why is an "Unknown action" with empty
2932 // argument even dispatched in the first
2933 // place? I`ll probably change that. (Lgb)
2935 setErrorMessage(N_("Unknown action"));
2941 lyxerr << "A truly unknown func!" << endl;
2946 string const res = getMessage();
2949 if (!commandshortcut.empty()) {
2950 string const newbuf =
2951 owner->getMiniBuffer()->GetText();
2952 if (newbuf != commandshortcut) {
2953 owner->getMiniBuffer()->Set(newbuf
2961 msg += commandshortcut;
2962 owner->getMiniBuffer()->Set(msg);
2969 void LyXFunc::setupLocalKeymap()
2971 keyseq.stdmap = keyseq.curmap = toplevel_keymap;
2972 cancel_meta_seq.stdmap = cancel_meta_seq.curmap = toplevel_keymap;
2976 void LyXFunc::MenuNew(bool fromTemplate)
2978 string initpath = lyxrc.document_path;
2981 if (owner->view()->available()) {
2982 string const trypath = owner->buffer()->filepath;
2983 // If directory is writeable, use this as default.
2984 if (IsDirWriteable(trypath) == 1)
2988 static int newfile_number = 0;
2991 if (lyxrc.new_ask_filename) {
2992 ProhibitInput(owner->view());
2993 fileDlg.SetButton(0, _("Documents"), lyxrc.document_path);
2994 fileDlg.SetButton(1, _("Templates"), lyxrc.template_path);
2995 string fname = fileDlg.Select(_("Enter Filename for new document"),
2996 initpath, "*.lyx", _("newfile"));
2997 AllowInput(owner->view());
2999 if (fname.empty()) {
3000 owner->getMiniBuffer()->Set(_("Canceled."));
3001 lyxerr.debug() << "New Document Cancelled." << endl;
3005 // get absolute path of file and make sure the filename ends
3007 s = MakeAbsPath(fname);
3008 if (!IsLyXFilename(s))
3011 // Check if the document already is open
3012 if (bufferlist.exists(s)) {
3013 switch (AskConfirmation(_("Document is already open:"),
3014 MakeDisplayPath(s, 50),
3015 _("Do you want to close that document now?\n"
3016 "('No' will just switch to the open version)")))
3018 case 1: // Yes: close the document
3019 if (!bufferlist.close(bufferlist.getBuffer(s)))
3020 // If close is canceled, we cancel here too.
3023 case 2: // No: switch to the open document
3024 owner->view()->buffer(bufferlist.getBuffer(s));
3026 case 3: // Cancel: Do nothing
3027 owner->getMiniBuffer()->Set(_("Canceled."));
3031 // Check whether the file already exists
3032 if (IsLyXFilename(s)) {
3034 if (fi.readable() &&
3035 AskQuestion(_("File already exists:"),
3036 MakeDisplayPath(s, 50),
3037 _("Do you want to open the document?"))) {
3039 owner->getMiniBuffer()->Set(_("Opening document"),
3040 MakeDisplayPath(s), "...");
3041 XFlush(fl_get_display());
3042 owner->view()->buffer(
3043 bufferlist.loadLyXFile(s));
3044 owner->getMiniBuffer()->Set(_("Document"),
3051 s = AddName(lyxrc.document_path,
3052 "newfile" + tostr(++newfile_number) + ".lyx");
3054 while (bufferlist.exists(s) || fi.readable()) {
3056 s = AddName(lyxrc.document_path,
3057 "newfile" + tostr(newfile_number) +
3063 // The template stuff
3066 ProhibitInput(owner->view());
3067 string const fname = fileDlg.Select(_("Choose template"),
3068 lyxrc.template_path,
3070 AllowInput(owner->view());
3071 if (fname.empty()) return;
3075 // find a free buffer
3076 lyxerr.debug() << "Find a free buffer." << endl;
3077 owner->view()->buffer(bufferlist.newFile(s, templname));
3081 void LyXFunc::MenuOpen()
3083 string initpath = lyxrc.document_path;
3086 if (owner->view()->available()) {
3087 string const trypath = owner->buffer()->filepath;
3088 // If directory is writeable, use this as default.
3089 if (IsDirWriteable(trypath) == 1)
3094 ProhibitInput(owner->view());
3095 fileDlg.SetButton(0, _("Documents"), lyxrc.document_path);
3096 fileDlg.SetButton(1, _("Examples"),
3097 AddPath(system_lyxdir, "examples"));
3098 string filename = fileDlg.Select(_("Select Document to Open"),
3100 AllowInput(owner->view());
3102 // check selected filename
3103 if (filename.empty()) {
3104 owner->getMiniBuffer()->Set(_("Canceled."));
3108 // get absolute path of file and make sure the filename ends
3110 filename = MakeAbsPath(filename);
3111 if (!IsLyXFilename(filename))
3115 owner->getMiniBuffer()->Set(_("Opening document"),
3116 MakeDisplayPath(filename), "...");
3117 Buffer * openbuf = bufferlist.loadLyXFile(filename);
3119 owner->view()->buffer(openbuf);
3120 owner->getMiniBuffer()->Set(_("Document"),
3121 MakeDisplayPath(filename),
3124 owner->getMiniBuffer()->Set(_("Could not open document"),
3125 MakeDisplayPath(filename));
3130 // checks for running without gui are missing.
3131 void LyXFunc::doImport(string const & argument)
3134 string filename = split(argument, format, ' ');
3135 lyxerr.debug() << "LyXFunc::doImport: " << format
3136 << " file: " << filename << endl;
3138 if (filename.empty()) { // need user interaction
3139 string initpath = lyxrc.document_path;
3142 if (owner->view()->available()) {
3143 string const trypath = owner->buffer()->filepath;
3144 // If directory is writeable, use this as default.
3145 if (IsDirWriteable(trypath) == 1)
3150 ProhibitInput(owner->view());
3151 fileDlg.SetButton(0, _("Documents"), lyxrc.document_path);
3152 fileDlg.SetButton(1, _("Examples"),
3153 AddPath(system_lyxdir, "examples"));
3154 string const text = _("Select ") + formats.PrettyName(format)
3155 + _(" file to import");
3156 string const extension = "*." + formats.Extension(format);
3157 filename = fileDlg.Select(text, initpath, extension);
3158 AllowInput(owner->view());
3160 // check selected filename
3161 if (filename.empty())
3162 owner->getMiniBuffer()->Set(_("Canceled."));
3165 // still no filename? abort
3166 if (filename.empty())
3169 // get absolute path of file
3170 filename = MakeAbsPath(filename);
3172 string const lyxfile = ChangeExtension(filename, ".lyx");
3174 // Check if the document already is open
3175 if (bufferlist.exists(lyxfile)) {
3176 switch (AskConfirmation(_("Document is already open:"),
3177 MakeDisplayPath(lyxfile, 50),
3178 _("Do you want to close that document now?\n"
3179 "('No' will just switch to the open version)")))
3181 case 1: // Yes: close the document
3182 if (!bufferlist.close(bufferlist.getBuffer(lyxfile)))
3183 // If close is canceled, we cancel here too.
3186 case 2: // No: switch to the open document
3187 owner->view()->buffer(bufferlist.getBuffer(lyxfile));
3189 case 3: // Cancel: Do nothing
3190 owner->getMiniBuffer()->Set(_("Canceled."));
3195 // Check if a LyX document by the same root exists in filesystem
3196 FileInfo const f(lyxfile, true);
3197 if (f.exist() && !AskQuestion(_("A document by the name"),
3198 MakeDisplayPath(lyxfile),
3199 _("already exists. Overwrite?"))) {
3200 owner->getMiniBuffer()->Set(_("Canceled."));
3203 // filename should be valid now
3205 Importer::Import(owner, filename, format);
3209 void LyXFunc::MenuInsertLyXFile(string const & filen)
3211 string filename = filen;
3213 if (filename.empty()) {
3214 // Launch a file browser
3215 string initpath = lyxrc.document_path;
3218 if (owner->view()->available()) {
3219 string const trypath = owner->buffer()->filepath;
3220 // If directory is writeable, use this as default.
3221 if (IsDirWriteable(trypath) == 1)
3226 ProhibitInput(owner->view());
3227 fileDlg.SetButton(0, _("Documents"), lyxrc.document_path);
3228 fileDlg.SetButton(1, _("Examples"),
3229 AddPath(system_lyxdir, "examples"));
3230 filename = fileDlg.Select(_("Select Document to Insert"),
3232 AllowInput(owner->view());
3234 // check selected filename
3235 if (filename.empty()) {
3236 owner->getMiniBuffer()->Set(_("Canceled."));
3241 // get absolute path of file and make sure the filename ends
3243 filename = MakeAbsPath(filename);
3244 if (!IsLyXFilename(filename))
3248 owner->getMiniBuffer()->Set(_("Inserting document"),
3249 MakeDisplayPath(filename), "...");
3250 bool const res = owner->view()->insertLyXFile(filename);
3252 owner->getMiniBuffer()->Set(_("Document"),
3253 MakeDisplayPath(filename),
3256 owner->getMiniBuffer()->Set(_("Could not insert document"),
3257 MakeDisplayPath(filename));
3262 void LyXFunc::reloadBuffer()
3264 string const fn = owner->buffer()->fileName();
3265 if (bufferlist.close(owner->buffer()))
3266 owner->view()->buffer(bufferlist.loadLyXFile(fn));
3270 void LyXFunc::CloseBuffer()
3272 if (bufferlist.close(owner->buffer()) && !quitting) {
3273 if (bufferlist.empty()) {
3274 // need this otherwise SEGV may occur while trying to
3275 // set variables that don't exist
3276 // since there's no current buffer
3277 owner->getDialogs()->hideBufferDependent();
3279 owner->view()->buffer(bufferlist.first());
3285 Inset * LyXFunc::getInsetByCode(Inset::Code code)
3287 LyXCursor cursor = owner->view()->text->cursor;
3288 Buffer * buffer = owner->view()->buffer();
3289 Buffer::inset_iterator it =
3290 find_if(Buffer::inset_iterator(cursor.par(),
3292 buffer->inset_iterator_end(),
3293 compare_memfun(&Inset::LyxCode, code));
3294 return it != buffer->inset_iterator_end() ? (*it) : 0;
3298 // Each "owner" should have it's own message method. lyxview and
3299 // the minibuffer would use the minibuffer, but lyxserver would
3300 // send an ERROR signal to its client. Alejandro 970603
3301 // This func is bit problematic when it comes to NLS, to make the
3302 // lyx servers client be language indepenent we must not translate
3303 // strings sent to this func.
3304 void LyXFunc::setErrorMessage(string const & m) const
3306 dispatch_buffer = m;
3311 void LyXFunc::setMessage(string const & m)
3313 dispatch_buffer = m;