]> git.lyx.org Git - features.git/blob - src/LyXAction.C
The command-sequence patch from Andre'; also remove the comment in first
[features.git] / src / LyXAction.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-1999 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #include <cstdlib>
14 #include <cstdio>
15 #include <cctype>
16 #include <cstring>
17
18 #ifdef __GNUG__
19 #pragma implementation
20 #endif
21
22 #include "LyXAction.h"
23 #include "debug.h"
24 #include "gettext.h"
25 #include "support/lstrings.h"
26
27  /*  
28      NAMING RULES FOR USER-COMMANDS
29      Here's the set of rules to apply when a new command name is introduced:
30  
31      1) Use the object.event order. That is, use `word-forward'
32         instead of `forward-word'.
33      2) Don't introduce an alias for an already named object. Same for events.
34      3) Forward movement or focus is called `forward' (not `right').
35      4) Backward movement or focus is called `backward' (not `left').
36      5) Upward movement of focus is called `up'.
37      6) Downward movement is called `down'.
38      7) The begin of an object is called `begin' (not `start').
39      8) The end of an object is called `end'.
40  
41      (May 19 1996, 12:04, RvdK)
42  */
43  
44
45 // These are globals. 
46 LyXAction lyxaction;
47
48
49 /* This table is sorted alphabetically [asierra 14Jan96] */
50 /* This table MUST be sorted alphabetically, incidentally! */ 
51 kb_func_table const lyx_func_table[] = {
52         { "accent-acute",                         LFUN_ACUTE },
53         { "accent-breve",                         LFUN_BREVE },
54         { "accent-caron",                         LFUN_CARON },
55         { "accent-cedilla",                       LFUN_CEDILLA },
56         { "accent-circle",                        LFUN_CIRCLE },
57         { "accent-circumflex",                    LFUN_CIRCUMFLEX },
58         { "accent-dot",                           LFUN_DOT },
59         { "accent-grave",                         LFUN_GRAVE },
60         { "accent-hungarian-umlaut",              LFUN_HUNG_UMLAUT },
61         { "accent-macron",                        LFUN_MACRON },
62         { "accent-ogonek",                        LFUN_OGONEK },
63         { "accent-special-caron",                 LFUN_SPECIAL_CARON },
64         { "accent-tie",                           LFUN_TIE },
65         { "accent-tilde",                         LFUN_TILDE },
66         { "accent-umlaut",                        LFUN_UMLAUT },
67         { "accent-underbar",                      LFUN_UNDERBAR },
68         { "accent-underdot",                      LFUN_UNDERDOT },
69         { "accent-vector",                        LFUN_VECTOR }, 
70         { "appendix",                         LFUN_APPENDIX }, 
71         { "apropos",                              LFUN_APROPOS },
72         { "backward-select",                      LFUN_LEFTSEL },
73         { "bibtex-database-add",                  LFUN_BIBDB_ADD },
74         { "bibtex-database-del",                  LFUN_BIBDB_DEL },
75         { "bibtex-insert",                        LFUN_INSERT_BIBTEX },
76         { "bibtex-style",                         LFUN_BIBTEX_STYLE },
77         { "break-line",                           LFUN_BREAKLINE },
78         { "break-paragraph",                      LFUN_BREAKPARAGRAPH },
79         { "break-paragraph-keep-layout",          LFUN_BREAKPARAGRAPHKEEPLAYOUT },
80         { "break-paragraph-skip",                 LFUN_BREAKPARAGRAPH_SKIP },
81         { "buffer-auto-save",                     LFUN_AUTOSAVE },
82         { "buffer-begin",                         LFUN_BEGINNINGBUF },
83         { "buffer-begin-select",                  LFUN_BEGINNINGBUFSEL },
84         { "buffer-child-insert",                  LFUN_CHILDINSERT },  // ale970521
85         { "buffer-child-open",                    LFUN_CHILDOPEN },  // ale970528
86         { "buffer-chktex",                        LFUN_RUNCHKTEX }, // Asger 971030
87         { "buffer-close",                         LFUN_CLOSEBUFFER },         
88         { "buffer-end",                           LFUN_ENDBUF },
89         { "buffer-end-select",                    LFUN_ENDBUFSEL },
90         { "buffer-export",                        LFUN_EXPORT },
91         { "buffer-fax",                           LFUN_FAX },
92         { "buffer-float-insert",                  LFUN_INSERTFOOTNOTE },
93         { "buffer-import",                        LFUN_IMPORT },
94         { "buffer-itemize-bullets-select",        LFUN_BUFFERBULLETSSELECT },
95         { "buffer-new",                           LFUN_MENUNEW },     
96         { "buffer-new-template",                  LFUN_MENUNEWTMPLT },
97         { "buffer-open",                          LFUN_MENUOPEN },    
98         { "buffer-previous",                      LFUN_PREVBUFFER },  
99         { "buffer-print",                         LFUN_MENUPRINT },   
100         { "buffer-reload",                        LFUN_MENURELOAD },   
101         { "buffer-toggle-read-only",              LFUN_READ_ONLY_TOGGLE },
102         { "buffer-typeset",                       LFUN_RUNLATEX },        // Alejandro's proposal
103         { "buffer-typeset-ps",                    LFUN_RUNDVIPS },
104         { "buffer-view",                          LFUN_PREVIEW },
105         { "buffer-view-ps",                       LFUN_PREVIEWPS },
106         { "buffer-write",                         LFUN_MENUWRITE },   
107         { "buffer-write-as",                      LFUN_MENUWRITEAS }, 
108         { "build-program",                        LFUN_BUILDPROG },
109         { "cancel",                               LFUN_CANCEL },
110         { "char-backward",                        LFUN_LEFT },
111         { "char-forward",                         LFUN_RIGHT },
112         { "citation-insert",                      LFUN_INSERT_CITATION },
113         { "command-execute",                      LFUN_EXEC_COMMAND },
114         { "command-prefix",                       LFUN_PREFIX },
115         { "command-sequence",                       LFUN_SEQUENCE },
116         { "copy",                                 LFUN_COPY },
117         { "cut",                                  LFUN_CUT },
118         { "delete-backward",                      LFUN_BACKSPACE },
119         { "delete-backward-skip",                 LFUN_BACKSPACE_SKIP },
120         { "delete-forward",                       LFUN_DELETE },
121         { "delete-forward-skip",                  LFUN_DELETE_SKIP },
122         { "depth-decrement",                      LFUN_DEPTH_MIN },
123         { "depth-increment",                      LFUN_DEPTH_PLUS },  
124         { "depth-next",                           LFUN_DEPTH },
125         { "dots-insert",                          LFUN_LDOTS },
126         { "down",                                 LFUN_DOWN },                 
127         { "down-select",                          LFUN_DOWNSEL },
128         { "drop-layouts-choice",                  LFUN_DROP_LAYOUTS_CHOICE },
129         { "end-of-sentence-period-insert",        LFUN_END_OF_SENTENCE },
130         { "error-next",                           LFUN_GOTOERROR },   
131         { "error-remove-all",                     LFUN_REMOVEERRORS },
132         { "figure-insert",                        LFUN_FIGURE },
133         { "file-insert",                          LFUN_FILE_INSERT },
134         { "file-insert-ascii",                    LFUN_FILE_INSERT_ASCII },
135         { "file-new",                             LFUN_FILE_NEW },
136         { "file-open",                            LFUN_FILE_OPEN },
137         { "find-replace",                         LFUN_MENUSEARCH },  
138         { "font-bold",                            LFUN_BOLD },        
139         { "font-code",                            LFUN_CODE },        
140         { "font-default",                         LFUN_DEFAULT },
141         { "font-emph",                            LFUN_EMPH },
142         { "font-free",                            LFUN_FREE },
143         { "font-noun",                            LFUN_NOUN },
144         { "font-roman",                           LFUN_ROMAN },
145         { "font-sans",                            LFUN_SANS },
146         { "font-size",                            LFUN_FONT_SIZE },
147         { "font-state",                           LFUN_FONT_STATE }, 
148         { "font-underline",                       LFUN_UNDERLINE },   
149         { "footnote-insert",                      LFUN_FOOTMELT },    
150         { "forward-select",                       LFUN_RIGHTSEL },
151         { "hfill-insert",                         LFUN_HFILL },
152         { "html-insert",                          LFUN_HTMLURL },
153         { "hyphenation-point-insert",             LFUN_HYPHENATION },
154         { "index-insert",                         LFUN_INDEX_INSERT },
155         { "index-insert-last",                    LFUN_INDEX_INSERT_LAST },
156         { "index-print",                          LFUN_INDEX_PRINT },
157 #if 0
158         { "inset-latex-insert",                   LFUN_INSERT_INSET_LATEX },
159 #endif
160         { "keymap-off",                           LFUN_KMAP_OFF },
161         { "keymap-primary",                       LFUN_KMAP_PRIM },
162         { "keymap-secondary",                     LFUN_KMAP_SEC },
163         { "keymap-toggle",                        LFUN_KMAP_TOGGLE },
164         { "label-insert",                         LFUN_INSERT_LABEL },
165         { "latex-view-log",                       LFUN_LATEX_LOG },
166         { "layout",                               LFUN_LAYOUT },
167         { "layout-character",                     LFUN_LAYOUT_CHARACTER },
168         { "layout-copy",                          LFUN_LAYOUT_COPY },
169         { "layout-document",                      LFUN_LAYOUT_DOCUMENT },
170         //{ "layout-number",                      LFUN_LAYOUTNO }, // internal only
171         { "layout-paper",                         LFUN_LAYOUT_PAPER },
172         { "layout-paragraph",                     LFUN_LAYOUT_PARAGRAPH },
173         { "layout-paste",                         LFUN_LAYOUT_PASTE },
174         { "layout-preamble",                      LFUN_LAYOUT_PREAMBLE },
175         { "layout-quotes",                        LFUN_LAYOUT_QUOTES },
176         { "layout-save-default",                  LFUN_LAYOUT_SAVE_DEFAULT },
177         { "layout-table",                         LFUN_LAYOUT_TABLE },
178         { "line-begin",                           LFUN_HOME },        
179         { "line-begin-select",                    LFUN_HOMESEL },     
180         { "line-delete-forward",                  LFUN_DELETE_LINE_FORWARD },  
181         { "line-end",                             LFUN_END },         
182         { "line-end-select",                      LFUN_ENDSEL },
183         { "loa-insert",                           LFUN_LOA_INSERT },
184         { "lof-insert",                           LFUN_LOF_INSERT },
185         { "lot-insert",                           LFUN_LOT_INSERT },
186         { "lyx-quit",                             LFUN_QUIT },
187         { "marginpar-insert",                     LFUN_MARGINMELT },  
188         { "mark-off",                             LFUN_MARK_OFF },    
189         { "mark-on",                              LFUN_MARK_ON },     
190         { "mark-toggle",                          LFUN_SETMARK }, 
191         { "math-delim",                           LFUN_MATH_DELIM },
192         { "math-display",                         LFUN_MATH_DISPLAY }, // Alejandro's proposal
193         { "math-greek",                           LFUN_GREEK },   
194         { "math-greek-toggle",                    LFUN_GREEK_TOGGLE },   
195         { "math-insert",                          LFUN_INSERT_MATH },   
196         { "math-limits",                          LFUN_MATH_LIMITS },
197         { "math-macro",                           LFUN_MATH_MACRO },
198         { "math-macro-arg",                       LFUN_MATH_MACROARG },
199         { "math-matrix",                          LFUN_INSERT_MATRIX }, 
200         { "math-mode",                            LFUN_MATH_MODE },
201         { "math-nonumber",                        LFUN_MATH_NONUMBER },
202         { "math-number",                          LFUN_MATH_NUMBER }, 
203         { "math-size",                            LFUN_MATH_SIZE }, 
204         { "melt",                                 LFUN_MELT },            // Needs better name. What about "float-disolve" or "float-extract" (Lgb)
205         { "menu-open",                            LFUN_MENU_OPEN_BY_NAME },
206         { "menu-separator-insert",                LFUN_MENU_SEPARATOR },
207         { "meta-prefix",                          LFUN_META_FAKE },
208         { "note-insert",                          LFUN_INSERT_NOTE },
209         { "note-next",                            LFUN_GOTONOTE },
210         { "open-stuff",                           LFUN_OPENSTUFF },       // Needs better name.
211         { "paragraph-down",                       LFUN_DOWN_PARAGRAPH },
212         { "paragraph-down-select",                LFUN_DOWN_PARAGRAPHSEL },
213         { "paragraph-up",                         LFUN_UP_PARAGRAPH },
214         { "paragraph-up-select",                  LFUN_UP_PARAGRAPHSEL },
215         { "parent-insert",                        LFUN_PARENTINSERT },
216         { "paste",                                LFUN_PASTE },
217         { "primary-selection-paste",              LFUN_PASTESELECTION },
218         { "protected-space-insert",               LFUN_PROTECTEDSPACE },
219         { "quote-insert",                         LFUN_QUOTE },
220         { "reconfigure",                          LFUN_RECONFIGURE },
221         { "redo",                                 LFUN_REDO },
222         { "reference-back",                       LFUN_REFBACK },
223         { "reference-goto",                       LFUN_REFGOTO }, 
224         { "reference-insert",                     LFUN_INSERT_REF },
225         { "reference-toggle",                     LFUN_REFTOGGLE },
226         { "screen-down",                          LFUN_NEXT },        
227         { "screen-down-select",                   LFUN_NEXTSEL },     
228         { "screen-recenter",                      LFUN_CENTER },
229         { "screen-up",                            LFUN_PRIOR },       
230         { "screen-up-select",                     LFUN_PRIORSEL },    
231         { "self-insert",                          LFUN_SELFINSERT },
232         { "server-char-after",                    LFUN_CHARATCURSOR },
233         { "server-get-font",                      LFUN_GETFONT },
234         { "server-get-latex",                     LFUN_GETLATEX },
235         { "server-get-layout",                    LFUN_GETLAYOUT },
236         { "server-get-name",                      LFUN_GETNAME },
237         { "server-get-tip",                       LFUN_GETTIP },
238         { "server-get-xy",                        LFUN_GETXY },
239         { "server-goto-file-row",                 LFUN_GOTOFILEROW },
240         { "server-notify",                        LFUN_NOTIFY },
241         { "server-set-xy",                        LFUN_SETXY },
242         { "spellchecker",                         LFUN_SPELLCHECK },  
243         { "symbol-insert",                        LFUN_INSERT_MATH },
244         { "tab-forward",                          LFUN_TAB },
245         { "tab-insert",                           LFUN_TABINSERT },
246         { "table-insert",                         LFUN_TABLE },
247         { "tex-mode",                             LFUN_TEX },
248         { "toc-insert",                           LFUN_TOC_INSERT },
249         { "toc-view",                             LFUN_TOCVIEW },
250         { "toggle-cursor-follows-scrollbar",      LFUN_TOGGLECURSORFOLLOW },
251         { "toolbar-add-to",                       LFUN_ADD_TO_TOOLBAR },
252         { "toolbar-push",                         LFUN_PUSH_TOOLBAR },
253         { "undo",                                 LFUN_UNDO },
254         { "up",                                   LFUN_UP },          
255         { "up-select",                            LFUN_UPSEL },
256         { "url-insert",                           LFUN_URL },
257         { "vc-check-in",                          LFUN_VC_CHECKIN }, 
258         { "vc-check-out",                         LFUN_VC_CHECKOUT }, 
259         { "vc-history",                           LFUN_VC_HISTORY }, 
260         { "vc-register",                          LFUN_VC_REGISTER }, 
261         { "vc-revert",                            LFUN_VC_REVERT }, 
262         { "vc-undo-last",                         LFUN_VC_UNDO }, 
263         { "word-backward",                        LFUN_WORDLEFT },
264         { "word-backward-select",                 LFUN_WORDLEFTSEL },
265         { "word-capitalize",                      LFUN_CAPITALIZE_WORD },
266         { "word-delete-backward",                 LFUN_DELETE_WORD_BACKWARD },
267         { "word-delete-forward",                  LFUN_DELETE_WORD_FORWARD }, 
268         { "word-find-backward",                   LFUN_WORDFINDBACKWARD },
269         { "word-find-forward",                    LFUN_WORDFINDFORWARD },
270         { "word-forward",                         LFUN_WORDRIGHT },
271         { "word-forward-select",                  LFUN_WORDRIGHTSEL },
272         { "word-lowcase",                         LFUN_LOWCASE_WORD },
273         { "word-upcase",                          LFUN_UPCASE_WORD }
274 };
275
276
277 /* 
278    This table contains the actions that modify a buffer and therefore
279    are not allowed for RO files. Do you think we have too much tables?
280    Each single integer in this table replaces 5 lines of code in lyxfunc
281    that include at least 3 function calls (several integers in the 
282    code segment).
283  
284    The table could in the near future be expanded adding a second integer 
285    field with attributes using these tags:
286
287 enum FUNC_ATTRIB {
288     LFAT_NONE= 0,     // Nothing special
289     LFAT_ISRO= 1,     // Is readonly (does not modify a buffer)
290     LFAT_ISIA= 2,     // Is interactive (requires a GUI)
291     LFAT_REQARG= 4,   // Requires argument
292     LFAT_ISMO= 8,     // Only math mode
293     LFAT_ETCETC
294 };
295
296 struct {
297     kb_action action;
298     unsigned  attrib; 
299 };
300
301 Alejandro-970604
302 */
303
304 kb_action func_attrib_table[] = {
305         LFUN_ACUTE,
306         LFUN_AUTOSAVE,
307         LFUN_BACKSPACE,
308         LFUN_BACKSPACE_SKIP,
309         LFUN_BIBDB_ADD,
310         LFUN_BIBDB_DEL,
311         LFUN_BIBTEX_STYLE,
312         LFUN_BOLD,
313         LFUN_BREAKLINE,
314         LFUN_BREAKPARAGRAPH,
315         LFUN_BREAKPARAGRAPHKEEPLAYOUT,
316         LFUN_BREAKPARAGRAPH_SKIP,
317         LFUN_BREVE,
318         LFUN_BUFFERBULLETSSELECT,
319         LFUN_CAPITALIZE_WORD,
320         LFUN_CARON,
321         LFUN_CEDILLA,
322         LFUN_CHILDINSERT,
323         LFUN_CIRCLE,
324         LFUN_CIRCUMFLEX,
325         LFUN_CODE,
326         LFUN_CUT,
327         LFUN_DEFAULT,
328         LFUN_DELETE,
329         LFUN_DELETE_LINE_FORWARD,
330         LFUN_DELETE_SKIP,
331         LFUN_DELETE_WORD_BACKWARD,
332         LFUN_DELETE_WORD_FORWARD,
333         LFUN_DEPTH,
334         LFUN_DEPTH_MIN,
335         LFUN_DEPTH_PLUS,
336         LFUN_DOT,
337         LFUN_EMPH,
338         LFUN_END_OF_SENTENCE,
339         LFUN_FIGURE,
340         LFUN_FILE_INSERT,
341         LFUN_FILE_INSERT_ASCII,
342         LFUN_FONT_SIZE,
343         LFUN_FOOTMELT,
344         LFUN_FREE,
345         LFUN_GRAVE,
346         LFUN_HFILL,
347         LFUN_HTMLURL,
348         LFUN_HUNG_UMLAUT,
349         LFUN_HYPHENATION,
350         LFUN_INDEX_INSERT,
351         LFUN_INDEX_INSERT_LAST,
352         LFUN_INDEX_PRINT,
353         LFUN_INSERTFOOTNOTE,
354         LFUN_INSERT_BIBTEX,
355         LFUN_INSERT_CITATION,
356 #if 0
357         LFUN_INSERT_INSET_LATEX,
358 #endif
359         LFUN_INSERT_LABEL,
360         LFUN_INSERT_MATH,
361         LFUN_INSERT_MATRIX,
362         LFUN_INSERT_NOTE,
363         LFUN_INSERT_REF,
364         LFUN_LAYOUT,
365         LFUN_LAYOUTNO,
366         LFUN_LAYOUT_CHARACTER,
367         LFUN_LAYOUT_PASTE,
368         LFUN_LAYOUT_QUOTES,
369         LFUN_LDOTS,
370         LFUN_LOA_INSERT,
371         LFUN_LOF_INSERT,
372         LFUN_LOT_INSERT,
373         LFUN_LOWCASE_WORD,
374         LFUN_MACRON,
375         LFUN_MARGINMELT,
376         LFUN_MATH_DELIM,
377         LFUN_MATH_DISPLAY,
378         LFUN_MATH_MACRO,
379         LFUN_MATH_MACROARG,
380         LFUN_MATH_MODE,
381         LFUN_MATH_NONUMBER,
382         LFUN_MATH_NUMBER,
383         LFUN_MATH_SIZE,
384         LFUN_MELT,
385         LFUN_MENU_SEPARATOR,
386         LFUN_NOUN,
387         LFUN_OGONEK,
388         LFUN_PARENTINSERT,
389         LFUN_PASTE,
390         LFUN_PASTESELECTION,
391         LFUN_PROTECTEDSPACE,
392         LFUN_QUOTE,
393         LFUN_REDO,
394         LFUN_REFTOGGLE,
395         LFUN_ROMAN,
396         LFUN_SANS,
397         LFUN_SELFINSERT,
398         LFUN_SPECIAL_CARON,
399         LFUN_TABINSERT,
400         LFUN_TABLE,
401         LFUN_TEX,
402         LFUN_TIE,
403         LFUN_TILDE,
404         LFUN_TOC_INSERT,
405         LFUN_UMLAUT,
406         LFUN_UNDERBAR,
407         LFUN_UNDERDOT,
408         LFUN_UNDERLINE,
409         LFUN_UNDO,
410         LFUN_UNKNOWN_ACTION,
411         LFUN_UPCASE_WORD,
412         LFUN_URL,
413         LFUN_VECTOR,
414         LFUN_WORDFINDFORWARD,
415         LFUN_WORDFINDBACKWARD
416 };
417
418 int LyXAction::psd_idx = 0;
419 kb_func_table const * LyXAction::lyx_func_table = &::lyx_func_table[0];
420 kb_func_table* LyXAction::lyx_func_args = 0;
421  
422 /* === code ============================================================== */
423
424 /* This routines allow binding actions with argument.
425  * Provisionally a fixed size array and global functions are used.
426  * [asierra 20Jan96]
427  */
428 #define MAX_PSEUDO_ACTION 128
429
430
431 LyXAction::LyXAction()
432 {
433         lyx_func_args= new kb_func_table[MAX_PSEUDO_ACTION];
434         funcCount = sizeof(::lyx_func_table) / sizeof(::kb_func_table);
435 }
436
437
438 LyXAction::~LyXAction()
439 {
440         if (lyx_func_args) {
441 // This is wrong, so I'll just disable it for now.
442 // The problem is that we might free memory twice in some situations...
443 // It's better to leak a bit that to crash. (Asger)
444 //              for (int i= 0; i < psd_idx; i++) {
445 //                      free(lyx_func_args[i].name);
446 //              }
447                 delete[] lyx_func_args;
448                 lyx_func_args = 0;
449         }
450 }
451
452
453 // Search for an existent pseudoaction, return -1 if it doesn't exist.
454 int  LyXAction::searchActionArg(kb_action action, char const *arg)
455 {
456         kb_func_table *tb = &lyx_func_args[0];
457         for (int i= 0; i<psd_idx; i++) {
458                 if (action == tb->action && !strcmp(tb->name, arg)) {    
459
460                         lyxerr[Debug::KEY] << "Pseudoaction already exist[" 
461                                            << action << '|' 
462                                            << arg << ']' << endl;
463
464                         return LFUN_LASTACTION+i;
465                 }
466                 tb++;
467         }
468         return -1;
469 }
470
471
472 // Returns a pseudo-action given an action and its argument.
473 int LyXAction::getPseudoAction(kb_action action, char const *arg)
474 {
475         // Check if the pseudo-action already exist.
476         int psdaction = searchActionArg(action, arg);
477    
478         if (psdaction >= 0) return psdaction;
479
480         if (psd_idx>= MAX_PSEUDO_ACTION) {
481                 lyxerr << "Lyx Error: No more pseudo-actions allowed"
482                        << "           Tell the developers." << endl;
483                 return -1;
484         }
485         lyx_func_args[psd_idx].name = strdup(arg);
486         lyx_func_args[psd_idx].action = action;
487         psd_idx++;
488         return LFUN_LASTACTION+psd_idx-1;
489 }
490
491
492 // Retrieves the real action and its argument.
493 int LyXAction::retrieveActionArg(int i, char const** arg)
494 {
495         i -= LFUN_LASTACTION;
496         if (i >= 0 &&  i <psd_idx) {
497                 *arg = lyx_func_args[i].name;
498                 return (int)lyx_func_args[i].action;
499         } else {
500                 lyxerr << "Lyx Error: Unrecognized pseudo-action" << endl;
501                 return -1;
502         }
503 }
504
505
506 // Returns an action tag from a string.
507 int LyXAction::LookupFunc(char const * func)
508 {
509         if (!func) 
510                 return LFUN_UNKNOWN_ACTION;         
511         if (func[0] == '\0')
512                 return LFUN_NOACTION;
513  
514    /* In the scan loop below, l can never become r, so set r one past the last
515       valid func table slot. RVDK_PATCH_5 */
516         int k, l= 0, r = funcCount;
517         int action = LFUN_UNKNOWN_ACTION;
518         char * arg = strchr(const_cast<char*>(func), ' '); // const cast to
519         // help a sun complier, will go away when this func is rewritten
520         // to use std::containers and std::string.
521
522         if (arg) *(arg++) = '\0';      
523
524         while (l < r) {
525                 last_action_idx = (l+r)/2;
526                 k = strcmp(lyx_func_table[last_action_idx].name, func);
527                 if (k == 0) {
528                         action = lyx_func_table[last_action_idx].action;
529                         break;
530                 } else
531                         if (k<0) l = last_action_idx+1; else r = last_action_idx;
532         }
533         if (arg && action >= 0) {
534                 action = getPseudoAction((kb_action)action, arg);
535                 lyxerr[Debug::KEY] << "Pseudo action_arg["
536                                    << action << '|' 
537                                    << arg << ']' << endl;
538         }
539         return action;
540 }
541
542
543 int LyXAction::getApproxFunc(char const *func)
544 {
545     int action = LookupFunc(func);
546     if (action<0) {
547         int k = strncmp(lyx_func_table[last_action_idx].name,
548                         func, strlen(func));
549         if (k<0 && last_action_idx<funcCount-1) 
550           last_action_idx++;
551         else if (k>0 && last_action_idx>0)
552           last_action_idx--;
553         
554         action = lyx_func_table[last_action_idx].action;
555     } else if (last_action_idx<funcCount-1)
556       last_action_idx++;
557     
558     return action;
559 }
560
561
562 char const *LyXAction::getApproxFuncName(char const *func)
563 {
564     getApproxFunc(func);
565     return lyx_func_table[last_action_idx].name;
566 }
567
568
569 char const *LyXAction::getActionName(int action) const
570 {
571         // why LFUN_LASTACTION -1? Because LFUN_LASTACTION is too
572         // large an because there is one internal command, hence
573         // lyx_func_table is 2 less then LFUN_LASTACTION (Lgb)
574     for (int i= 0; i < funcCount; i++) {
575         if (lyx_func_table[i].action == action)
576           return lyx_func_table[i].name;
577     }
578     
579     // Hmm.. let's see whether this is a pseudoaction
580     action -= LFUN_LASTACTION;
581     if (action>= 0 && action<psd_idx) {
582         return lyx_func_args[action].name;
583     }
584     
585     return "";
586 }
587
588
589 // Returns one line help associated with function
590 // Now the missing strings are replaced by the command names. (Alejandro)
591 char const *LyXAction::helpText(kb_action action) const
592 {
593         static bool is_sorted = false;
594         static kb_func_table helpTexts[LFUN_LASTACTION] = 
595         {
596                 { _("Describe command"), LFUN_APROPOS },
597                 { _("Select previous char"), LFUN_LEFTSEL },
598                 { _("Insert bibtex"), LFUN_INSERT_BIBTEX },
599                 { _("Autosave"), LFUN_AUTOSAVE },
600                 { _("Go to beginning of document"), LFUN_BEGINNINGBUF },
601                 { _("Select to beginning of document"), LFUN_BEGINNINGBUFSEL },
602                 { _("Close"), LFUN_CLOSEBUFFER },
603                 { _("Go to end of document"), LFUN_ENDBUF },
604                 { _("Select to end of document"), LFUN_ENDBUFSEL },
605                 { _("Fax"), LFUN_FAX },
606                 { _("New document"), LFUN_MENUNEW },
607                 { _("New document from template"), LFUN_MENUNEWTMPLT },
608                 { _("Open"), LFUN_MENUOPEN },
609                 { _("Switch to previous document"), LFUN_PREVBUFFER },
610                 { _("Print"), LFUN_MENUPRINT },
611                 { _("Revert to saved"), LFUN_MENURELOAD },
612                 { _("Update DVI"), LFUN_RUNLATEX },
613                 { _("Update PostScript"), LFUN_RUNDVIPS },
614                 { _("View DVI"), LFUN_PREVIEW },
615                 { _("View PostScript"), LFUN_PREVIEWPS },
616                 { _("Build program"), LFUN_BUILDPROG },
617                 { _("Check TeX"), LFUN_RUNCHKTEX },
618                 { _("Save"), LFUN_MENUWRITE },
619                 { _("Save As"), LFUN_MENUWRITEAS },
620                 { _("Cancel"), LFUN_CANCEL },
621                 { _("Go one char back"), LFUN_LEFT },
622                 { _("Go one char forward"), LFUN_RIGHT },
623                 { _("Insert citation"), LFUN_INSERT_CITATION },
624                 { _("Execute command"), LFUN_EXEC_COMMAND },
625                 { _("Copy"), LFUN_COPY },
626                 { _("Cut"), LFUN_CUT },
627                 { _("Decrement environment depth"), LFUN_DEPTH_MIN },
628                 { _("Increment environment depth"), LFUN_DEPTH_PLUS },
629                 { _("Change environment depth"), LFUN_DEPTH },
630                 { _("Change itemize bullet settings"), LFUN_BUFFERBULLETSSELECT },
631                 { _("Go down"), LFUN_DOWN },
632                 { _("Select next line"), LFUN_DOWNSEL },
633                 { _("Choose Paragraph Environment"), LFUN_DROP_LAYOUTS_CHOICE },
634                 { _("Go to next error"), LFUN_GOTOERROR },
635                 { _("Insert Figure"), LFUN_FIGURE },
636                 { _("Find & Replace"), LFUN_MENUSEARCH },
637                 { _("Toggle cursor does/doesn't follow the scrollbar"), LFUN_TOGGLECURSORFOLLOW },
638                 { _("Toggle bold"), LFUN_BOLD },
639                 { _("Toggle code style"), LFUN_CODE },
640                 { _("Default font style"), LFUN_DEFAULT },
641                 { _("Toggle emphasize"), LFUN_EMPH },
642                 { _("Toggle user defined style"), LFUN_FREE },
643                 { _("Toggle noun style"), LFUN_NOUN },
644                 { _("Toggle roman font style"), LFUN_ROMAN },
645                 { _("Toggle sans font style"), LFUN_SANS },
646                 { _("Set font size"), LFUN_FONT_SIZE },
647                 { _("Show font state"), LFUN_FONT_STATE },
648                 { _("Toggle font underline"), LFUN_UNDERLINE },
649                 { _("Insert Footnote"), LFUN_FOOTMELT },
650                 { _("Select next char"), LFUN_RIGHTSEL },
651                 { _("Insert horizontal fill"), LFUN_HFILL },
652                 { _("Insert hyphenation point"), LFUN_HYPHENATION },
653                 { _("Insert ... dots"), LFUN_LDOTS },
654                 { _("Insert end of sentence period"), LFUN_END_OF_SENTENCE },
655                 { _("Turn off keymap"), LFUN_KMAP_OFF },
656                 { _("Use primary keymap"), LFUN_KMAP_PRIM },
657                 { _("Use secondary keymap"), LFUN_KMAP_SEC },
658                 { _("Toggle keymap"), LFUN_KMAP_TOGGLE },
659                 { _("Insert Label"), LFUN_INSERT_LABEL },
660                 { _("Copy paragraph environment type"), LFUN_LAYOUT_COPY },
661                 { _("Paste paragraph environment type"), LFUN_LAYOUT_PASTE },
662                 { _("Specify paper size and margins"), LFUN_LAYOUT_PAPER },
663                 { _("Go to beginning of line"), LFUN_HOME },
664                 { _("Select to beginning of line"), LFUN_HOMESEL },
665                 { _("Go to end of line"), LFUN_END },
666                 { _("Select to end of line"), LFUN_ENDSEL },
667                 { _("Exit"), LFUN_QUIT },
668                 { _("Insert Margin note"), LFUN_MARGINMELT },
669                 { _("Math Greek"), LFUN_GREEK },   
670                 { _("Math mode"), LFUN_MATH_MODE },
671                 { _("Go one paragraph down"), LFUN_DOWN_PARAGRAPH },
672                 { _("Select next paragraph"), LFUN_DOWN_PARAGRAPHSEL },
673                 { _("Go one paragraph up"), LFUN_UP_PARAGRAPH },
674                 { _("Select previous paragraph"), LFUN_UP_PARAGRAPHSEL },
675                 { _("Paste"), LFUN_PASTE },
676                 { _("Insert protected space"), LFUN_PROTECTEDSPACE },
677                 { _("Insert quote"), LFUN_QUOTE },
678                 { _("Reconfigure"), LFUN_RECONFIGURE },
679                 { _("Redo"), LFUN_REDO },
680                 { _("Insert cross reference"), LFUN_INSERT_REF },
681                 { _("Insert Table"), LFUN_TABLE },
682                 { _("Toggle TeX style"), LFUN_TEX },
683                 { _("Undo"), LFUN_UNDO },
684                 { _("Melt"), LFUN_MELT },
685                 { _("Import document"), LFUN_IMPORT },
686                 { _("Remove all error boxes"), LFUN_REMOVEERRORS },
687                 { _("Insert menu separator"), LFUN_MENU_SEPARATOR }
688 //              { "reference-back", LFUN_REFBACK },
689 //              { "reference-goto", LFUN_REFGOTO }, 
690         };
691         
692         // Sort to make it faster
693         if (!is_sorted) {
694                 int i= 0; 
695                 while (i < LFUN_LASTACTION-1) {
696                     if (helpTexts[i].action == 0) {
697                         helpTexts[i].action = (kb_action)i;
698                         helpTexts[i].name = getActionName(i);
699                         i++;
700                     } else if (helpTexts[i].action != i) {
701                         int k = helpTexts[i].action;
702                         kb_func_table tmp = helpTexts[k];
703                         helpTexts[k] = helpTexts[i];
704                         helpTexts[i] = tmp;
705                         if (k < i) i++;
706                     } else {
707                         i++;
708                     }
709                 }
710                 is_sorted = true;
711         }
712
713         if (action <= 1 || action >= funcCount)
714                 goto no_desc;
715                 
716         if (helpTexts[action].action == action) {
717             return helpTexts[action].name;
718         } 
719         //        + string(' ') + int(is_ro) + string(']'));
720   no_desc:
721         // In an ideal world, this never happens:
722         return _("No description available!");
723 }
724
725
726 // Function to compare items from the attrib table.
727 extern "C" int actioncomp(const void *a, const void *b)
728 {
729     int const *ia= (int const*)a, *ib= (int const*)b;
730     return (*ia)-(*ib);
731 }
732
733  
734 bool LyXAction::isFuncRO(kb_action action) const
735 {
736     static bool is_sorted = false;    
737     static int fCount = sizeof(::func_attrib_table) / sizeof(kb_action);
738     
739     if (!is_sorted) {
740         qsort(func_attrib_table, fCount, sizeof(kb_action), actioncomp);
741         is_sorted = true;
742 //      for (int i= 0; i<fCount; i++) 
743 //        fprintf(stdout, "%d: %d\n", i, func_attrib_table[i]);
744     }
745
746     int m, k, l= 0, r = fCount;
747     int is_ro = false;
748
749     while (l < r) {
750         m = (l+r)/2;
751         k = func_attrib_table[m] - action;
752         if (k == 0) {
753             is_ro = true;
754             break;
755         } else
756           if (k<0) l = m+1; else r = m;
757     }
758     lyxerr.debug() << "RO[" << action
759                    << " " << is_ro << "]" << endl;
760     return is_ro;
761 }
762
763 ostream & operator<<(ostream & o, kb_action action)
764 {
765         return o << int(action);
766 }