aboutsummaryrefslogtreecommitdiff
path: root/src/MenuCreator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/MenuCreator.cc')
-rw-r--r--src/MenuCreator.cc132
1 files changed, 108 insertions, 24 deletions
diff --git a/src/MenuCreator.cc b/src/MenuCreator.cc
index 2aa73ba..e33db19 100644
--- a/src/MenuCreator.cc
+++ b/src/MenuCreator.cc
@@ -55,6 +55,11 @@
55#include <iostream> 55#include <iostream>
56using namespace std; 56using namespace std;
57 57
58std::list<std::string> MenuCreator::encoding_stack;
59std::list<size_t> MenuCreator::stacksize_stack;
60
61FbTk::StringConvertor MenuCreator::m_stringconvertor(FbTk::StringConvertor::ToFbString);
62
58static void createStyleMenu(FbTk::Menu &parent, const std::string &label, 63static void createStyleMenu(FbTk::Menu &parent, const std::string &label,
59 const std::string &directory) { 64 const std::string &directory) {
60 // perform shell style ~ home directory expansion 65 // perform shell style ~ home directory expansion
@@ -131,8 +136,9 @@ class ParseItem {
131public: 136public:
132 explicit ParseItem(FbTk::Menu *menu):m_menu(menu) {} 137 explicit ParseItem(FbTk::Menu *menu):m_menu(menu) {}
133 138
134 inline void load(Parser &p) { 139 inline void load(Parser &p, FbTk::StringConvertor &m_labelconvertor) {
135 p>>m_key>>m_label>>m_cmd>>m_icon; 140 p>>m_key>>m_label>>m_cmd>>m_icon;
141 m_label.second = m_labelconvertor.recode(m_label.second);
136 } 142 }
137 inline const std::string &icon() const { return m_icon.second; } 143 inline const std::string &icon() const { return m_icon.second; }
138 inline const std::string &command() const { return m_cmd.second; } 144 inline const std::string &command() const { return m_cmd.second; }
@@ -158,20 +164,20 @@ public:
158 } 164 }
159}; 165};
160 166
161static void translateMenuItem(Parser &parse, ParseItem &item); 167static void translateMenuItem(Parser &parse, ParseItem &item, FbTk::StringConvertor &labelconvertor);
162 168
163 169
164static void parseMenu(Parser &pars, FbTk::Menu &menu) { 170static void parseMenu(Parser &pars, FbTk::Menu &menu, FbTk::StringConvertor &label_convertor) {
165 ParseItem pitem(&menu); 171 ParseItem pitem(&menu);
166 while (!pars.eof()) { 172 while (!pars.eof()) {
167 pitem.load(pars); 173 pitem.load(pars, label_convertor);
168 if (pitem.key() == "end") 174 if (pitem.key() == "end")
169 return; 175 return;
170 translateMenuItem(pars, pitem); 176 translateMenuItem(pars, pitem, label_convertor);
171 } 177 }
172} 178}
173 179
174static void translateMenuItem(Parser &parse, ParseItem &pitem) { 180static void translateMenuItem(Parser &parse, ParseItem &pitem, FbTk::StringConvertor &labelconvertor) {
175 if (pitem.menu() == 0) 181 if (pitem.menu() == 0)
176 throw string("translateMenuItem: We must have a menu in ParseItem!"); 182 throw string("translateMenuItem: We must have a menu in ParseItem!");
177 183
@@ -256,14 +262,12 @@ static void translateMenuItem(Parser &parse, ParseItem &pitem) {
256 (filelist[file_index][0] != '.') && 262 (filelist[file_index][0] != '.') &&
257 (thisfile[thisfile.length() - 1] != '~')) { 263 (thisfile[thisfile.length() - 1] != '~')) {
258 MenuCreator::createFromFile(thisfile, menu, false); 264 MenuCreator::createFromFile(thisfile, menu, false);
259 Fluxbox::instance()->saveMenuFilename(thisfile.c_str());
260 } 265 }
261 } 266 }
262 267
263 } else { 268 } else {
264 // inject this file into the current menu 269 // inject this file into the current menu
265 MenuCreator::createFromFile(newfile, menu, false); 270 MenuCreator::createFromFile(newfile, menu, false);
266 Fluxbox::instance()->saveMenuFilename(newfile.c_str());
267 } 271 }
268 272
269 safe_counter--; 273 safe_counter--;
@@ -280,7 +284,7 @@ static void translateMenuItem(Parser &parse, ParseItem &pitem) {
280 else 284 else
281 submenu->setLabel(str_label); 285 submenu->setLabel(str_label);
282 286
283 parseMenu(parse, *submenu); 287 parseMenu(parse, *submenu, labelconvertor);
284 submenu->updateMenu(); 288 submenu->updateMenu();
285 menu.insert(str_label, submenu); 289 menu.insert(str_label, submenu);
286 // save to screen list so we can delete it later 290 // save to screen list so we can delete it later
@@ -310,6 +314,10 @@ static void translateMenuItem(Parser &parse, ParseItem &pitem) {
310 } 314 }
311 } else if (str_key == "separator") { 315 } else if (str_key == "separator") {
312 menu.insert(new FbTk::MenuSeparator()); 316 menu.insert(new FbTk::MenuSeparator());
317 } else if (str_key == "encoding") {
318 MenuCreator::startEncoding(str_cmd);
319 } else if (str_key == "endencoding") {
320 MenuCreator::endEncoding();
313 } 321 }
314 else { // ok, if we didn't find any special menu item we try with command parser 322 else { // ok, if we didn't find any special menu item we try with command parser
315 // we need to attach command with arguments so command parser can parse it 323 // we need to attach command with arguments so command parser can parse it
@@ -337,11 +345,11 @@ static void translateMenuItem(Parser &parse, ParseItem &pitem) {
337} 345}
338 346
339 347
340static void parseWindowMenu(Parser &parse, FbTk::Menu &menu) { 348static void parseWindowMenu(Parser &parse, FbTk::Menu &menu, FbTk::StringConvertor &labelconvertor) {
341 349
342 ParseItem pitem(&menu); 350 ParseItem pitem(&menu);
343 while (!parse.eof()) { 351 while (!parse.eof()) {
344 pitem.load(parse); 352 pitem.load(parse, labelconvertor);
345 if (MenuCreator::createWindowMenuItem(pitem.key(), pitem.label(), menu)) 353 if (MenuCreator::createWindowMenuItem(pitem.key(), pitem.label(), menu))
346 continue; 354 continue;
347 355
@@ -349,12 +357,12 @@ static void parseWindowMenu(Parser &parse, FbTk::Menu &menu) {
349 return; 357 return;
350 } else if (pitem.key() == "submenu") { 358 } else if (pitem.key() == "submenu") {
351 FbTk::Menu *submenu = MenuCreator::createMenu(pitem.label(), menu.screenNumber()); 359 FbTk::Menu *submenu = MenuCreator::createMenu(pitem.label(), menu.screenNumber());
352 parseWindowMenu(parse, *submenu); 360 parseWindowMenu(parse, *submenu, labelconvertor);
353 submenu->updateMenu(); 361 submenu->updateMenu();
354 menu.insert(pitem.label(), submenu); 362 menu.insert(pitem.label(), submenu);
355 363
356 } else { // try non window menu specific stuff 364 } else { // try non window menu specific stuff
357 translateMenuItem(parse, pitem); 365 translateMenuItem(parse, pitem, labelconvertor);
358 } 366 }
359 } 367 }
360} 368}
@@ -373,11 +381,11 @@ FbTk::Menu *MenuCreator::createMenu(const std::string &label, int screen_number)
373 return menu; 381 return menu;
374} 382}
375 383
376bool getStart(FbMenuParser &parser, std::string &label) { 384bool getStart(FbMenuParser &parser, std::string &label, FbTk::StringConvertor &labelconvertor) {
377 ParseItem pitem(0); 385 ParseItem pitem(0);
378 while (!parser.eof()) { 386 while (!parser.eof()) {
379 // get first begin line 387 // get first begin line
380 pitem.load(parser); 388 pitem.load(parser, labelconvertor);
381 if (pitem.key() == "begin") { 389 if (pitem.key() == "begin") {
382 break; 390 break;
383 } 391 }
@@ -391,19 +399,22 @@ bool getStart(FbMenuParser &parser, std::string &label) {
391 399
392FbTk::Menu *MenuCreator::createFromFile(const std::string &filename, int screen_number, bool require_begin) { 400FbTk::Menu *MenuCreator::createFromFile(const std::string &filename, int screen_number, bool require_begin) {
393 std::string real_filename = FbTk::StringUtil::expandFilename(filename); 401 std::string real_filename = FbTk::StringUtil::expandFilename(filename);
402 Fluxbox::instance()->saveMenuFilename(real_filename.c_str());
403
394 FbMenuParser parser(real_filename); 404 FbMenuParser parser(real_filename);
395 if (!parser.isLoaded()) 405 if (!parser.isLoaded())
396 return 0; 406 return 0;
397 407
398 Fluxbox::instance()->saveMenuFilename(real_filename.c_str());
399
400 std::string label; 408 std::string label;
401 if (require_begin && !getStart(parser, label)) 409 if (require_begin && !getStart(parser, label, m_stringconvertor))
402 return 0; 410 return 0;
403 411
404 FbTk::Menu *menu = createMenu(label, screen_number); 412 FbTk::Menu *menu = createMenu(label, screen_number);
405 if (menu != 0) 413 if (menu != 0) {
406 parseMenu(parser, *menu); 414 startFile();
415 parseMenu(parser, *menu, m_stringconvertor);
416 endFile();
417 }
407 418
408 return menu; 419 return menu;
409} 420}
@@ -418,10 +429,13 @@ bool MenuCreator::createFromFile(const std::string &filename,
418 return false; 429 return false;
419 430
420 std::string label; 431 std::string label;
421 if (require_begin && !getStart(parser, label)) 432 if (require_begin && !getStart(parser, label, m_stringconvertor))
422 return false; 433 return false;
423 434
424 parseMenu(parser, inject_into); 435 startFile();
436 parseMenu(parser, inject_into, m_stringconvertor);
437 endFile();
438
425 return true; 439 return true;
426} 440}
427 441
@@ -436,10 +450,13 @@ bool MenuCreator::createWindowMenuFromFile(const std::string &filename,
436 450
437 std::string label; 451 std::string label;
438 452
439 if (require_begin && !getStart(parser, label)) 453 if (require_begin && !getStart(parser, label, m_stringconvertor))
440 return false; 454 return false;
441 455
442 parseWindowMenu(parser, inject_into); 456 startFile();
457 parseWindowMenu(parser, inject_into, m_stringconvertor);
458 endFile();
459
443 return true; 460 return true;
444} 461}
445 462
@@ -580,3 +597,70 @@ bool MenuCreator::createWindowMenuItem(const std::string &type,
580 597
581 return true; 598 return true;
582} 599}
600
601/* push our encoding-stacksize onto the stack */
602void MenuCreator::startFile() {
603 if (encoding_stack.empty())
604 m_stringconvertor.setSource("");
605 stacksize_stack.push_back(encoding_stack.size());
606}
607
608/**
609 * Pop necessary encodings from the stack
610 * (and endEncoding the final one) to our matching encoding-stacksize.
611 */
612void MenuCreator::endFile() {
613 size_t target_size = stacksize_stack.back();
614 size_t curr_size = encoding_stack.size();
615
616 if (target_size != curr_size) {
617 _FB_USES_NLS;
618 cerr<<_FB_CONSOLETEXT(Menu, ErrorEndEncoding, "Warning: unbalanced [encoding] tags", "User menu file had unbalanced [encoding] tags")<<endl;
619 }
620
621 for (; curr_size > (target_size+1); --curr_size)
622 encoding_stack.pop_back();
623
624 if (curr_size == (target_size+1))
625 endEncoding();
626
627 stacksize_stack.pop_back();
628}
629
630/**
631 * Push the encoding onto the stack, and make it active.
632 */
633void MenuCreator::startEncoding(const std::string &encoding) {
634 // we push it regardless of whether it's valid, since we
635 // need to stay balanced with the endEncodings.
636 encoding_stack.push_back(encoding);
637
638 // this won't change if it doesn't succeed
639 m_stringconvertor.setSource(encoding);
640}
641
642/**
643 * Pop the encoding from the stack, unless we are at our stacksize limit.
644 * Restore the previous (valid) encoding.
645 */
646void MenuCreator::endEncoding() {
647 size_t min_size = stacksize_stack.back();
648 if (encoding_stack.size() <= min_size) {
649 // TODO: nls
650 _FB_USES_NLS;
651 cerr<<_FB_CONSOLETEXT(Menu, ErrorEndEncoding, "Warning: unbalanced [encoding] tags", "User menu file had unbalanced [encoding] tags")<<endl;
652 return;
653 }
654
655 encoding_stack.pop_back();
656 m_stringconvertor.reset();
657
658 std::list<std::string>::reverse_iterator it = encoding_stack.rbegin();
659 std::list<std::string>::reverse_iterator it_end = encoding_stack.rend();
660 while (it != it_end && !m_stringconvertor.setSource(*it))
661 ++it;
662
663 if (it == it_end)
664 m_stringconvertor.setSource("");
665}
666