]> git.lyx.org Git - lyx.git/blob - src/MenuBackend.C
Remove unused font variable which caused a warning.
[lyx.git] / src / MenuBackend.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2001 The LyX Team.
8  *
9  *
10  * ====================================================== */
11
12 #include <config.h>
13
14 #ifdef __GNUG__
15 #pragma implementation
16 #endif
17
18 #include "MenuBackend.h"
19 #include "lyxlex.h"
20 #include "LyXAction.h"
21 #include "debug.h"
22 #include "gettext.h"
23 #include "lastfiles.h"
24 #include "bufferlist.h"
25 #include "converter.h"
26 #include "exporter.h"
27 #include "importer.h"
28 #include "FloatList.h"
29 #include "support/LAssert.h"
30 #include "support/filetools.h"
31 #include "support/lyxfunctional.h"
32
33 extern LyXAction lyxaction;
34 extern LastFiles * lastfiles; 
35 extern BufferList bufferlist;
36
37 using std::endl;
38 using std::vector;
39 using std::pair;
40 using std::find_if;
41 using std::sort;
42
43 // This is the global menu definition
44 MenuBackend menubackend;
45
46
47 MenuItem::MenuItem(Kind kind, string const & label, 
48                    string const & command, bool optional) 
49         : kind_(kind), label_(label), optional_(optional)
50 {
51         switch (kind) {
52         case Separator:
53         case Documents:
54         case Lastfiles:
55         case Toc:
56         case ViewFormats:
57         case UpdateFormats:
58         case ExportFormats:
59         case ImportFormats:
60         case FloatListInsert:
61         case FloatInsert:
62                 break;
63         case Command:
64                 action_ = lyxaction.LookupFunc(command);
65
66                 if (action_ == LFUN_UNKNOWN_ACTION) {
67                         lyxerr << "MenuItem(): LyX command `"
68                                << command << "' does not exist." << endl; 
69                 }
70                 if (optional_)
71                         lyxerr[Debug::GUI] << "Optional item " 
72                                            << command << endl; 
73                 break;
74         case Submenu:
75                 submenu_ = command;
76                 break;
77         }
78 }
79
80
81 Menu & Menu::add(MenuItem const & i)
82 {
83         items_.push_back(i);
84         return *this;
85 }
86
87
88 Menu & Menu::read(LyXLex & lex)
89 {
90         enum Menutags {
91                 md_item = 1,
92                 md_documents,
93                 md_endmenu,
94                 md_exportformats,
95                 md_importformats,
96                 md_lastfiles,
97                 md_optitem,
98                 md_separator,
99                 md_submenu,
100                 md_toc,
101                 md_updateformats,
102                 md_viewformats,
103                 md_floatlistinsert,
104                 md_floatinsert,
105                 md_last
106         };
107
108         struct keyword_item menutags[md_last - 1] = {
109                 { "documents", md_documents },
110                 { "end", md_endmenu },
111                 { "exportformats", md_exportformats },
112                 { "floatinsert", md_floatinsert },
113                 { "floatlistinsert", md_floatlistinsert },
114                 { "importformats", md_importformats },
115                 { "item", md_item },
116                 { "lastfiles", md_lastfiles },
117                 { "optitem", md_optitem }, 
118                 { "separator", md_separator },
119                 { "submenu", md_submenu },
120                 { "toc", md_toc },
121                 { "updateformats", md_updateformats },
122                 { "viewformats", md_viewformats }
123         };
124
125         lex.pushTable(menutags, md_last - 1);
126         if (lyxerr.debugging(Debug::PARSER))
127                 lex.printTable(lyxerr);
128
129         bool quit = false;
130         bool optional = false;
131
132         while (lex.IsOK() && !quit) {
133                 switch (lex.lex()) {
134                 case md_optitem:
135                         optional = true;
136                         // fallback to md_item
137                 case md_item: {
138                         lex.next(true);
139                         string const name = _(lex.GetString());
140                         lex.next(true);
141                         string const command = lex.GetString();
142                         add(MenuItem(MenuItem::Command, name, 
143                                      command, optional));
144                         optional = false;
145                         break;
146                 }
147
148                 case md_separator:
149                         add(MenuItem(MenuItem::Separator));
150                         break;
151
152                 case md_lastfiles:
153                         add(MenuItem(MenuItem::Lastfiles));
154                         break;
155
156                 case md_documents:
157                         add(MenuItem(MenuItem::Documents));
158                         break;
159
160                 case md_toc:
161                         add(MenuItem(MenuItem::Toc));
162                         break;
163
164                 case md_viewformats:
165                         add(MenuItem(MenuItem::ViewFormats));
166                         break;
167
168                 case md_updateformats:
169                         add(MenuItem(MenuItem::UpdateFormats));
170                         break;
171
172                 case md_exportformats:
173                         add(MenuItem(MenuItem::ExportFormats));
174                         break;
175
176                 case md_importformats:
177                         add(MenuItem(MenuItem::ImportFormats));
178                         break;
179
180                 case md_floatlistinsert:
181                         add(MenuItem(MenuItem::FloatListInsert));
182                         break;
183
184                 case md_floatinsert:
185                         add(MenuItem(MenuItem::FloatInsert));
186                         break;
187                         
188                 case md_submenu: {
189                         lex.next(true);
190                         string mlabel = _(lex.GetString());
191                         lex.next(true);
192                         string mname = lex.GetString();
193                         add(MenuItem(MenuItem::Submenu, mlabel, mname));
194                         break;
195                 }
196
197                 case md_endmenu:
198                         quit = true;
199                         break;
200
201                 default:
202                         lex.printError("menubar::read: "
203                                        "Unknown menu tag: `$$Token'");
204                         break;
205                 }
206         }
207         lex.popTable();
208         return *this;
209 }
210
211
212 void Menu::checkShortcuts() const
213 {
214         // This is a quadratic algorithm, but we do not care because
215         // it is used for debugging only.
216         for (const_iterator it1 = begin(); it1 != end(); ++it1) {
217                 string shortcut = it1->shortcut();
218                 if (shortcut.empty())
219                         continue;
220                 if (!contains(it1->label(), shortcut))
221                         lyxerr << "Menu warning: menu entry \""
222                                << it1->label()
223                                << "\" does not contain shortcut `"
224                                << shortcut << '\'' << endl;
225                 for (const_iterator it2 = begin(); it2 != it1 ; ++it2) {
226                         if (!compare_no_case(it2->shortcut(), shortcut)) {
227                                 lyxerr << "Menu warning: menu entries "
228                                        << '"' << it1->fulllabel()
229                                        << "\" and \"" << it2->fulllabel()
230                                        << "\" share the same shortcut."
231                                        << endl;
232                         }
233                 }
234         }
235 }
236
237
238 namespace {
239
240 class compare_format {
241 public:
242         bool operator()(Format const * p1, Format const * p2) {
243                 return *p1 < *p2;       
244         }
245 };
246
247 } // namespace anon
248
249
250 void Menu::expand(Menu & tomenu, Buffer * buf) const
251 {
252         for (const_iterator cit = begin();
253              cit != end() ; ++cit) {
254                 switch (cit->kind()) {
255                 case MenuItem::Lastfiles: {
256                         int ii = 1;
257                         LastFiles::const_iterator lfit = lastfiles->begin();
258                         LastFiles::const_iterator end = lastfiles->end();
259                         
260                         for (; lfit != end && ii < 10; ++lfit, ++ii) {
261                                 string const label = tostr(ii) + ". "
262                                         + MakeDisplayPath((*lfit), 30)
263                                         + '|' + tostr(ii);
264                                 int const action = lyxaction.
265                                         getPseudoAction(LFUN_FILE_OPEN,
266                                                         (*lfit));
267                                 tomenu.add(MenuItem(MenuItem::Command,
268                                                     label, action));
269                         }
270                 }
271                 break;
272                 
273                 case MenuItem::Documents: {
274                         typedef vector<string> Strings;
275                         
276                         Strings const names = bufferlist.getFileNames();
277                         
278                         if (names.empty()) {
279                                 tomenu.add(MenuItem(MenuItem::Command,
280                                                     _("No Documents Open!"),
281                                                     LFUN_NOACTION));
282                                 break;
283                         }
284
285                         Strings::const_iterator docit = names.begin();
286                         Strings::const_iterator end = names.end();
287                         for (; docit != end ; ++docit) {
288                                 int const action = lyxaction
289                                         .getPseudoAction(LFUN_SWITCHBUFFER,
290                                                          *docit);
291                                 string const label =
292                                         MakeDisplayPath(*docit, 30);
293                                 tomenu.add(MenuItem(MenuItem::Command,
294                                                     label, action));
295                         }
296                 }
297                 break;
298
299                 case MenuItem::ImportFormats:
300                 case MenuItem::ViewFormats:
301                 case MenuItem::UpdateFormats:
302                 case MenuItem::ExportFormats: {
303                         typedef vector<Format const *> Formats;
304                         
305                         Formats formats;
306                         
307                         kb_action action;
308                         switch (cit->kind()) {
309                         case MenuItem::ImportFormats:
310                                 formats = Importer::GetImportableFormats();
311                                 action = LFUN_IMPORT;
312                                 break;
313                         case MenuItem::ViewFormats:
314                                 formats = Exporter::GetExportableFormats(buf, true); 
315                                 action = LFUN_PREVIEW;
316                                 break;
317                         case MenuItem::UpdateFormats:
318                                 formats = Exporter::GetExportableFormats(buf, true); 
319                                 action = LFUN_UPDATE;
320                                 break;
321                         default:
322                                 formats = Exporter::GetExportableFormats(buf, false); 
323                                 action = LFUN_EXPORT;
324                         }
325                         sort(formats.begin(), formats.end(), compare_format());
326
327                         Formats::const_iterator fit = formats.begin();
328                         Formats::const_iterator end = formats.end();
329                         
330                         for (; fit != end ; ++fit) {
331                                 if ((*fit)->dummy())
332                                         continue;
333                                 string label = (*fit)->prettyname();
334                                 if (cit->kind() == MenuItem::ImportFormats)
335                                         if ((*fit)->name() == "text")
336                                                 label = _("Ascii text as lines");
337                                         else if ((*fit)->name() == "textparagraph")
338                                                 label = _("Ascii text as paragraphs");
339                                 if (!(*fit)->shortcut().empty())
340                                         label += "|" + (*fit)->shortcut();
341                                 int const action2 = lyxaction.
342                                         getPseudoAction(action,
343                                                         (*fit)->name());
344                                 tomenu.add(MenuItem(MenuItem::Command,
345                                                     label, action2));
346                         }
347                 }
348                 break;
349
350                 case MenuItem::FloatListInsert:
351                 {
352                         FloatList::const_iterator cit = floatList.begin();
353                         FloatList::const_iterator end = floatList.end();
354                         for (; cit != end; ++cit) {
355                                 int const action =  lyxaction
356                                         .getPseudoAction(LFUN_FLOAT_LIST,
357                                                          cit->second.type());
358                                 string label = _("List of ");
359                                 label += cit->second.name();
360                                 tomenu.add(MenuItem(MenuItem::Command,
361                                                     label, action));
362                         }
363                 }
364                 break;
365
366                 case MenuItem::FloatInsert:
367                 {
368                         FloatList::const_iterator cit = floatList.begin();
369                         FloatList::const_iterator end = floatList.end();
370                         for (; cit != end; ++cit) {
371                                 // normal float
372                                 int const action = lyxaction
373                                         .getPseudoAction(LFUN_INSET_FLOAT,
374                                                          cit->second.type());
375                                 string const label = cit->second.name();
376                                 tomenu.add(MenuItem(MenuItem::Command,
377                                                     label, action));
378                                 
379                                 // and the wide version
380                                 int const action2 = lyxaction
381                                         .getPseudoAction(LFUN_INSET_WIDE_FLOAT,
382                                                          cit->second.type());
383                                 string const label2 = _("Wide ") + label;
384                                 tomenu.add(MenuItem(MenuItem::Command,
385                                                     label2, action2));
386                         }
387                 }
388                 break;
389                 
390                 default:
391                         tomenu.add(*cit);
392                 }
393         }
394
395         // Check whether the shortcuts are unique
396         if (lyxerr.debugging(Debug::GUI))
397                 checkShortcuts();
398 }
399
400
401 bool Menu::hasSubmenu(string const & name) const
402 {
403         return find_if(begin(), end(),
404                        lyx::compare_memfun(&MenuItem::submenu, name)) != end();
405 }
406
407
408 void MenuBackend::read(LyXLex & lex)
409 {
410         enum Menutags {
411                 md_menu = 1,
412                 md_menubar,
413                 md_endmenuset,
414                 md_last
415         };
416
417         struct keyword_item menutags[md_last - 1] = {
418                 { "end", md_endmenuset },
419                 { "menu", md_menu },
420                 { "menubar", md_menubar }
421         };
422
423         //consistency check
424         if (compare_no_case(lex.GetString(), "menuset"))
425                 lyxerr << "Menubackend::read: ERROR wrong token:`"
426                        << lex.GetString() << '\'' << endl;
427
428         lex.pushTable(menutags, md_last - 1);
429         if (lyxerr.debugging(Debug::PARSER))
430                 lex.printTable(lyxerr);
431
432         bool quit = false;
433         bool menubar = false;
434
435         while (lex.IsOK() && !quit) {
436                 switch (lex.lex()) {
437                 case md_menubar: 
438                         menubar = true;
439                         // fallback to md_menu
440                 case md_menu: {
441                         lex.next(true);
442                         string name = lex.GetString();
443                         if (hasMenu(name)) {
444                                 if (getMenu(name).menubar() == menubar) {
445                                         getMenu(name).read(lex);
446                                 } else {
447                                         lex.printError("Cannot append to menu `$$Token' unless it is of the same type");
448                                         return;
449                                 }
450                         } else {                                
451                                 Menu menu(name, menubar);
452                                 menu.read(lex);
453                                 add(menu);
454                         }
455                         menubar = false;
456                         break;
457                 }
458                 case md_endmenuset:
459                         quit = true;
460                         break;
461                 default:
462                         lex.printError("menubackend::read: "
463                                        "Unknown menu tag: `$$Token'");
464                         break;
465                 }
466         }
467         lex.popTable();
468 }
469
470
471 void MenuBackend::defaults()
472 {
473         menulist_.clear();
474
475         lyxerr[Debug::GUI] << "MenuBackend::defaults: using default values" 
476                            << endl;
477
478         Menu file("file");
479         file
480                 .add(MenuItem(MenuItem::Command, _("New...|N"), "buffer-new"))
481                 .add(MenuItem(MenuItem::Command, _("Open...|O"), "buffer-open"))
482                 .add(MenuItem(MenuItem::Submenu, _("Import|I"), "import"))
483                 .add(MenuItem(MenuItem::Command, _("Quit|Q"), "lyx-quit"))
484                 .add(MenuItem(MenuItem::Separator))
485                 .add(MenuItem(MenuItem::Lastfiles));
486         add(file);
487
488         Menu import("import");
489         import
490                 .add(MenuItem(MenuItem::Command,
491                               _("LaTeX...|L"), "buffer-import latex"))
492                 .add(MenuItem(MenuItem::Command,
493                               _("LinuxDoc...|L"), "buffer-import linuxdoc"));
494         add(import);
495  
496         Menu edit("edit");
497         edit
498                 .add(MenuItem(MenuItem::Command, _("Cut"), "cut"))
499                 .add(MenuItem(MenuItem::Command, _("Copy"), "copy"))
500                 .add(MenuItem(MenuItem::Command, _("Paste"), "paste"))
501                 .add(MenuItem(MenuItem::Command, _("Emphasize"), "font-emph"));
502         add(edit);
503
504         Menu documents("documents");
505         documents.add(MenuItem(MenuItem::Documents));
506         add(documents);
507
508         Menu main("main", true);
509         main
510                 .add(MenuItem(MenuItem::Submenu, _("File|F"), "file"))
511                 .add(MenuItem(MenuItem::Submenu, _("Edit|E"), "edit"))
512                 .add(MenuItem(MenuItem::Submenu,
513                               _("Documents|D"), "documents"));
514         add(main);
515
516         Menu main_nobuffer("main_nobuffer", true);
517         main_nobuffer.add(MenuItem(MenuItem::Submenu, _("File|F"), "file"));
518         add(main_nobuffer);
519
520         if (lyxerr.debugging(Debug::GUI)) {
521                 for (const_iterator cit = begin();
522                     cit != end() ; ++cit)
523                         lyxerr << "Menu name: " << cit->name() 
524                                << ", Menubar: " << cit->menubar() 
525                                << endl;
526         }
527 }
528
529
530 void MenuBackend::add(Menu const & menu)
531 {
532         menulist_.push_back(menu);
533 }
534
535
536 bool MenuBackend::hasMenu(string const & name) const
537 {
538         return find_if(begin(), end(),
539                        lyx::compare_memfun(&Menu::name, name)) != end();
540 }
541
542
543 Menu const & MenuBackend::getMenu(string const & name) const
544 {
545         const_iterator cit = find_if(begin(), end(),
546                                      lyx::compare_memfun(&Menu::name, name));
547         lyx::Assert(cit != end());
548         return (*cit);
549 }
550
551
552 Menu & MenuBackend::getMenu(string const & name)
553 {
554         MenuList::iterator it =
555                 find_if(menulist_.begin(), menulist_.end(),
556                         lyx::compare_memfun(&Menu::name, name));
557         lyx::Assert(it != menulist_.end());
558         return (*it);
559 }