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"
62 #include "support/lstrings.h"
64 extern bool cursor_follows_scrollbar;
66 extern void InsertAsciiFile(string const &, bool);
67 extern void math_insert_symbol(char const*);
68 extern Bool math_insert_greek(char const); // why "Bool"?
69 extern BufferList bufferlist;
70 extern LyXServer *lyxserver;
71 extern short greek_kb_flag;
72 extern FD_form_toc *fd_form_toc;
73 extern bool selection_possible;
75 extern kb_keymap *toplevel_keymap;
77 extern void BeforeChange();
78 extern void MenuWrite(Buffer*);
79 extern void MenuWriteAs(Buffer*);
80 extern int MenuRunLaTeX(Buffer*);
81 extern int MenuBuildProg(Buffer*);
82 extern int MenuRunChktex(Buffer*);
83 extern bool MenuRunDvips(Buffer *,bool);
84 extern void MenuPrint(Buffer*);
85 extern void MenuSendto();
86 extern void QuitLyX();
87 extern void MenuFax(Buffer *);
88 extern void MenuMakeLaTeX(Buffer *);
89 extern void MenuMakeLinuxDoc(Buffer *);
90 extern void MenuMakeDocBook(Buffer *);
91 extern void MenuMakeAscii(Buffer *);
92 extern void MenuPasteSelection(char at);
93 extern LyXAction lyxaction;
95 extern tex_accent_struct get_accent(kb_action action);
97 extern void AutoSave();
98 extern void MenuSearch();
100 extern void CopyEnvironmentCB();
101 extern void PasteEnvironmentCB();
102 extern void GotoNote();
103 extern void NoteCB();
104 extern void OpenStuff();
105 extern void HyphenationPoint();
107 extern void EndOfSentenceDot();
108 extern void MenuSeparator();
110 extern void MenuUndo();
111 extern void MenuRedo();
112 extern void SmallUpdate(signed char);
113 extern void SetUpdateTimer(float timer= 0.3);
114 extern void FreeUpdateTimer();
115 extern bool MenuPreview(Buffer*);
116 extern bool MenuPreviewPS(Buffer*);
117 extern void MenuInsertLabel(const char *);
118 extern void MenuInsertRef();
119 extern void MenuLayoutCharacter();
120 extern void MenuLayoutParagraph();
121 extern void MenuLayoutDocument();
122 extern void MenuLayoutPaper();
123 extern void MenuLayoutTable(int flag);
124 extern void MenuLayoutQuotes();
125 extern void MenuLayoutPreamble();
126 extern void MenuLayoutSave();
127 extern void bulletForm();
129 extern Buffer * NewLyxFile(string const &);
130 extern void LoadLyXFile(string const &);
131 extern void Reconfigure();
133 extern int current_layout;
134 extern int getISOCodeFromLaTeX(char *);
136 extern int UnlockInset(UpdatableInset*);
138 extern void ShowLatexLog();
140 extern void UpdateInset(Inset* inset, bool mark_dirty = true);
142 /* === globals =========================================================== */
144 bool LyXFunc::show_sc = true;
147 LyXFunc::LyXFunc(LyXView *o)
151 lyx_dead_action = LFUN_NOACTION;
152 lyx_calling_dead_action = LFUN_NOACTION;
162 // I changed this func slightly. I commented out the ...FinishUndo(),
163 // this means that all places that used to have a moveCursorUpdate, now
164 // have a ...FinishUndo() as the preceeding statement. I have also added
165 // a moveCursorUpdate to some of the functions that updated the cursor, but
166 // that did not show its new position.
168 void LyXFunc::moveCursorUpdate(bool selecting)
170 if (selecting || owner->currentBuffer()->text->mark_set) {
171 owner->currentBuffer()->text->SetSelection();
172 owner->currentView()->getScreen()->ToggleToggle();
173 owner->currentBuffer()->update(0);
175 owner->currentBuffer()->update(-2); // this IS necessary
178 owner->currentView()->getScreen()->ShowCursor();
180 /* ---> Everytime the cursor is moved, show the current font state. */
181 // should this too me moved out of this func?
182 //owner->getMiniBuffer()->Set(CurrentState());
186 int LyXFunc::processKeyEvent(XEvent *ev)
193 XKeyEvent *keyevent = &ev->xkey;
194 KeySym keysym_return;
196 num_bytes = LyXLookupString(ev, s_r, 10, &keysym_return);
198 if (lyxerr.debugging(Debug::KEY)) {
199 lyxerr << "KeySym is "
200 << XKeysymToString(keysym_return)
202 << keysym_return << "]"
203 << " and num_bytes is "
205 << " the string returned is \""
206 << s_r << '\"' << endl;
208 // Do nothing if we have nothing (JMarc)
209 if (num_bytes == 0 && keysym_return == NoSymbol) {
210 lyxerr[Debug::KEY] << "Empty kbd action (probably composing)"
215 // this function should be used always [asierra060396]
216 if (owner->currentView()->available() &&
217 owner->currentBuffer()->the_locking_inset &&
218 keysym_return == XK_Escape) {
219 UnlockInset(owner->currentBuffer()->the_locking_inset);
220 owner->currentBuffer()->text->CursorRight();
224 // Can we be sure that this will work for all X-Windows
225 // implementations? (Lgb)
226 // This code snippet makes lyx ignore some keys. Perhaps
227 // all of them should be explictly mentioned?
228 if((keysym_return >= XK_Shift_L && keysym_return <= XK_Hyper_R)
229 || keysym_return == XK_Mode_switch || keysym_return == 0x0)
232 // Do a one-deep top-level lookup for
233 // cancel and meta-fake keys. RVDK_PATCH_5
234 cancel_meta_seq.reset();
236 action = cancel_meta_seq.addkey(keysym_return, keyevent->state
237 &(ShiftMask|ControlMask
240 // When not cancel or meta-fake, do the normal lookup.
241 // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
242 // Mostly, meta_fake_bit = 0. RVDK_PATCH_5.
243 if ( (action != LFUN_CANCEL) && (action != LFUN_META_FAKE) ) {
245 // remove Caps Lock and Mod2 as a modifiers
246 action = keyseq.addkey(keysym_return,
247 (keyevent->state | meta_fake_bit)
248 &(ShiftMask|ControlMask
251 // Dont remove this unless you know what you are doing.
254 if (action == 0) action = LFUN_PREFIX;
256 if (lyxerr.debugging(Debug::KEY)) {
258 keyseq.print(buf,100);
262 << num_bytes << "]" << endl;
265 // already here we know if it any point in going further
266 // why not return already here if action == -1 and
267 // num_bytes == 0? (Lgb)
269 if(keyseq.length>1 || keyseq.length<-1){
271 keyseq.print(buf,100);
272 owner->getMiniBuffer()->Set(buf);
276 if (keyseq.length<-1) { // unknown key sequence...
279 keyseq.print(buf,100);
280 owner->getMiniBuffer()->Set(_("Unknown sequence:"),buf);
284 char isochar = keyseq.getiso();
285 if (!(keyevent->state&ControlMask) &&
286 !(keyevent->state&Mod1Mask) &&
287 (isochar && keysym_return < 0xF000)) {
288 argument = s_r[0]; // shall this be here
291 if (argument.empty()) {
292 lyxerr.debug() << "Empty argument!" << endl;
293 // This can`t possibly be of any use
294 // so we`ll skip the dispatch.
298 if (action==LFUN_SELFINSERT) {
302 bool tmp_sc = show_sc;
304 Dispatch(action, argument.c_str());
307 // Need this for deadkeys (alkis)
309 // ...but that breaks the minibuffer's display of "M-"...
311 #warning How does the deadkeys react to this?
317 string LyXFunc::Dispatch(string const &cmd, string const &arg)
319 return Dispatch(lyxaction.LookupFunc(cmd.c_str()),
324 string LyXFunc::Dispatch(int ac,
325 char const *do_not_use_this_arg)
331 FL_OBJECT *ob = 0; // This will disapear soon
333 // we have not done anything wrong yet.
335 dispatch_buffer = string();
337 // if action is a pseudo-action, we need the real action
338 if (lyxaction.isPseudoAction(ac)) {
339 char const *tmparg = 0;
340 action = (kb_action)lyxaction.retrieveActionArg(ac, &tmparg);
344 action = (kb_action)ac;
345 if (do_not_use_this_arg)
346 argument = do_not_use_this_arg; // except here
349 selection_possible = false;
351 if (owner->currentView()->available()
352 && owner->currentView()->getScreen())
353 owner->currentView()->getScreen()->HideCursor();
355 if(!owner->currentView()->available()) {
356 // This lists the allowed funcs when we have no
359 case LFUN_MENU_OPEN_BY_NAME:
362 case LFUN_MENUNEWTMPLT:
365 case LFUN_PUSH_TOOLBAR:
366 case LFUN_ADD_TO_TOOLBAR:
367 case LFUN_EXEC_COMMAND:
368 case LFUN_DROP_LAYOUTS_CHOICE:
372 case LFUN_RECONFIGURE:
378 case LFUN_UNKNOWN_ACTION:
379 setErrorMessage(N_("Unknown action"));
380 goto exit_with_message;
382 setErrorMessage(N_("Command not allowed with"
383 "out any document open"));
384 goto exit_with_message; // action not allowed
388 commandshortcut = string();
390 if (lyxrc->display_shortcuts && show_sc) {
391 if (action != LFUN_SELFINSERT) {
392 // Put name of command and list of shortcuts
393 // for it in minibuffer
394 string comname = lyxaction.getActionName(action);
396 int pseudoaction = action;
397 bool argsadded = false;
399 if (!argument.empty()) {
400 // If we have the command with argument,
403 lyxaction.searchActionArg(action,
406 if (pseudoaction == -1) {
407 pseudoaction = action;
409 comname += " " + argument;
414 string shortcuts = toplevel_keymap->findbinding(pseudoaction);
416 if (!shortcuts.empty()) {
417 comname += ": " + shortcuts;
418 } else if (!argsadded) {
419 comname += " " + argument;
422 if (!comname.empty()) {
423 comname = strip(comname);
424 commandshortcut = "(" + comname + ')';
425 owner->getMiniBuffer()->Set(commandshortcut);
426 // Here we could even add a small pause,
427 // to annoy the user and make him learn
429 // No! That will just annoy, not teach
430 // anything. The user will read the messages
431 // if they are interested. (Asger)
436 // Now that we know which action, if the buffer is RO let's check
437 // whether the action is legal. Alejandro 970603
438 if (owner->currentView()->available() &&
439 owner->currentBuffer()->isReadonly() &&
440 lyxaction.isFuncRO(action)) {
441 setErrorMessage(N_("Document is read-only"));
442 lyxerr.debug() << "Error: Document is read-only." << endl;
443 goto exit_with_message;
446 // If in math mode pass the control to
447 // the math inset [asierra060396]
448 if (owner->currentView()->available() &&
449 owner->currentBuffer()->the_locking_inset) {
450 if (action>1 || (action==LFUN_UNKNOWN_ACTION && keyseq.length>=-1)) {
451 if (action==LFUN_UNKNOWN_ACTION && argument.empty()) {
452 argument = keyseq.getiso();
454 // Undo/Redo pre 0.13 is a bit tricky for insets.
455 if (action==LFUN_UNDO) {
457 UpdatableInset* inset =
458 owner->currentBuffer()->the_locking_inset;
459 inset->GetCursorPos(slx, sly);
462 inset = (UpdatableInset*)owner->currentBuffer()->text->cursor.par->GetInset(owner->currentBuffer()->text->cursor.pos);
464 inset->Edit(slx, sly);
467 if (action==LFUN_REDO) {
469 UpdatableInset* inset = owner->currentBuffer()->the_locking_inset;
470 inset->GetCursorPos(slx, sly);
473 inset = (UpdatableInset*)owner->currentBuffer()->text->cursor.par->GetInset(owner->currentBuffer()->text->cursor.pos);
475 inset->Edit(slx, sly);
478 if (owner->currentBuffer()->the_locking_inset->LocalDispatch(action, argument.c_str()))
481 setMessage(N_("Text mode"));
482 if (action==LFUN_RIGHT || action==-1)
483 owner->currentBuffer()->text->CursorRight();
484 if (action==LFUN_LEFT || action==LFUN_RIGHT)
491 // --- Misc -------------------------------------------
492 case LFUN_WORDFINDFORWARD :
493 case LFUN_WORDFINDBACKWARD : {
495 static string last_search;
496 string searched_string;
498 if (!argument.empty()) {
499 last_search = argument;
500 searched_string = argument;
502 searched_string = last_search;
505 ltCur = owner->currentView()->currentBuffer()->text ;
507 if (!searched_string.empty() &&
508 ( (action == LFUN_WORDFINDBACKWARD) ?
509 ltCur->SearchBackward( searched_string.c_str() ) :
510 ltCur->SearchForward( searched_string.c_str() )
513 // ??? What is that ???
514 owner->currentView()->currentBuffer()->update(-2);
517 // clear the selection (if there is any)
518 owner->currentView()->getScreen()->ToggleSelection();
519 owner->currentView()->currentBuffer()->text->ClearSelection();
521 // Move cursor so that successive C-s 's will not stand in place.
522 if( action == LFUN_WORDFINDFORWARD )
523 owner->currentBuffer()->text->CursorRightOneWord();
524 owner->currentBuffer()->text->FinishUndo();
525 moveCursorUpdate(false);
528 // set the new selection
529 // SetSelectionOverLenChars(owner->currentView()->currentBuffer()->text, iLenSelected);
530 owner->currentView()->getScreen()->ToggleSelection(false);
534 // REMOVED : if (owner->currentView()->getWorkArea()->focus)
535 owner->currentView()->getScreen()->ShowCursor();
541 if (owner->currentView()->available()
542 && owner->currentView()->getScreen()) {
543 owner->currentBuffer()->update(-2);
546 keyseq.print(buf,100, true);
547 owner->getMiniBuffer()->Set(buf, string(), string(), 1);
551 // --- Misc -------------------------------------------
552 case LFUN_EXEC_COMMAND:
553 owner->getMiniBuffer()->ExecCommand();
556 case LFUN_CANCEL: // RVDK_PATCH_5
559 if(owner->currentView()->available())
560 // cancel any selection
561 Dispatch(int(LFUN_MARK_OFF), 0);
562 setMessage(N_("Cancel"));
565 case LFUN_META_FAKE: // RVDK_PATCH_5
567 meta_fake_bit = Mod1Mask;
569 keyseq.print(buf, 98, true);
570 string res = string("M-") + buf;
571 setMessage(buf); // RVDK_PATCH_5
575 case LFUN_READ_ONLY_TOGGLE:
576 if (owner->currentBuffer()->lyxvc.inUse()) {
577 owner->currentBuffer()->lyxvc.toggleReadOnly();
579 owner->currentBuffer()->setReadonly(
580 !owner->currentBuffer()->isReadonly());
584 case LFUN_CENTER: // this is center and redraw.
586 if (owner->currentBuffer()->text->cursor.y >
587 owner->currentView()->getWorkArea()->h / 2) {
588 owner->currentView()->getScreen()->
589 Draw(owner->currentBuffer()->text->cursor.y -
590 owner->currentView()->getWorkArea()->h/2);
592 owner->currentView()->getScreen()->
595 owner->currentBuffer()->update(0);
596 owner->currentView()->redraw();
600 if (owner->currentView()->available()) {
601 owner->currentBuffer()->text->toggleAppendix();
602 owner->currentBuffer()->update(1);
606 // --- Menus -----------------------------------------------
611 case LFUN_MENUNEWTMPLT:
619 case LFUN_CLOSEBUFFER:
624 MenuWrite(owner->currentBuffer());
627 case LFUN_MENUWRITEAS:
628 MenuWriteAs(owner->currentBuffer());
631 case LFUN_MENURELOAD:
636 MenuPreview(owner->currentBuffer());
640 MenuPreviewPS(owner->currentBuffer());
644 MenuRunLaTeX(owner->currentBuffer());
648 MenuBuildProg(owner->currentBuffer());
652 MenuRunChktex(owner->currentBuffer());
656 MenuRunDvips(owner->currentBuffer(), false);
660 MenuPrint(owner->currentBuffer());
664 MenuFax(owner->currentBuffer());
669 //needs argument as string
670 string extyp=argument;
673 if (extyp == "latex") {
674 // make sure that this buffer is not linuxdoc
675 MenuMakeLaTeX(owner->currentBuffer());
678 else if (extyp == "linuxdoc") {
679 // make sure that this buffer is not latex
680 MenuMakeLinuxDoc(owner->currentBuffer());
683 else if (extyp == "docbook") {
684 // make sure that this buffer is not latex or linuxdoc
685 MenuMakeDocBook(owner->currentBuffer());
688 else if (extyp == "dvi") {
689 // Run LaTeX as "Update dvi..." Bernhard.
690 // We want the dvi in the current directory. This
691 // is achieved by temporarily disabling use of
692 // temp directory. As a side-effect, we get
693 // *.log and *.aux files also. (Asger)
694 bool flag = lyxrc->use_tempdir;
695 lyxrc->use_tempdir = false;
696 MenuRunLaTeX(owner->currentBuffer());
697 lyxrc->use_tempdir = flag;
700 else if (extyp == "postscript") {
701 // Start Print-dialog. Not as good as dvi... Bernhard.
702 MenuPrint(owner->currentBuffer());
703 // Since the MenuPrint is a pop-up, we can't use
704 // the same trick as above. (Asger)
705 // MISSING: Move of ps-file :-(
708 else if (extyp == "ascii") {
709 MenuMakeAscii(owner->currentBuffer());
711 else if (extyp == "custom") {
716 else if (extyp == "html") {
717 // First, create LaTeX file
718 MenuMakeLaTeX(owner->currentBuffer());
721 string file = owner->currentBuffer()->getFileName();
722 file = ChangeExtension(file, ".tex", false);
723 string result = ChangeExtension(file, ".html", false);
724 string tmp = lyxrc->tth_command + " < " + file
727 int res = one.startscript(Systemcalls::System, tmp);
730 N_("Document exported as HTML to file: ")) + result);
732 setErrorMessage(string(
733 N_("An unexpected error occured while converting document to HTML in file:")) + result);
737 setErrorMessage(string(N_("Unknown export type: "))
745 //needs argument as string
746 string imtyp=argument;
749 if (imtyp == "latex") {
750 doImportLaTeX(false);
753 else if (imtyp == "ascii") {
754 doImportASCII(false);
755 } else if (imtyp == "asciiparagraph") {
758 } else if (imtyp == "noweb") {
761 setErrorMessage(string(N_("Unknown import type: "))
773 if (fd_form_toc->form_toc->visible) {
774 fl_raise_form(fd_form_toc->form_toc);
776 fl_show_form(fd_form_toc->form_toc,
778 FL_FREE_SIZE, FL_FULLBORDER,
779 _("Table of Contents"));
783 case LFUN_TOC_INSERT:
786 new InsetTOC(owner->currentBuffer());
787 owner->currentBuffer()->insertInset(new_inset,
792 case LFUN_LOF_INSERT:
795 new InsetLOF(owner->currentBuffer());
796 owner->currentBuffer()->insertInset(new_inset,
801 case LFUN_LOA_INSERT:
804 new InsetLOA(owner->currentBuffer());
805 owner->currentBuffer()->insertInset(new_inset,
810 case LFUN_LOT_INSERT:
813 new InsetLOT(owner->currentBuffer());
814 owner->currentBuffer()->insertInset(new_inset,
839 case LFUN_MENUSEARCH:
847 case LFUN_PASTESELECTION:
850 if (string(argument) == "paragraph") asPara = true;
851 MenuPasteSelection(asPara);
863 case LFUN_LAYOUT_COPY:
867 case LFUN_LAYOUT_PASTE:
868 PasteEnvironmentCB();
872 owner->currentView()->gotoError();
875 case LFUN_REMOVEERRORS:
876 if (owner->currentBuffer()->removeAutoInsets()) {
877 owner->currentView()->redraw();
878 owner->currentView()->fitCursor();
879 owner->currentView()->updateScrollbar();
891 case LFUN_HYPHENATION:
899 case LFUN_END_OF_SENTENCE:
903 case LFUN_MENU_SEPARATOR:
919 case LFUN_DEPTH_PLUS:
935 case LFUN_RECONFIGURE:
940 if (owner->currentView()->available()
941 && !owner->currentBuffer()->text->selection
942 && owner->currentBuffer()->text->cursor.par->footnoteflag
943 != LyXParagraph::NO_FOOTNOTE)
944 { // only melt footnotes with FOOTMELT, not margins etc
945 if(owner->currentBuffer()->text->cursor.par->footnotekind == LyXParagraph::FOOTNOTE)
952 case LFUN_MARGINMELT:
953 if (owner->currentView()->available()
954 && !owner->currentBuffer()->text->selection
955 && owner->currentBuffer()->text->cursor.par->footnoteflag
956 != LyXParagraph::NO_FOOTNOTE)
957 { // only melt margins
958 if(owner->currentBuffer()->text->cursor.par->footnotekind == LyXParagraph::MARGIN)
965 // --- version control -------------------------------
966 case LFUN_VC_REGISTER:
968 if (!owner->currentBuffer()->lyxvc.inUse())
969 owner->currentBuffer()->lyxvc.registrer();
973 case LFUN_VC_CHECKIN:
975 if (owner->currentBuffer()->lyxvc.inUse()
976 && !owner->currentBuffer()->isReadonly())
977 owner->currentBuffer()->lyxvc.checkIn();
981 case LFUN_VC_CHECKOUT:
983 if (owner->currentBuffer()->lyxvc.inUse()
984 && owner->currentBuffer()->isReadonly())
985 owner->currentBuffer()->lyxvc.checkOut();
991 owner->currentBuffer()->lyxvc.revert();
997 owner->currentBuffer()->lyxvc.undoLast();
1001 case LFUN_VC_HISTORY:
1003 owner->currentBuffer()->lyxvc.showLog();
1007 // --- buffers ----------------------------------------
1008 case LFUN_PREVBUFFER:
1009 #ifdef WITH_WARNINGS
1010 #warning fix this please
1012 // it is the LyXView or the BufferView that should
1013 // remember the previous buffer, not bufferlist.
1014 // if (owner->currentView()->available()){
1016 // owner->currentBuffer()->update(-2);
1018 // owner->currentView()->setBuffer(bufferlist.prev());
1020 // owner->currentView()->
1021 // resizeCurrentBufferPseudoExpose();
1024 case LFUN_FILE_INSERT:
1026 MenuInsertLyXFile(argument);
1030 case LFUN_FILE_INSERT_ASCII:
1032 bool asPara = false;
1033 asPara = (string(argument) == "paragraph");
1034 InsertAsciiFile(string(), asPara);
1040 // servercmd: argument must be <file>:<template>
1041 Buffer * tmpbuf = 0;
1042 tmpbuf = NewLyxFile(argument);
1044 owner->currentView()->setBuffer(tmpbuf);
1048 case LFUN_FILE_OPEN:
1049 owner->currentView()->setBuffer(
1050 bufferlist.loadLyXFile(argument));
1053 case LFUN_LATEX_LOG:
1059 lyxerr.debug() << "LFUN_LAYOUTNO: (arg) " << argument << endl;
1060 int sel = strToInt(argument);
1061 lyxerr.debug() << "LFUN_LAYOUTNO: (sel) "<< sel << endl;
1063 // Should this give a setMessage instead?
1065 return string(); // illegal argument
1067 sel--; // sel 1..., but layout 0...
1069 // Pretend we got the name instead.
1070 Dispatch(int(LFUN_LAYOUT),
1071 lyxstyle.NameOfLayout(owner->currentBuffer()->
1080 lyxerr.debug() << "LFUN_LAYOUT: (arg) "
1081 << argument << endl;
1083 // Derive layout number from given argument (string)
1084 // and current buffer's textclass (number). */
1087 lyxstyle.NumberOfLayout(owner->
1093 // see if we found the layout number:
1094 if (layoutno == -1) {
1095 setErrorMessage(string(N_("Layout ")) + argument +
1100 if (current_layout != layoutno) {
1101 owner->currentView()->getScreen()->HideCursor();
1102 current_layout = layoutno;
1103 owner->currentBuffer()->update(-2);
1104 owner->currentBuffer()->text->
1105 SetLayout(layoutno);
1106 owner->getToolbar()->combox->
1107 select(owner->currentBuffer()->
1110 owner->currentBuffer()->update(1);
1115 case LFUN_LAYOUT_DOCUMENT:
1116 MenuLayoutDocument();
1119 case LFUN_LAYOUT_PARAGRAPH:
1120 MenuLayoutParagraph();
1123 case LFUN_LAYOUT_CHARACTER:
1124 MenuLayoutCharacter();
1127 case LFUN_LAYOUT_TABLE:
1130 if (string(argument) == "true") flag = 1;
1131 MenuLayoutTable(flag);
1135 case LFUN_LAYOUT_PAPER:
1139 case LFUN_LAYOUT_QUOTES:
1143 case LFUN_LAYOUT_PREAMBLE:
1144 MenuLayoutPreamble();
1147 case LFUN_LAYOUT_SAVE_DEFAULT:
1151 case LFUN_DROP_LAYOUTS_CHOICE:
1152 owner->getToolbar()->combox->Show();
1183 case LFUN_UNDERLINE:
1187 case LFUN_FONT_SIZE:
1188 FontSizeCB(argument);
1191 case LFUN_FONT_STATE:
1192 setMessage(CurrentState());
1195 case LFUN_UPCASE_WORD:
1196 owner->currentBuffer()->update(-2);
1198 owner->currentBuffer()->text->ChangeWordCase(2);
1199 owner->currentBuffer()->update(1);
1203 case LFUN_LOWCASE_WORD:
1204 owner->currentBuffer()->update(-2);
1206 owner->currentBuffer()->text->ChangeWordCase(0);
1207 owner->currentBuffer()->update(1);
1211 case LFUN_CAPITALIZE_WORD:
1212 owner->currentBuffer()->update(-2);
1214 owner->currentBuffer()->text->ChangeWordCase(1);
1215 owner->currentBuffer()->update(1);
1219 case LFUN_INSERT_LABEL:
1220 MenuInsertLabel(argument.c_str());
1223 case LFUN_INSERT_REF:
1227 case LFUN_REFTOGGLE:
1230 (InsetRef*)getInsetByCode(Inset::REF_CODE);
1232 if (inset->getFlag()==InsetRef::REF)
1233 inset->setFlag(InsetRef::PAGE_REF);
1235 inset->setFlag(InsetRef::REF);
1238 setErrorMessage(N_("No cross-reference to toggle"));
1245 owner->currentView()->restorePosition();
1251 string label(argument);
1252 if (label.empty()) {
1254 (InsetRef*)getInsetByCode(Inset::REF_CODE);
1256 label = inset->getContents();
1259 if (!label.empty()) {
1260 owner->currentView()->savePosition();
1261 owner->currentBuffer()->gotoLabel(label.c_str());
1266 case LFUN_MENU_OPEN_BY_NAME:
1267 owner->getMenus()->openByName(argument);
1268 break; // RVDK_PATCH_5
1270 case LFUN_SPELLCHECK:
1271 if (lyxrc->isp_command != "none")
1273 break; // RVDK_PATCH_5
1275 // --- Cursor Movements -----------------------------
1278 Buffer *tmpbuffer = owner->currentBuffer();
1279 LyXText *tmptext = owner->currentBuffer()->text;
1280 if(!tmptext->mark_set)
1282 tmpbuffer->update(-2);
1283 if (tmptext->cursor.pos < tmptext->cursor.par->Last()
1284 && tmptext->cursor.par->GetChar(tmptext->cursor.pos)
1286 && tmptext->cursor.par->GetInset(tmptext->cursor.pos)
1287 && tmptext->cursor.par->GetInset(tmptext->cursor.pos)->Editable()==2){
1288 Inset* tmpinset = tmptext->cursor.par->GetInset(tmptext->cursor.pos);
1289 setMessage(tmpinset->EditMessage());
1290 tmpinset->Edit(0,0);
1293 tmptext->CursorRight();
1294 owner->currentBuffer()->text->FinishUndo();
1295 moveCursorUpdate(false);
1296 owner->getMiniBuffer()->Set(CurrentState());
1302 // This is soooo ugly. Isn`t it possible to make
1303 // it simpler? (Lgb)
1304 LyXText *txt= owner->currentBuffer()->text;
1305 if(!txt->mark_set) BeforeChange();
1306 owner->currentBuffer()->update(-2);
1308 if (txt->cursor.pos < txt->cursor.par->Last()
1309 && txt->cursor.par->GetChar(txt->cursor.pos)
1311 && txt->cursor.par->GetInset(txt->cursor.pos)
1312 && txt->cursor.par->GetInset(txt->cursor.pos)->Editable()==2) {
1313 Inset* tmpinset = txt->cursor.par->GetInset(txt->cursor.pos);
1314 setMessage(tmpinset->EditMessage());
1315 tmpinset->Edit(tmpinset->Width(txt->GetFont(txt->cursor.par,
1316 txt->cursor.pos)),0);
1317 // tmpinset->Edit(-1, 0); // -1 means go rightmost
1320 owner->currentBuffer()->text->FinishUndo();
1321 moveCursorUpdate(false);
1322 owner->getMiniBuffer()->Set(CurrentState());
1327 if(!owner->currentBuffer()->text->mark_set) BeforeChange();
1328 owner->currentBuffer()->update(-3);
1329 owner->currentBuffer()->text->CursorUp();
1330 owner->currentBuffer()->text->FinishUndo();
1331 moveCursorUpdate(false);
1332 owner->getMiniBuffer()->Set(CurrentState());
1336 if(!owner->currentBuffer()->text->mark_set)
1338 owner->currentBuffer()->update(-3);
1339 owner->currentBuffer()->text->CursorDown();
1340 owner->currentBuffer()->text->FinishUndo();
1341 moveCursorUpdate(false);
1342 owner->getMiniBuffer()->Set(CurrentState());
1345 case LFUN_UP_PARAGRAPH:
1346 if(!owner->currentBuffer()->text->mark_set)
1348 owner->currentBuffer()->update(-3);
1349 owner->currentBuffer()->text->CursorUpParagraph();
1350 owner->currentBuffer()->text->FinishUndo();
1351 moveCursorUpdate(false);
1352 owner->getMiniBuffer()->Set(CurrentState());
1355 case LFUN_DOWN_PARAGRAPH:
1356 if(!owner->currentBuffer()->text->mark_set)
1358 owner->currentBuffer()->update(-3);
1359 owner->currentBuffer()->text->CursorDownParagraph();
1360 owner->currentBuffer()->text->FinishUndo();
1361 moveCursorUpdate(false);
1362 owner->getMiniBuffer()->Set(CurrentState());
1366 if(!owner->currentBuffer()->text->mark_set)
1368 owner->currentBuffer()->update(-3);
1369 owner->currentView()->cursorPrevious();
1370 owner->currentBuffer()->text->FinishUndo();
1371 moveCursorUpdate(false);
1372 owner->getMiniBuffer()->Set(CurrentState());
1376 if(!owner->currentBuffer()->text->mark_set)
1378 owner->currentBuffer()->update(-3);
1379 owner->currentView()->cursorNext();
1380 owner->currentBuffer()->text->FinishUndo();
1381 moveCursorUpdate(false);
1382 owner->getMiniBuffer()->Set(CurrentState());
1386 if(!owner->currentBuffer()->text->mark_set)
1388 owner->currentBuffer()->update(-2);
1389 owner->currentBuffer()->text->CursorHome();
1390 owner->currentBuffer()->text->FinishUndo();
1391 moveCursorUpdate(false);
1392 owner->getMiniBuffer()->Set(CurrentState());
1396 if(!owner->currentBuffer()->text->mark_set)
1398 owner->currentBuffer()->update(-2);
1399 owner->currentBuffer()->text->CursorEnd();
1400 owner->currentBuffer()->text->FinishUndo();
1401 moveCursorUpdate(false);
1402 owner->getMiniBuffer()->Set(CurrentState());
1406 if(!owner->currentBuffer()->text->mark_set)
1408 owner->currentBuffer()->update(-2);
1409 owner->currentBuffer()->text->CursorTab();
1410 owner->currentBuffer()->text->FinishUndo();
1411 moveCursorUpdate(false);
1412 owner->getMiniBuffer()->Set(CurrentState());
1415 case LFUN_WORDRIGHT:
1416 if(!owner->currentBuffer()->text->mark_set)
1418 owner->currentBuffer()->update(-2);
1419 owner->currentBuffer()->text->CursorRightOneWord();
1420 owner->currentBuffer()->text->FinishUndo();
1421 moveCursorUpdate(false);
1422 owner->getMiniBuffer()->Set(CurrentState());
1426 if(!owner->currentBuffer()->text->mark_set)
1428 owner->currentBuffer()->update(-2);
1429 owner->currentBuffer()->text->CursorLeftOneWord();
1430 owner->currentBuffer()->text->FinishUndo();
1431 moveCursorUpdate(false);
1432 owner->getMiniBuffer()->Set(CurrentState());
1435 case LFUN_BEGINNINGBUF:
1436 if(!owner->currentBuffer()->text->mark_set)
1438 owner->currentBuffer()->update(-2);
1439 owner->currentBuffer()->text->CursorTop();
1440 owner->currentBuffer()->text->FinishUndo();
1441 moveCursorUpdate(false);
1442 owner->getMiniBuffer()->Set(CurrentState());
1446 if(!owner->currentBuffer()->text->mark_set)
1448 owner->currentBuffer()->update(-2);
1449 owner->currentBuffer()->text->CursorBottom();
1450 owner->currentBuffer()->text->FinishUndo();
1451 moveCursorUpdate(false);
1452 owner->getMiniBuffer()->Set(CurrentState());
1456 /* cursor selection ---------------------------- */
1458 owner->currentBuffer()->update(-2);
1459 owner->currentBuffer()->text->CursorRight();
1460 owner->currentBuffer()->text->FinishUndo();
1461 moveCursorUpdate(true);
1462 owner->getMiniBuffer()->Set(CurrentState());
1466 owner->currentBuffer()->update(-2);
1467 owner->currentBuffer()->text->CursorLeft();
1468 owner->currentBuffer()->text->FinishUndo();
1469 moveCursorUpdate(true);
1470 owner->getMiniBuffer()->Set(CurrentState());
1474 owner->currentBuffer()->update(-2);
1475 owner->currentBuffer()->text->CursorUp();
1476 owner->currentBuffer()->text->FinishUndo();
1477 moveCursorUpdate(true);
1478 owner->getMiniBuffer()->Set(CurrentState());
1482 owner->currentBuffer()->update(-2);
1483 owner->currentBuffer()->text->CursorDown();
1484 owner->currentBuffer()->text->FinishUndo();
1485 moveCursorUpdate(true);
1486 owner->getMiniBuffer()->Set(CurrentState());
1489 case LFUN_UP_PARAGRAPHSEL:
1490 owner->currentBuffer()->update(-2);
1491 owner->currentBuffer()->text->CursorUpParagraph();
1492 owner->currentBuffer()->text->FinishUndo();
1493 moveCursorUpdate(true);
1494 owner->getMiniBuffer()->Set(CurrentState());
1497 case LFUN_DOWN_PARAGRAPHSEL:
1498 owner->currentBuffer()->update(-2);
1499 owner->currentBuffer()->text->CursorDownParagraph();
1500 owner->currentBuffer()->text->FinishUndo();
1501 moveCursorUpdate(true);
1502 owner->getMiniBuffer()->Set(CurrentState());
1506 owner->currentBuffer()->update(-2);
1507 owner->currentView()->cursorPrevious();
1508 owner->currentBuffer()->text->FinishUndo();
1509 moveCursorUpdate(true);
1510 owner->getMiniBuffer()->Set(CurrentState());
1514 owner->currentBuffer()->update(-2);
1515 owner->currentView()->cursorNext();
1516 owner->currentBuffer()->text->FinishUndo();
1517 moveCursorUpdate(true);
1518 owner->getMiniBuffer()->Set(CurrentState());
1522 owner->currentBuffer()->update(-2);
1523 owner->currentBuffer()->text->CursorHome();
1524 owner->currentBuffer()->text->FinishUndo();
1525 moveCursorUpdate(true);
1526 owner->getMiniBuffer()->Set(CurrentState());
1530 owner->currentBuffer()->update(-2);
1531 owner->currentBuffer()->text->CursorEnd();
1532 owner->currentBuffer()->text->FinishUndo();
1533 moveCursorUpdate(true);
1534 owner->getMiniBuffer()->Set(CurrentState());
1537 case LFUN_WORDRIGHTSEL:
1538 owner->currentBuffer()->update(-2);
1539 owner->currentBuffer()->text->CursorRightOneWord();
1540 owner->currentBuffer()->text->FinishUndo();
1541 moveCursorUpdate(true);
1542 owner->getMiniBuffer()->Set(CurrentState());
1545 case LFUN_WORDLEFTSEL:
1546 owner->currentBuffer()->update(-2);
1547 owner->currentBuffer()->text->CursorLeftOneWord();
1548 owner->currentBuffer()->text->FinishUndo();
1549 moveCursorUpdate(true);
1550 owner->getMiniBuffer()->Set(CurrentState());
1553 case LFUN_BEGINNINGBUFSEL:
1554 owner->currentBuffer()->update(-2);
1555 owner->currentBuffer()->text->CursorTop();
1556 owner->currentBuffer()->text->FinishUndo();
1557 moveCursorUpdate(true);
1558 owner->getMiniBuffer()->Set(CurrentState());
1561 case LFUN_ENDBUFSEL:
1562 owner->currentBuffer()->update(-2);
1563 owner->currentBuffer()->text->CursorBottom();
1564 owner->currentBuffer()->text->FinishUndo();
1565 moveCursorUpdate(true);
1566 owner->getMiniBuffer()->Set(CurrentState());
1569 // --- text changing commands ------------------------
1570 case LFUN_BREAKLINE:
1572 owner->currentBuffer()->text->InsertChar(LYX_META_NEWLINE);
1574 SetUpdateTimer(0.01);
1575 moveCursorUpdate(false);
1578 case LFUN_PROTECTEDSPACE:
1580 owner->currentBuffer()->text->
1581 InsertChar(LYX_META_PROTECTED_SEPARATOR);
1584 moveCursorUpdate(false);
1588 if(owner->currentBuffer()->text->mark_set) {
1590 owner->currentBuffer()->update(0);
1591 setMessage(N_("Mark removed"));
1594 owner->currentBuffer()->text->mark_set = 1;
1595 owner->currentBuffer()->update(0);
1596 setMessage(N_("Mark set"));
1598 owner->currentBuffer()->text->sel_cursor =
1599 owner->currentBuffer()->text->cursor;
1604 if (!owner->currentBuffer()->text->selection) {
1605 owner->currentBuffer()->text->Delete();
1606 owner->currentBuffer()->text->sel_cursor =
1607 owner->currentBuffer()->text->cursor;
1609 // It is possible to make it a lot faster still
1610 // just comment out the lone below...
1611 owner->currentView()->getScreen()->ShowCursor();
1618 case LFUN_DELETE_SKIP:
1620 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
1622 LyXCursor cursor = owner->currentBuffer()->text->cursor;
1625 if (!owner->currentBuffer()->text->selection) {
1626 if (cursor.pos == cursor.par->Last()) {
1627 owner->currentBuffer()->text->CursorRight();
1628 cursor = owner->currentBuffer()->text->cursor;
1630 && !(cursor.par->added_space_top
1631 == VSpace (VSpace::NONE))) {
1632 owner->currentBuffer()->text->SetParagraph
1633 (cursor.par->line_top,
1634 cursor.par->line_bottom,
1635 cursor.par->pagebreak_top,
1636 cursor.par->pagebreak_bottom,
1637 VSpace(VSpace::NONE),
1638 cursor.par->added_space_bottom,
1640 cursor.par->labelwidthstring, 0);
1641 owner->currentBuffer()->text->CursorLeft();
1642 owner->currentBuffer()->update (1);
1644 owner->currentBuffer()->text->CursorLeft();
1645 owner->currentBuffer()->text->Delete();
1646 owner->currentBuffer()->text->sel_cursor =
1647 owner->currentBuffer()->text->cursor;
1651 owner->currentBuffer()->text->Delete();
1652 owner->currentBuffer()->text->sel_cursor =
1653 owner->currentBuffer()->text->cursor;
1663 /* -------> Delete word forward. */
1664 case LFUN_DELETE_WORD_FORWARD:
1665 owner->currentBuffer()->update(-2);
1667 owner->currentBuffer()->text->DeleteWordForward();
1668 owner->currentBuffer()->update( 1 );
1670 moveCursorUpdate(false);
1673 /* -------> Delete word backward. */
1674 case LFUN_DELETE_WORD_BACKWARD:
1675 owner->currentBuffer()->update(-2);
1677 owner->currentBuffer()->text->DeleteWordBackward();
1678 owner->currentBuffer()->update( 1 );
1680 moveCursorUpdate(false);
1683 /* -------> Kill to end of line. */
1684 case LFUN_DELETE_LINE_FORWARD:
1686 owner->currentBuffer()->update(-2);
1687 owner->currentBuffer()->text->DeleteLineForward();
1688 owner->currentBuffer()->update( 1 );
1690 moveCursorUpdate(false);
1693 /* -------> Set mark off. */
1696 owner->currentBuffer()->update(0);
1697 owner->currentBuffer()->text->sel_cursor =
1698 owner->currentBuffer()->text->cursor;
1699 setMessage(N_("Mark off"));
1702 /* -------> Set mark on. */
1705 owner->currentBuffer()->text->mark_set = 1;
1706 owner->currentBuffer()->update( 0 );
1707 owner->currentBuffer()->text->sel_cursor =
1708 owner->currentBuffer()->text->cursor;
1709 setMessage(N_("Mark on"));
1712 case LFUN_BACKSPACE:
1715 if (!owner->currentBuffer()->text->selection) {
1716 if (owner->getIntl()->getTrans()->backspace()) {
1717 owner->currentBuffer()->text->Backspace();
1718 owner->currentBuffer()->text->sel_cursor =
1719 owner->currentBuffer()->text->cursor;
1721 // It is possible to make it a lot faster still
1722 // just comment out the lone below...
1723 owner->currentView()->getScreen()->ShowCursor();
1732 case LFUN_BACKSPACE_SKIP:
1734 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
1736 LyXCursor cursor = owner->currentBuffer()->text->cursor;
1739 if (!owner->currentBuffer()->text->selection) {
1741 && !(cursor.par->added_space_top
1742 == VSpace (VSpace::NONE))) {
1743 owner->currentBuffer()->text->SetParagraph
1744 (cursor.par->line_top,
1745 cursor.par->line_bottom,
1746 cursor.par->pagebreak_top,
1747 cursor.par->pagebreak_bottom,
1748 VSpace(VSpace::NONE), cursor.par->added_space_bottom,
1750 cursor.par->labelwidthstring, 0);
1751 owner->currentBuffer()->update (1);
1753 owner->currentBuffer()->text->Backspace();
1754 owner->currentBuffer()->text->sel_cursor
1764 case LFUN_BREAKPARAGRAPH:
1767 owner->currentBuffer()->text->BreakParagraph(0);
1769 SetUpdateTimer(0.01);
1770 owner->currentBuffer()->text->sel_cursor =
1771 owner->currentBuffer()->text->cursor;
1775 case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
1778 owner->currentBuffer()->text->BreakParagraph(1);
1780 SetUpdateTimer(0.01);
1781 owner->currentBuffer()->text->sel_cursor =
1782 owner->currentBuffer()->text->cursor;
1786 case LFUN_BREAKPARAGRAPH_SKIP:
1788 // When at the beginning of a paragraph, remove
1789 // indentation and add a "defskip" at the top.
1790 // Otherwise, do the same as LFUN_BREAKPARAGRAPH.
1792 LyXCursor cursor = owner->currentBuffer()->text->cursor;
1795 if (cursor.pos == 0) {
1796 if (cursor.par->added_space_top == VSpace(VSpace::NONE)) {
1797 owner->currentBuffer()->text->SetParagraph
1798 (cursor.par->line_top,
1799 cursor.par->line_bottom,
1800 cursor.par->pagebreak_top,
1801 cursor.par->pagebreak_bottom,
1802 VSpace(VSpace::DEFSKIP), cursor.par->added_space_bottom,
1804 cursor.par->labelwidthstring, 1);
1805 owner->currentBuffer()->update(1);
1809 owner->currentBuffer()->text->BreakParagraph(0);
1812 SetUpdateTimer(0.01);
1813 owner->currentBuffer()->text->sel_cursor = cursor;
1819 owner->currentBuffer()->text->InsertChar('\"'); // This " matches the single quote in the code
1822 moveCursorUpdate(false);
1828 InsetCommand *new_inset;
1829 if (action == LFUN_HTMLURL)
1830 new_inset = new InsetUrl("htmlurl", "", "");
1832 new_inset = new InsetUrl("url", "", "");
1833 owner->currentBuffer()->insertInset(new_inset);
1834 new_inset->Edit(0, 0);
1838 // --- lyxserver commands ----------------------------
1840 case LFUN_CHARATCURSOR:
1842 int pos = owner->currentBuffer()->text->cursor.pos;
1843 if(pos < owner->currentBuffer()->text->cursor.par->last)
1844 dispatch_buffer = owner->currentBuffer()->text->
1845 cursor.par->text[pos];
1847 dispatch_buffer = "EOF";
1853 tostr(owner->currentBuffer()->text->cursor.x) + ' '
1854 + tostr(owner->currentBuffer()->text->cursor.y);
1861 sscanf(argument.c_str(), " %d %ld", &x, &y);
1862 owner->currentBuffer()->text->SetCursorFromCoordinates(x, y);
1866 case LFUN_GETLAYOUT:
1868 tostr(owner->currentBuffer()->text->cursor.par->layout);
1873 LyXFont *font = &(owner->currentBuffer()->text->current_font);
1874 if(font->shape() == LyXFont::ITALIC_SHAPE)
1875 dispatch_buffer = 'E';
1876 else if(font->shape() == LyXFont::SMALLCAPS_SHAPE)
1877 dispatch_buffer = 'N';
1879 dispatch_buffer = '0';
1886 LyXFont *font = &(owner->currentBuffer()->text->current_font);
1887 if(font->latex() == LyXFont::ON)
1888 dispatch_buffer = 'L';
1890 dispatch_buffer = '0';
1895 setMessage(owner->currentBuffer()->getFileName());
1896 lyxerr.debug() << "FNAME["
1897 << owner->currentBuffer()->getFileName()
1904 keyseq.print(buf,100);
1905 dispatch_buffer = buf;
1906 lyxserver->notifyClient(dispatch_buffer);
1910 case LFUN_GOTOFILEROW:
1912 char file_name[100];
1914 sscanf(argument.c_str(), " %s %d", file_name, &row);
1916 // Must replace extension of the file to be .lyx and get full path
1917 string s = ChangeExtension(string(file_name), ".lyx", false);
1919 // Either change buffer or load the file
1920 if (bufferlist.exists(s))
1921 owner->currentView()->setBuffer(bufferlist.getBuffer(s));
1923 owner->currentView()->setBuffer(bufferlist.loadLyXFile(s));
1926 owner->currentBuffer()->setCursorFromRow(row);
1930 if (owner->currentBuffer()->text->cursor.y >
1931 owner->currentView()->getWorkArea()->h / 2) {
1932 owner->currentView()->getScreen()->
1933 Draw(owner->currentBuffer()->text->cursor.y -
1934 owner->currentView()->getWorkArea()->h/2);
1936 owner->currentView()->getScreen()->
1939 owner->currentBuffer()->update(0);
1940 owner->currentView()->redraw();
1947 int qa = lyxaction.LookupFunc(argument.c_str());
1948 setMessage(lyxaction.helpText((kb_action)qa));
1952 // --- accented characters ---------------------------
1955 case LFUN_CIRCUMFLEX:
1965 case LFUN_SPECIAL_CARON:
1968 case LFUN_HUNG_UMLAUT:
1974 if (keyseq.length==-1 && keyseq.getiso()!=0)
1979 owner->getIntl()->getTrans()->
1980 deadkey(c, get_accent(action).accent,
1981 owner->currentBuffer()->text);
1983 // Need to reset, in case the minibuffer calls these
1988 // copied verbatim from do_accent_char
1991 owner->currentBuffer()->text->sel_cursor =
1992 owner->currentBuffer()->text->cursor;
1996 // --- toolbar ----------------------------------
1997 case LFUN_PUSH_TOOLBAR:
1999 int nth = strToInt(argument);
2000 if (lyxerr.debugging(Debug::TOOLBAR)) {
2001 lyxerr << "LFUN_PUSH_TOOLBAR: argument = `"
2002 << argument << "'\n"
2003 << "LFUN_PUSH_TOOLBAR: nth = `"
2004 << nth << "'" << endl;
2009 setErrorMessage(N_("Push-toolbar needs argument > 0"));
2011 owner->getToolbar()->push(nth);
2016 case LFUN_ADD_TO_TOOLBAR:
2018 if (lyxerr.debugging(Debug::TOOLBAR)) {
2019 lyxerr << "LFUN_ADD_TO_TOOLBAR:"
2020 "argument = `" << argument << '\'' << endl;
2022 string tmp(argument);
2023 //lyxerr <<string("Argument: ") + argument);
2024 //lyxerr <<string("Tmp : ") + tmp);
2027 setErrorMessage(N_("Usage: toolbar-add-to <LyX command>"));
2029 owner->getToolbar()->add(argument, false);
2030 owner->getToolbar()->set();
2035 // --- insert characters ----------------------------------------
2037 case LFUN_INSERT_INSET_LATEX:
2039 Inset *new_inset = new InsetLatex(argument);
2040 owner->currentBuffer()->insertInset(new_inset);
2044 // --- Mathed stuff. If we are here, there is no locked inset yet.
2049 if (!greek_kb_flag) {
2051 setMessage(N_("Math greek mode on"));
2058 case LFUN_GREEK_TOGGLE:
2060 greek_kb_flag = (greek_kb_flag) ? 0: 2;
2061 if (greek_kb_flag) {
2062 setMessage(N_("Math greek keyboard on"));
2064 setMessage(N_("Math greek keyboard off"));
2069 case LFUN_MATH_DELIM:
2070 case LFUN_INSERT_MATRIX:
2072 if (owner->currentView()->available()) {
2073 owner->currentBuffer()->
2074 open_new_inset(new InsetFormula(false));
2075 owner->currentBuffer()->
2076 the_locking_inset->LocalDispatch(action, argument.c_str());
2081 case LFUN_INSERT_MATH:
2083 math_insert_symbol(argument.c_str());
2087 case LFUN_MATH_DISPLAY:
2089 if (owner->currentView()->available())
2090 owner->currentBuffer()->open_new_inset(new InsetFormula(true));
2094 case LFUN_MATH_MACRO:
2096 if (owner->currentView()->available()) {
2099 setErrorMessage(N_("Missing argument"));
2101 string s1 = token(s, ' ', 1);
2102 int na = s1.empty() ? 0: atoi(s1.c_str());
2103 owner->currentBuffer()->
2104 open_new_inset(new InsetFormulaMacro(token(s, ' ', 0), na));
2110 case LFUN_MATH_MODE: // Open or create a math inset
2113 if (owner->currentView()->available())
2114 owner->currentBuffer()->open_new_inset(new InsetFormula);
2115 setMessage(N_("Math editor mode"));
2119 case LFUN_MATH_NUMBER:
2120 case LFUN_MATH_LIMITS:
2122 setErrorMessage(N_("This is only allowed in math mode!"));
2126 case LFUN_INSERT_CITATION:
2128 InsetCitation *new_inset = new InsetCitation();
2130 // The note, if any, must be after the key, delimited
2131 // by a | so both key and remark can have spaces.
2132 if (!argument.empty()) {
2133 string lsarg(argument);
2134 if (contains(lsarg, "|")) {
2135 new_inset->setContents(token(lsarg, '|', 0));
2136 new_inset->setOptions(token(lsarg, '|', 1));
2138 new_inset->setContents(lsarg);
2139 owner->currentBuffer()->insertInset(new_inset);
2141 owner->currentBuffer()->insertInset(new_inset);
2142 new_inset->Edit(0,0);
2147 case LFUN_INSERT_BIBTEX:
2149 // ale970405+lasgoutt970425
2150 // The argument can be up to two tokens separated
2151 // by a space. The first one is the bibstyle.
2152 string lsarg(argument);
2153 string bibstyle = token(lsarg, ' ', 1);
2154 if (bibstyle.empty())
2156 InsetBibtex *new_inset
2157 = new InsetBibtex(token(lsarg, ' ', 0),
2159 owner->currentBuffer());
2161 owner->currentBuffer()->insertInset(new_inset);
2162 if (lsarg.empty()) {
2163 new_inset->Edit(0,0);
2168 // BibTeX data bases
2169 case LFUN_BIBDB_ADD:
2171 InsetBibtex *inset =
2172 (InsetBibtex*)getInsetByCode(Inset::BIBTEX_CODE);
2174 inset->addDatabase(argument);
2179 case LFUN_BIBDB_DEL:
2181 InsetBibtex *inset =
2182 (InsetBibtex*)getInsetByCode(Inset::BIBTEX_CODE);
2184 inset->delDatabase(argument);
2189 case LFUN_BIBTEX_STYLE:
2191 InsetBibtex *inset =
2192 (InsetBibtex*)getInsetByCode(Inset::BIBTEX_CODE);
2194 inset->setOptions(argument);
2199 case LFUN_INDEX_INSERT:
2200 case LFUN_INDEX_INSERT_LAST:
2202 InsetIndex *new_inset = new InsetIndex();
2203 if (!argument.empty()) {
2204 string lsarg(argument);
2205 new_inset->setContents(lsarg);
2206 owner->currentBuffer()->insertInset(new_inset);
2209 //get the current word for an argument
2214 int lastpos =owner->currentBuffer()->text->cursor.pos-1;
2216 //this shouldn't happen, but let's be careful
2217 if (lastpos < 0) lastpos=0;
2219 // get the current word
2220 // note that this must be done before
2221 // inserting the inset, or the inset will break
2223 string curstring(owner->currentBuffer()->text->cursor.par->GetWord(lastpos));
2225 //make the new inset and write the current word into it
2226 InsetIndex *new_inset = new InsetIndex();
2228 new_inset->setContents(curstring);
2230 //don't edit it if the call was to INSERT_LAST
2231 if(action!=LFUN_INDEX_INSERT_LAST) {
2232 new_inset->Edit(0,0);
2234 //it looks blank on the screen unless
2235 //we do something. put it here.
2237 // move the cursor to the returned value of lastpos
2238 // but only for the auto-insert
2239 owner->currentBuffer()->text->cursor.pos=lastpos;
2242 //put the new inset into the buffer.
2243 // there should be some way of knowing the user
2244 //cancelled & avoiding this, but i don't know how
2245 owner->currentBuffer()->insertInset(new_inset);
2250 case LFUN_INDEX_PRINT:
2252 Inset *new_inset = new InsetPrintIndex(owner->currentBuffer());
2253 owner->currentBuffer()->insertInset(new_inset, "Standard", true);
2257 case LFUN_PARENTINSERT:
2259 lyxerr << "arg " << argument << endl;
2260 Inset *new_inset = new InsetParent(argument, owner->currentBuffer());
2261 owner->currentBuffer()->insertInset(new_inset, "Standard", true);
2265 case LFUN_CHILDINSERT:
2267 Inset *new_inset = new InsetInclude(argument,owner->currentBuffer());
2268 owner->currentBuffer()->insertInset(new_inset, "Standard", true);
2269 new_inset->Edit(0,0);
2273 case LFUN_CHILDOPEN:
2275 string filename = MakeAbsPath(argument,
2276 OnlyPath(owner->currentBuffer()->getFileName()));
2277 setMessage(N_("Opening child document ") +
2278 MakeDisplayPath(filename) + "...");
2279 owner->currentView()->savePosition();
2280 if (bufferlist.exists(filename))
2281 owner->currentView()->setBuffer(bufferlist.getBuffer(filename));
2283 owner->currentView()->setBuffer(bufferlist.loadLyXFile(filename));
2287 case LFUN_INSERT_NOTE:
2291 case LFUN_INSERTFOOTNOTE:
2293 LyXParagraph::footnote_kind kind;
2294 if (argument == "footnote")
2295 { kind = LyXParagraph::FOOTNOTE; }
2296 else if (argument == "margin")
2297 { kind = LyXParagraph::MARGIN; }
2298 else if (argument == "figure")
2299 { kind = LyXParagraph::FIG; }
2300 else if (argument == "table")
2301 { kind = LyXParagraph::TAB; }
2302 else if (argument == "wide-fig")
2303 { kind = LyXParagraph::WIDE_FIG; }
2304 else if (argument == "wide-tab")
2305 { kind = LyXParagraph::WIDE_TAB; }
2306 else if (argument == "algorithm")
2307 { kind = LyXParagraph::ALGORITHM; }
2309 setErrorMessage(N_("Unknown kind of footnote"));
2312 owner->currentBuffer()->text->InsertFootnoteEnvironment(kind);
2313 owner->currentBuffer()->update(1);
2317 case LFUN_BUFFERBULLETSSELECT:
2321 case LFUN_TOGGLECURSORFOLLOW:
2322 cursor_follows_scrollbar = !cursor_follows_scrollbar;
2325 case LFUN_KMAP_OFF: // keymap off
2326 owner->getIntl()->KeyMapOn(false);
2329 case LFUN_KMAP_PRIM: // primary keymap
2330 owner->getIntl()->KeyMapPrim();
2333 case LFUN_KMAP_SEC: // secondary keymap
2334 owner->getIntl()->KeyMapSec();
2337 case LFUN_KMAP_TOGGLE: // toggle keymap
2338 owner->getIntl()->ToggleKeyMap();
2341 case LFUN_SELFINSERT:
2343 for (string::size_type i = 0; i < argument.length(); ++i) {
2344 owner->currentBuffer()->text->InsertChar(argument[i]);
2345 // This needs to be in the loop, or else we
2346 // won't break lines correctly. (Asger)
2350 owner->currentBuffer()->text->sel_cursor =
2351 owner->currentBuffer()->text->cursor;
2352 moveCursorUpdate(false);
2356 case LFUN_UNKNOWN_ACTION:
2358 if (owner->currentBuffer()->isReadonly()) {
2360 setErrorMessage(N_("Document is read only"));
2364 if (!argument.empty()) {
2366 /* Automatically delete the currently selected
2367 * text and replace it with what is being
2368 * typed in now. Depends on lyxrc settings
2369 * "auto_region_delete", which defaults to
2372 if ( lyxrc->auto_region_delete ) {
2373 if (owner->currentBuffer()->text->selection){
2374 owner->currentBuffer()->text->CutSelection(false);
2375 owner->currentBuffer()->update(-1);
2380 for (string::size_type i = 0; i < argument.length(); ++i) {
2381 if (greek_kb_flag) {
2382 if (!math_insert_greek(argument[i]))
2383 owner->getIntl()->getTrans()->TranslateAndInsert(argument[i], owner->currentBuffer()->text);
2385 owner->getIntl()->getTrans()->TranslateAndInsert(argument[i], owner->currentBuffer()->text);
2391 owner->currentBuffer()->text->sel_cursor =
2392 owner->currentBuffer()->text->cursor;
2393 moveCursorUpdate(false);
2396 // why is an "Unknown action" with empty
2397 // argument even dispatched in the first
2398 // place? I`ll probably change that. (Lgb)
2400 setErrorMessage(N_("Unknown action"));
2404 lyxerr << "A truly unknown func!" << endl;
2410 string res=getMessage();
2413 if (!commandshortcut.empty()) {
2414 string newbuf = owner->getMiniBuffer()->GetText();
2415 if (newbuf != commandshortcut) {
2416 owner->getMiniBuffer()->Set(newbuf
2422 owner->getMiniBuffer()->Set(string(_(res.c_str()))
2423 + " " + commandshortcut);
2426 return getMessage();
2430 void LyXFunc::setupLocalKeymap()
2432 keyseq.stdmap = keyseq.curmap = toplevel_keymap;
2433 cancel_meta_seq.stdmap = cancel_meta_seq.curmap = toplevel_keymap;
2437 void LyXFunc::MenuNew(bool fromTemplate)
2439 string fname, initpath = lyxrc->document_path;
2442 if (owner->currentView()->available()) {
2443 string trypath = owner->currentBuffer()->filepath;
2444 // If directory is writeable, use this as default.
2445 if (IsDirWriteable(trypath) == 1)
2450 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2451 fileDlg.SetButton(1, _("Templates"), lyxrc->template_path);
2452 fname = fileDlg.Select(_("Enter Filename for new document"),
2453 initpath, "*.lyx", _("newfile"));
2456 if (fname.empty()) {
2457 owner->getMiniBuffer()->Set(_("Canceled."));
2458 lyxerr.debug() << "New Document Cancelled." << endl;
2462 // get absolute path of file and make sure the filename ends
2464 string s = MakeAbsPath(fname);
2465 if (!IsLyXFilename(s))
2468 // Check if the document already is open
2469 if (bufferlist.exists(s)){
2470 switch(AskConfirmation(_("Document is already open:"),
2471 MakeDisplayPath(s,50),
2472 _("Do you want to close that document now?\n"
2473 "('No' will just switch to the open version)")))
2475 case 1: // Yes: close the document
2476 if (!bufferlist.close(bufferlist.getBuffer(s)))
2477 // If close is canceled, we cancel here too.
2480 case 2: // No: switch to the open document
2481 owner->currentView()->setBuffer(bufferlist.getBuffer(s));
2483 case 3: // Cancel: Do nothing
2484 owner->getMiniBuffer()->Set(_("Canceled."));
2489 // Check whether the file already exists
2490 if (IsLyXFilename(s)) {
2491 FilePtr myfile(s, FilePtr::read);
2493 AskQuestion(_("File already exists:"),
2494 MakeDisplayPath(s,50),
2495 _("Do you want to open the document?"))) {
2497 owner->getMiniBuffer()->Set(_("Opening document"),
2498 MakeDisplayPath(s), "...");
2500 owner->currentView()->setBuffer(
2501 bufferlist.loadLyXFile(s));
2502 owner->getMiniBuffer()->Set(_("Document"),
2509 // The template stuff
2513 fname = fileDlg.Select(_("Choose template"),
2514 lyxrc->template_path,
2520 // find a free buffer
2521 lyxerr.debug() << "Find a free buffer." << endl;
2522 owner->currentView()->setBuffer(bufferlist.newFile(s,templname));
2526 void LyXFunc::MenuOpen()
2528 string initpath = lyxrc->document_path;
2531 if (owner->currentView()->available()) {
2532 string trypath = owner->currentBuffer()->filepath;
2533 // If directory is writeable, use this as default.
2534 if (IsDirWriteable(trypath) == 1)
2540 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2541 fileDlg.SetButton(1, _("Examples"),
2542 AddPath(system_lyxdir, "examples"));
2543 string filename = fileDlg.Select(_("Select Document to Open"),
2547 // check selected filename
2548 if (filename.empty()) {
2549 owner->getMiniBuffer()->Set(_("Canceled."));
2553 // get absolute path of file and make sure the filename ends
2555 filename = MakeAbsPath(filename);
2556 if (!IsLyXFilename(filename))
2560 owner->getMiniBuffer()->Set(_("Opening document"),
2561 MakeDisplayPath(filename), "...");
2562 Buffer * openbuf = bufferlist.loadLyXFile(filename);
2564 owner->currentView()->setBuffer(openbuf);
2565 owner->getMiniBuffer()->Set(_("Document"),
2566 MakeDisplayPath(filename),
2569 owner->getMiniBuffer()->Set(_("Could not open document"),
2570 MakeDisplayPath(filename));
2575 void LyXFunc::doImportASCII(bool linorpar)
2577 string initpath = lyxrc->document_path;
2580 if (owner->currentView()->available()) {
2581 string trypath = owner->currentBuffer()->filepath;
2582 // If directory is writeable, use this as default.
2583 if (IsDirWriteable(trypath) == 1)
2589 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2590 fileDlg.SetButton(1, _("Examples"),
2591 AddPath(system_lyxdir, "examples"));
2592 string filename = fileDlg.Select(_("Select ASCII file to Import"),
2596 // check selected filename
2597 if (filename.empty()) {
2598 owner->getMiniBuffer()->Set(_("Canceled."));
2602 // get absolute path of file
2603 filename = MakeAbsPath(filename);
2605 string s = ChangeExtension(filename, ".lyx", false);
2607 // Check if the document already is open
2608 if (bufferlist.exists(s)){
2609 switch(AskConfirmation(_("Document is already open:"),
2610 MakeDisplayPath(s,50),
2611 _("Do you want to close that document now?\n"
2612 "('No' will just switch to the open version)")))
2614 case 1: // Yes: close the document
2615 if (!bufferlist.close(bufferlist.getBuffer(s)))
2616 // If close is canceled, we cancel here too.
2619 case 2: // No: switch to the open document
2620 owner->currentView()->setBuffer(bufferlist.getBuffer(s));
2622 case 3: // Cancel: Do nothing
2623 owner->getMiniBuffer()->Set(_("Canceled."));
2628 // Check if a LyX document by the same root exists in filesystem
2629 FileInfo f(s, true);
2630 if (f.exist() && !AskQuestion(_("A document by the name"),
2632 _("already exists. Overwrite?"))) {
2633 owner->getMiniBuffer()->Set(_("Canceled."));
2637 owner->currentView()->setBuffer(bufferlist.newFile(s,string()));
2638 owner->getMiniBuffer()->Set(_("Importing ASCII file"),
2639 MakeDisplayPath(filename), "...");
2640 // Insert ASCII file
2641 InsertAsciiFile(filename,linorpar);
2642 owner->getMiniBuffer()->Set(_("ASCII file "),
2643 MakeDisplayPath(filename),
2648 void LyXFunc::doImportLaTeX(bool isnoweb)
2650 string initpath = lyxrc->document_path;
2653 if (owner->currentView()->available()) {
2654 string trypath = owner->currentBuffer()->filepath;
2655 // If directory is writeable, use this as default.
2656 if (IsDirWriteable(trypath) == 1)
2662 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2663 fileDlg.SetButton(1, _("Examples"),
2664 AddPath(system_lyxdir, "examples"));
2667 filename = fileDlg.Select(_("Select Noweb file to Import"),
2670 filename = fileDlg.Select(_("Select LaTeX file to Import"),
2676 // check selected filename
2677 if (filename.empty()) {
2678 owner->getMiniBuffer()->Set(_("Canceled."));
2682 // get absolute path of file
2683 filename = MakeAbsPath(filename);
2685 // Check if the document already is open
2686 string LyXfilename = ChangeExtension(filename, ".lyx", false);
2687 if (bufferlist.exists(LyXfilename)){
2688 switch(AskConfirmation(_("Document is already open:"),
2689 MakeDisplayPath(LyXfilename,50),
2690 _("Do you want to close that document now?\n"
2691 "('No' will just switch to the open version)")))
2693 case 1: // Yes: close the document
2694 if (!bufferlist.close(bufferlist.getBuffer(LyXfilename)))
2695 // If close is canceled, we cancel here too.
2698 case 2: // No: switch to the open document
2699 owner->currentView()->setBuffer(
2700 bufferlist.getBuffer(LyXfilename));
2702 case 3: // Cancel: Do nothing
2703 owner->getMiniBuffer()->Set(_("Canceled."));
2708 // Check if a LyX document by the same root exists in filesystem
2709 FileInfo f(LyXfilename, true);
2710 if (f.exist() && !AskQuestion(_("A document by the name"),
2711 MakeDisplayPath(LyXfilename),
2712 _("already exists. Overwrite?"))) {
2713 owner->getMiniBuffer()->Set(_("Canceled."));
2720 owner->getMiniBuffer()->Set(_("Importing LaTeX file"),
2721 MakeDisplayPath(filename), "...");
2722 ImportLaTeX myImport(filename);
2723 openbuf = myImport.run();
2725 owner->getMiniBuffer()->Set(_("Importing Noweb file"),
2726 MakeDisplayPath(filename), "...");
2727 ImportNoweb myImport(filename);
2728 openbuf = myImport.run();
2731 owner->currentView()->setBuffer(openbuf);
2732 owner->getMiniBuffer()->Set(isnoweb ?
2733 _("Noweb file ") : _("LateX file "),
2734 MakeDisplayPath(filename),
2737 owner->getMiniBuffer()->Set(isnoweb ?
2738 _("Could not import Noweb file") :
2739 _("Could not import LaTeX file"),
2740 MakeDisplayPath(filename));
2745 void LyXFunc::MenuInsertLyXFile(string const & filen)
2747 string filename = filen;
2749 if (filename.empty()) {
2750 // Launch a file browser
2751 string initpath = lyxrc->document_path;
2754 if (owner->currentView()->available()) {
2755 string trypath = owner->currentBuffer()->filepath;
2756 // If directory is writeable, use this as default.
2757 if (IsDirWriteable(trypath) == 1)
2763 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2764 fileDlg.SetButton(1, _("Examples"),
2765 AddPath(system_lyxdir, "examples"));
2766 filename = fileDlg.Select(_("Select Document to Insert"),
2770 // check selected filename
2771 if (filename.empty()) {
2772 owner->getMiniBuffer()->Set(_("Canceled."));
2777 // get absolute path of file and make sure the filename ends
2779 filename = MakeAbsPath(filename);
2780 if (!IsLyXFilename(filename))
2784 owner->getMiniBuffer()->Set(_("Inserting document"),
2785 MakeDisplayPath(filename), "...");
2786 bool res = owner->currentBuffer()->insertLyXFile(filename);
2788 owner->getMiniBuffer()->Set(_("Document"),
2789 MakeDisplayPath(filename),
2792 owner->getMiniBuffer()->Set(_("Could not insert document"),
2793 MakeDisplayPath(filename));
2798 void LyXFunc::reloadBuffer()
2800 string fn = owner->currentBuffer()->getFileName();
2801 if (bufferlist.close(owner->currentBuffer()))
2802 owner->currentView()->setBuffer(bufferlist.loadLyXFile(fn));
2806 void LyXFunc::CloseBuffer()
2808 if (bufferlist.close(owner->currentBuffer()) && !quitting) {
2809 if (bufferlist.isEmpty()) {
2810 // need this otherwise SEGV may occur while trying to
2811 // set variables that don't exist
2812 // since there's no current buffer
2813 CloseAllBufferRelatedPopups();
2816 owner->currentView()->setBuffer(bufferlist.first());
2822 Inset* LyXFunc::getInsetByCode(Inset::Code code)
2826 LyXCursor cursor = owner->currentBuffer()->text->cursor;
2827 int pos = cursor.pos;
2828 LyXParagraph *par = cursor.par;
2830 while (par && !found) {
2831 while ((inset = par->ReturnNextInsetPointer(pos))){
2832 if (inset->LyxCode()==code) {
2840 return (found) ? inset: 0;
2844 // Each "owner" should have it's own message method. lyxview and
2845 // the minibuffer would use the minibuffer, but lyxserver would
2846 // send an ERROR signal to its client. Alejandro 970603
2847 // This func is bit problematic when it comes to NLS, to make the
2848 // lyx servers client be language indepenent we must not translate
2849 // strings sent to this func.
2850 void LyXFunc::setErrorMessage(string const &m)
2852 dispatch_buffer = m;
2857 void LyXFunc::setMessage(string const & m)
2859 dispatch_buffer = m;