1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-1999 The LyX Team.
9 * ======================================================*/
18 #pragma implementation
21 #include "definitions.h"
22 #include "lyxlookup.h"
25 #include "bufferlist.h"
26 #include "lyxserver.h"
31 #include "insets/insetlatex.h"
32 #include "insets/inseturl.h"
33 #include "insets/insetlatexaccent.h"
34 #include "insets/insettoc.h"
35 #include "insets/insetlof.h"
36 #include "insets/insetloa.h"
37 #include "insets/insetlot.h"
38 #include "insets/insetref.h"
39 #include "insets/insetparent.h"
40 #include "mathed/formulamacro.h"
42 #include "spellchecker.h" // RVDK_PATCH_5
43 #include "minibuffer.h"
45 #include "insets/insetbib.h"
47 #include "insets/insetindex.h"
48 #include "insets/insetinclude.h"
50 #include "lyx_gui_misc.h"
51 #include "support/filetools.h"
52 #include "support/FileInfo.h"
53 #include "lyxscreen.h"
58 #include "trans_mgr.h"
59 #include "ImportLaTeX.h"
60 #include "ImportNoweb.h"
61 #include "support/syscall.h"
63 extern bool cursor_follows_scrollbar;
65 extern void InsertAsciiFile(string const &, bool);
66 extern void math_insert_symbol(char const*);
67 extern Bool math_insert_greek(char const); // why "Bool"?
68 extern BufferList bufferlist;
69 extern LyXServer *lyxserver;
70 extern short greek_kb_flag;
71 extern FD_form_toc *fd_form_toc;
72 extern bool selection_possible;
74 extern kb_keymap *toplevel_keymap;
76 extern void BeforeChange();
77 extern void MenuWrite(Buffer*);
78 extern void MenuWriteAs(Buffer*);
79 extern int MenuRunLaTeX(Buffer*);
80 extern int MenuBuildProg(Buffer*);
81 extern int MenuRunChktex(Buffer*);
82 extern bool MenuRunDvips(Buffer *,bool);
83 extern void MenuPrint(Buffer*);
84 extern void MenuSendto();
85 extern void QuitLyX();
86 extern void MenuFax(Buffer *);
87 extern void MenuMakeLaTeX(Buffer *);
88 extern void MenuMakeLinuxDoc(Buffer *);
89 extern void MenuMakeDocBook(Buffer *);
90 extern void MenuMakeAscii(Buffer *);
91 extern void MenuPasteSelection(char at);
92 extern LyXAction lyxaction;
94 extern tex_accent_struct get_accent(kb_action action);
96 extern void AutoSave();
97 extern void MenuSearch();
99 extern void CopyEnvironmentCB();
100 extern void PasteEnvironmentCB();
101 extern void GotoNote();
102 extern void NoteCB();
103 extern void OpenStuff();
104 extern void HyphenationPoint();
106 extern void EndOfSentenceDot();
107 extern void MenuSeparator();
109 extern void MenuUndo();
110 extern void MenuRedo();
111 extern void SmallUpdate(signed char);
112 extern void SetUpdateTimer(float timer= 0.3);
113 extern void FreeUpdateTimer();
114 extern bool MenuPreview(Buffer*);
115 extern bool MenuPreviewPS(Buffer*);
116 extern void MenuInsertLabel(const char *);
117 extern void MenuInsertRef();
118 extern void MenuLayoutCharacter();
119 extern void MenuLayoutParagraph();
120 extern void MenuLayoutDocument();
121 extern void MenuLayoutPaper();
122 extern void MenuLayoutTable(int flag);
123 extern void MenuLayoutQuotes();
124 extern void MenuLayoutPreamble();
125 extern void MenuLayoutSave();
126 extern void bulletForm();
128 extern Buffer * NewLyxFile(string const &);
129 extern void LoadLyXFile(string const &);
130 extern void Reconfigure();
132 extern int current_layout;
133 extern int getISOCodeFromLaTeX(char *);
135 extern int UnlockInset(UpdatableInset*);
137 extern void ShowLatexLog();
139 extern void UpdateInset(Inset* inset, bool mark_dirty = true);
141 /* === globals =========================================================== */
143 bool LyXFunc::show_sc = true;
146 LyXFunc::LyXFunc(LyXView *o)
150 lyx_dead_action = LFUN_NOACTION;
151 lyx_calling_dead_action = LFUN_NOACTION;
161 string LyXFunc::argAsString(char const * const argument)
163 string tmp(argument);
166 // get the arg from somewhere else, a popup, or ask for
167 // it in the minibuffer.
169 lyxerr.debug() << "argAsString: <" << tmp << '>' << endl;
174 // I changed this func slightly. I commented out the ...FinishUndo(),
175 // this means that all places that used to have a moveCursorUpdate, now
176 // have a ...FinishUndo() as the preceeding statement. I have also added
177 // a moveCursorUpdate to some of the functions that updated the cursor, but
178 // that did not show its new position.
180 void LyXFunc::moveCursorUpdate(bool selecting)
182 if (selecting || owner->currentBuffer()->text->mark_set) {
183 owner->currentBuffer()->text->SetSelection();
184 owner->currentView()->getScreen()->ToggleToggle();
185 owner->currentBuffer()->update(0);
187 owner->currentBuffer()->update(-2); // this IS necessary
190 owner->currentView()->getScreen()->ShowCursor();
192 /* ---> Everytime the cursor is moved, show the current font state. */
193 // should this too me moved out of this func?
194 //owner->getMiniBuffer()->Set(CurrentState());
198 int LyXFunc::processKeyEvent(XEvent *ev)
205 XKeyEvent *keyevent = &ev->xkey;
206 KeySym keysym_return;
208 num_bytes = LyXLookupString(ev, s_r, 10, &keysym_return);
210 if (lyxerr.debugging(Debug::KEY)) {
211 lyxerr << "KeySym is "
212 << XKeysymToString(keysym_return)
214 << keysym_return << "]"
215 << " and num_bytes is "
217 << " the string returned is \""
218 << s_r << '\"' << endl;
220 // Do nothing if we have nothing (JMarc)
221 if (num_bytes == 0 && keysym_return == NoSymbol) {
222 lyxerr[Debug::KEY] << "Empty kbd action (probably composing)"
227 // this function should be used always [asierra060396]
228 if (owner->currentView()->available() &&
229 owner->currentBuffer()->the_locking_inset &&
230 keysym_return == XK_Escape) {
231 UnlockInset(owner->currentBuffer()->the_locking_inset);
232 owner->currentBuffer()->text->CursorRight();
236 // Can we be sure that this will work for all X-Windows
237 // implementations? (Lgb)
238 // This code snippet makes lyx ignore some keys. Perhaps
239 // all of them should be explictly mentioned?
240 if((keysym_return >= XK_Shift_L && keysym_return <= XK_Hyper_R)
241 || keysym_return == XK_Mode_switch || keysym_return == 0x0)
244 // Do a one-deep top-level lookup for
245 // cancel and meta-fake keys. RVDK_PATCH_5
246 cancel_meta_seq.reset();
248 action = cancel_meta_seq.addkey(keysym_return, keyevent->state
249 &(ShiftMask|ControlMask
252 // When not cancel or meta-fake, do the normal lookup.
253 // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
254 // Mostly, meta_fake_bit = 0. RVDK_PATCH_5.
255 if ( (action != LFUN_CANCEL) && (action != LFUN_META_FAKE) ) {
257 // remove Caps Lock and Mod2 as a modifiers
258 action = keyseq.addkey(keysym_return,
259 (keyevent->state | meta_fake_bit)
260 &(ShiftMask|ControlMask
263 // Dont remove this unless you know what you are doing.
266 if (action == 0) action = LFUN_PREFIX;
268 if (lyxerr.debugging(Debug::KEY)) {
270 keyseq.print(buf,100);
274 << num_bytes << "]" << endl;
277 // already here we know if it any point in going further
278 // why not return already here if action == -1 and
279 // num_bytes == 0? (Lgb)
281 if(keyseq.length>1 || keyseq.length<-1){
283 keyseq.print(buf,100);
284 owner->getMiniBuffer()->Set(buf);
288 if (keyseq.length<-1) { // unknown key sequence...
291 keyseq.print(buf,100);
292 owner->getMiniBuffer()->Set(_("Unknown sequence:"),buf);
296 char isochar = keyseq.getiso();
297 if (!(keyevent->state&ControlMask) &&
298 !(keyevent->state&Mod1Mask) &&
299 (isochar && keysym_return < 0xF000)) {
300 argument = &s_r[0]; // shall this be here
301 argument[0] = isochar;
305 lyxerr.debug() << "Empty argument!" << endl;
306 // This can`t possibly be of any use
307 // so we`ll skip the dispatch.
311 if (action==LFUN_SELFINSERT) {
316 bool tmp_sc = show_sc;
318 Dispatch(action, argument);
321 // Need this for deadkeys (alkis)
323 // ...but that breaks the minibuffer's display of "M-"...
325 #warning How does the deadkeys react to this?
331 string LyXFunc::Dispatch(string const &cmd, string const &arg)
333 return Dispatch(lyxaction.LookupFunc(cmd.c_str()),
338 string LyXFunc::Dispatch(int ac,
339 char const *do_not_use_this_arg)
341 char const * argument = 0;
345 FL_OBJECT *ob = 0; // This will disapear soon
347 // we have not done anything wrong yet.
349 dispatch_buffer = string();
351 // if action is a pseudo-action, we need the real action
352 if (lyxaction.isPseudoAction(ac)) {
353 char const *tmparg = 0;
354 action = (kb_action)lyxaction.retrieveActionArg(ac, &tmparg);
358 action = (kb_action)ac;
359 argument = do_not_use_this_arg; // except here
362 selection_possible = false;
364 if (owner->currentView()->available()
365 && owner->currentView()->getScreen())
366 owner->currentView()->getScreen()->HideCursor();
368 if(!owner->currentView()->available()) {
369 // This lists the allowed funcs when we have no
372 case LFUN_MENU_OPEN_BY_NAME:
375 case LFUN_MENUNEWTMPLT:
378 case LFUN_PUSH_TOOLBAR:
379 case LFUN_ADD_TO_TOOLBAR:
380 case LFUN_EXEC_COMMAND:
381 case LFUN_DROP_LAYOUTS_CHOICE:
385 case LFUN_RECONFIGURE:
391 case LFUN_UNKNOWN_ACTION:
392 setErrorMessage(N_("Unknown action"));
393 goto exit_with_message;
395 setErrorMessage(N_("Command not allowed with"
396 "out any document open"));
397 goto exit_with_message; // action not allowed
401 commandshortcut = string();
403 if (lyxrc->display_shortcuts && show_sc) {
404 if (action != LFUN_SELFINSERT) {
405 // Put name of command and list of shortcuts
406 // for it in minibuffer
407 string comname = lyxaction.getActionName(action);
409 int pseudoaction = action;
410 bool argsadded = false;
415 // If we have the command with argument,
418 lyxaction.searchActionArg(action,
421 if (pseudoaction == -1) {
422 pseudoaction = action;
424 comname += " " + argu;
429 string shortcuts = toplevel_keymap->findbinding(pseudoaction);
431 if (!shortcuts.empty()) {
432 comname += ": " + shortcuts;
433 } else if (!argsadded) {
434 comname += " " + argu;
437 if (!comname.empty()) {
438 comname = strip(comname);
439 commandshortcut = "(" + comname + ')';
440 owner->getMiniBuffer()->Set(commandshortcut);
441 // Here we could even add a small pause,
442 // to annoy the user and make him learn
444 // No! That will just annoy, not teach
445 // anything. The user will read the messages
446 // if they are interested. (Asger)
451 // Now that we know which action, if the buffer is RO let's check
452 // whether the action is legal. Alejandro 970603
453 if (owner->currentView()->available() &&
454 owner->currentBuffer()->isReadonly() &&
455 lyxaction.isFuncRO(action)) {
456 setErrorMessage(N_("Document is read-only"));
457 lyxerr.debug() << "Error: Document is read-only." << endl;
458 goto exit_with_message;
461 // If in math mode pass the control to
462 // the math inset [asierra060396]
463 if (owner->currentView()->available() &&
464 owner->currentBuffer()->the_locking_inset) {
465 if (action>1 || (action==LFUN_UNKNOWN_ACTION && keyseq.length>=-1)) {
467 if (action==LFUN_UNKNOWN_ACTION && !argument) {
468 sprintf(s, "%c", keyseq.getiso());
471 // Undo/Redo pre 0.13 is a bit tricky for insets.
472 if (action==LFUN_UNDO) {
474 UpdatableInset* inset =
475 owner->currentBuffer()->the_locking_inset;
476 inset->GetCursorPos(slx, sly);
479 inset = (UpdatableInset*)owner->currentBuffer()->text->cursor.par->GetInset(owner->currentBuffer()->text->cursor.pos);
481 inset->Edit(slx, sly);
484 if (action==LFUN_REDO) {
486 UpdatableInset* inset = owner->currentBuffer()->the_locking_inset;
487 inset->GetCursorPos(slx, sly);
490 inset = (UpdatableInset*)owner->currentBuffer()->text->cursor.par->GetInset(owner->currentBuffer()->text->cursor.pos);
492 inset->Edit(slx, sly);
495 if (owner->currentBuffer()->the_locking_inset->LocalDispatch(action, argument))
498 setMessage(N_("Text mode"));
499 if (action==LFUN_RIGHT || action==-1)
500 owner->currentBuffer()->text->CursorRight();
501 if (action==LFUN_LEFT || action==LFUN_RIGHT)
508 // --- Misc -------------------------------------------
509 case LFUN_WORDFINDFORWARD :
510 case LFUN_WORDFINDBACKWARD : {
512 static string last_search;
513 string searched_string;
515 string arg = argAsString(argument);
519 searched_string = arg;
521 searched_string = last_search;
524 ltCur = owner->currentView()->currentBuffer()->text ;
526 if (!searched_string.empty() &&
527 ( (action == LFUN_WORDFINDBACKWARD) ?
528 ltCur->SearchBackward( searched_string.c_str() ) :
529 ltCur->SearchForward( searched_string.c_str() )
532 // ??? What is that ???
533 owner->currentView()->currentBuffer()->update(-2);
536 // clear the selection (if there is any)
537 owner->currentView()->getScreen()->ToggleSelection();
538 owner->currentView()->currentBuffer()->text->ClearSelection();
540 // Move cursor so that successive C-s 's will not stand in place.
541 if( action == LFUN_WORDFINDFORWARD )
542 owner->currentBuffer()->text->CursorRightOneWord();
543 owner->currentBuffer()->text->FinishUndo();
544 moveCursorUpdate(false);
547 // set the new selection
548 // SetSelectionOverLenChars(owner->currentView()->currentBuffer()->text, iLenSelected);
549 owner->currentView()->getScreen()->ToggleSelection(false);
553 // REMOVED : if (owner->currentView()->getWorkArea()->focus)
554 owner->currentView()->getScreen()->ShowCursor();
560 if (owner->currentView()->available()
561 && owner->currentView()->getScreen()) {
562 owner->currentBuffer()->update(-2);
565 keyseq.print(buf,100, true);
566 owner->getMiniBuffer()->Set(buf, string(), string(), 1);
570 // --- Misc -------------------------------------------
571 case LFUN_EXEC_COMMAND:
572 owner->getMiniBuffer()->ExecCommand();
575 case LFUN_CANCEL: // RVDK_PATCH_5
578 if(owner->currentView()->available())
579 // cancel any selection
580 Dispatch(int(LFUN_MARK_OFF), 0);
581 setMessage(N_("Cancel"));
584 case LFUN_META_FAKE: // RVDK_PATCH_5
586 meta_fake_bit = Mod1Mask;
588 keyseq.print(buf, 98, true);
589 string res = string("M-") + buf;
590 setMessage(buf); // RVDK_PATCH_5
594 case LFUN_READ_ONLY_TOGGLE:
595 if (owner->currentBuffer()->lyxvc.inUse()) {
596 owner->currentBuffer()->lyxvc.toggleReadOnly();
598 owner->currentBuffer()->setReadonly(
599 !owner->currentBuffer()->isReadonly());
603 case LFUN_CENTER: // this is center and redraw.
605 if (owner->currentBuffer()->text->cursor.y >
606 owner->currentView()->getWorkArea()->h / 2) {
607 owner->currentView()->getScreen()->
608 Draw(owner->currentBuffer()->text->cursor.y -
609 owner->currentView()->getWorkArea()->h/2);
611 owner->currentView()->getScreen()->
614 owner->currentBuffer()->update(0);
615 owner->currentView()->redraw();
619 if (owner->currentView()->available()) {
620 owner->currentBuffer()->text->toggleAppendix();
621 owner->currentBuffer()->update(1);
625 // --- Menus -----------------------------------------------
630 case LFUN_MENUNEWTMPLT:
638 case LFUN_CLOSEBUFFER:
643 MenuWrite(owner->currentBuffer());
646 case LFUN_MENUWRITEAS:
647 MenuWriteAs(owner->currentBuffer());
650 case LFUN_MENURELOAD:
655 MenuPreview(owner->currentBuffer());
659 MenuPreviewPS(owner->currentBuffer());
663 MenuRunLaTeX(owner->currentBuffer());
667 MenuBuildProg(owner->currentBuffer());
671 MenuRunChktex(owner->currentBuffer());
675 MenuRunDvips(owner->currentBuffer(), false);
679 MenuPrint(owner->currentBuffer());
683 MenuFax(owner->currentBuffer());
688 //needs argument as string
689 string extyp=argAsString(argument);
692 if (extyp == "latex") {
693 // make sure that this buffer is not linuxdoc
694 MenuMakeLaTeX(owner->currentBuffer());
697 else if (extyp == "linuxdoc") {
698 // make sure that this buffer is not latex
699 MenuMakeLinuxDoc(owner->currentBuffer());
702 else if (extyp == "docbook") {
703 // make sure that this buffer is not latex or linuxdoc
704 MenuMakeDocBook(owner->currentBuffer());
707 else if (extyp == "dvi") {
708 // Run LaTeX as "Update dvi..." Bernhard.
709 // We want the dvi in the current directory. This
710 // is achieved by temporarily disabling use of
711 // temp directory. As a side-effect, we get
712 // *.log and *.aux files also. (Asger)
713 bool flag = lyxrc->use_tempdir;
714 lyxrc->use_tempdir = false;
715 MenuRunLaTeX(owner->currentBuffer());
716 lyxrc->use_tempdir = flag;
719 else if (extyp == "postscript") {
720 // Start Print-dialog. Not as good as dvi... Bernhard.
721 MenuPrint(owner->currentBuffer());
722 // Since the MenuPrint is a pop-up, we can't use
723 // the same trick as above. (Asger)
724 // MISSING: Move of ps-file :-(
727 else if (extyp == "ascii") {
728 MenuMakeAscii(owner->currentBuffer());
730 else if (extyp == "custom") {
735 else if (extyp == "html") {
736 // First, create LaTeX file
737 MenuMakeLaTeX(owner->currentBuffer());
740 string file = owner->currentBuffer()->getFileName();
741 file = ChangeExtension(file, ".tex", false);
742 string result = ChangeExtension(file, ".html", false);
743 string tmp = lyxrc->tth_command + " < " + file
746 int res = one.startscript(Systemcalls::System, tmp);
749 N_("Document exported as HTML to file: ")) + result);
751 setErrorMessage(string(
752 N_("An unexpected error occured while converting document to HTML in file:")) + result);
756 setErrorMessage(string(N_("Unknown export type: "))
764 //needs argument as string
765 string imtyp=argAsString(argument);
768 if (imtyp == "latex") {
769 doImportLaTeX(false);
772 else if (imtyp == "ascii") {
773 doImportASCII(false);
774 } else if (imtyp == "asciiparagraph") {
777 } else if (imtyp == "noweb") {
780 setErrorMessage(string(N_("Unknown import type: "))
792 if (fd_form_toc->form_toc->visible) {
793 fl_raise_form(fd_form_toc->form_toc);
795 fl_show_form(fd_form_toc->form_toc,
797 FL_FREE_SIZE, FL_FULLBORDER,
798 _("Table of Contents"));
802 case LFUN_TOC_INSERT:
805 new InsetTOC(owner->currentBuffer());
806 owner->currentBuffer()->insertInset(new_inset,
811 case LFUN_LOF_INSERT:
814 new InsetLOF(owner->currentBuffer());
815 owner->currentBuffer()->insertInset(new_inset,
820 case LFUN_LOA_INSERT:
823 new InsetLOA(owner->currentBuffer());
824 owner->currentBuffer()->insertInset(new_inset,
829 case LFUN_LOT_INSERT:
832 new InsetLOT(owner->currentBuffer());
833 owner->currentBuffer()->insertInset(new_inset,
858 case LFUN_MENUSEARCH:
866 case LFUN_PASTESELECTION:
869 if (string(argument) == "paragraph") asPara = true;
870 MenuPasteSelection(asPara);
882 case LFUN_LAYOUT_COPY:
886 case LFUN_LAYOUT_PASTE:
887 PasteEnvironmentCB();
891 owner->currentView()->gotoError();
894 case LFUN_REMOVEERRORS:
895 if (owner->currentBuffer()->removeAutoInsets()) {
896 owner->currentView()->redraw();
897 owner->currentView()->fitCursor();
898 owner->currentView()->updateScrollbar();
910 case LFUN_HYPHENATION:
918 case LFUN_END_OF_SENTENCE:
922 case LFUN_MENU_SEPARATOR:
938 case LFUN_DEPTH_PLUS:
954 case LFUN_RECONFIGURE:
959 if (owner->currentView()->available()
960 && !owner->currentBuffer()->text->selection
961 && owner->currentBuffer()->text->cursor.par->footnoteflag
962 != LyXParagraph::NO_FOOTNOTE)
963 { // only melt footnotes with FOOTMELT, not margins etc
964 if(owner->currentBuffer()->text->cursor.par->footnotekind == LyXParagraph::FOOTNOTE)
971 case LFUN_MARGINMELT:
972 if (owner->currentView()->available()
973 && !owner->currentBuffer()->text->selection
974 && owner->currentBuffer()->text->cursor.par->footnoteflag
975 != LyXParagraph::NO_FOOTNOTE)
976 { // only melt margins
977 if(owner->currentBuffer()->text->cursor.par->footnotekind == LyXParagraph::MARGIN)
984 // --- version control -------------------------------
985 case LFUN_VC_REGISTER:
987 if (!owner->currentBuffer()->lyxvc.inUse())
988 owner->currentBuffer()->lyxvc.registrer();
992 case LFUN_VC_CHECKIN:
994 if (owner->currentBuffer()->lyxvc.inUse()
995 && !owner->currentBuffer()->isReadonly())
996 owner->currentBuffer()->lyxvc.checkIn();
1000 case LFUN_VC_CHECKOUT:
1002 if (owner->currentBuffer()->lyxvc.inUse()
1003 && owner->currentBuffer()->isReadonly())
1004 owner->currentBuffer()->lyxvc.checkOut();
1008 case LFUN_VC_REVERT:
1010 owner->currentBuffer()->lyxvc.revert();
1016 owner->currentBuffer()->lyxvc.undoLast();
1020 case LFUN_VC_HISTORY:
1022 owner->currentBuffer()->lyxvc.showLog();
1026 // --- buffers ----------------------------------------
1027 case LFUN_PREVBUFFER:
1028 #ifdef WITH_WARNINGS
1029 #warning fix this please
1031 // it is the LyXView or the BufferView that should
1032 // remember the previous buffer, not bufferlist.
1033 // if (owner->currentView()->available()){
1035 // owner->currentBuffer()->update(-2);
1037 // owner->currentView()->setBuffer(bufferlist.prev());
1039 // owner->currentView()->
1040 // resizeCurrentBufferPseudoExpose();
1043 case LFUN_FILE_INSERT:
1045 // needs argument as string
1046 string fil = argAsString(argument);
1047 MenuInsertLyXFile(fil);
1051 case LFUN_FILE_INSERT_ASCII:
1053 bool asPara = false;
1054 asPara = (string(argument) == "paragraph");
1055 InsertAsciiFile(string(), asPara);
1061 // servercmd: argument must be <file>:<template>
1062 Buffer * tmpbuf = 0;
1063 tmpbuf = NewLyxFile(argument);
1065 owner->currentView()->setBuffer(tmpbuf);
1069 case LFUN_FILE_OPEN:
1070 owner->currentView()->setBuffer(
1071 bufferlist.loadLyXFile(argument));
1074 case LFUN_LATEX_LOG:
1080 lyxerr.debug() << "LFUN_LAYOUTNO: (arg) " << argument << endl;
1081 int sel = atoi(argument);
1082 lyxerr.debug() << "LFUN_LAYOUTNO: (sel) "<< sel << endl;
1084 // Should this give a setMessage instead?
1086 return string(); // illegal argument
1088 sel--; // sel 1..., but layout 0...
1090 // Pretend we got the name instead.
1091 Dispatch(int(LFUN_LAYOUT),
1092 lyxstyle.NameOfLayout(owner->currentBuffer()->
1101 lyxerr.debug() << "LFUN_LAYOUT: (arg) "
1102 << argument << endl;
1104 // Derive layout number from given argument (string)
1105 // and current buffer's textclass (number). */
1108 lyxstyle.NumberOfLayout(owner->
1114 // see if we found the layout number:
1115 if (layoutno == -1) {
1116 setErrorMessage(string(N_("Layout ")) + argument +
1121 if (current_layout != layoutno) {
1122 owner->currentView()->getScreen()->HideCursor();
1123 current_layout = layoutno;
1124 owner->currentBuffer()->update(-2);
1125 owner->currentBuffer()->text->
1126 SetLayout(layoutno);
1127 owner->getToolbar()->combox->
1128 select(owner->currentBuffer()->
1131 owner->currentBuffer()->update(1);
1136 case LFUN_LAYOUT_DOCUMENT:
1137 MenuLayoutDocument();
1140 case LFUN_LAYOUT_PARAGRAPH:
1141 MenuLayoutParagraph();
1144 case LFUN_LAYOUT_CHARACTER:
1145 MenuLayoutCharacter();
1148 case LFUN_LAYOUT_TABLE:
1151 if (string(argument) == "true") flag = 1;
1152 MenuLayoutTable(flag);
1156 case LFUN_LAYOUT_PAPER:
1160 case LFUN_LAYOUT_QUOTES:
1164 case LFUN_LAYOUT_PREAMBLE:
1165 MenuLayoutPreamble();
1168 case LFUN_LAYOUT_SAVE_DEFAULT:
1172 case LFUN_DROP_LAYOUTS_CHOICE:
1173 owner->getToolbar()->combox->Show();
1204 case LFUN_UNDERLINE:
1208 case LFUN_FONT_SIZE:
1209 FontSizeCB(argument);
1212 case LFUN_FONT_STATE:
1213 setMessage(CurrentState());
1216 case LFUN_UPCASE_WORD:
1217 owner->currentBuffer()->update(-2);
1219 owner->currentBuffer()->text->ChangeWordCase(2);
1220 owner->currentBuffer()->update(1);
1224 case LFUN_LOWCASE_WORD:
1225 owner->currentBuffer()->update(-2);
1227 owner->currentBuffer()->text->ChangeWordCase(0);
1228 owner->currentBuffer()->update(1);
1232 case LFUN_CAPITALIZE_WORD:
1233 owner->currentBuffer()->update(-2);
1235 owner->currentBuffer()->text->ChangeWordCase(1);
1236 owner->currentBuffer()->update(1);
1240 case LFUN_INSERT_LABEL:
1241 MenuInsertLabel(argument);
1244 case LFUN_INSERT_REF:
1248 case LFUN_REFTOGGLE:
1251 (InsetRef*)getInsetByCode(Inset::REF_CODE);
1253 if (inset->getFlag()==InsetRef::REF)
1254 inset->setFlag(InsetRef::PAGE_REF);
1256 inset->setFlag(InsetRef::REF);
1259 setErrorMessage(N_("No cross-reference to toggle"));
1266 owner->currentView()->restorePosition();
1272 string label(argument);
1273 if (label.empty()) {
1275 (InsetRef*)getInsetByCode(Inset::REF_CODE);
1277 label = inset->getContents();
1280 if (!label.empty()) {
1281 owner->currentView()->savePosition();
1282 owner->currentBuffer()->gotoLabel(label.c_str());
1287 case LFUN_MENU_OPEN_BY_NAME:
1288 owner->getMenus()->openByName(argument);
1289 break; // RVDK_PATCH_5
1291 case LFUN_SPELLCHECK:
1292 if (lyxrc->isp_command != "none")
1294 break; // RVDK_PATCH_5
1296 // --- Cursor Movements -----------------------------
1299 Buffer *tmpbuffer = owner->currentBuffer();
1300 LyXText *tmptext = owner->currentBuffer()->text;
1301 if(!tmptext->mark_set)
1303 tmpbuffer->update(-2);
1304 if (tmptext->cursor.pos < tmptext->cursor.par->Last()
1305 && tmptext->cursor.par->GetChar(tmptext->cursor.pos)
1307 && tmptext->cursor.par->GetInset(tmptext->cursor.pos)
1308 && tmptext->cursor.par->GetInset(tmptext->cursor.pos)->Editable()==2){
1309 Inset* tmpinset = tmptext->cursor.par->GetInset(tmptext->cursor.pos);
1310 setMessage(tmpinset->EditMessage());
1311 tmpinset->Edit(0,0);
1314 tmptext->CursorRight();
1315 owner->currentBuffer()->text->FinishUndo();
1316 moveCursorUpdate(false);
1317 owner->getMiniBuffer()->Set(CurrentState());
1323 // This is soooo ugly. Isn`t it possible to make
1324 // it simpler? (Lgb)
1325 LyXText *txt= owner->currentBuffer()->text;
1326 if(!txt->mark_set) BeforeChange();
1327 owner->currentBuffer()->update(-2);
1329 if (txt->cursor.pos < txt->cursor.par->Last()
1330 && txt->cursor.par->GetChar(txt->cursor.pos)
1332 && txt->cursor.par->GetInset(txt->cursor.pos)
1333 && txt->cursor.par->GetInset(txt->cursor.pos)->Editable()==2) {
1334 Inset* tmpinset = txt->cursor.par->GetInset(txt->cursor.pos);
1335 setMessage(tmpinset->EditMessage());
1336 tmpinset->Edit(tmpinset->Width(txt->GetFont(txt->cursor.par,
1337 txt->cursor.pos)),0);
1338 // tmpinset->Edit(-1, 0); // -1 means go rightmost
1341 owner->currentBuffer()->text->FinishUndo();
1342 moveCursorUpdate(false);
1343 owner->getMiniBuffer()->Set(CurrentState());
1348 if(!owner->currentBuffer()->text->mark_set) BeforeChange();
1349 owner->currentBuffer()->update(-3);
1350 owner->currentBuffer()->text->CursorUp();
1351 owner->currentBuffer()->text->FinishUndo();
1352 moveCursorUpdate(false);
1353 owner->getMiniBuffer()->Set(CurrentState());
1357 if(!owner->currentBuffer()->text->mark_set)
1359 owner->currentBuffer()->update(-3);
1360 owner->currentBuffer()->text->CursorDown();
1361 owner->currentBuffer()->text->FinishUndo();
1362 moveCursorUpdate(false);
1363 owner->getMiniBuffer()->Set(CurrentState());
1366 case LFUN_UP_PARAGRAPH:
1367 if(!owner->currentBuffer()->text->mark_set)
1369 owner->currentBuffer()->update(-3);
1370 owner->currentBuffer()->text->CursorUpParagraph();
1371 owner->currentBuffer()->text->FinishUndo();
1372 moveCursorUpdate(false);
1373 owner->getMiniBuffer()->Set(CurrentState());
1376 case LFUN_DOWN_PARAGRAPH:
1377 if(!owner->currentBuffer()->text->mark_set)
1379 owner->currentBuffer()->update(-3);
1380 owner->currentBuffer()->text->CursorDownParagraph();
1381 owner->currentBuffer()->text->FinishUndo();
1382 moveCursorUpdate(false);
1383 owner->getMiniBuffer()->Set(CurrentState());
1387 if(!owner->currentBuffer()->text->mark_set)
1389 owner->currentBuffer()->update(-3);
1390 owner->currentView()->cursorPrevious();
1391 owner->currentBuffer()->text->FinishUndo();
1392 moveCursorUpdate(false);
1393 owner->getMiniBuffer()->Set(CurrentState());
1397 if(!owner->currentBuffer()->text->mark_set)
1399 owner->currentBuffer()->update(-3);
1400 owner->currentView()->cursorNext();
1401 owner->currentBuffer()->text->FinishUndo();
1402 moveCursorUpdate(false);
1403 owner->getMiniBuffer()->Set(CurrentState());
1407 if(!owner->currentBuffer()->text->mark_set)
1409 owner->currentBuffer()->update(-2);
1410 owner->currentBuffer()->text->CursorHome();
1411 owner->currentBuffer()->text->FinishUndo();
1412 moveCursorUpdate(false);
1413 owner->getMiniBuffer()->Set(CurrentState());
1417 if(!owner->currentBuffer()->text->mark_set)
1419 owner->currentBuffer()->update(-2);
1420 owner->currentBuffer()->text->CursorEnd();
1421 owner->currentBuffer()->text->FinishUndo();
1422 moveCursorUpdate(false);
1423 owner->getMiniBuffer()->Set(CurrentState());
1427 if(!owner->currentBuffer()->text->mark_set)
1429 owner->currentBuffer()->update(-2);
1430 owner->currentBuffer()->text->CursorTab();
1431 owner->currentBuffer()->text->FinishUndo();
1432 moveCursorUpdate(false);
1433 owner->getMiniBuffer()->Set(CurrentState());
1436 case LFUN_WORDRIGHT:
1437 if(!owner->currentBuffer()->text->mark_set)
1439 owner->currentBuffer()->update(-2);
1440 owner->currentBuffer()->text->CursorRightOneWord();
1441 owner->currentBuffer()->text->FinishUndo();
1442 moveCursorUpdate(false);
1443 owner->getMiniBuffer()->Set(CurrentState());
1447 if(!owner->currentBuffer()->text->mark_set)
1449 owner->currentBuffer()->update(-2);
1450 owner->currentBuffer()->text->CursorLeftOneWord();
1451 owner->currentBuffer()->text->FinishUndo();
1452 moveCursorUpdate(false);
1453 owner->getMiniBuffer()->Set(CurrentState());
1456 case LFUN_BEGINNINGBUF:
1457 if(!owner->currentBuffer()->text->mark_set)
1459 owner->currentBuffer()->update(-2);
1460 owner->currentBuffer()->text->CursorTop();
1461 owner->currentBuffer()->text->FinishUndo();
1462 moveCursorUpdate(false);
1463 owner->getMiniBuffer()->Set(CurrentState());
1467 if(!owner->currentBuffer()->text->mark_set)
1469 owner->currentBuffer()->update(-2);
1470 owner->currentBuffer()->text->CursorBottom();
1471 owner->currentBuffer()->text->FinishUndo();
1472 moveCursorUpdate(false);
1473 owner->getMiniBuffer()->Set(CurrentState());
1477 /* cursor selection ---------------------------- */
1479 owner->currentBuffer()->update(-2);
1480 owner->currentBuffer()->text->CursorRight();
1481 owner->currentBuffer()->text->FinishUndo();
1482 moveCursorUpdate(true);
1483 owner->getMiniBuffer()->Set(CurrentState());
1487 owner->currentBuffer()->update(-2);
1488 owner->currentBuffer()->text->CursorLeft();
1489 owner->currentBuffer()->text->FinishUndo();
1490 moveCursorUpdate(true);
1491 owner->getMiniBuffer()->Set(CurrentState());
1495 owner->currentBuffer()->update(-2);
1496 owner->currentBuffer()->text->CursorUp();
1497 owner->currentBuffer()->text->FinishUndo();
1498 moveCursorUpdate(true);
1499 owner->getMiniBuffer()->Set(CurrentState());
1503 owner->currentBuffer()->update(-2);
1504 owner->currentBuffer()->text->CursorDown();
1505 owner->currentBuffer()->text->FinishUndo();
1506 moveCursorUpdate(true);
1507 owner->getMiniBuffer()->Set(CurrentState());
1510 case LFUN_UP_PARAGRAPHSEL:
1511 owner->currentBuffer()->update(-2);
1512 owner->currentBuffer()->text->CursorUpParagraph();
1513 owner->currentBuffer()->text->FinishUndo();
1514 moveCursorUpdate(true);
1515 owner->getMiniBuffer()->Set(CurrentState());
1518 case LFUN_DOWN_PARAGRAPHSEL:
1519 owner->currentBuffer()->update(-2);
1520 owner->currentBuffer()->text->CursorDownParagraph();
1521 owner->currentBuffer()->text->FinishUndo();
1522 moveCursorUpdate(true);
1523 owner->getMiniBuffer()->Set(CurrentState());
1527 owner->currentBuffer()->update(-2);
1528 owner->currentView()->cursorPrevious();
1529 owner->currentBuffer()->text->FinishUndo();
1530 moveCursorUpdate(true);
1531 owner->getMiniBuffer()->Set(CurrentState());
1535 owner->currentBuffer()->update(-2);
1536 owner->currentView()->cursorNext();
1537 owner->currentBuffer()->text->FinishUndo();
1538 moveCursorUpdate(true);
1539 owner->getMiniBuffer()->Set(CurrentState());
1543 owner->currentBuffer()->update(-2);
1544 owner->currentBuffer()->text->CursorHome();
1545 owner->currentBuffer()->text->FinishUndo();
1546 moveCursorUpdate(true);
1547 owner->getMiniBuffer()->Set(CurrentState());
1551 owner->currentBuffer()->update(-2);
1552 owner->currentBuffer()->text->CursorEnd();
1553 owner->currentBuffer()->text->FinishUndo();
1554 moveCursorUpdate(true);
1555 owner->getMiniBuffer()->Set(CurrentState());
1558 case LFUN_WORDRIGHTSEL:
1559 owner->currentBuffer()->update(-2);
1560 owner->currentBuffer()->text->CursorRightOneWord();
1561 owner->currentBuffer()->text->FinishUndo();
1562 moveCursorUpdate(true);
1563 owner->getMiniBuffer()->Set(CurrentState());
1566 case LFUN_WORDLEFTSEL:
1567 owner->currentBuffer()->update(-2);
1568 owner->currentBuffer()->text->CursorLeftOneWord();
1569 owner->currentBuffer()->text->FinishUndo();
1570 moveCursorUpdate(true);
1571 owner->getMiniBuffer()->Set(CurrentState());
1574 case LFUN_BEGINNINGBUFSEL:
1575 owner->currentBuffer()->update(-2);
1576 owner->currentBuffer()->text->CursorTop();
1577 owner->currentBuffer()->text->FinishUndo();
1578 moveCursorUpdate(true);
1579 owner->getMiniBuffer()->Set(CurrentState());
1582 case LFUN_ENDBUFSEL:
1583 owner->currentBuffer()->update(-2);
1584 owner->currentBuffer()->text->CursorBottom();
1585 owner->currentBuffer()->text->FinishUndo();
1586 moveCursorUpdate(true);
1587 owner->getMiniBuffer()->Set(CurrentState());
1590 // --- text changing commands ------------------------
1591 case LFUN_BREAKLINE:
1593 owner->currentBuffer()->text->InsertChar(LYX_META_NEWLINE);
1595 SetUpdateTimer(0.01);
1596 moveCursorUpdate(false);
1599 case LFUN_PROTECTEDSPACE:
1601 owner->currentBuffer()->text->
1602 InsertChar(LYX_META_PROTECTED_SEPARATOR);
1605 moveCursorUpdate(false);
1609 if(owner->currentBuffer()->text->mark_set) {
1611 owner->currentBuffer()->update(0);
1612 setMessage(N_("Mark removed"));
1615 owner->currentBuffer()->text->mark_set = 1;
1616 owner->currentBuffer()->update(0);
1617 setMessage(N_("Mark set"));
1619 owner->currentBuffer()->text->sel_cursor =
1620 owner->currentBuffer()->text->cursor;
1625 if (!owner->currentBuffer()->text->selection) {
1626 owner->currentBuffer()->text->Delete();
1627 owner->currentBuffer()->text->sel_cursor =
1628 owner->currentBuffer()->text->cursor;
1630 // It is possible to make it a lot faster still
1631 // just comment out the lone below...
1632 owner->currentView()->getScreen()->ShowCursor();
1639 case LFUN_DELETE_SKIP:
1641 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
1643 LyXCursor cursor = owner->currentBuffer()->text->cursor;
1646 if (!owner->currentBuffer()->text->selection) {
1647 if (cursor.pos == cursor.par->Last()) {
1648 owner->currentBuffer()->text->CursorRight();
1649 cursor = owner->currentBuffer()->text->cursor;
1651 && !(cursor.par->added_space_top
1652 == VSpace (VSpace::NONE))) {
1653 owner->currentBuffer()->text->SetParagraph
1654 (cursor.par->line_top,
1655 cursor.par->line_bottom,
1656 cursor.par->pagebreak_top,
1657 cursor.par->pagebreak_bottom,
1658 VSpace(VSpace::NONE),
1659 cursor.par->added_space_bottom,
1661 cursor.par->labelwidthstring, 0);
1662 owner->currentBuffer()->text->CursorLeft();
1663 owner->currentBuffer()->update (1);
1665 owner->currentBuffer()->text->CursorLeft();
1666 owner->currentBuffer()->text->Delete();
1667 owner->currentBuffer()->text->sel_cursor =
1668 owner->currentBuffer()->text->cursor;
1672 owner->currentBuffer()->text->Delete();
1673 owner->currentBuffer()->text->sel_cursor =
1674 owner->currentBuffer()->text->cursor;
1684 /* -------> Delete word forward. */
1685 case LFUN_DELETE_WORD_FORWARD:
1686 owner->currentBuffer()->update(-2);
1688 owner->currentBuffer()->text->DeleteWordForward();
1689 owner->currentBuffer()->update( 1 );
1691 moveCursorUpdate(false);
1694 /* -------> Delete word backward. */
1695 case LFUN_DELETE_WORD_BACKWARD:
1696 owner->currentBuffer()->update(-2);
1698 owner->currentBuffer()->text->DeleteWordBackward();
1699 owner->currentBuffer()->update( 1 );
1701 moveCursorUpdate(false);
1704 /* -------> Kill to end of line. */
1705 case LFUN_DELETE_LINE_FORWARD:
1707 owner->currentBuffer()->update(-2);
1708 owner->currentBuffer()->text->DeleteLineForward();
1709 owner->currentBuffer()->update( 1 );
1711 moveCursorUpdate(false);
1714 /* -------> Set mark off. */
1717 owner->currentBuffer()->update(0);
1718 owner->currentBuffer()->text->sel_cursor =
1719 owner->currentBuffer()->text->cursor;
1720 setMessage(N_("Mark off"));
1723 /* -------> Set mark on. */
1726 owner->currentBuffer()->text->mark_set = 1;
1727 owner->currentBuffer()->update( 0 );
1728 owner->currentBuffer()->text->sel_cursor =
1729 owner->currentBuffer()->text->cursor;
1730 setMessage(N_("Mark on"));
1733 case LFUN_BACKSPACE:
1736 if (!owner->currentBuffer()->text->selection) {
1737 if (owner->getIntl()->getTrans()->backspace()) {
1738 owner->currentBuffer()->text->Backspace();
1739 owner->currentBuffer()->text->sel_cursor =
1740 owner->currentBuffer()->text->cursor;
1742 // It is possible to make it a lot faster still
1743 // just comment out the lone below...
1744 owner->currentView()->getScreen()->ShowCursor();
1753 case LFUN_BACKSPACE_SKIP:
1755 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
1757 LyXCursor cursor = owner->currentBuffer()->text->cursor;
1760 if (!owner->currentBuffer()->text->selection) {
1762 && !(cursor.par->added_space_top
1763 == VSpace (VSpace::NONE))) {
1764 owner->currentBuffer()->text->SetParagraph
1765 (cursor.par->line_top,
1766 cursor.par->line_bottom,
1767 cursor.par->pagebreak_top,
1768 cursor.par->pagebreak_bottom,
1769 VSpace(VSpace::NONE), cursor.par->added_space_bottom,
1771 cursor.par->labelwidthstring, 0);
1772 owner->currentBuffer()->update (1);
1774 owner->currentBuffer()->text->Backspace();
1775 owner->currentBuffer()->text->sel_cursor
1785 case LFUN_BREAKPARAGRAPH:
1788 owner->currentBuffer()->text->BreakParagraph(0);
1790 SetUpdateTimer(0.01);
1791 owner->currentBuffer()->text->sel_cursor =
1792 owner->currentBuffer()->text->cursor;
1796 case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
1799 owner->currentBuffer()->text->BreakParagraph(1);
1801 SetUpdateTimer(0.01);
1802 owner->currentBuffer()->text->sel_cursor =
1803 owner->currentBuffer()->text->cursor;
1807 case LFUN_BREAKPARAGRAPH_SKIP:
1809 // When at the beginning of a paragraph, remove
1810 // indentation and add a "defskip" at the top.
1811 // Otherwise, do the same as LFUN_BREAKPARAGRAPH.
1813 LyXCursor cursor = owner->currentBuffer()->text->cursor;
1816 if (cursor.pos == 0) {
1817 if (cursor.par->added_space_top == VSpace(VSpace::NONE)) {
1818 owner->currentBuffer()->text->SetParagraph
1819 (cursor.par->line_top,
1820 cursor.par->line_bottom,
1821 cursor.par->pagebreak_top,
1822 cursor.par->pagebreak_bottom,
1823 VSpace(VSpace::DEFSKIP), cursor.par->added_space_bottom,
1825 cursor.par->labelwidthstring, 1);
1826 owner->currentBuffer()->update(1);
1830 owner->currentBuffer()->text->BreakParagraph(0);
1833 SetUpdateTimer(0.01);
1834 owner->currentBuffer()->text->sel_cursor = cursor;
1840 owner->currentBuffer()->text->InsertChar('\"'); // This " matches the single quote in the code
1843 moveCursorUpdate(false);
1849 InsetCommand *new_inset;
1850 if (action == LFUN_HTMLURL)
1851 new_inset = new InsetUrl("htmlurl", "", "");
1853 new_inset = new InsetUrl("url", "", "");
1854 owner->currentBuffer()->insertInset(new_inset);
1855 new_inset->Edit(0, 0);
1859 // --- lyxserver commands ----------------------------
1861 case LFUN_CHARATCURSOR:
1863 int pos = owner->currentBuffer()->text->cursor.pos;
1864 if(pos < owner->currentBuffer()->text->cursor.par->last)
1865 dispatch_buffer = owner->currentBuffer()->text->
1866 cursor.par->text[pos];
1868 dispatch_buffer = "EOF";
1874 tostr(owner->currentBuffer()->text->cursor.x) + ' '
1875 + tostr(owner->currentBuffer()->text->cursor.y);
1882 sscanf(argument, " %d %ld", &x, &y);
1883 owner->currentBuffer()->text->SetCursorFromCoordinates(x, y);
1887 case LFUN_GETLAYOUT:
1889 tostr(owner->currentBuffer()->text->cursor.par->layout);
1894 LyXFont *font = &(owner->currentBuffer()->text->current_font);
1895 if(font->shape() == LyXFont::ITALIC_SHAPE)
1896 dispatch_buffer = 'E';
1897 else if(font->shape() == LyXFont::SMALLCAPS_SHAPE)
1898 dispatch_buffer = 'N';
1900 dispatch_buffer = '0';
1907 LyXFont *font = &(owner->currentBuffer()->text->current_font);
1908 if(font->latex() == LyXFont::ON)
1909 dispatch_buffer = 'L';
1911 dispatch_buffer = '0';
1916 setMessage(owner->currentBuffer()->getFileName());
1917 lyxerr.debug() << "FNAME["
1918 << owner->currentBuffer()->getFileName()
1925 keyseq.print(buf,100);
1926 dispatch_buffer = buf;
1927 lyxserver->notifyClient(dispatch_buffer);
1931 case LFUN_GOTOFILEROW:
1933 char file_name[100];
1935 sscanf(argument, " %s %d", file_name, &row);
1937 // Must replace extension of the file to be .lyx and get full path
1938 string s = ChangeExtension(string(file_name), ".lyx", false);
1940 // Either change buffer or load the file
1941 if (bufferlist.exists(s))
1942 owner->currentView()->setBuffer(bufferlist.getBuffer(s));
1944 owner->currentView()->setBuffer(bufferlist.loadLyXFile(s));
1947 owner->currentBuffer()->setCursorFromRow(row);
1951 if (owner->currentBuffer()->text->cursor.y >
1952 owner->currentView()->getWorkArea()->h / 2) {
1953 owner->currentView()->getScreen()->
1954 Draw(owner->currentBuffer()->text->cursor.y -
1955 owner->currentView()->getWorkArea()->h/2);
1957 owner->currentView()->getScreen()->
1960 owner->currentBuffer()->update(0);
1961 owner->currentView()->redraw();
1968 int qa = lyxaction.LookupFunc((const char*)argument);
1969 setMessage(lyxaction.helpText((kb_action)qa));
1973 // --- accented characters ---------------------------
1976 case LFUN_CIRCUMFLEX:
1986 case LFUN_SPECIAL_CARON:
1989 case LFUN_HUNG_UMLAUT:
1995 if (keyseq.length==-1 && keyseq.getiso()!=0)
2000 owner->getIntl()->getTrans()->
2001 deadkey(c, get_accent(action).accent,
2002 owner->currentBuffer()->text);
2004 // Need to reset, in case the minibuffer calls these
2009 // copied verbatim from do_accent_char
2012 owner->currentBuffer()->text->sel_cursor =
2013 owner->currentBuffer()->text->cursor;
2017 // --- toolbar ----------------------------------
2018 case LFUN_PUSH_TOOLBAR:
2020 int nth = atoi(argument);
2021 if (lyxerr.debugging(Debug::TOOLBAR)) {
2022 lyxerr << "LFUN_PUSH_TOOLBAR: argument = `"
2023 << argument << "'\n"
2024 << "LFUN_PUSH_TOOLBAR: nth = `"
2025 << nth << "'" << endl;
2030 setErrorMessage(N_("Push-toolbar needs argument > 0"));
2032 owner->getToolbar()->push(nth);
2037 case LFUN_ADD_TO_TOOLBAR:
2039 if (lyxerr.debugging(Debug::TOOLBAR)) {
2040 lyxerr << "LFUN_ADD_TO_TOOLBAR:"
2041 "argument = `" << argument << '\'' << endl;
2043 string tmp(argument);
2044 //lyxerr <<string("Argument: ") + argument);
2045 //lyxerr <<string("Tmp : ") + tmp);
2048 setErrorMessage(N_("Usage: toolbar-add-to <LyX command>"));
2050 owner->getToolbar()->add(argument, false);
2051 owner->getToolbar()->set();
2056 // --- insert characters ----------------------------------------
2058 case LFUN_INSERT_INSET_LATEX:
2060 Inset *new_inset = new InsetLatex(argument);
2061 owner->currentBuffer()->insertInset(new_inset);
2065 // --- Mathed stuff. If we are here, there is no locked inset yet.
2070 if (!greek_kb_flag) {
2072 setMessage(N_("Math greek mode on"));
2079 case LFUN_GREEK_TOGGLE:
2081 greek_kb_flag = (greek_kb_flag) ? 0: 2;
2082 if (greek_kb_flag) {
2083 setMessage(N_("Math greek keyboard on"));
2085 setMessage(N_("Math greek keyboard off"));
2090 case LFUN_MATH_DELIM:
2091 case LFUN_INSERT_MATRIX:
2093 if (owner->currentView()->available()) {
2094 owner->currentBuffer()->
2095 open_new_inset(new InsetFormula(false));
2096 owner->currentBuffer()->
2097 the_locking_inset->LocalDispatch(action, argument);
2102 case LFUN_INSERT_MATH:
2104 math_insert_symbol(argument);
2108 case LFUN_MATH_DISPLAY:
2110 if (owner->currentView()->available())
2111 owner->currentBuffer()->open_new_inset(new InsetFormula(true));
2115 case LFUN_MATH_MACRO:
2117 if (owner->currentView()->available()) {
2120 setErrorMessage(N_("Missing argument"));
2122 string s1 = token(s, ' ', 1);
2123 int na = s1.empty() ? 0: atoi(s1.c_str());
2124 owner->currentBuffer()->
2125 open_new_inset(new InsetFormulaMacro(token(s, ' ', 0), na));
2131 case LFUN_MATH_MODE: // Open or create a math inset
2134 if (owner->currentView()->available())
2135 owner->currentBuffer()->open_new_inset(new InsetFormula);
2136 setMessage(N_("Math editor mode"));
2140 case LFUN_MATH_NUMBER:
2141 case LFUN_MATH_LIMITS:
2143 setErrorMessage(N_("This is only allowed in math mode!"));
2147 case LFUN_INSERT_CITATION:
2149 InsetCitation *new_inset = new InsetCitation();
2151 // The note, if any, must be after the key, delimited
2152 // by a | so both key and remark can have spaces.
2154 string lsarg(argument);
2155 if (contains(lsarg, "|")) {
2156 new_inset->setContents(token(lsarg, '|', 0));
2157 new_inset->setOptions(token(lsarg, '|', 1));
2159 new_inset->setContents(lsarg);
2160 owner->currentBuffer()->insertInset(new_inset);
2162 owner->currentBuffer()->insertInset(new_inset);
2163 new_inset->Edit(0,0);
2168 case LFUN_INSERT_BIBTEX:
2170 // ale970405+lasgoutt970425
2171 // The argument can be up to two tokens separated
2172 // by a space. The first one is the bibstyle.
2173 string lsarg(argument);
2174 string bibstyle = token(lsarg, ' ', 1);
2175 if (bibstyle.empty())
2177 InsetBibtex *new_inset
2178 = new InsetBibtex(token(lsarg, ' ', 0),
2180 owner->currentBuffer());
2182 owner->currentBuffer()->insertInset(new_inset);
2183 if (lsarg.empty()) {
2184 new_inset->Edit(0,0);
2189 // BibTeX data bases
2190 case LFUN_BIBDB_ADD:
2192 InsetBibtex *inset =
2193 (InsetBibtex*)getInsetByCode(Inset::BIBTEX_CODE);
2195 inset->addDatabase(argument);
2200 case LFUN_BIBDB_DEL:
2202 InsetBibtex *inset =
2203 (InsetBibtex*)getInsetByCode(Inset::BIBTEX_CODE);
2205 inset->delDatabase(argument);
2210 case LFUN_BIBTEX_STYLE:
2212 InsetBibtex *inset =
2213 (InsetBibtex*)getInsetByCode(Inset::BIBTEX_CODE);
2215 inset->setOptions(argument);
2220 case LFUN_INDEX_INSERT:
2221 case LFUN_INDEX_INSERT_LAST:
2223 InsetIndex *new_inset = new InsetIndex();
2225 string lsarg(argument);
2226 new_inset->setContents(lsarg);
2227 owner->currentBuffer()->insertInset(new_inset);
2230 //get the current word for an argument
2235 int lastpos =owner->currentBuffer()->text->cursor.pos-1;
2237 //this shouldn't happen, but let's be careful
2238 if (lastpos < 0) lastpos=0;
2240 // get the current word
2241 // note that this must be done before
2242 // inserting the inset, or the inset will break
2244 string curstring(owner->currentBuffer()->text->cursor.par->GetWord(lastpos));
2246 //make the new inset and write the current word into it
2247 InsetIndex *new_inset = new InsetIndex();
2249 new_inset->setContents(curstring);
2251 //don't edit it if the call was to INSERT_LAST
2252 if(action!=LFUN_INDEX_INSERT_LAST) {
2253 new_inset->Edit(0,0);
2255 //it looks blank on the screen unless
2256 //we do something. put it here.
2258 // move the cursor to the returned value of lastpos
2259 // but only for the auto-insert
2260 owner->currentBuffer()->text->cursor.pos=lastpos;
2263 //put the new inset into the buffer.
2264 // there should be some way of knowing the user
2265 //cancelled & avoiding this, but i don't know how
2266 owner->currentBuffer()->insertInset(new_inset);
2271 case LFUN_INDEX_PRINT:
2273 Inset *new_inset = new InsetPrintIndex(owner->currentBuffer());
2274 owner->currentBuffer()->insertInset(new_inset, "Standard", true);
2278 case LFUN_PARENTINSERT:
2280 lyxerr << "arg " << argument << endl;
2281 Inset *new_inset = new InsetParent(argument, owner->currentBuffer());
2282 owner->currentBuffer()->insertInset(new_inset, "Standard", true);
2286 case LFUN_CHILDINSERT:
2288 Inset *new_inset = new InsetInclude(argument,owner->currentBuffer());
2289 owner->currentBuffer()->insertInset(new_inset, "Standard", true);
2290 new_inset->Edit(0,0);
2294 case LFUN_CHILDOPEN:
2296 string filename = MakeAbsPath(argument,
2297 OnlyPath(owner->currentBuffer()->getFileName()));
2298 setMessage(N_("Opening child document ") +
2299 MakeDisplayPath(filename) + "...");
2300 owner->currentView()->savePosition();
2301 if (bufferlist.exists(filename))
2302 owner->currentView()->setBuffer(bufferlist.getBuffer(filename));
2304 owner->currentView()->setBuffer(bufferlist.loadLyXFile(filename));
2308 case LFUN_INSERT_NOTE:
2312 case LFUN_INSERTFOOTNOTE:
2314 LyXParagraph::footnote_kind kind;
2315 string arg = argument;
2316 if (arg == "footnote")
2317 { kind = LyXParagraph::FOOTNOTE; }
2318 else if (arg == "margin")
2319 { kind = LyXParagraph::MARGIN; }
2320 else if (arg == "figure")
2321 { kind = LyXParagraph::FIG; }
2322 else if (arg == "table")
2323 { kind = LyXParagraph::TAB; }
2324 else if (arg == "wide-fig")
2325 { kind = LyXParagraph::WIDE_FIG; }
2326 else if (arg == "wide-tab")
2327 { kind = LyXParagraph::WIDE_TAB; }
2328 else if (arg == "algorithm")
2329 { kind = LyXParagraph::ALGORITHM; }
2331 setErrorMessage(N_("Unknown kind of footnote"));
2334 owner->currentBuffer()->text->InsertFootnoteEnvironment(kind);
2335 owner->currentBuffer()->update(1);
2339 case LFUN_BUFFERBULLETSSELECT:
2343 case LFUN_TOGGLECURSORFOLLOW:
2344 cursor_follows_scrollbar = !cursor_follows_scrollbar;
2347 case LFUN_KMAP_OFF: // keymap off
2348 owner->getIntl()->KeyMapOn(false);
2351 case LFUN_KMAP_PRIM: // primary keymap
2352 owner->getIntl()->KeyMapPrim();
2355 case LFUN_KMAP_SEC: // secondary keymap
2356 owner->getIntl()->KeyMapSec();
2359 case LFUN_KMAP_TOGGLE: // toggle keymap
2360 owner->getIntl()->ToggleKeyMap();
2363 case LFUN_SELFINSERT:
2365 string const text = argument;
2366 for (string::size_type i = 0; i < text.length(); ++i) {
2367 owner->currentBuffer()->text->InsertChar(text[i]);
2368 // This needs to be in the loop, or else we
2369 // won't break lines correctly. (Asger)
2373 owner->currentBuffer()->text->sel_cursor =
2374 owner->currentBuffer()->text->cursor;
2375 moveCursorUpdate(false);
2379 case LFUN_UNKNOWN_ACTION:
2381 if (owner->currentBuffer()->isReadonly()) {
2383 setErrorMessage(N_("Document is read only"));
2389 /* Automatically delete the currently selected
2390 * text and replace it with what is being
2391 * typed in now. Depends on lyxrc settings
2392 * "auto_region_delete", which defaults to
2395 if ( lyxrc->auto_region_delete ) {
2396 if (owner->currentBuffer()->text->selection){
2397 owner->currentBuffer()->text->CutSelection(false);
2398 owner->currentBuffer()->update(-1);
2403 for(char const *p = argument; *p; p++) {
2404 if (greek_kb_flag) {
2405 if (!math_insert_greek(*p))
2406 owner->getIntl()->getTrans()->TranslateAndInsert(*p, owner->currentBuffer()->text);
2408 owner->getIntl()->getTrans()->TranslateAndInsert(*p, owner->currentBuffer()->text);
2414 owner->currentBuffer()->text->sel_cursor =
2415 owner->currentBuffer()->text->cursor;
2416 moveCursorUpdate(false);
2419 // why is an "Unknown action" with empty
2420 // argument even dispatched in the first
2421 // place? I`ll probably change that. (Lgb)
2423 setErrorMessage(N_("Unknown action"));
2427 lyxerr << "A truly unknown func!" << endl;
2433 string res=getMessage();
2436 if (!commandshortcut.empty()) {
2437 string newbuf = owner->getMiniBuffer()->GetText();
2438 if (newbuf != commandshortcut) {
2439 owner->getMiniBuffer()->Set(newbuf
2445 owner->getMiniBuffer()->Set(string(_(res.c_str()))
2446 + " " + commandshortcut);
2449 return getMessage();
2453 void LyXFunc::setupLocalKeymap()
2455 keyseq.stdmap = keyseq.curmap = toplevel_keymap;
2456 cancel_meta_seq.stdmap = cancel_meta_seq.curmap = toplevel_keymap;
2460 void LyXFunc::MenuNew(bool fromTemplate)
2462 string fname, initpath = lyxrc->document_path;
2465 if (owner->currentView()->available()) {
2466 string trypath = owner->currentBuffer()->filepath;
2467 // If directory is writeable, use this as default.
2468 if (IsDirWriteable(trypath) == 1)
2473 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2474 fileDlg.SetButton(1, _("Templates"), lyxrc->template_path);
2475 fname = fileDlg.Select(_("Enter Filename for new document"),
2476 initpath, "*.lyx", _("newfile"));
2479 if (fname.empty()) {
2480 owner->getMiniBuffer()->Set(_("Canceled."));
2481 lyxerr.debug() << "New Document Cancelled." << endl;
2485 // get absolute path of file and make sure the filename ends
2487 string s = MakeAbsPath(fname);
2488 if (!IsLyXFilename(s))
2491 // Check if the document already is open
2492 if (bufferlist.exists(s)){
2493 switch(AskConfirmation(_("Document is already open:"),
2494 MakeDisplayPath(s,50),
2495 _("Do you want to close that document now?\n"
2496 "('No' will just switch to the open version)")))
2498 case 1: // Yes: close the document
2499 if (!bufferlist.close(bufferlist.getBuffer(s)))
2500 // If close is canceled, we cancel here too.
2503 case 2: // No: switch to the open document
2504 owner->currentView()->setBuffer(bufferlist.getBuffer(s));
2506 case 3: // Cancel: Do nothing
2507 owner->getMiniBuffer()->Set(_("Canceled."));
2512 // Check whether the file already exists
2513 if (IsLyXFilename(s)) {
2514 FilePtr myfile(s, FilePtr::read);
2516 AskQuestion(_("File already exists:"),
2517 MakeDisplayPath(s,50),
2518 _("Do you want to open the document?"))) {
2520 owner->getMiniBuffer()->Set(_("Opening document"),
2521 MakeDisplayPath(s), "...");
2523 owner->currentView()->setBuffer(
2524 bufferlist.loadLyXFile(s));
2525 owner->getMiniBuffer()->Set(_("Document"),
2532 // The template stuff
2536 fname = fileDlg.Select(_("Choose template"),
2537 lyxrc->template_path,
2543 // find a free buffer
2544 lyxerr.debug() << "Find a free buffer." << endl;
2545 owner->currentView()->setBuffer(bufferlist.newFile(s,templname));
2549 void LyXFunc::MenuOpen()
2551 string initpath = lyxrc->document_path;
2554 if (owner->currentView()->available()) {
2555 string trypath = owner->currentBuffer()->filepath;
2556 // If directory is writeable, use this as default.
2557 if (IsDirWriteable(trypath) == 1)
2563 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2564 fileDlg.SetButton(1, _("Examples"),
2565 AddPath(system_lyxdir, "examples"));
2566 string filename = fileDlg.Select(_("Select Document to Open"),
2570 // check selected filename
2571 if (filename.empty()) {
2572 owner->getMiniBuffer()->Set(_("Canceled."));
2576 // get absolute path of file and make sure the filename ends
2578 filename = MakeAbsPath(filename);
2579 if (!IsLyXFilename(filename))
2583 owner->getMiniBuffer()->Set(_("Opening document"),
2584 MakeDisplayPath(filename), "...");
2585 Buffer * openbuf = bufferlist.loadLyXFile(filename);
2587 owner->currentView()->setBuffer(openbuf);
2588 owner->getMiniBuffer()->Set(_("Document"),
2589 MakeDisplayPath(filename),
2592 owner->getMiniBuffer()->Set(_("Could not open document"),
2593 MakeDisplayPath(filename));
2598 void LyXFunc::doImportASCII(bool linorpar)
2600 string initpath = lyxrc->document_path;
2603 if (owner->currentView()->available()) {
2604 string trypath = owner->currentBuffer()->filepath;
2605 // If directory is writeable, use this as default.
2606 if (IsDirWriteable(trypath) == 1)
2612 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2613 fileDlg.SetButton(1, _("Examples"),
2614 AddPath(system_lyxdir, "examples"));
2615 string filename = fileDlg.Select(_("Select ASCII file to Import"),
2619 // check selected filename
2620 if (filename.empty()) {
2621 owner->getMiniBuffer()->Set(_("Canceled."));
2625 // get absolute path of file
2626 filename = MakeAbsPath(filename);
2628 string s = ChangeExtension(filename, ".lyx", false);
2630 // Check if the document already is open
2631 if (bufferlist.exists(s)){
2632 switch(AskConfirmation(_("Document is already open:"),
2633 MakeDisplayPath(s,50),
2634 _("Do you want to close that document now?\n"
2635 "('No' will just switch to the open version)")))
2637 case 1: // Yes: close the document
2638 if (!bufferlist.close(bufferlist.getBuffer(s)))
2639 // If close is canceled, we cancel here too.
2642 case 2: // No: switch to the open document
2643 owner->currentView()->setBuffer(bufferlist.getBuffer(s));
2645 case 3: // Cancel: Do nothing
2646 owner->getMiniBuffer()->Set(_("Canceled."));
2651 // Check if a LyX document by the same root exists in filesystem
2652 FileInfo f(s, true);
2653 if (f.exist() && !AskQuestion(_("A document by the name"),
2655 _("already exists. Overwrite?"))) {
2656 owner->getMiniBuffer()->Set(_("Canceled."));
2660 owner->currentView()->setBuffer(bufferlist.newFile(s,string()));
2661 owner->getMiniBuffer()->Set(_("Importing ASCII file"),
2662 MakeDisplayPath(filename), "...");
2663 // Insert ASCII file
2664 InsertAsciiFile(filename,linorpar);
2665 owner->getMiniBuffer()->Set(_("ASCII file "),
2666 MakeDisplayPath(filename),
2671 void LyXFunc::doImportLaTeX(bool isnoweb)
2673 string initpath = lyxrc->document_path;
2676 if (owner->currentView()->available()) {
2677 string trypath = owner->currentBuffer()->filepath;
2678 // If directory is writeable, use this as default.
2679 if (IsDirWriteable(trypath) == 1)
2685 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2686 fileDlg.SetButton(1, _("Examples"),
2687 AddPath(system_lyxdir, "examples"));
2690 filename = fileDlg.Select(_("Select Noweb file to Import"),
2693 filename = fileDlg.Select(_("Select LaTeX file to Import"),
2699 // check selected filename
2700 if (filename.empty()) {
2701 owner->getMiniBuffer()->Set(_("Canceled."));
2705 // get absolute path of file
2706 filename = MakeAbsPath(filename);
2708 // Check if the document already is open
2709 string LyXfilename = ChangeExtension(filename, ".lyx", false);
2710 if (bufferlist.exists(LyXfilename)){
2711 switch(AskConfirmation(_("Document is already open:"),
2712 MakeDisplayPath(LyXfilename,50),
2713 _("Do you want to close that document now?\n"
2714 "('No' will just switch to the open version)")))
2716 case 1: // Yes: close the document
2717 if (!bufferlist.close(bufferlist.getBuffer(LyXfilename)))
2718 // If close is canceled, we cancel here too.
2721 case 2: // No: switch to the open document
2722 owner->currentView()->setBuffer(
2723 bufferlist.getBuffer(LyXfilename));
2725 case 3: // Cancel: Do nothing
2726 owner->getMiniBuffer()->Set(_("Canceled."));
2731 // Check if a LyX document by the same root exists in filesystem
2732 FileInfo f(LyXfilename, true);
2733 if (f.exist() && !AskQuestion(_("A document by the name"),
2734 MakeDisplayPath(LyXfilename),
2735 _("already exists. Overwrite?"))) {
2736 owner->getMiniBuffer()->Set(_("Canceled."));
2743 owner->getMiniBuffer()->Set(_("Importing LaTeX file"),
2744 MakeDisplayPath(filename), "...");
2745 ImportLaTeX myImport(filename);
2746 openbuf = myImport.run();
2748 owner->getMiniBuffer()->Set(_("Importing Noweb file"),
2749 MakeDisplayPath(filename), "...");
2750 ImportNoweb myImport(filename);
2751 openbuf = myImport.run();
2754 owner->currentView()->setBuffer(openbuf);
2755 owner->getMiniBuffer()->Set(isnoweb ?
2756 _("Noweb file ") : _("LateX file "),
2757 MakeDisplayPath(filename),
2760 owner->getMiniBuffer()->Set(isnoweb ?
2761 _("Could not import Noweb file") :
2762 _("Could not import LaTeX file"),
2763 MakeDisplayPath(filename));
2768 void LyXFunc::MenuInsertLyXFile(string const & filen)
2770 string filename = filen;
2772 if (filename.empty()) {
2773 // Launch a file browser
2774 string initpath = lyxrc->document_path;
2777 if (owner->currentView()->available()) {
2778 string trypath = owner->currentBuffer()->filepath;
2779 // If directory is writeable, use this as default.
2780 if (IsDirWriteable(trypath) == 1)
2786 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2787 fileDlg.SetButton(1, _("Examples"),
2788 AddPath(system_lyxdir, "examples"));
2789 filename = fileDlg.Select(_("Select Document to Insert"),
2793 // check selected filename
2794 if (filename.empty()) {
2795 owner->getMiniBuffer()->Set(_("Canceled."));
2800 // get absolute path of file and make sure the filename ends
2802 filename = MakeAbsPath(filename);
2803 if (!IsLyXFilename(filename))
2807 owner->getMiniBuffer()->Set(_("Inserting document"),
2808 MakeDisplayPath(filename), "...");
2809 bool res = owner->currentBuffer()->insertLyXFile(filename);
2811 owner->getMiniBuffer()->Set(_("Document"),
2812 MakeDisplayPath(filename),
2815 owner->getMiniBuffer()->Set(_("Could not insert document"),
2816 MakeDisplayPath(filename));
2821 void LyXFunc::reloadBuffer()
2823 string fn = owner->currentBuffer()->getFileName();
2824 if (bufferlist.close(owner->currentBuffer()))
2825 owner->currentView()->setBuffer(bufferlist.loadLyXFile(fn));
2829 void LyXFunc::CloseBuffer()
2831 if (bufferlist.close(owner->currentBuffer()) && !quitting) {
2832 if (bufferlist.isEmpty()) {
2833 // need this otherwise SEGV may occur while trying to
2834 // set variables that don't exist
2835 // since there's no current buffer
2836 CloseAllBufferRelatedPopups();
2839 owner->currentView()->setBuffer(bufferlist.first());
2845 Inset* LyXFunc::getInsetByCode(Inset::Code code)
2849 LyXCursor cursor = owner->currentBuffer()->text->cursor;
2850 int pos = cursor.pos;
2851 LyXParagraph *par = cursor.par;
2853 while (par && !found) {
2854 while ((inset = par->ReturnNextInsetPointer(pos))){
2855 if (inset->LyxCode()==code) {
2863 return (found) ? inset: 0;
2867 // Each "owner" should have it's own message method. lyxview and
2868 // the minibuffer would use the minibuffer, but lyxserver would
2869 // send an ERROR signal to its client. Alejandro 970603
2870 // This func is bit problematic when it comes to NLS, to make the
2871 // lyx servers client be language indepenent we must not translate
2872 // strings sent to this func.
2873 void LyXFunc::setErrorMessage(string const &m)
2875 dispatch_buffer = m;
2880 void LyXFunc::setMessage(string const & m)
2882 dispatch_buffer = m;