1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2001 The LyX Team.
10 * ====================================================== */
15 #pragma implementation
19 #include "MenuBackend.h"
21 #include "LyXAction.h"
24 #include "lastfiles.h"
25 #include "bufferlist.h"
26 #include "converter.h"
29 #include "FloatList.h"
30 #include "support/LAssert.h"
31 #include "support/filetools.h"
32 #include "support/lyxfunctional.h"
34 extern LyXAction lyxaction;
35 extern LastFiles * lastfiles;
36 extern BufferList bufferlist;
44 // This is the global menu definition
45 MenuBackend menubackend;
48 MenuItem::MenuItem(Kind kind, string const & label,
49 string const & command, bool optional)
50 : kind_(kind), label_(label), optional_(optional)
65 action_ = lyxaction.LookupFunc(command);
67 if (action_ == LFUN_UNKNOWN_ACTION) {
68 lyxerr << "MenuItem(): LyX command `"
69 << command << "' does not exist." << endl;
72 lyxerr[Debug::GUI] << "Optional item "
82 Menu & Menu::add(MenuItem const & i)
89 Menu & Menu::read(LyXLex & lex)
109 struct keyword_item menutags[md_last - 1] = {
110 { "documents", md_documents },
111 { "end", md_endmenu },
112 { "exportformats", md_exportformats },
113 { "floatinsert", md_floatinsert },
114 { "floatlistinsert", md_floatlistinsert },
115 { "importformats", md_importformats },
117 { "lastfiles", md_lastfiles },
118 { "optitem", md_optitem },
119 { "separator", md_separator },
120 { "submenu", md_submenu },
122 { "updateformats", md_updateformats },
123 { "viewformats", md_viewformats }
126 lex.pushTable(menutags, md_last - 1);
127 if (lyxerr.debugging(Debug::PARSER))
128 lex.printTable(lyxerr);
131 bool optional = false;
133 while (lex.IsOK() && !quit) {
137 // fallback to md_item
140 string const name = _(lex.GetString());
142 string const command = lex.GetString();
143 add(MenuItem(MenuItem::Command, name,
150 add(MenuItem(MenuItem::Separator));
154 add(MenuItem(MenuItem::Lastfiles));
158 add(MenuItem(MenuItem::Documents));
162 add(MenuItem(MenuItem::Toc));
166 add(MenuItem(MenuItem::ViewFormats));
169 case md_updateformats:
170 add(MenuItem(MenuItem::UpdateFormats));
173 case md_exportformats:
174 add(MenuItem(MenuItem::ExportFormats));
177 case md_importformats:
178 add(MenuItem(MenuItem::ImportFormats));
181 case md_floatlistinsert:
182 add(MenuItem(MenuItem::FloatListInsert));
186 add(MenuItem(MenuItem::FloatInsert));
191 string mlabel = _(lex.GetString());
193 string mname = lex.GetString();
194 add(MenuItem(MenuItem::Submenu, mlabel, mname));
203 lex.printError("menubar::read: "
204 "Unknown menu tag: `$$Token'");
213 void Menu::checkShortcuts() const
215 // This is a quadratic algorithm, but we do not care because
216 // it is used for debugging only.
217 for (const_iterator it1 = begin(); it1 != end(); ++it1) {
218 string shortcut = it1->shortcut();
219 if (shortcut.empty())
221 if (!contains(it1->label(), shortcut))
222 lyxerr << "Menu warning: menu entry \""
224 << "\" does not contain shortcut `"
225 << shortcut << '\'' << endl;
226 for (const_iterator it2 = begin(); it2 != it1 ; ++it2) {
227 if (!compare_no_case(it2->shortcut(), shortcut)) {
228 lyxerr << "Menu warning: menu entries "
229 << '"' << it1->fulllabel()
230 << "\" and \"" << it2->fulllabel()
231 << "\" share the same shortcut."
241 class compare_format {
243 bool operator()(Format const * p1, Format const * p2) {
251 void Menu::expand(Menu & tomenu, Buffer * buf) const
253 for (const_iterator cit = begin();
254 cit != end() ; ++cit) {
255 switch (cit->kind()) {
256 case MenuItem::Lastfiles: {
258 LastFiles::const_iterator lfit = lastfiles->begin();
259 LastFiles::const_iterator end = lastfiles->end();
261 for (; lfit != end && ii < 10; ++lfit, ++ii) {
262 string const label = tostr(ii) + ". "
263 + MakeDisplayPath((*lfit), 30)
265 int const action = lyxaction.
266 getPseudoAction(LFUN_FILE_OPEN,
268 tomenu.add(MenuItem(MenuItem::Command,
274 case MenuItem::Documents: {
275 typedef vector<string> Strings;
277 Strings const names = bufferlist.getFileNames();
280 tomenu.add(MenuItem(MenuItem::Command,
281 _("No Documents Open!"),
286 Strings::const_iterator docit = names.begin();
287 Strings::const_iterator end = names.end();
288 for (; docit != end ; ++docit) {
289 int const action = lyxaction
290 .getPseudoAction(LFUN_SWITCHBUFFER,
293 MakeDisplayPath(*docit, 30);
294 tomenu.add(MenuItem(MenuItem::Command,
300 case MenuItem::ImportFormats:
301 case MenuItem::ViewFormats:
302 case MenuItem::UpdateFormats:
303 case MenuItem::ExportFormats: {
304 typedef vector<Format const *> Formats;
309 switch (cit->kind()) {
310 case MenuItem::ImportFormats:
311 formats = Importer::GetImportableFormats();
312 action = LFUN_IMPORT;
314 case MenuItem::ViewFormats:
315 formats = Exporter::GetExportableFormats(buf, true);
316 action = LFUN_PREVIEW;
318 case MenuItem::UpdateFormats:
319 formats = Exporter::GetExportableFormats(buf, true);
320 action = LFUN_UPDATE;
323 formats = Exporter::GetExportableFormats(buf, false);
324 action = LFUN_EXPORT;
326 sort(formats.begin(), formats.end(), compare_format());
328 Formats::const_iterator fit = formats.begin();
329 Formats::const_iterator end = formats.end();
331 for (; fit != end ; ++fit) {
334 string label = (*fit)->prettyname();
335 if (cit->kind() == MenuItem::ImportFormats)
336 if ((*fit)->name() == "text")
337 label = _("Ascii text as lines");
338 else if ((*fit)->name() == "textparagraph")
339 label = _("Ascii text as paragraphs");
340 if (!(*fit)->shortcut().empty())
341 label += "|" + (*fit)->shortcut();
342 int const action2 = lyxaction.
343 getPseudoAction(action,
345 tomenu.add(MenuItem(MenuItem::Command,
351 case MenuItem::FloatListInsert:
353 FloatList::const_iterator cit = floatList.begin();
354 FloatList::const_iterator end = floatList.end();
355 for (; cit != end; ++cit) {
356 int const action = lyxaction
357 .getPseudoAction(LFUN_FLOAT_LIST,
359 string label = _("List of ");
360 label += cit->second.name();
361 tomenu.add(MenuItem(MenuItem::Command,
367 case MenuItem::FloatInsert:
369 FloatList::const_iterator cit = floatList.begin();
370 FloatList::const_iterator end = floatList.end();
371 for (; cit != end; ++cit) {
373 int const action = lyxaction
374 .getPseudoAction(LFUN_INSET_FLOAT,
376 string const label = cit->second.name();
377 tomenu.add(MenuItem(MenuItem::Command,
380 // and the wide version
381 int const action2 = lyxaction
382 .getPseudoAction(LFUN_INSET_WIDE_FLOAT,
384 string const label2 = _("Wide ") + label;
385 tomenu.add(MenuItem(MenuItem::Command,
396 // Check whether the shortcuts are unique
397 if (lyxerr.debugging(Debug::GUI))
402 bool Menu::hasSubmenu(string const & name) const
404 return find_if(begin(), end(),
405 lyx::compare_memfun(&MenuItem::submenu, name)) != end();
409 void MenuBackend::read(LyXLex & lex)
418 struct keyword_item menutags[md_last - 1] = {
419 { "end", md_endmenuset },
421 { "menubar", md_menubar }
425 if (compare_no_case(lex.GetString(), "menuset"))
426 lyxerr << "Menubackend::read: ERROR wrong token:`"
427 << lex.GetString() << '\'' << endl;
429 lex.pushTable(menutags, md_last - 1);
430 if (lyxerr.debugging(Debug::PARSER))
431 lex.printTable(lyxerr);
434 bool menubar = false;
436 while (lex.IsOK() && !quit) {
440 // fallback to md_menu
443 string name = lex.GetString();
445 if (getMenu(name).menubar() == menubar) {
446 getMenu(name).read(lex);
448 lex.printError("Cannot append to menu `$$Token' unless it is of the same type");
452 Menu menu(name, menubar);
463 lex.printError("menubackend::read: "
464 "Unknown menu tag: `$$Token'");
472 void MenuBackend::defaults()
476 lyxerr[Debug::GUI] << "MenuBackend::defaults: using default values"
481 .add(MenuItem(MenuItem::Command, _("New...|N"), "buffer-new"))
482 .add(MenuItem(MenuItem::Command, _("Open...|O"), "buffer-open"))
483 .add(MenuItem(MenuItem::Submenu, _("Import|I"), "import"))
484 .add(MenuItem(MenuItem::Command, _("Quit|Q"), "lyx-quit"))
485 .add(MenuItem(MenuItem::Separator))
486 .add(MenuItem(MenuItem::Lastfiles));
489 Menu import("import");
491 .add(MenuItem(MenuItem::Command,
492 _("LaTeX...|L"), "buffer-import latex"))
493 .add(MenuItem(MenuItem::Command,
494 _("LinuxDoc...|L"), "buffer-import linuxdoc"));
499 .add(MenuItem(MenuItem::Command, _("Cut"), "cut"))
500 .add(MenuItem(MenuItem::Command, _("Copy"), "copy"))
501 .add(MenuItem(MenuItem::Command, _("Paste"), "paste"))
502 .add(MenuItem(MenuItem::Command, _("Emphasize"), "font-emph"));
505 Menu documents("documents");
506 documents.add(MenuItem(MenuItem::Documents));
509 Menu main("main", true);
511 .add(MenuItem(MenuItem::Submenu, _("File|F"), "file"))
512 .add(MenuItem(MenuItem::Submenu, _("Edit|E"), "edit"))
513 .add(MenuItem(MenuItem::Submenu,
514 _("Documents|D"), "documents"));
517 Menu main_nobuffer("main_nobuffer", true);
518 main_nobuffer.add(MenuItem(MenuItem::Submenu, _("File|F"), "file"));
521 if (lyxerr.debugging(Debug::GUI)) {
522 for (const_iterator cit = begin();
523 cit != end() ; ++cit)
524 lyxerr << "Menu name: " << cit->name()
525 << ", Menubar: " << cit->menubar()
531 void MenuBackend::add(Menu const & menu)
533 menulist_.push_back(menu);
537 bool MenuBackend::hasMenu(string const & name) const
539 return find_if(begin(), end(),
540 lyx::compare_memfun(&Menu::name, name)) != end();
544 Menu const & MenuBackend::getMenu(string const & name) const
546 const_iterator cit = find_if(begin(), end(),
547 lyx::compare_memfun(&Menu::name, name));
548 lyx::Assert(cit != end());
553 Menu & MenuBackend::getMenu(string const & name)
555 MenuList::iterator it =
556 find_if(menulist_.begin(), menulist_.end(),
557 lyx::compare_memfun(&Menu::name, name));
558 lyx::Assert(it != menulist_.end());