1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright (C) 1995 Matthias Ettrich
7 * Copyright (C) 1995-1998 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 "filetools.h"
53 #include "lyxscreen.h"
58 #include "trans_mgr.h"
59 #include "ImportLaTeX.h"
60 #include "ImportNoweb.h"
62 // $Id: lyxfunc.C,v 1.1 1999/09/27 18:44:37 larsbj Exp $
64 #if !defined(lint) && !defined(WITH_WARNINGS)
65 static char vcid[] = "$Id: lyxfunc.C,v 1.1 1999/09/27 18:44:37 larsbj Exp $";
68 extern bool cursor_follows_scrollbar;
70 extern void InsertAsciiFile(LString const &, bool);
71 extern void math_insert_symbol(char const*);
72 extern Bool math_insert_greek(char const); // why "Bool"?
73 extern BufferList bufferlist;
74 extern LyXServer *lyxserver;
75 extern short greek_kb_flag;
76 extern FD_form_toc *fd_form_toc;
77 extern bool selection_possible;
79 extern kb_keymap *toplevel_keymap;
81 extern void BeforeChange();
82 extern void MenuWrite(Buffer*);
83 extern void MenuWriteAs(Buffer*);
84 extern int MenuRunLaTeX(Buffer*);
85 extern int MenuBuildProg(Buffer*);
86 extern int MenuRunChktex(Buffer*);
87 extern bool MenuRunDvips(Buffer *,bool);
88 extern void MenuPrint(Buffer*);
89 extern void MenuSendto();
90 extern void QuitLyX();
91 extern void MenuFax(Buffer *);
92 extern void MenuMakeLaTeX(Buffer *);
93 extern void MenuMakeLinuxDoc(Buffer *);
94 extern void MenuMakeDocBook(Buffer *);
95 extern void MenuMakeAscii(Buffer *);
96 extern void MenuPasteSelection(char at);
97 extern LyXAction lyxaction;
99 extern tex_accent_struct get_accent(kb_action action);
101 extern void AutoSave();
102 extern void MenuSearch();
103 extern void CopyCB();
104 extern void CopyEnvironmentCB();
105 extern void PasteEnvironmentCB();
106 extern void GotoNote();
107 extern void NoteCB();
108 extern void OpenStuff();
109 extern void HyphenationPoint();
111 extern void EndOfSentenceDot();
112 extern void MenuSeparator();
114 extern void MenuUndo();
115 extern void MenuRedo();
116 extern void SmallUpdate(signed char);
117 extern void SetUpdateTimer(float timer= 0.3);
118 extern void FreeUpdateTimer();
119 extern bool MenuPreview(Buffer*);
120 extern bool MenuPreviewPS(Buffer*);
121 extern void MenuInsertLabel(const char *);
122 extern void MenuInsertRef();
123 extern void MenuLayoutCharacter();
124 extern void MenuLayoutParagraph();
125 extern void MenuLayoutDocument();
126 extern void MenuLayoutPaper();
127 extern void MenuLayoutTable(int flag);
128 extern void MenuLayoutQuotes();
129 extern void MenuLayoutPreamble();
130 extern void MenuLayoutSave();
131 extern void bulletForm();
133 extern Buffer * NewLyxFile(LString const &);
134 extern void LoadLyXFile(LString const &);
135 extern void Reconfigure();
137 extern int current_layout;
138 extern int getISOCodeFromLaTeX(char *);
140 extern int UnlockInset(UpdatableInset*);
142 extern void ShowLatexLog();
144 extern void UpdateInset(Inset* inset, bool mark_dirty = true);
146 /* === globals =========================================================== */
148 bool LyXFunc::show_sc = true;
151 LyXFunc::LyXFunc(LyXView *o)
155 lyx_dead_action = LFUN_NOACTION;
156 lyx_calling_dead_action = LFUN_NOACTION;
166 LString LyXFunc::argAsString(char const *const argument)
168 LString tmp(argument);
171 // get the arg from somewhere else, a popup, or ask for
172 // it in the minibuffer.
174 lyxerr.debug("argAsString: <" + tmp + '>');
179 // I changed this func slightly. I commented out the ...FinishUndo(),
180 // this means that all places that used to have a moveCursorUpdate, now
181 // have a ...FinishUndo() as the preceeding statement. I have also added
182 // a moveCursorUpdate to some of the functions that updated the cursor, but
183 // that did not show its new position.
185 void LyXFunc::moveCursorUpdate(bool selecting)
187 if (selecting || owner->currentBuffer()->text->mark_set) {
188 owner->currentBuffer()->text->SetSelection();
189 owner->currentView()->getScreen()->ToggleToggle();
190 owner->currentBuffer()->update(0);
192 owner->currentBuffer()->update(-2); // this IS necessary
195 owner->currentView()->getScreen()->ShowCursor();
197 /* ---> Everytime the cursor is moved, show the current font state. */
198 // should this too me moved out of this func?
199 //owner->getMiniBuffer()->Set(CurrentState());
203 int LyXFunc::processKeyEvent(XEvent *ev)
210 XKeyEvent *keyevent = &ev->xkey;
211 KeySym keysym_return;
213 num_bytes = LyXLookupString(ev, s_r, 10, &keysym_return);
215 if (lyxerr.debugging(Error::KEY)) {
216 lyxerr.print(LString("KeySym is ")
217 + XKeysymToString(keysym_return)
219 + int(keysym_return) + "]"
220 + " and num_bytes is "
222 + " the string returned is \""
223 + LString(s_r) + '\"');
225 // Do nothing if we have nothing (JMarc)
226 if (num_bytes == 0 && keysym_return == NoSymbol) {
227 lyxerr.debug("Empty kbd action (probably composing)",
232 // this function should be used always [asierra060396]
233 if (owner->currentView()->available() &&
234 owner->currentBuffer()->the_locking_inset &&
235 keysym_return == XK_Escape) {
236 UnlockInset(owner->currentBuffer()->the_locking_inset);
237 owner->currentBuffer()->text->CursorRight();
241 // Can we be sure that this will work for all X-Windows
242 // implementations? (Lgb)
243 // This code snippet makes lyx ignore some keys. Perhaps
244 // all of them should be explictly mentioned?
245 if((keysym_return >= XK_Shift_L && keysym_return <= XK_Hyper_R)
246 || keysym_return == XK_Mode_switch || keysym_return == 0x0)
249 // Do a one-deep top-level lookup for
250 // cancel and meta-fake keys. RVDK_PATCH_5
251 cancel_meta_seq.reset();
253 action = cancel_meta_seq.addkey(keysym_return, keyevent->state
254 &(ShiftMask|ControlMask
257 // When not cancel or meta-fake, do the normal lookup.
258 // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
259 // Mostly, meta_fake_bit = 0. RVDK_PATCH_5.
260 if ( (action != LFUN_CANCEL) && (action != LFUN_META_FAKE) ) {
262 // remove Caps Lock and Mod2 as a modifiers
263 action = keyseq.addkey(keysym_return,
264 (keyevent->state | meta_fake_bit)
265 &(ShiftMask|ControlMask
268 // Dont remove this unless you know what you are doing.
271 if (action == 0) action = LFUN_PREFIX;
273 if (lyxerr.debugging(Error::KEY)) {
275 keyseq.print(buf,100);
276 lyxerr.print(LString("Key [")
282 // already here we know if it any point in going further
283 // why not return already here if action == -1 and
284 // num_bytes == 0? (Lgb)
286 if(keyseq.length>1 || keyseq.length<-1){
288 keyseq.print(buf,100);
289 owner->getMiniBuffer()->Set(buf);
293 if (keyseq.length<-1) { // unknown key sequence...
296 keyseq.print(buf,100);
297 owner->getMiniBuffer()->Set(_("Unknown sequence:"),buf);
301 char isochar = keyseq.getiso();
302 if (!(keyevent->state&ControlMask) &&
303 !(keyevent->state&Mod1Mask) &&
304 (isochar && keysym_return < 0xF000)) {
305 argument = &s_r[0]; // shall this be here
306 argument[0] = isochar;
310 lyxerr.debug("Empty argument!");
311 // This can`t possibly be of any use
312 // so we`ll skip the dispatch.
316 if (action==LFUN_SELFINSERT) {
321 bool tmp_sc = show_sc;
323 Dispatch(action, argument);
326 // Need this for deadkeys (alkis)
328 // ...but that breaks the minibuffer's display of "M-"...
330 #warning How does the deadkeys react to this?
336 LString LyXFunc::Dispatch(LString const &cmd, LString const &arg)
338 return Dispatch(lyxaction.LookupFunc(cmd.c_str()),
343 LString LyXFunc::Dispatch(int ac,
344 char const *do_not_use_this_arg)
346 char const * argument = 0;
350 FL_OBJECT *ob = 0; // This will disapear soon
352 // we have not done anything wrong yet.
354 dispatch_buffer = LString();
356 // if action is a pseudo-action, we need the real action
357 if (lyxaction.isPseudoAction(ac)) {
358 char const *tmparg = 0;
359 action = (kb_action)lyxaction.retrieveActionArg(ac, &tmparg);
363 action = (kb_action)ac;
364 argument = do_not_use_this_arg; // except here
367 selection_possible = false;
369 if (owner->currentView()->available()
370 && owner->currentView()->getScreen())
371 owner->currentView()->getScreen()->HideCursor();
373 if(!owner->currentView()->available()) {
374 // This lists the allowed funcs when we have no
377 case LFUN_MENU_OPEN_BY_NAME:
380 case LFUN_MENUNEWTMPLT:
383 case LFUN_PUSH_TOOLBAR:
384 case LFUN_ADD_TO_TOOLBAR:
385 case LFUN_EXEC_COMMAND:
386 case LFUN_DROP_LAYOUTS_CHOICE:
390 case LFUN_RECONFIGURE:
396 case LFUN_UNKNOWN_ACTION:
397 setErrorMessage(N_("Unknown action"));
398 goto exit_with_message;
400 setErrorMessage(N_("Command not allowed with"
401 "out any document open"));
402 goto exit_with_message; // action not allowed
406 commandshortcut = LString();
408 if (lyxrc->display_shortcuts && show_sc) {
409 if (action != LFUN_SELFINSERT) {
410 // Put name of command and list of shortcuts
411 // for it in minibuffer
412 LString comname = lyxaction.getActionName(action);
414 int pseudoaction = action;
415 bool argsadded = false;
417 LString argu = argument;
419 // If we have the command with argument,
422 lyxaction.searchActionArg(action,
425 if (pseudoaction == -1) {
426 pseudoaction = action;
428 comname += " " + argu;
433 LString shortcuts = toplevel_keymap->findbinding(pseudoaction);
435 if (!shortcuts.empty()) {
436 comname += ": " + shortcuts;
437 } else if (!argsadded) {
438 comname += " " + argu;
441 if (!comname.empty()) {
443 commandshortcut = "(" + comname + ')';
444 owner->getMiniBuffer()->Set(commandshortcut);
445 // Here we could even add a small pause,
446 // to annoy the user and make him learn
448 // No! That will just annoy, not teach
449 // anything. The user will read the messages
450 // if they are interested. (Asger)
455 // Now that we know which action, if the buffer is RO let's check
456 // whether the action is legal. Alejandro 970603
457 if (owner->currentView()->available() &&
458 owner->currentBuffer()->isReadonly() &&
459 lyxaction.isFuncRO(action)) {
460 setErrorMessage(N_("Document is read-only"));
461 lyxerr.debug("Error: Document is read-only.");
462 goto exit_with_message;
465 // If in math mode pass the control to
466 // the math inset [asierra060396]
467 if (owner->currentView()->available() &&
468 owner->currentBuffer()->the_locking_inset) {
469 if (action>1 || (action==LFUN_UNKNOWN_ACTION && keyseq.length>=-1)) {
471 if (action==LFUN_UNKNOWN_ACTION && !argument) {
472 sprintf(s, "%c", keyseq.getiso());
475 // Undo/Redo pre 0.13 is a bit tricky for insets.
476 if (action==LFUN_UNDO) {
478 UpdatableInset* inset =
479 owner->currentBuffer()->the_locking_inset;
480 inset->GetCursorPos(slx, sly);
483 inset = (UpdatableInset*)owner->currentBuffer()->text->cursor.par->GetInset(owner->currentBuffer()->text->cursor.pos);
485 inset->Edit(slx, sly);
488 if (action==LFUN_REDO) {
490 UpdatableInset* inset = owner->currentBuffer()->the_locking_inset;
491 inset->GetCursorPos(slx, sly);
494 inset = (UpdatableInset*)owner->currentBuffer()->text->cursor.par->GetInset(owner->currentBuffer()->text->cursor.pos);
496 inset->Edit(slx, sly);
499 if (owner->currentBuffer()->the_locking_inset->LocalDispatch(action, argument))
502 setMessage(N_("Text mode"));
503 if (action==LFUN_RIGHT || action==-1)
504 owner->currentBuffer()->text->CursorRight();
505 if (action==LFUN_LEFT || action==LFUN_RIGHT)
512 // --- Misc -------------------------------------------
513 case LFUN_WORDFINDFORWARD :
514 case LFUN_WORDFINDBACKWARD : {
516 static LString last_search;
517 LString searched_string;
519 LString arg = argAsString(argument);
523 searched_string = arg;
525 searched_string = last_search;
528 ltCur = owner->currentView()->currentBuffer()->text ;
530 if (!searched_string.empty() &&
531 ( (action == LFUN_WORDFINDBACKWARD) ?
532 ltCur->SearchBackward( searched_string.c_str() ) :
533 ltCur->SearchForward( searched_string.c_str() )
536 // ??? What is that ???
537 owner->currentView()->currentBuffer()->update(-2);
540 // clear the selection (if there is any)
541 owner->currentView()->getScreen()->ToggleSelection();
542 owner->currentView()->currentBuffer()->text->ClearSelection();
544 // Move cursor so that successive C-s 's will not stand in place.
545 if( action == LFUN_WORDFINDFORWARD )
546 owner->currentBuffer()->text->CursorRightOneWord();
547 owner->currentBuffer()->text->FinishUndo();
548 moveCursorUpdate(false);
551 // set the new selection
552 // SetSelectionOverLenChars(owner->currentView()->currentBuffer()->text, iLenSelected);
553 owner->currentView()->getScreen()->ToggleSelection(false);
557 // REMOVED : if (owner->currentView()->getWorkArea()->focus)
558 owner->currentView()->getScreen()->ShowCursor();
564 if (owner->currentView()->available()
565 && owner->currentView()->getScreen()) {
566 owner->currentBuffer()->update(-2);
569 keyseq.print(buf,100, true);
570 owner->getMiniBuffer()->Set(buf, LString(), LString(), 1);
574 // --- Misc -------------------------------------------
575 case LFUN_EXEC_COMMAND:
576 owner->getMiniBuffer()->ExecCommand();
579 case LFUN_CANCEL: // RVDK_PATCH_5
582 if(owner->currentView()->available())
583 // cancel any selection
584 Dispatch(int(LFUN_MARK_OFF), NULL);
585 setMessage(N_("Cancel"));
588 case LFUN_META_FAKE: // RVDK_PATCH_5
590 meta_fake_bit = Mod1Mask;
592 keyseq.print(buf, 98, true);
593 LString res = LString("M-") + buf;
594 setMessage(buf); // RVDK_PATCH_5
598 case LFUN_READ_ONLY_TOGGLE:
599 if (owner->currentBuffer()->lyxvc.inUse()) {
600 owner->currentBuffer()->lyxvc.toggleReadOnly();
602 owner->currentBuffer()->setReadonly(
603 !owner->currentBuffer()->isReadonly());
607 case LFUN_CENTER: // this is center and redraw.
609 if (owner->currentBuffer()->text->cursor.y >
610 owner->currentView()->getWorkArea()->h / 2) {
611 owner->currentView()->getScreen()->
612 Draw(owner->currentBuffer()->text->cursor.y -
613 owner->currentView()->getWorkArea()->h/2);
615 owner->currentView()->getScreen()->
618 owner->currentBuffer()->update(0);
619 owner->currentView()->redraw();
623 if (owner->currentView()->available()) {
624 owner->currentBuffer()->text->toggleAppendix();
625 owner->currentBuffer()->update(1);
629 // --- Menus -----------------------------------------------
634 case LFUN_MENUNEWTMPLT:
642 case LFUN_CLOSEBUFFER:
647 MenuWrite(owner->currentBuffer());
650 case LFUN_MENUWRITEAS:
651 MenuWriteAs(owner->currentBuffer());
654 case LFUN_MENURELOAD:
659 MenuPreview(owner->currentBuffer());
663 MenuPreviewPS(owner->currentBuffer());
667 MenuRunLaTeX(owner->currentBuffer());
671 MenuBuildProg(owner->currentBuffer());
675 MenuRunChktex(owner->currentBuffer());
679 MenuRunDvips(owner->currentBuffer(), false);
683 MenuPrint(owner->currentBuffer());
687 MenuFax(owner->currentBuffer());
692 //needs argument as string
693 LString extyp=argAsString(argument);
696 if (extyp == "latex") {
697 // make sure that this buffer is not linuxdoc
698 MenuMakeLaTeX(owner->currentBuffer());
701 else if (extyp == "linuxdoc") {
702 // make sure that this buffer is not latex
703 MenuMakeLinuxDoc(owner->currentBuffer());
706 else if (extyp == "docbook") {
707 // make sure that this buffer is not latex or linuxdoc
708 MenuMakeDocBook(owner->currentBuffer());
711 else if (extyp == "dvi") {
712 // Run LaTeX as "Update dvi..." Bernhard.
713 // We want the dvi in the current directory. This
714 // is achieved by temporarily disabling use of
715 // temp directory. As a side-effect, we get
716 // *.log and *.aux files also. (Asger)
717 bool flag = lyxrc->use_tempdir;
718 lyxrc->use_tempdir = false;
719 MenuRunLaTeX(owner->currentBuffer());
720 lyxrc->use_tempdir = flag;
723 else if (extyp == "postscript") {
724 // Start Print-dialog. Not as good as dvi... Bernhard.
725 MenuPrint(owner->currentBuffer());
726 // Since the MenuPrint is a pop-up, we can't use
727 // the same trick as above. (Asger)
728 // MISSING: Move of ps-file :-(
731 else if (extyp == "ascii") {
732 MenuMakeAscii(owner->currentBuffer());
734 else if (extyp == "custom") {
739 setErrorMessage(LString(N_("Unknown export type: "))
747 //needs argument as string
748 LString imtyp=argAsString(argument);
751 if (imtyp == "latex") {
752 doImportLaTeX(false);
755 else if (imtyp == "ascii") {
756 doImportASCII(false);
757 } else if (imtyp == "asciiparagraph") {
760 } else if (imtyp == "noweb") {
763 setErrorMessage(LString(N_("Unknown import type: "))
775 if (fd_form_toc->form_toc->visible) {
776 fl_raise_form(fd_form_toc->form_toc);
778 fl_show_form(fd_form_toc->form_toc,
780 FL_FREE_SIZE, FL_FULLBORDER,
781 _("Table of Contents"));
785 case LFUN_TOC_INSERT:
788 new InsetTOC(owner->currentBuffer());
789 owner->currentBuffer()->insertInset(new_inset,
794 case LFUN_LOF_INSERT:
797 new InsetLOF(owner->currentBuffer());
798 owner->currentBuffer()->insertInset(new_inset,
803 case LFUN_LOA_INSERT:
806 new InsetLOA(owner->currentBuffer());
807 owner->currentBuffer()->insertInset(new_inset,
812 case LFUN_LOT_INSERT:
815 new InsetLOT(owner->currentBuffer());
816 owner->currentBuffer()->insertInset(new_inset,
841 case LFUN_MENUSEARCH:
849 case LFUN_PASTESELECTION:
852 if (LString(argument) == "paragraph") asPara = true;
853 MenuPasteSelection(asPara);
865 case LFUN_LAYOUT_COPY:
869 case LFUN_LAYOUT_PASTE:
870 PasteEnvironmentCB();
874 owner->currentView()->gotoError();
877 case LFUN_REMOVEERRORS:
878 if (owner->currentBuffer()->removeAutoInsets()) {
879 owner->currentView()->redraw();
880 owner->currentView()->fitCursor();
881 owner->currentView()->updateScrollbar();
893 case LFUN_HYPHENATION:
901 case LFUN_END_OF_SENTENCE:
905 case LFUN_MENU_SEPARATOR:
921 case LFUN_DEPTH_PLUS:
937 case LFUN_RECONFIGURE:
942 if (owner->currentView()->available()
943 && !owner->currentBuffer()->text->selection
944 && owner->currentBuffer()->text->cursor.par->footnoteflag
945 != LyXParagraph::NO_FOOTNOTE)
946 { // only melt footnotes with FOOTMELT, not margins etc
947 if(owner->currentBuffer()->text->cursor.par->footnotekind == LyXParagraph::FOOTNOTE)
954 case LFUN_MARGINMELT:
955 if (owner->currentView()->available()
956 && !owner->currentBuffer()->text->selection
957 && owner->currentBuffer()->text->cursor.par->footnoteflag
958 != LyXParagraph::NO_FOOTNOTE)
959 { // only melt margins
960 if(owner->currentBuffer()->text->cursor.par->footnotekind == LyXParagraph::MARGIN)
967 // --- version control -------------------------------
968 case LFUN_VC_REGISTER:
970 if (!owner->currentBuffer()->lyxvc.inUse())
971 owner->currentBuffer()->lyxvc.registrer();
975 case LFUN_VC_CHECKIN:
977 if (owner->currentBuffer()->lyxvc.inUse()
978 && !owner->currentBuffer()->isReadonly())
979 owner->currentBuffer()->lyxvc.checkIn();
983 case LFUN_VC_CHECKOUT:
985 if (owner->currentBuffer()->lyxvc.inUse()
986 && owner->currentBuffer()->isReadonly())
987 owner->currentBuffer()->lyxvc.checkOut();
993 owner->currentBuffer()->lyxvc.revert();
999 owner->currentBuffer()->lyxvc.undoLast();
1003 case LFUN_VC_HISTORY:
1005 owner->currentBuffer()->lyxvc.showLog();
1009 // --- buffers ----------------------------------------
1010 case LFUN_PREVBUFFER:
1011 #ifdef WITH_WARNINGS
1012 #warning fix this please
1014 // it is the LyXView or the BufferView that should
1015 // remember the previous buffer, not bufferlist.
1016 // if (owner->currentView()->available()){
1018 // owner->currentBuffer()->update(-2);
1020 // owner->currentView()->setBuffer(bufferlist.prev());
1022 // owner->currentView()->
1023 // resizeCurrentBufferPseudoExpose();
1026 case LFUN_FILE_INSERT:
1028 // needs argument as string
1029 LString fil = argAsString(argument);
1030 MenuInsertLyXFile(fil);
1034 case LFUN_FILE_INSERT_ASCII:
1036 bool asPara = false;
1037 asPara = (LString(argument) == "paragraph");
1038 InsertAsciiFile(LString(), asPara);
1044 // servercmd: argument must be <file>:<template>
1045 Buffer * tmpbuf = 0;
1046 tmpbuf = NewLyxFile(argument);
1048 owner->currentView()->setBuffer(tmpbuf);
1052 case LFUN_FILE_OPEN:
1053 owner->currentView()->setBuffer(
1054 bufferlist.loadLyXFile(argument));
1057 case LFUN_LATEX_LOG:
1063 lyxerr.debug("LFUN_LAYOUTNO: (arg) " + LString(argument));
1064 int sel = atoi(argument);
1065 lyxerr.debug(LString("LFUN_LAYOUTNO: (sel) ") + int(sel));
1067 // Should this give a setMessage instead?
1069 return LString(); // illegal argument
1071 sel--; // sel 1..., but layout 0...
1073 // Pretend we got the name instead.
1074 Dispatch(int(LFUN_LAYOUT),
1075 lyxstyle.NameOfLayout(owner->currentBuffer()->
1084 lyxerr.debug("LFUN_LAYOUT: (arg) "
1085 + LString(argument));
1087 // Derive layout number from given argument (string)
1088 // and current buffer's textclass (number). */
1091 lyxstyle.NumberOfLayout(owner->
1097 // see if we found the layout number:
1098 if (layoutno == -1) {
1099 setErrorMessage(LString(N_("Layout ")) + argument +
1104 if (current_layout != layoutno) {
1105 owner->currentView()->getScreen()->HideCursor();
1106 current_layout = layoutno;
1107 owner->currentBuffer()->update(-2);
1108 owner->currentBuffer()->text->
1109 SetLayout(layoutno);
1110 owner->getToolbar()->combox->
1111 select(owner->currentBuffer()->
1114 owner->currentBuffer()->update(1);
1119 case LFUN_LAYOUT_DOCUMENT:
1120 MenuLayoutDocument();
1123 case LFUN_LAYOUT_PARAGRAPH:
1124 MenuLayoutParagraph();
1127 case LFUN_LAYOUT_CHARACTER:
1128 MenuLayoutCharacter();
1131 case LFUN_LAYOUT_TABLE:
1134 if (LString(argument) == "true") flag = 1;
1135 MenuLayoutTable(flag);
1139 case LFUN_LAYOUT_PAPER:
1143 case LFUN_LAYOUT_QUOTES:
1147 case LFUN_LAYOUT_PREAMBLE:
1148 MenuLayoutPreamble();
1151 case LFUN_LAYOUT_SAVE_DEFAULT:
1155 case LFUN_DROP_LAYOUTS_CHOICE:
1156 owner->getToolbar()->combox->Show();
1187 case LFUN_UNDERLINE:
1191 case LFUN_FONT_SIZE:
1192 FontSizeCB(argument);
1195 case LFUN_FONT_STATE:
1196 setMessage(CurrentState());
1199 case LFUN_UPCASE_WORD:
1200 owner->currentBuffer()->update(-2);
1202 owner->currentBuffer()->text->ChangeWordCase(2);
1203 owner->currentBuffer()->update(1);
1207 case LFUN_LOWCASE_WORD:
1208 owner->currentBuffer()->update(-2);
1210 owner->currentBuffer()->text->ChangeWordCase(0);
1211 owner->currentBuffer()->update(1);
1215 case LFUN_CAPITALIZE_WORD:
1216 owner->currentBuffer()->update(-2);
1218 owner->currentBuffer()->text->ChangeWordCase(1);
1219 owner->currentBuffer()->update(1);
1223 case LFUN_INSERT_LABEL:
1224 MenuInsertLabel(argument);
1227 case LFUN_INSERT_REF:
1231 case LFUN_REFTOGGLE:
1234 (InsetRef*)getInsetByCode(Inset::REF_CODE);
1236 if (inset->getFlag()==InsetRef::REF)
1237 inset->setFlag(InsetRef::PAGE_REF);
1239 inset->setFlag(InsetRef::REF);
1242 setErrorMessage(N_("No cross-reference to toggle"));
1249 owner->currentView()->restorePosition();
1255 LString label(argument);
1256 if (label.empty()) {
1258 (InsetRef*)getInsetByCode(Inset::REF_CODE);
1260 label = inset->getContents();
1263 if (!label.empty()) {
1264 owner->currentView()->savePosition();
1265 owner->currentBuffer()->gotoLabel(label.c_str());
1270 case LFUN_MENU_OPEN_BY_NAME:
1271 owner->getMenus()->openByName(argument);
1272 break; // RVDK_PATCH_5
1274 case LFUN_SPELLCHECK:
1275 if (lyxrc->isp_command != "none")
1277 break; // RVDK_PATCH_5
1279 // --- Cursor Movements -----------------------------
1282 Buffer *tmpbuffer = owner->currentBuffer();
1283 LyXText *tmptext = owner->currentBuffer()->text;
1284 if(!tmptext->mark_set)
1286 tmpbuffer->update(-2);
1287 if (tmptext->cursor.pos < tmptext->cursor.par->Last()
1288 && tmptext->cursor.par->GetChar(tmptext->cursor.pos)
1290 && tmptext->cursor.par->GetInset(tmptext->cursor.pos)
1291 && tmptext->cursor.par->GetInset(tmptext->cursor.pos)->Editable()==2){
1292 Inset* tmpinset = tmptext->cursor.par->GetInset(tmptext->cursor.pos);
1293 setMessage(tmpinset->EditMessage());
1294 tmpinset->Edit(0,0);
1297 tmptext->CursorRight();
1298 owner->currentBuffer()->text->FinishUndo();
1299 moveCursorUpdate(false);
1300 owner->getMiniBuffer()->Set(CurrentState());
1306 // This is soooo ugly. Isn`t it possible to make
1307 // it simpler? (Lgb)
1308 LyXText *txt= owner->currentBuffer()->text;
1309 if(!txt->mark_set) BeforeChange();
1310 owner->currentBuffer()->update(-2);
1312 if (txt->cursor.pos < txt->cursor.par->Last()
1313 && txt->cursor.par->GetChar(txt->cursor.pos)
1315 && txt->cursor.par->GetInset(txt->cursor.pos)
1316 && txt->cursor.par->GetInset(txt->cursor.pos)->Editable()==2) {
1317 Inset* tmpinset = txt->cursor.par->GetInset(txt->cursor.pos);
1318 setMessage(tmpinset->EditMessage());
1319 tmpinset->Edit(tmpinset->Width(txt->GetFont(txt->cursor.par,
1320 txt->cursor.pos)),0);
1321 // tmpinset->Edit(-1, 0); // -1 means go rightmost
1324 owner->currentBuffer()->text->FinishUndo();
1325 moveCursorUpdate(false);
1326 owner->getMiniBuffer()->Set(CurrentState());
1331 if(!owner->currentBuffer()->text->mark_set) BeforeChange();
1332 owner->currentBuffer()->update(-3);
1333 owner->currentBuffer()->text->CursorUp();
1334 owner->currentBuffer()->text->FinishUndo();
1335 moveCursorUpdate(false);
1336 owner->getMiniBuffer()->Set(CurrentState());
1340 if(!owner->currentBuffer()->text->mark_set)
1342 owner->currentBuffer()->update(-3);
1343 owner->currentBuffer()->text->CursorDown();
1344 owner->currentBuffer()->text->FinishUndo();
1345 moveCursorUpdate(false);
1346 owner->getMiniBuffer()->Set(CurrentState());
1349 case LFUN_UP_PARAGRAPH:
1350 if(!owner->currentBuffer()->text->mark_set)
1352 owner->currentBuffer()->update(-3);
1353 owner->currentBuffer()->text->CursorUpParagraph();
1354 owner->currentBuffer()->text->FinishUndo();
1355 moveCursorUpdate(false);
1356 owner->getMiniBuffer()->Set(CurrentState());
1359 case LFUN_DOWN_PARAGRAPH:
1360 if(!owner->currentBuffer()->text->mark_set)
1362 owner->currentBuffer()->update(-3);
1363 owner->currentBuffer()->text->CursorDownParagraph();
1364 owner->currentBuffer()->text->FinishUndo();
1365 moveCursorUpdate(false);
1366 owner->getMiniBuffer()->Set(CurrentState());
1370 if(!owner->currentBuffer()->text->mark_set)
1372 owner->currentBuffer()->update(-3);
1373 owner->currentView()->cursorPrevious();
1374 owner->currentBuffer()->text->FinishUndo();
1375 moveCursorUpdate(false);
1376 owner->getMiniBuffer()->Set(CurrentState());
1380 if(!owner->currentBuffer()->text->mark_set)
1382 owner->currentBuffer()->update(-3);
1383 owner->currentView()->cursorNext();
1384 owner->currentBuffer()->text->FinishUndo();
1385 moveCursorUpdate(false);
1386 owner->getMiniBuffer()->Set(CurrentState());
1390 if(!owner->currentBuffer()->text->mark_set)
1392 owner->currentBuffer()->update(-2);
1393 owner->currentBuffer()->text->CursorHome();
1394 owner->currentBuffer()->text->FinishUndo();
1395 moveCursorUpdate(false);
1396 owner->getMiniBuffer()->Set(CurrentState());
1400 if(!owner->currentBuffer()->text->mark_set)
1402 owner->currentBuffer()->update(-2);
1403 owner->currentBuffer()->text->CursorEnd();
1404 owner->currentBuffer()->text->FinishUndo();
1405 moveCursorUpdate(false);
1406 owner->getMiniBuffer()->Set(CurrentState());
1410 if(!owner->currentBuffer()->text->mark_set)
1412 owner->currentBuffer()->update(-2);
1413 owner->currentBuffer()->text->CursorTab();
1414 owner->currentBuffer()->text->FinishUndo();
1415 moveCursorUpdate(false);
1416 owner->getMiniBuffer()->Set(CurrentState());
1419 case LFUN_WORDRIGHT:
1420 if(!owner->currentBuffer()->text->mark_set)
1422 owner->currentBuffer()->update(-2);
1423 owner->currentBuffer()->text->CursorRightOneWord();
1424 owner->currentBuffer()->text->FinishUndo();
1425 moveCursorUpdate(false);
1426 owner->getMiniBuffer()->Set(CurrentState());
1430 if(!owner->currentBuffer()->text->mark_set)
1432 owner->currentBuffer()->update(-2);
1433 owner->currentBuffer()->text->CursorLeftOneWord();
1434 owner->currentBuffer()->text->FinishUndo();
1435 moveCursorUpdate(false);
1436 owner->getMiniBuffer()->Set(CurrentState());
1439 case LFUN_BEGINNINGBUF:
1440 if(!owner->currentBuffer()->text->mark_set)
1442 owner->currentBuffer()->update(-2);
1443 owner->currentBuffer()->text->CursorTop();
1444 owner->currentBuffer()->text->FinishUndo();
1445 moveCursorUpdate(false);
1446 owner->getMiniBuffer()->Set(CurrentState());
1450 if(!owner->currentBuffer()->text->mark_set)
1452 owner->currentBuffer()->update(-2);
1453 owner->currentBuffer()->text->CursorBottom();
1454 owner->currentBuffer()->text->FinishUndo();
1455 moveCursorUpdate(false);
1456 owner->getMiniBuffer()->Set(CurrentState());
1460 /* cursor selection ---------------------------- */
1462 owner->currentBuffer()->update(-2);
1463 owner->currentBuffer()->text->CursorRight();
1464 owner->currentBuffer()->text->FinishUndo();
1465 moveCursorUpdate(true);
1466 owner->getMiniBuffer()->Set(CurrentState());
1470 owner->currentBuffer()->update(-2);
1471 owner->currentBuffer()->text->CursorLeft();
1472 owner->currentBuffer()->text->FinishUndo();
1473 moveCursorUpdate(true);
1474 owner->getMiniBuffer()->Set(CurrentState());
1478 owner->currentBuffer()->update(-2);
1479 owner->currentBuffer()->text->CursorUp();
1480 owner->currentBuffer()->text->FinishUndo();
1481 moveCursorUpdate(true);
1482 owner->getMiniBuffer()->Set(CurrentState());
1486 owner->currentBuffer()->update(-2);
1487 owner->currentBuffer()->text->CursorDown();
1488 owner->currentBuffer()->text->FinishUndo();
1489 moveCursorUpdate(true);
1490 owner->getMiniBuffer()->Set(CurrentState());
1493 case LFUN_UP_PARAGRAPHSEL:
1494 owner->currentBuffer()->update(-2);
1495 owner->currentBuffer()->text->CursorUpParagraph();
1496 owner->currentBuffer()->text->FinishUndo();
1497 moveCursorUpdate(true);
1498 owner->getMiniBuffer()->Set(CurrentState());
1501 case LFUN_DOWN_PARAGRAPHSEL:
1502 owner->currentBuffer()->update(-2);
1503 owner->currentBuffer()->text->CursorDownParagraph();
1504 owner->currentBuffer()->text->FinishUndo();
1505 moveCursorUpdate(true);
1506 owner->getMiniBuffer()->Set(CurrentState());
1510 owner->currentBuffer()->update(-2);
1511 owner->currentView()->cursorPrevious();
1512 owner->currentBuffer()->text->FinishUndo();
1513 moveCursorUpdate(true);
1514 owner->getMiniBuffer()->Set(CurrentState());
1518 owner->currentBuffer()->update(-2);
1519 owner->currentView()->cursorNext();
1520 owner->currentBuffer()->text->FinishUndo();
1521 moveCursorUpdate(true);
1522 owner->getMiniBuffer()->Set(CurrentState());
1526 owner->currentBuffer()->update(-2);
1527 owner->currentBuffer()->text->CursorHome();
1528 owner->currentBuffer()->text->FinishUndo();
1529 moveCursorUpdate(true);
1530 owner->getMiniBuffer()->Set(CurrentState());
1534 owner->currentBuffer()->update(-2);
1535 owner->currentBuffer()->text->CursorEnd();
1536 owner->currentBuffer()->text->FinishUndo();
1537 moveCursorUpdate(true);
1538 owner->getMiniBuffer()->Set(CurrentState());
1541 case LFUN_WORDRIGHTSEL:
1542 owner->currentBuffer()->update(-2);
1543 owner->currentBuffer()->text->CursorRightOneWord();
1544 owner->currentBuffer()->text->FinishUndo();
1545 moveCursorUpdate(true);
1546 owner->getMiniBuffer()->Set(CurrentState());
1549 case LFUN_WORDLEFTSEL:
1550 owner->currentBuffer()->update(-2);
1551 owner->currentBuffer()->text->CursorLeftOneWord();
1552 owner->currentBuffer()->text->FinishUndo();
1553 moveCursorUpdate(true);
1554 owner->getMiniBuffer()->Set(CurrentState());
1557 case LFUN_BEGINNINGBUFSEL:
1558 owner->currentBuffer()->update(-2);
1559 owner->currentBuffer()->text->CursorTop();
1560 owner->currentBuffer()->text->FinishUndo();
1561 moveCursorUpdate(true);
1562 owner->getMiniBuffer()->Set(CurrentState());
1565 case LFUN_ENDBUFSEL:
1566 owner->currentBuffer()->update(-2);
1567 owner->currentBuffer()->text->CursorBottom();
1568 owner->currentBuffer()->text->FinishUndo();
1569 moveCursorUpdate(true);
1570 owner->getMiniBuffer()->Set(CurrentState());
1573 // --- text changing commands ------------------------
1574 case LFUN_BREAKLINE:
1576 owner->currentBuffer()->text->InsertChar(LYX_META_NEWLINE);
1578 SetUpdateTimer(0.01);
1579 moveCursorUpdate(false);
1582 case LFUN_PROTECTEDSPACE:
1584 owner->currentBuffer()->text->
1585 InsertChar(LYX_META_PROTECTED_SEPARATOR);
1588 moveCursorUpdate(false);
1592 if(owner->currentBuffer()->text->mark_set) {
1594 owner->currentBuffer()->update(0);
1595 setMessage(N_("Mark removed"));
1598 owner->currentBuffer()->text->mark_set = 1;
1599 owner->currentBuffer()->update(0);
1600 setMessage(N_("Mark set"));
1602 owner->currentBuffer()->text->sel_cursor =
1603 owner->currentBuffer()->text->cursor;
1608 if (!owner->currentBuffer()->text->selection) {
1609 owner->currentBuffer()->text->Delete();
1610 owner->currentBuffer()->text->sel_cursor =
1611 owner->currentBuffer()->text->cursor;
1613 // It is possible to make it a lot faster still
1614 // just comment out the lone below...
1615 owner->currentView()->getScreen()->ShowCursor();
1622 case LFUN_DELETE_SKIP:
1624 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
1626 LyXCursor cursor = owner->currentBuffer()->text->cursor;
1629 if (!owner->currentBuffer()->text->selection) {
1630 if (cursor.pos == cursor.par->Last()) {
1631 owner->currentBuffer()->text->CursorRight();
1632 cursor = owner->currentBuffer()->text->cursor;
1634 && !(cursor.par->added_space_top
1635 == VSpace (VSpace::NONE))) {
1636 owner->currentBuffer()->text->SetParagraph
1637 (cursor.par->line_top,
1638 cursor.par->line_bottom,
1639 cursor.par->pagebreak_top,
1640 cursor.par->pagebreak_bottom,
1641 VSpace(VSpace::NONE),
1642 cursor.par->added_space_bottom,
1644 cursor.par->labelwidthstring, 0);
1645 owner->currentBuffer()->text->CursorLeft();
1646 owner->currentBuffer()->update (1);
1648 owner->currentBuffer()->text->CursorLeft();
1649 owner->currentBuffer()->text->Delete();
1650 owner->currentBuffer()->text->sel_cursor =
1651 owner->currentBuffer()->text->cursor;
1655 owner->currentBuffer()->text->Delete();
1656 owner->currentBuffer()->text->sel_cursor =
1657 owner->currentBuffer()->text->cursor;
1667 /* -------> Delete word forward. */
1668 case LFUN_DELETE_WORD_FORWARD:
1669 owner->currentBuffer()->update(-2);
1671 owner->currentBuffer()->text->DeleteWordForward();
1672 owner->currentBuffer()->update( 1 );
1674 moveCursorUpdate(false);
1677 /* -------> Delete word backward. */
1678 case LFUN_DELETE_WORD_BACKWARD:
1679 owner->currentBuffer()->update(-2);
1681 owner->currentBuffer()->text->DeleteWordBackward();
1682 owner->currentBuffer()->update( 1 );
1684 moveCursorUpdate(false);
1687 /* -------> Kill to end of line. */
1688 case LFUN_DELETE_LINE_FORWARD:
1690 owner->currentBuffer()->update(-2);
1691 owner->currentBuffer()->text->DeleteLineForward();
1692 owner->currentBuffer()->update( 1 );
1694 moveCursorUpdate(false);
1697 /* -------> Set mark off. */
1700 owner->currentBuffer()->update(0);
1701 owner->currentBuffer()->text->sel_cursor =
1702 owner->currentBuffer()->text->cursor;
1703 setMessage(N_("Mark off"));
1706 /* -------> Set mark on. */
1709 owner->currentBuffer()->text->mark_set = 1;
1710 owner->currentBuffer()->update( 0 );
1711 owner->currentBuffer()->text->sel_cursor =
1712 owner->currentBuffer()->text->cursor;
1713 setMessage(N_("Mark on"));
1716 case LFUN_BACKSPACE:
1719 if (!owner->currentBuffer()->text->selection) {
1720 if (owner->getIntl()->getTrans()->backspace()) {
1721 owner->currentBuffer()->text->Backspace();
1722 owner->currentBuffer()->text->sel_cursor =
1723 owner->currentBuffer()->text->cursor;
1725 // It is possible to make it a lot faster still
1726 // just comment out the lone below...
1727 owner->currentView()->getScreen()->ShowCursor();
1736 case LFUN_BACKSPACE_SKIP:
1738 // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP.
1740 LyXCursor cursor = owner->currentBuffer()->text->cursor;
1743 if (!owner->currentBuffer()->text->selection) {
1745 && !(cursor.par->added_space_top
1746 == VSpace (VSpace::NONE))) {
1747 owner->currentBuffer()->text->SetParagraph
1748 (cursor.par->line_top,
1749 cursor.par->line_bottom,
1750 cursor.par->pagebreak_top,
1751 cursor.par->pagebreak_bottom,
1752 VSpace(VSpace::NONE), cursor.par->added_space_bottom,
1754 cursor.par->labelwidthstring, 0);
1755 owner->currentBuffer()->update (1);
1757 owner->currentBuffer()->text->Backspace();
1758 owner->currentBuffer()->text->sel_cursor
1768 case LFUN_BREAKPARAGRAPH:
1771 owner->currentBuffer()->text->BreakParagraph(0);
1773 SetUpdateTimer(0.01);
1774 owner->currentBuffer()->text->sel_cursor =
1775 owner->currentBuffer()->text->cursor;
1779 case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
1782 owner->currentBuffer()->text->BreakParagraph(1);
1784 SetUpdateTimer(0.01);
1785 owner->currentBuffer()->text->sel_cursor =
1786 owner->currentBuffer()->text->cursor;
1790 case LFUN_BREAKPARAGRAPH_SKIP:
1792 // When at the beginning of a paragraph, remove
1793 // indentation and add a "defskip" at the top.
1794 // Otherwise, do the same as LFUN_BREAKPARAGRAPH.
1796 LyXCursor cursor = owner->currentBuffer()->text->cursor;
1799 if (cursor.pos == 0) {
1800 if (cursor.par->added_space_top == VSpace(VSpace::NONE)) {
1801 owner->currentBuffer()->text->SetParagraph
1802 (cursor.par->line_top,
1803 cursor.par->line_bottom,
1804 cursor.par->pagebreak_top,
1805 cursor.par->pagebreak_bottom,
1806 VSpace(VSpace::DEFSKIP), cursor.par->added_space_bottom,
1808 cursor.par->labelwidthstring, 1);
1809 owner->currentBuffer()->update(1);
1813 owner->currentBuffer()->text->BreakParagraph(0);
1816 SetUpdateTimer(0.01);
1817 owner->currentBuffer()->text->sel_cursor = cursor;
1823 owner->currentBuffer()->text->InsertChar('\"'); // This " matches the single quote in the code
1826 moveCursorUpdate(false);
1832 InsetCommand *new_inset;
1833 if (action == LFUN_HTMLURL)
1834 new_inset = new InsetUrl("htmlurl", "", "");
1836 new_inset = new InsetUrl("url", "", "");
1837 owner->currentBuffer()->insertInset(new_inset);
1838 new_inset->Edit(0, 0);
1842 // --- lyxserver commands ----------------------------
1844 case LFUN_CHARATCURSOR:
1846 int pos = owner->currentBuffer()->text->cursor.pos;
1847 if(pos < owner->currentBuffer()->text->cursor.par->last)
1848 dispatch_buffer = owner->currentBuffer()->text->
1849 cursor.par->text[pos];
1851 dispatch_buffer = "EOF";
1856 dispatch_buffer = LString()
1857 + owner->currentBuffer()->text->cursor.x + ' '
1858 + owner->currentBuffer()->text->cursor.y;
1865 sscanf(argument, " %d %ld", &x, &y);
1866 owner->currentBuffer()->text->SetCursorFromCoordinates(x, y);
1870 case LFUN_GETLAYOUT:
1871 dispatch_buffer = LString() +
1872 int(owner->currentBuffer()->text->cursor.par->layout);
1877 LyXFont *font = &(owner->currentBuffer()->text->current_font);
1878 if(font->shape() == LyXFont::ITALIC_SHAPE)
1879 dispatch_buffer = 'E';
1880 else if(font->shape() == LyXFont::SMALLCAPS_SHAPE)
1881 dispatch_buffer = 'N';
1883 dispatch_buffer = '0';
1890 LyXFont *font = &(owner->currentBuffer()->text->current_font);
1891 if(font->latex() == LyXFont::ON)
1892 dispatch_buffer = 'L';
1894 dispatch_buffer = '0';
1899 setMessage(owner->currentBuffer()->getFileName());
1900 lyxerr.debug(LString("FNAME[") +
1901 owner->currentBuffer()->getFileName() +
1908 keyseq.print(buf,100);
1909 dispatch_buffer = buf;
1910 lyxserver->notifyClient(dispatch_buffer);
1914 case LFUN_GOTOFILEROW:
1916 char file_name[100];
1918 sscanf(argument, " %s %d", file_name, &row);
1920 // Must replace extension of the file to be .lyx and get full path
1921 LString s = ChangeExtension(LString(file_name), ".lyx", false);
1923 // Either change buffer or load the file
1924 if (bufferlist.exists(s))
1925 owner->currentView()->setBuffer(bufferlist.getBuffer(s));
1927 owner->currentView()->setBuffer(bufferlist.loadLyXFile(s));
1930 owner->currentBuffer()->setCursorFromRow(row);
1934 if (owner->currentBuffer()->text->cursor.y >
1935 owner->currentView()->getWorkArea()->h / 2) {
1936 owner->currentView()->getScreen()->
1937 Draw(owner->currentBuffer()->text->cursor.y -
1938 owner->currentView()->getWorkArea()->h/2);
1940 owner->currentView()->getScreen()->
1943 owner->currentBuffer()->update(0);
1944 owner->currentView()->redraw();
1951 int qa = lyxaction.LookupFunc((const char*)argument);
1952 setMessage(lyxaction.helpText((kb_action)qa));
1956 // --- accented characters ---------------------------
1959 case LFUN_CIRCUMFLEX:
1969 case LFUN_SPECIAL_CARON:
1972 case LFUN_HUNG_UMLAUT:
1978 if (keyseq.length==-1 && keyseq.getiso()!=0)
1983 owner->getIntl()->getTrans()->
1984 deadkey(c, get_accent(action).accent,
1985 owner->currentBuffer()->text);
1987 // Need to reset, in case the minibuffer calls these
1992 // copied verbatim from do_accent_char
1995 owner->currentBuffer()->text->sel_cursor =
1996 owner->currentBuffer()->text->cursor;
2000 // --- toolbar ----------------------------------
2001 case LFUN_PUSH_TOOLBAR:
2003 int nth = atoi(argument);
2004 if (lyxerr.debugging(Error::TOOLBAR)) {
2005 lyxerr.print(LString("LFUN_PUSH_TOOLBAR: argument = `")
2007 lyxerr.print(LString("LFUN_PUSH_TOOLBAR: nth = `")
2013 setErrorMessage(N_("Push-toolbar needs argument > 0"));
2015 owner->getToolbar()->push(nth);
2020 case LFUN_ADD_TO_TOOLBAR:
2022 if (lyxerr.debugging(Error::TOOLBAR)) {
2023 lyxerr.print(LString("LFUN_ADD_TO_TOOLBAR:"
2024 "argument = `")+ argument + '\'');
2026 LString tmp(argument);
2027 //lyxerr.print(LString("Argument: ") + argument);
2028 //lyxerr.print(LString("Tmp : ") + tmp);
2031 setErrorMessage(N_("Usage: toolbar-add-to <LyX command>"));
2033 owner->getToolbar()->add(argument, false);
2034 owner->getToolbar()->set();
2039 // --- insert characters ----------------------------------------
2041 case LFUN_INSERT_INSET_LATEX:
2043 Inset *new_inset = new InsetLatex(argument);
2044 owner->currentBuffer()->insertInset(new_inset);
2048 // --- Mathed stuff. If we are here, there is no locked inset yet.
2053 if (!greek_kb_flag) {
2055 setMessage(N_("Math greek mode on"));
2062 case LFUN_GREEK_TOGGLE:
2064 greek_kb_flag = (greek_kb_flag) ? 0: 2;
2065 if (greek_kb_flag) {
2066 setMessage(N_("Math greek keyboard on"));
2068 setMessage(N_("Math greek keyboard off"));
2073 case LFUN_MATH_DELIM:
2074 case LFUN_INSERT_MATRIX:
2076 if (owner->currentView()->available()) {
2077 owner->currentBuffer()->
2078 open_new_inset(new InsetFormula(false));
2079 owner->currentBuffer()->
2080 the_locking_inset->LocalDispatch(action, argument);
2085 case LFUN_INSERT_MATH:
2087 math_insert_symbol(argument);
2091 case LFUN_MATH_DISPLAY:
2093 if (owner->currentView()->available())
2094 owner->currentBuffer()->open_new_inset(new InsetFormula(true));
2098 case LFUN_MATH_MACRO:
2100 if (owner->currentView()->available()) {
2101 LString s(argument);
2103 setErrorMessage(N_("Missing argument"));
2105 LString s1 = s.token(' ', 1);
2106 int na = s1.empty() ? 0: atoi(s1.c_str());
2107 owner->currentBuffer()->
2108 open_new_inset(new InsetFormulaMacro(s.token(' ', 0), na));
2114 case LFUN_MATH_MODE: // Open or create a math inset
2117 if (owner->currentView()->available())
2118 owner->currentBuffer()->open_new_inset(new InsetFormula);
2119 setMessage(N_("Math editor mode"));
2123 case LFUN_MATH_NUMBER:
2124 case LFUN_MATH_LIMITS:
2126 setErrorMessage(N_("This is only allowed in math mode!"));
2130 case LFUN_INSERT_CITATION:
2132 InsetCitation *new_inset = new InsetCitation();
2134 // The note, if any, must be after the key, delimited
2135 // by a | so both key and remark can have spaces.
2137 LString lsarg(argument);
2138 if (lsarg.contains("|")) {
2139 new_inset->setContents(lsarg.token('|', 0));
2140 new_inset->setOptions(lsarg.token('|', 1));
2142 new_inset->setContents(lsarg);
2143 owner->currentBuffer()->insertInset(new_inset);
2145 owner->currentBuffer()->insertInset(new_inset);
2146 new_inset->Edit(0,0);
2151 case LFUN_INSERT_BIBTEX:
2153 // ale970405+lasgoutt970425
2154 // The argument can be up to two tokens separated
2155 // by a space. The first one is the bibstyle.
2156 LString lsarg(argument);
2157 LString bibstyle = lsarg.token(' ', 1);
2158 if (bibstyle.empty())
2160 InsetBibtex *new_inset
2161 = new InsetBibtex(lsarg.token(' ', 0),
2163 owner->currentBuffer());
2165 owner->currentBuffer()->insertInset(new_inset);
2166 if (lsarg.empty()) {
2167 new_inset->Edit(0,0);
2172 // BibTeX data bases
2173 case LFUN_BIBDB_ADD:
2175 InsetBibtex *inset =
2176 (InsetBibtex*)getInsetByCode(Inset::BIBTEX_CODE);
2178 inset->addDatabase(argument);
2183 case LFUN_BIBDB_DEL:
2185 InsetBibtex *inset =
2186 (InsetBibtex*)getInsetByCode(Inset::BIBTEX_CODE);
2188 inset->delDatabase(argument);
2193 case LFUN_BIBTEX_STYLE:
2195 InsetBibtex *inset =
2196 (InsetBibtex*)getInsetByCode(Inset::BIBTEX_CODE);
2198 inset->setOptions(argument);
2203 case LFUN_INDEX_INSERT:
2204 case LFUN_INDEX_INSERT_LAST:
2206 InsetIndex *new_inset = new InsetIndex();
2208 LString lsarg(argument);
2209 new_inset->setContents(lsarg);
2210 owner->currentBuffer()->insertInset(new_inset);
2213 //get the current word for an argument
2218 int lastpos =owner->currentBuffer()->text->cursor.pos-1;
2220 //this shouldn't happen, but let's be careful
2221 if (lastpos < 0) lastpos=0;
2223 // get the current word
2224 // note that this must be done before
2225 // inserting the inset, or the inset will break
2227 LString curstring(owner->currentBuffer()->text->cursor.par->GetWord(lastpos));
2229 //make the new inset and write the current word into it
2230 InsetIndex *new_inset = new InsetIndex();
2232 new_inset->setContents(curstring);
2234 //don't edit it if the call was to INSERT_LAST
2235 if(action!=LFUN_INDEX_INSERT_LAST) {
2236 new_inset->Edit(0,0);
2238 //it looks blank on the screen unless
2239 //we do something. put it here.
2241 // move the cursor to the returned value of lastpos
2242 // but only for the auto-insert
2243 owner->currentBuffer()->text->cursor.pos=lastpos;
2246 //put the new inset into the buffer.
2247 // there should be some way of knowing the user
2248 //cancelled & avoiding this, but i don't know how
2249 owner->currentBuffer()->insertInset(new_inset);
2254 case LFUN_INDEX_PRINT:
2256 Inset *new_inset = new InsetPrintIndex(owner->currentBuffer());
2257 owner->currentBuffer()->insertInset(new_inset, "Standard", true);
2261 case LFUN_PARENTINSERT:
2263 lyxerr.print(LString("arg ") + argument);
2264 Inset *new_inset = new InsetParent(argument, owner->currentBuffer());
2265 owner->currentBuffer()->insertInset(new_inset, "Standard", true);
2269 case LFUN_CHILDINSERT:
2271 Inset *new_inset = new InsetInclude(argument,owner->currentBuffer());
2272 owner->currentBuffer()->insertInset(new_inset, "Standard", true);
2273 new_inset->Edit(0,0);
2277 case LFUN_CHILDOPEN:
2279 LString filename = MakeAbsPath(argument,
2280 OnlyPath(owner->currentBuffer()->getFileName()));
2281 setMessage(N_("Opening child document ") +
2282 MakeDisplayPath(filename) + "...");
2283 owner->currentView()->savePosition();
2284 if (bufferlist.exists(filename))
2285 owner->currentView()->setBuffer(bufferlist.getBuffer(filename));
2287 owner->currentView()->setBuffer(bufferlist.loadLyXFile(filename));
2291 case LFUN_INSERT_NOTE:
2295 case LFUN_INSERTFOOTNOTE:
2297 LyXParagraph::footnote_kind kind;
2298 LString arg = argument;
2299 if (arg == "footnote")
2300 { kind = LyXParagraph::FOOTNOTE; }
2301 else if (arg == "margin")
2302 { kind = LyXParagraph::MARGIN; }
2303 else if (arg == "figure")
2304 { kind = LyXParagraph::FIG; }
2305 else if (arg == "table")
2306 { kind = LyXParagraph::TAB; }
2307 else if (arg == "wide-fig")
2308 { kind = LyXParagraph::WIDE_FIG; }
2309 else if (arg == "wide-tab")
2310 { kind = LyXParagraph::WIDE_TAB; }
2311 else if (arg == "algorithm")
2312 { kind = LyXParagraph::ALGORITHM; }
2314 setErrorMessage(N_("Unknown kind of footnote"));
2317 owner->currentBuffer()->text->InsertFootnoteEnvironment(kind);
2318 owner->currentBuffer()->update(1);
2322 case LFUN_BUFFERBULLETSSELECT:
2326 case LFUN_TOGGLECURSORFOLLOW:
2327 cursor_follows_scrollbar = !cursor_follows_scrollbar;
2330 case LFUN_KMAP_OFF: // keymap off
2331 owner->getIntl()->KeyMapOn(false);
2334 case LFUN_KMAP_PRIM: // primary keymap
2335 owner->getIntl()->KeyMapPrim();
2338 case LFUN_KMAP_SEC: // secondary keymap
2339 owner->getIntl()->KeyMapSec();
2342 case LFUN_KMAP_TOGGLE: // toggle keymap
2343 owner->getIntl()->ToggleKeyMap();
2346 case LFUN_SELFINSERT:
2348 LString const text = argument;
2349 for (int i=0; i<text.length(); i++) {
2350 owner->currentBuffer()->text->InsertChar(text[i]);
2351 // This needs to be in the loop, or else we
2352 // won't break lines correctly. (Asger)
2356 owner->currentBuffer()->text->sel_cursor =
2357 owner->currentBuffer()->text->cursor;
2358 moveCursorUpdate(false);
2362 case LFUN_UNKNOWN_ACTION:
2364 if (owner->currentBuffer()->isReadonly()) {
2366 setErrorMessage(N_("Document is read only"));
2372 /* Automatically delete the currently selected
2373 * text and replace it with what is being
2374 * typed in now. Depends on lyxrc settings
2375 * "auto_region_delete", which defaults to
2378 if ( lyxrc->auto_region_delete ) {
2379 if (owner->currentBuffer()->text->selection){
2380 owner->currentBuffer()->text->CutSelection(false);
2381 owner->currentBuffer()->update(-1);
2386 for(char const *p = argument; *p; p++) {
2387 if (greek_kb_flag) {
2388 if (!math_insert_greek(*p))
2389 owner->getIntl()->getTrans()->TranslateAndInsert(*p, owner->currentBuffer()->text);
2391 owner->getIntl()->getTrans()->TranslateAndInsert(*p, owner->currentBuffer()->text);
2397 owner->currentBuffer()->text->sel_cursor =
2398 owner->currentBuffer()->text->cursor;
2399 moveCursorUpdate(false);
2402 // why is an "Unknown action" with empty
2403 // argument even dispatched in the first
2404 // place? I`ll probably change that. (Lgb)
2406 setErrorMessage(N_("Unknown action"));
2410 lyxerr.print("A truly unknown func!");
2416 LString res=getMessage();
2419 if (!commandshortcut.empty()) {
2420 LString newbuf = owner->getMiniBuffer()->GetText();
2421 if (newbuf != commandshortcut) {
2422 owner->getMiniBuffer()->Set(newbuf
2428 owner->getMiniBuffer()->Set(LString(_(res.c_str()))
2429 + " " + commandshortcut);
2432 return getMessage();
2436 void LyXFunc::setupLocalKeymap()
2438 keyseq.stdmap = keyseq.curmap = toplevel_keymap;
2439 cancel_meta_seq.stdmap = cancel_meta_seq.curmap = toplevel_keymap;
2443 void LyXFunc::MenuNew(bool fromTemplate)
2445 LString fname, initpath = lyxrc->document_path;
2448 if (owner->currentView()->available()) {
2449 LString trypath = owner->currentBuffer()->filepath;
2450 // If directory is writeable, use this as default.
2451 if (IsDirWriteable(trypath) == 1)
2456 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2457 fileDlg.SetButton(1, _("Templates"), lyxrc->template_path);
2458 fname = fileDlg.Select(_("Enter Filename for new document"),
2459 initpath, "*.lyx", _("newfile"));
2462 if (fname.empty()) {
2463 owner->getMiniBuffer()->Set(_("Canceled."));
2464 lyxerr.debug("New Document Cancelled.");
2468 // get absolute path of file and make sure the filename ends
2470 LString s = MakeAbsPath(fname);
2471 if (!IsLyXFilename(s))
2474 // Check if the document already is open
2475 if (bufferlist.exists(s)){
2476 switch(AskConfirmation(_("Document is already open:"),
2477 MakeDisplayPath(s,50),
2478 _("Do you want to close that document now?\n"
2479 "('No' will just switch to the open version)")))
2481 case 1: // Yes: close the document
2482 if (!bufferlist.close(bufferlist.getBuffer(s)))
2483 // If close is canceled, we cancel here too.
2486 case 2: // No: switch to the open document
2487 owner->currentView()->setBuffer(bufferlist.getBuffer(s));
2489 case 3: // Cancel: Do nothing
2490 owner->getMiniBuffer()->Set(_("Canceled."));
2495 // Check whether the file already exists
2496 if (IsLyXFilename(s)) {
2497 FilePtr myfile(s, FilePtr::read);
2499 AskQuestion(_("File already exists:"),
2500 MakeDisplayPath(s,50),
2501 _("Do you want to open the document?"))) {
2503 owner->getMiniBuffer()->Set(_("Opening document"),
2504 MakeDisplayPath(s), "...");
2506 owner->currentView()->setBuffer(
2507 bufferlist.loadLyXFile(s));
2508 owner->getMiniBuffer()->Set(_("Document"),
2515 // The template stuff
2519 fname = fileDlg.Select(_("Choose template"),
2520 lyxrc->template_path,
2526 // find a free buffer
2527 lyxerr.debug("Find a free buffer.");
2528 owner->currentView()->setBuffer(bufferlist.newFile(s,templname));
2532 void LyXFunc::MenuOpen()
2534 LString initpath = lyxrc->document_path;
2537 if (owner->currentView()->available()) {
2538 LString trypath = owner->currentBuffer()->filepath;
2539 // If directory is writeable, use this as default.
2540 if (IsDirWriteable(trypath) == 1)
2546 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2547 fileDlg.SetButton(1, _("Examples"),
2548 AddPath(system_lyxdir, "examples"));
2549 LString filename = fileDlg.Select(_("Select Document to Open"),
2553 // check selected filename
2554 if (filename.empty()) {
2555 owner->getMiniBuffer()->Set(_("Canceled."));
2559 // get absolute path of file and make sure the filename ends
2561 filename = MakeAbsPath(filename);
2562 if (!IsLyXFilename(filename))
2566 owner->getMiniBuffer()->Set(_("Opening document"),
2567 MakeDisplayPath(filename), "...");
2568 Buffer * openbuf = bufferlist.loadLyXFile(filename);
2570 owner->currentView()->setBuffer(openbuf);
2571 owner->getMiniBuffer()->Set(_("Document"),
2572 MakeDisplayPath(filename),
2575 owner->getMiniBuffer()->Set(_("Could not open document"),
2576 MakeDisplayPath(filename));
2581 void LyXFunc::doImportASCII(bool linorpar)
2583 LString initpath = lyxrc->document_path;
2586 if (owner->currentView()->available()) {
2587 LString trypath = owner->currentBuffer()->filepath;
2588 // If directory is writeable, use this as default.
2589 if (IsDirWriteable(trypath) == 1)
2595 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2596 fileDlg.SetButton(1, _("Examples"),
2597 AddPath(system_lyxdir, "examples"));
2598 LString filename = fileDlg.Select(_("Select ASCII file to Import"),
2602 // check selected filename
2603 if (filename.empty()) {
2604 owner->getMiniBuffer()->Set(_("Canceled."));
2608 // get absolute path of file
2609 filename = MakeAbsPath(filename);
2611 LString s = ChangeExtension(filename, ".lyx", false);
2613 // Check if the document already is open
2614 if (bufferlist.exists(s)){
2615 switch(AskConfirmation(_("Document is already open:"),
2616 MakeDisplayPath(s,50),
2617 _("Do you want to close that document now?\n"
2618 "('No' will just switch to the open version)")))
2620 case 1: // Yes: close the document
2621 if (!bufferlist.close(bufferlist.getBuffer(s)))
2622 // If close is canceled, we cancel here too.
2625 case 2: // No: switch to the open document
2626 owner->currentView()->setBuffer(bufferlist.getBuffer(s));
2628 case 3: // Cancel: Do nothing
2629 owner->getMiniBuffer()->Set(_("Canceled."));
2634 // Check if a LyX document by the same root exists in filesystem
2635 FileInfo f(s, true);
2636 if (f.exist() && !AskQuestion(_("A document by the name"),
2638 _("already exists. Overwrite?"))) {
2639 owner->getMiniBuffer()->Set(_("Canceled."));
2643 owner->currentView()->setBuffer(bufferlist.newFile(s,LString()));
2644 owner->getMiniBuffer()->Set(_("Importing ASCII file"),
2645 MakeDisplayPath(filename), "...");
2646 // Insert ASCII file
2647 InsertAsciiFile(filename,linorpar);
2648 owner->getMiniBuffer()->Set(_("ASCII file "),
2649 MakeDisplayPath(filename),
2654 void LyXFunc::doImportLaTeX(bool isnoweb)
2656 LString initpath = lyxrc->document_path;
2659 if (owner->currentView()->available()) {
2660 LString trypath = owner->currentBuffer()->filepath;
2661 // If directory is writeable, use this as default.
2662 if (IsDirWriteable(trypath) == 1)
2668 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2669 fileDlg.SetButton(1, _("Examples"),
2670 AddPath(system_lyxdir, "examples"));
2673 filename = fileDlg.Select(_("Select Noweb file to Import"),
2676 filename = fileDlg.Select(_("Select LaTeX file to Import"),
2682 // check selected filename
2683 if (filename.empty()) {
2684 owner->getMiniBuffer()->Set(_("Canceled."));
2688 // get absolute path of file
2689 filename = MakeAbsPath(filename);
2691 // Check if the document already is open
2692 LString LyXfilename = ChangeExtension(filename, ".lyx", false);
2693 if (bufferlist.exists(LyXfilename)){
2694 switch(AskConfirmation(_("Document is already open:"),
2695 MakeDisplayPath(LyXfilename,50),
2696 _("Do you want to close that document now?\n"
2697 "('No' will just switch to the open version)")))
2699 case 1: // Yes: close the document
2700 if (!bufferlist.close(bufferlist.getBuffer(LyXfilename)))
2701 // If close is canceled, we cancel here too.
2704 case 2: // No: switch to the open document
2705 owner->currentView()->setBuffer(
2706 bufferlist.getBuffer(LyXfilename));
2708 case 3: // Cancel: Do nothing
2709 owner->getMiniBuffer()->Set(_("Canceled."));
2714 // Check if a LyX document by the same root exists in filesystem
2715 FileInfo f(LyXfilename, true);
2716 if (f.exist() && !AskQuestion(_("A document by the name"),
2717 MakeDisplayPath(LyXfilename),
2718 _("already exists. Overwrite?"))) {
2719 owner->getMiniBuffer()->Set(_("Canceled."));
2726 owner->getMiniBuffer()->Set(_("Importing LaTeX file"),
2727 MakeDisplayPath(filename), "...");
2728 ImportLaTeX myImport(filename);
2729 openbuf = myImport.run();
2731 owner->getMiniBuffer()->Set(_("Importing Noweb file"),
2732 MakeDisplayPath(filename), "...");
2733 ImportNoweb myImport(filename);
2734 openbuf = myImport.run();
2737 owner->currentView()->setBuffer(openbuf);
2738 owner->getMiniBuffer()->Set(isnoweb ?
2739 _("Noweb file ") : _("LateX file "),
2740 MakeDisplayPath(filename),
2743 owner->getMiniBuffer()->Set(isnoweb ?
2744 _("Could not import Noweb file") :
2745 _("Could not import LaTeX file"),
2746 MakeDisplayPath(filename));
2751 void LyXFunc::MenuInsertLyXFile(LString const & filen)
2753 LString filename = filen;
2755 if (filename.empty()) {
2756 // Launch a file browser
2757 LString initpath = lyxrc->document_path;
2760 if (owner->currentView()->available()) {
2761 LString trypath = owner->currentBuffer()->filepath;
2762 // If directory is writeable, use this as default.
2763 if (IsDirWriteable(trypath) == 1)
2769 fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
2770 fileDlg.SetButton(1, _("Examples"),
2771 AddPath(system_lyxdir, "examples"));
2772 filename = fileDlg.Select(_("Select Document to Insert"),
2776 // check selected filename
2777 if (filename.empty()) {
2778 owner->getMiniBuffer()->Set(_("Canceled."));
2783 // get absolute path of file and make sure the filename ends
2785 filename = MakeAbsPath(filename);
2786 if (!IsLyXFilename(filename))
2790 owner->getMiniBuffer()->Set(_("Inserting document"),
2791 MakeDisplayPath(filename), "...");
2792 bool res = owner->currentBuffer()->insertLyXFile(filename);
2794 owner->getMiniBuffer()->Set(_("Document"),
2795 MakeDisplayPath(filename),
2798 owner->getMiniBuffer()->Set(_("Could not insert document"),
2799 MakeDisplayPath(filename));
2804 void LyXFunc::reloadBuffer()
2806 LString fn = owner->currentBuffer()->getFileName();
2807 if (bufferlist.close(owner->currentBuffer()))
2808 owner->currentView()->setBuffer(bufferlist.loadLyXFile(fn));
2812 void LyXFunc::CloseBuffer()
2814 if (bufferlist.close(owner->currentBuffer()) && !quitting) {
2815 if (bufferlist.isEmpty()) {
2816 // need this otherwise SEGV may occur while trying to
2817 // set variables that don't exist
2818 // since there's no current buffer
2819 CloseAllBufferRelatedPopups();
2822 owner->currentView()->setBuffer(bufferlist.first());
2828 Inset* LyXFunc::getInsetByCode(Inset::Code code)
2832 LyXCursor cursor = owner->currentBuffer()->text->cursor;
2833 int pos = cursor.pos;
2834 LyXParagraph *par = cursor.par;
2836 while (par && !found) {
2837 while ((inset = par->ReturnNextInsetPointer(pos))){
2838 if (inset->LyxCode()==code) {
2846 return (found) ? inset: 0;
2850 // Each "owner" should have it's own message method. lyxview and
2851 // the minibuffer would use the minibuffer, but lyxserver would
2852 // send an ERROR signal to its client. Alejandro 970603
2853 // This func is bit problematic when it comes to NLS, to make the
2854 // lyx servers client be language indepenent we must not translate
2855 // strings sent to this func.
2856 void LyXFunc::setErrorMessage(LString const &m)
2858 dispatch_buffer = m;
2863 void LyXFunc::setMessage(LString const & m)
2865 dispatch_buffer = m;